Пытаемся понять как работать с общим кодом на основе постера картинок на стену ВК

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
Приветствую всех коллег по цеху!

Начну с благодарностей, спасибо @sibbora с его шикарными материалами из академии и @LaGir aka
@Klask с его разъяснениями и мини-обзорами!!!


Коротко о себе.
Новичок в теме ZennoPoster, как программист в баллах 0.1/100, работаю специалистом по интернет-рекламе на заводе))).
Для себя решил изучать работу в коде сразу, минуя кубики.

Тема заработка не стояла для меня приоритетом, а вот проблема экономии времени очень острая. И, соответственно, я решая эти проблемы и изучал C#.

Одна из проблем – это размещение картинок, видео и гифок на стену и альбомы в ВК. Стандартные сервисы меня не устраивали, так как надо было сидеть и вбивать посты и время для размещения, а мне надо, чтобы программа сама брала файл из папки, описание и текст поста из файла.
В этой статье будет простой шаблон для размещения фотографий на стену группы ВК.

В качестве инструментов мы берем:
1. Руки (какие есть те и берем)
2. Документацию API ВК -- https://vk.com/dev/photos
3. Библиотеку NewtonSoft.dll
4. C#
5. Зенку

Начинаем планировать.
Продумываем файловую систему и структуру кода

С файлами я решил сделать так.
upload_2018-5-9_17-23-24.png
И в папке "foto to upload" разместил файл с описанием к фото и его же использую для текста поста:
upload_2018-5-9_17-24-48.png

Для удобства организации пространства я использую такое расположение окон:
upload_2018-5-9_17-27-45.png

Как хочется чтобы в PM появилась тёмная тема!

Для начала читаем как работает API для постинга фото в ВК.
Идем по ссылке ниже: VK API
Оттуда мы узнаем, что нам нужны 3 метода:
1. photos.getWallUploadServer – получаем ссылку на место, куда загрузим фотку и грузим фото
2. photos.saveWallPhoto – загружаем фото на сервер вк
3. photos.wall.post – размещаем фото на стену

Структура кода будет такой:
1. Блок с переменными
2. Блок авторизации/получения токена
3. Блок получения файла для постинга
4. Постинг через API VK
5. Будут добавлены модифицированные методы, которые слегка оптимизируют код

Итак, поехали.
Помещаем библиотеку NewtonSoft из папки progs в папку Progs\ExternalAssemblies и прописываем юзинги:
upload_2018-5-9_18-7-21.png

upload_2018-5-9_18-8-16.png

upload_2018-5-9_18-9-7.png

upload_2018-5-9_18-9-36.png

upload_2018-5-9_18-4-15.png

С переменными все должно быть просто. (Решил не использовать переменные уровня проекта)
C#:
//==Блок с переменными
Random rnd = new Random();
//Создаем пустой список куда в последствии помести пути к файлам из папки strSourceDirectoryPath
List<string> lstListFotoFiles = new List<string>();
//Присваиваем переменной путь к папке с файлами
string strSourceDirectoryPath = project.Directory + @"\foto to upload\";
//Directory.EnumerateFiles: получаем список файлов jpg в папке strSourceDirectoryPath
lstListFotoFiles.AddRange(Directory.EnumerateFiles(strSourceDirectoryPath, "*.jpg", SearchOption.AllDirectories));
//Берем логин и пароль из списка
//Считываем содержимое файла vkInput.txt
string strVkInput = File.ReadAllText(project.Directory + @"/vkInput.txt");
/*
Во входном файле у нас указанны данные в таком виде:
Log:Pass|GroupId|token
Используя разделитель '|' разбиваем текст на части в массив, затем первый элемент:
Log:Pass
тоже делим на части разделителем ':'.
и берем первый (нулевой) элемент массива Log.Так получаем логин.
Массивы и списки индексируются или как еще говорять нумеруются с нуля!!!!
*/
string strVKLogin = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[0];
/*
Во входном файле у нас указанны данные в таком виде:
Log:Pass|GroupId|token
Используя разделитель '|' разбиваем текст на части в массив, затем первый элемент:
Log:Pass
тоже делим на части разделителем ':'.
и берем второй (первый) элемент массива Pass. Так получаем пароль.
*/
string strVKPass = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[1];
string strIdFoto = String.Empty;
//Берем текст из файла caption.txt, это будет описанием к фото и текстом поста
string strCaption = File.ReadAllText(project.Directory + @"\foto to upload\caption.txt");
/*
Во входном файле у нас указанны данные в таком виде:
Log:Pass|GroupId|token
Используя разделитель '|' разбиваем текст на части в массив, затем второй элемент [1] и используем его как id группы вк GroupId.
*/
string strGroupId = strVkInput.Split('|').ToArray()[1];
/*
Во входном файле у нас указанны данные в таком виде:
Log:Pass|GroupId|token
Используя разделитель '|' разбиваем текст на части в массив, затем третий элемент [2] и используем его как токен вк token.
*/
string strAccess_token = strVkInput.Split('|').ToArray()[2];
//==Конец блока с переменными
Авторизацию я решил делать через официальное приложение вк для андроид.
C#:
//==Модуль авторизации и получения нового токена
if(strAccess_token.Contains("token")){
    strAccess_token = "";
    //Авторизация апи
    string strOauthVk = String.Format("https://oauth.vk.com/token?grant_type=password"
        +"&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={0}&password={1}",strVKLogin,strVKPass);
    string VkResp = ZennoPoster.HttpGet(strOauthVk);
    JObject jsonVk = JObject.Parse(VkResp);
    strAccess_token = jsonVk.SelectToken("access_token").ToString();
    //Записываем обновленные входные данные с токеном в файл в туже строку
    string inputData = strVkInput.Replace("token", strAccess_token);
    File.WriteAllText(project.Directory +  @"/vkInput.txt",inputData);
    project.SendInfoToLog("Взяли новый токен: " + strAccess_token +"\n Он сохранен в файл vkInput.txt", true);
}else{
    project.SendInfoToLog("Берем токен из файла");
}
//==Конец Модуля авторизации и получения нового токена
Разумеется, если токен у нас заполнен и он рабочий, то авторизация не поднадобится

А теперь начинаем процедуру постинга:
Нам нужно получить адрес сервера куда будем грузить фото:
C#:
//Формируем запрос на получение адреса сервера для загрузки и записываем его в переменную strGetServerUrl
string strGetServerUrl = String.Format(@"https://api.vk.com/method/photos.getWallUploadServer?v=5.69&access_token={0}&group_id={1}",
    strAccess_token,strGroupId);
//Делаем запрос ZennoPoster.HttpGet и записываем его в переменную strServerResult
string strServerResult = ZennoPoster.HttpGet(strGetServerUrl);

//Забираем адрес из ответа strServerResult с помощью регулярок
string strUploadServer = new Regex(@"(?<=""upload_url"":"")[\w\W]*?(?=\"",""album_id)").Match(strServerResult).ToString().Replace(@"\","");
//Примитивная проверка. Если strUploadServer имеет пустое значение, то подставляем во входном файле слово "token"  и останавливаем шаблон
if(strUploadServer==String.Empty){
    //поправляем шаблон под корректный вид
    File.WriteAllText(project.Directory +  @"/vkInput.txt",String.Format(@"{0}:{1}|{2}|token",strVKLogin,strVKPass,strGroupId));
    throw new Exception("Что-то не то с входным файлом. Останалвиваем шаблон. Проверьте логин, пароль и ид группы/n ПЕРЕЗАПУСТИТЕ ШАБЛОН");
}
project.SendWarningToLog("Забираем сервер: "+strUploadServer);
Сформировать запрос для загрузки на сервер:
C#:
//Формируем тело контент для загрузки на сервер
//Получение информации о файле для загрузки
FileInfo strFileInfo = new FileInfo(lstListFotoFiles[0]);
string FileName = strFileInfo.Name;
//==Формируем тело content для POST-запроса
string boundary = "------WebKitFormBoundary"+rnd.Next(100000000,999999999).ToString();
string post_data = "";
post_data += boundary + "\n";
post_data += string.Format("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\n", FileName);
post_data += "Content-Type: image/jpg\n";
post_data += lstListFotoFiles[0];
//==Конец формирования тела content для POST-запроса

//Загружаем фото на сервер ВК
project.SendInfoToLog("Второй этап - Грузим фото на сервер vk",true);
string uploadItemInfo = ZennoPoster.HttpPost(strUploadServer, post_data,
    "multipart/form-data",
    "",
    "utf-8",
    ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.BodyOnly,
    30000);
//Забираем из ответа id фото, server и hash
string photo_id = new Regex(@"(?<=""photo"":"").*?(?="","")").Match(uploadItemInfo).ToString().Replace(@"\","");
string server = new Regex(@"(?<=""server"":).*?(?=,)").Match(uploadItemInfo).ToString();
string hash = new Regex(@"(?<=""hash"":"").*?(?="")").Match(uploadItemInfo).ToString();
project.SendWarningToLog("Забираем данные для отправки фото:" +Environment.NewLine+
    "Фото id: "+photo_id +Environment.NewLine+
    "Сервер: "+server +Environment.NewLine+
    "Хэш: "+hash);
В ответе мы забираем с помощью регулярок id фотографии, сервер и хэш.

И делаем запрос для сохранения фото:
C#:
//Сохраняем фото на стену
project.SendInfoToLog("Третий  этап - получаем адрес сервера для загрузки фото",true);
project.SendInfoToLog("Взяли для описания: " + strCaption);
//Формируем запрос для сохранения на стену
string PostRequestUrl = String.Format("https://api.vk.com/method/photos.saveWallPhoto?access_token={0}&group_id={1}&photo={2}&server={3}&hash={4}&caption={5}&v=5.69",
    strAccess_token,strGroupId,photo_id,server,hash,TextProcessing.UrlEncode(strCaption));

string PostRequest =  ZennoPoster.HttpGet(PostRequestUrl);

project.SendInfoToLog("photos.saveWallPhoto " + PostRequest);
//Забираем ссылку на запись на стену PostRequest
string PhotoToWall = new Regex(@"(?<=\{""response"":\[\{""id"":)[\w\W]*?(?=,"")").Match(PostRequest).ToString();
string Owner_id = new Regex(@"(?<=owner_id"":)[\w\W]*?(?=,)").Match(PostRequest).ToString();
project.SendInfoToLog("id фото для размещения на стене " + PostRequest);
project.SendInfoToLog("photos.saveWallPhoto " + PhotoToWall);

string attach ="photo"+Owner_id+"_"+PhotoToWall;
Постим сохраненное фото на стену нашей группы:
C#:
string PostText = TextProcessing.UrlEncode(strCaption);
//Формируем запрос для размещения поста
string PostUrlWallGet = String.Format("https://api.vk.com/method/wall.post?"+
    "access_token={0}"+
    "&owner_id=-{1}"+
    "&friends_only=0"+
    "&from_group=1"+
    "&attachments={2}"+
    "&signed=0"+
    "&message={3}"+
    "&mark_as_ads=0"+
    "&v=5.69",
    strAccess_token,strGroupId,attach,PostText);
//Отправляем запрос
string PostId = ZennoPoster.HttpGet(PostUrlWallGet);
//Пауза 1 сек.
Thread.Sleep(1000);
//Забираем i поста из ответа PostId
string PostIdOnly = new Regex(@"(?<=""post_id"":).*?(?=}})").Match(PostId).ToString();
Перемещаем отработанный файл в папку foto used:

C#:
//Перемещаем использованный файл в папку used
File.Move(lstListFotoFiles[0],project.Directory+"/foto used/"+FileName);
//======+++Тут процес постинга закончен
//Формируем ссылку на пост
string FinishPostUrlForCheck = String.Format(@"https://vk.com/club{0}?w=wall-{0}_{1}",strGroupId,PostIdOnly);
project.SendInfoToLog("Ссылка на пост: " + FinishPostUrlForCheck, true);
А теперь смотрим, как это можно преобразовать в общий код, не будем усложнять, просто разобьем на две части: модуль авторизации и модуль для постинга. Разумеется можно разделить на более мелкие функции, но поскольку цель статьи просто понять что есть «общий код» lтак:

Для начала создадим свое пространство имен SocialBot (Можно писать и в ZennoLab.OwnCode)
upload_2018-5-9_18-11-20.png

Прописываем в юзингах и в общем коде
upload_2018-5-9_18-11-30.png

upload_2018-5-9_18-12-0.png
Продумаем структуру кода, я решил что надо сделать 3 класса кода по функциональности Tech, Acc, Poster.
  • В первом я храню процедуры и функции чисто технического характера
  • Во втором авторизация и операция с токеном
  • В третьем процедура размещения фото на стену


При работе с общим кодом есть также нюанс – это объекты instance и project. Их нет в общем коде и их надо подключить.
Для этого в классе Tech создаем глобальные переменные:
public static IZennoPosterProjectModel project;
public static Instance instance;

В сниппете прописываем:
Tech.project = project;
Tech.instance = instance;

И в каждом классе, где используются эти объекты, прописываем:
public static Instance instance = Tech.instance;
public static IZennoPosterProjectModel project= Tech.project;



Поскольку все мы знаем, что такое кубики, то мы видели, что у них есть галочка «не возвращать значение». На примере модуля авторизации мы должны получить access_token,
upload_2018-5-9_17-47-48.png

access_token – это строка, а значит нам надо этот модуль завернуть в конструкцию
public static string{}
, что и говорит о том что модуль=метод=функция возвращает нам строковое значение.
Как используем?
string strAccess_token = Acc.GetVkApiToken();

То есть мы создали метод, который прочтет файл и если не найдет там токен, то создаст его, запишет в файл и вернет в качестве строкового значения для переменной strAccess_token.

Модуль постинга не должен что-либо возвращать поэтому мы оборачиваем его в конструкцию
public static void ApiVkPhotoPost() – это просто процедура.
Теперь в сниппете прописываем код.

Некоторые внимательные читатели заметили, что я в обоих методах GetVkApiToken() и ApiVkPhotoPost() обращаюсь к входному файлу и это не есть хорошо. Как это исправить?
Ведь метод может вернуть только одну переменную!

Мы используем ключевое слово out
И прописываем в коде вот так:
C#:
        //Модифицированный метод получения токена, логина, пароля и прочих входных данных
        public static void ModGetVkApiToken(out string strVKLogin, out string strVKPass, out string strGroupId, out string strAccess_token)
        {
            string strVkInput = File.ReadAllLines(project.Directory + @"/vkInput.txt").ToArray()[0];
            strVKLogin = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[0];
            strVKPass = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[1];
            //Считаем id группы из файла
            strGroupId = strVkInput.Split('|').ToArray()[1];
            //Считаем token группы из файла
            strAccess_token = strVkInput.Split('|').ToArray()[2];
   
            if(!strAccess_token.Contains("token"))
            {
                project.SendInfoToLog("Взяли токен: " + strAccess_token, true);
            }else{
                strAccess_token = "";
                //Авторизация апи
                string strOauthVk = String.Format("https://oauth.vk.com/token?grant_type=password"
                    +"&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={0}&password={1}",strVKLogin,strVKPass);

                string VkResp = ZennoPoster.HttpGet(strOauthVk);
                JObject jsonVk = JObject.Parse(VkResp);
                strAccess_token = jsonVk.SelectToken("access_token").ToString();
                //Записываем обновленные входные данные с токеном в файл в туже строку
                string inputData = strVkInput.Replace("token", strAccess_token);
                File.WriteAllText(project.Directory +  @"/vkInput.txt",inputData);
                project.SendInfoToLog("Взяли новый токен: " + strAccess_token +"\n Он сохранен в файл vkInput.txt", true);
            }

        }
И вызываем его:
C#:
string strVKLogin = String.Empty;
            string strVKPass = String.Empty;
            //Считаем id группы из файла
            string strGroupId = String.Empty;
            //Потом поднадобится
            string strIdFoto = String.Empty;
            //Считываем описание к фотографии
            string strCaption = File.ReadAllText(project.Directory + @"\foto to upload\caption.txt");
            //************** Считаем token группы из файла
            string strAccess_token = String.Empty;
            Acc.ModGetVkApiToken(out strVKLogin, out strVKPass, out strGroupId, out strAccess_token);//Блок получения токена перенесен в общий код
Таким образом мы обращаемся к входному файлу только из метода ModGetVkApiToken.
А в процедуре ModApiVkPhotoPost() заранее создал пустые переменные которые будут наполнены после строки
C#:
Acc.ModGetVkApiToken(out strVKLogin, out strVKPass, out strGroupId, out strAccess_token);
Ну вот вроде все.
 

Для запуска проектов требуется программа ZennoPoster.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте программу ZennoPoster. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Последнее редактирование:

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
Вот так выглядит общий код:
C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;
using ZennoLab.CommandCenter;
using ZennoLab.InterfacesLibrary;
using ZennoLab.InterfacesLibrary.ProjectModel;
using ZennoLab.InterfacesLibrary.ProjectModel.Collections;
using ZennoLab.InterfacesLibrary.ProjectModel.Enums;
using ZennoLab.Macros;
using Global.ZennoExtensions;
using ZennoLab.Emulation;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using SocialBot;

namespace SocialBot{
    //Технический блок, сюде я впихиваю логер, планировщик и операции с файлами
    public class Tech
    {
        //Заклинание базовое
        public static IZennoPosterProjectModel project;
        public static Instance instance;

    }
    //Тут действия связанные с авторизациями и токенами
    public class Acc
    {
        //Подключаемся к базовому заклинанию
        public static Instance instance = Tech.instance;
        public static IZennoPosterProjectModel project= Tech.project;
    
        //Извлечь токен через собственное приложение вк. Браузерная авторизация.
        public static string GetVkApiToken()
        {
            string strVkInput = File.ReadAllLines(project.Directory + @"/vkInput.txt").ToArray()[0];
            string strVKLogin = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[0];
            string strVKPass = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[1];
            //Считаем id группы из файла
            string strGroupId = strVkInput.Split('|').ToArray()[1];
            //Считаем token группы из файла
            string strAccess_token = strVkInput.Split('|').ToArray()[2];
    
            if(!strAccess_token.Contains("token"))
            {
                project.SendInfoToLog("Взяли токен: " + strAccess_token, true);
                return strAccess_token;
            }else{
                strAccess_token = "";
                //Авторизация апи
                string strOauthVk = String.Format("https://oauth.vk.com/token?grant_type=password"
                    +"&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={0}&password={1}",strVKLogin,strVKPass);

                string VkResp = ZennoPoster.HttpGet(strOauthVk);
                JObject jsonVk = JObject.Parse(VkResp);
                strAccess_token = jsonVk.SelectToken("access_token").ToString();
                //Записываем обновленные входные данные с токеном в файл в туже строку
                string inputData = strVkInput.Replace("token", strAccess_token);
                File.WriteAllText(project.Directory +  @"/vkInput.txt",inputData);
                project.SendInfoToLog("Взяли новый токен: " + strAccess_token +"\n Он сохранен в файл vkInput.txt", true);
                return strAccess_token;
            }

        }
        //Модифицированный метод получения токена, логина, пароля и прочих входных данных
        public static void ModGetVkApiToken(out string strVKLogin, out string strVKPass, out string strGroupId, out string strAccess_token)
        {
            string strVkInput = File.ReadAllLines(project.Directory + @"/vkInput.txt").ToArray()[0];
            strVKLogin = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[0];
            strVKPass = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[1];
            //Считаем id группы из файла
            strGroupId = strVkInput.Split('|').ToArray()[1];
            //Считаем token группы из файла
            strAccess_token = strVkInput.Split('|').ToArray()[2];
    
            if(!strAccess_token.Contains("token"))
            {
                project.SendInfoToLog("Взяли токен: " + strAccess_token, true);
            }else{
                strAccess_token = "";
                //Авторизация апи
                string strOauthVk = String.Format("https://oauth.vk.com/token?grant_type=password"
                    +"&client_id=2274003&client_secret=hHbZxrka2uZ6jB1inYsH&username={0}&password={1}",strVKLogin,strVKPass);

                string VkResp = ZennoPoster.HttpGet(strOauthVk);
                JObject jsonVk = JObject.Parse(VkResp);
                strAccess_token = jsonVk.SelectToken("access_token").ToString();
                //Записываем обновленные входные данные с токеном в файл в туже строку
                string inputData = strVkInput.Replace("token", strAccess_token);
                File.WriteAllText(project.Directory +  @"/vkInput.txt",inputData);
                project.SendInfoToLog("Взяли новый токен: " + strAccess_token +"\n Он сохранен в файл vkInput.txt", true);
            }

        }
        //Удаление токена
        public static void DeleteToken()
        {
            string strVkInput = File.ReadAllLines(project.Directory + @"/vkInput.txt").ToArray()[0];
            string strVKLogin = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[0];
            string strVKPass = strVkInput.Split('|').ToArray()[0].Split(':').ToArray()[1];
            //Считаем id группы из файла
            string strGroupId = strVkInput.Split('|').ToArray()[1];
            //поправляем шаблон под корректный вид
            File.WriteAllText(project.Directory +  @"/vkInput.txt",String.Format(@"{0}:{1}|{2}|token",strVKLogin,strVKPass,strGroupId));
        }
    }
    //Блок-постер всего и вся на стену
    public class Poster
    {
        //Подключаемся к базовому заклинанию
        public static Instance instance = Tech.instance;
        public static IZennoPosterProjectModel project= Tech.project;
        public static void ApiVkPhotoPost()
        {
            //==Блок с переменными
            Random rnd = new Random();
            //*************** Файлы для отправки
            //Создаем пустой список куда в последствии помести пути к файлам из папки strSourceDirectoryPath
            List<string> lstListFotoFiles = new List<string>();
            //Присваиваем переменной путь к папке с файлами
            string strSourceDirectoryPath = project.Directory + @"\foto to upload\";
            //Directory.EnumerateFiles: получаем список файлов jpg в папке strSourceDirectoryPath
            lstListFotoFiles.AddRange(Directory.EnumerateFiles(strSourceDirectoryPath, "*.jpg", SearchOption.AllDirectories));

            //Берем логин и пароль из списка
            string strVkInput = File.ReadAllLines(project.Directory + @"/vkInput.txt")[0];
            //Считаем id группы из файла
            string strGroupId = strVkInput.Split('|').ToArray()[1];
            //Потом поднадобится
            string strIdFoto = String.Empty;
            //Считываем описание к фотографии
            string strCaption = File.ReadAllText(project.Directory + @"\foto to upload\caption.txt");
            //************** Считаем token группы из файла
            string strAccess_token = Acc.GetVkApiToken();//Блок получения токена перенесен в общий код
            //*******************************************
            //==Конец блока с переменными

            //Загрузка фото в ВК
            //Запрос на получение адреса сервера для загрузки
            project.SendInfoToLog("Первый этап - получаем адрес сервера для загрузки фото",true);
            string strGetServerUrl = String.Format(@"https://api.vk.com/method/photos.getWallUploadServer?v=5.69&access_token={0}&group_id={1}",
                strAccess_token,strGroupId);
            string strServerResult = ZennoPoster.HttpGet(strGetServerUrl);
            //Забираем адрес из ответа
            string strUploadServer = new Regex(@"(?<=""upload_url"":"")[\w\W]*?(?=\"",""album_id)").Match(strServerResult).ToString().Replace(@"\","");
            //Если в ответе strServerResult имеет пустое значение, то удаляем токен и останавливаем шаблон
            if(strUploadServer==String.Empty)
            {
                Acc.DeleteToken();
                throw new Exception("Что-то не то с входным файлом. Останалвиваем шаблон. Проверьте логин, пароль и ид группы/n ПЕРЕЗАПУСТИТЕ ШАБЛОН");
            }
    
            project.SendWarningToLog("Забираем сервер: "+strUploadServer);
            //************** Формируем тело контент для загрузки на сервер
            //Получение информации о файле для загрузки
            FileInfo strFileInfo = new FileInfo(lstListFotoFiles[0]);
            string FileName = strFileInfo.Name;
            //==Формируем тело content для POST-запроса
            string boundary = "------WebKitFormBoundary"+rnd.Next(100000000,999999999).ToString();
            string post_data = "";
            post_data += boundary + "\n";
            post_data += string.Format("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\n", FileName);
            post_data += "Content-Type: image/jpg\n";
            post_data += lstListFotoFiles[0];
            //============== Конец формирования тела content для POST-запроса

            project.SendInfoToLog("Второй этап - Грузим фото на сервер vk",true);
            //Загружаем фото на сервер ВК
            string uploadItemInfo = ZennoPoster.HttpPost(strUploadServer, post_data,
                "multipart/form-data",
                "",
                "utf-8",
                ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.BodyOnly,
                30000);
            //Забираем из ответа id фото, server и hash
            string photo_id = new Regex(@"(?<=""photo"":"").*?(?="","")").Match(uploadItemInfo).ToString().Replace(@"\","");
            string server = new Regex(@"(?<=""server"":).*?(?=,)").Match(uploadItemInfo).ToString();
            string hash = new Regex(@"(?<=""hash"":"").*?(?="")").Match(uploadItemInfo).ToString();
            project.SendWarningToLog("Забираем данные для отправки фото:" +Environment.NewLine+
                "Фото id: "+photo_id +Environment.NewLine+
                "Сервер: "+server +Environment.NewLine+
                "Хэш: "+hash);

            //Сохраняем фото на стену
            project.SendInfoToLog("Третий  этап - получаем адрес сервера для загрузки фото",true);
            project.SendInfoToLog("Взяли для описания: " + strCaption);
            //Формируем запрос для сохранения на стену
            string PostRequestUrl = String.Format("https://api.vk.com/method/photos.saveWallPhoto?access_token={0}&group_id={1}&photo={2}&server={3}&hash={4}&caption={5}&v=5.69",
                strAccess_token,strGroupId,photo_id,server,hash,TextProcessing.UrlEncode(strCaption));

            string PostRequest =  ZennoPoster.HttpGet(PostRequestUrl);

            project.SendInfoToLog("photos.saveWallPhoto " + PostRequest);
            //Забираем ссылку на запись на стену PostRequest
            string PhotoToWall = new Regex(@"(?<=\{""response"":\[\{""id"":)[\w\W]*?(?=,"")").Match(PostRequest).ToString();
            string Owner_id = new Regex(@"(?<=owner_id"":)[\w\W]*?(?=,)").Match(PostRequest).ToString();
            project.SendInfoToLog("id фото для размещения на стене " + PostRequest);
            project.SendInfoToLog("photos.saveWallPhoto " + PhotoToWall);

            string attach ="photo"+Owner_id+"_"+PhotoToWall;

            //Формируем запрос для постинга на стену
            //Берем текст поста
            string PostText = TextProcessing.UrlEncode(strCaption);
            //Формируем запрос для размещения поста
            string PostUrlWallGet = String.Format("https://api.vk.com/method/wall.post?"+
                "access_token={0}"+
                "&owner_id=-{1}"+
                "&friends_only=0"+
                "&from_group=1"+
                "&attachments={2}"+
                "&signed=0"+
                "&message={3}"+
                "&mark_as_ads=0"+
                "&v=5.69",
                strAccess_token,strGroupId,attach,PostText);
            //Отправляем запрос
            string PostId = ZennoPoster.HttpGet(PostUrlWallGet);
            //Пауза 1 сек.
            Thread.Sleep(1000);
            //Забираем i поста из ответа PostId
            string PostIdOnly = new Regex(@"(?<=""post_id"":).*?(?=}})").Match(PostId).ToString();

            //Перемещаем использованный файл в папку used
            File.Move(lstListFotoFiles[0],project.Directory+"/foto used/"+FileName);
            //======+++Тут процес постинга закончен
            //Формируем ссылку на пост
            string FinishPostUrlForCheck = String.Format(@"https://vk.com/club{0}?w=wall-{0}_{1}",strGroupId,PostIdOnly);
            project.SendInfoToLog("Ссылка на пост: " + FinishPostUrlForCheck, true);
        }
        //Модифицированный постер
        public static void ModApiVkPhotoPost()
        {
            //==Блок с переменными
            Random rnd = new Random();
            //*************** Файлы для отправки
            //Создаем пустой список куда в последствии помести пути к файлам из папки strSourceDirectoryPath
            List<string> lstListFotoFiles = new List<string>();
            //Присваиваем переменной путь к папке с файлами
            string strSourceDirectoryPath = project.Directory + @"\foto to upload\";
            //Directory.EnumerateFiles: получаем список файлов jpg в папке strSourceDirectoryPath
            lstListFotoFiles.AddRange(Directory.EnumerateFiles(strSourceDirectoryPath, "*.jpg", SearchOption.AllDirectories));
    
            string strVKLogin = String.Empty;
            string strVKPass = String.Empty;
            //Считаем id группы из файла
            string strGroupId = String.Empty;
            //Потом поднадобится
            string strIdFoto = String.Empty;
            //Считываем описание к фотографии
            string strCaption = File.ReadAllText(project.Directory + @"\foto to upload\caption.txt");
            //************** Считаем token группы из файла
            string strAccess_token = String.Empty;
            Acc.ModGetVkApiToken(out strVKLogin, out strVKPass, out strGroupId, out strAccess_token);//Блок получения токена перенесен в общий код
            //*******************************************
            //==Конец блока с переменными

            //Загрузка фото в ВК
            //Запрос на получение адреса сервера для загрузки
            project.SendInfoToLog("Первый этап - получаем адрес сервера для загрузки фото",true);
            string strGetServerUrl = String.Format(@"https://api.vk.com/method/photos.getWallUploadServer?v=5.69&access_token={0}&group_id={1}",
                strAccess_token,strGroupId);
            string strServerResult = ZennoPoster.HttpGet(strGetServerUrl);
            //Забираем адрес из ответа
            string strUploadServer = new Regex(@"(?<=""upload_url"":"")[\w\W]*?(?=\"",""album_id)").Match(strServerResult).ToString().Replace(@"\","");
            //Если в ответе strServerResult имеет пустое значение, то удаляем токен и останавливаем шаблон
            if(strUploadServer==String.Empty)
            {
                Acc.DeleteToken();
                throw new Exception("Что-то не то с входным файлом. Останалвиваем шаблон. Проверьте логин, пароль и ид группы/n ПЕРЕЗАПУСТИТЕ ШАБЛОН");
            }
    
            project.SendWarningToLog("Забираем сервер: "+strUploadServer);
            //************** Формируем тело контент для загрузки на сервер
            //Получение информации о файле для загрузки
            FileInfo strFileInfo = new FileInfo(lstListFotoFiles[0]);
            string FileName = strFileInfo.Name;
            //==Формируем тело content для POST-запроса
            string boundary = "------WebKitFormBoundary"+rnd.Next(100000000,999999999).ToString();
            string post_data = "";
            post_data += boundary + "\n";
            post_data += string.Format("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"\n", FileName);
            post_data += "Content-Type: image/jpg\n";
            post_data += lstListFotoFiles[0];
            //============== Конец формирования тела content для POST-запроса

            project.SendInfoToLog("Второй этап - Грузим фото на сервер vk",true);
            //Загружаем фото на сервер ВК
            string uploadItemInfo = ZennoPoster.HttpPost(strUploadServer, post_data,
                "multipart/form-data",
                "",
                "utf-8",
                ZennoLab.InterfacesLibrary.Enums.Http.ResponceType.BodyOnly,
                30000);
            //Забираем из ответа id фото, server и hash
            string photo_id = new Regex(@"(?<=""photo"":"").*?(?="","")").Match(uploadItemInfo).ToString().Replace(@"\","");
            string server = new Regex(@"(?<=""server"":).*?(?=,)").Match(uploadItemInfo).ToString();
            string hash = new Regex(@"(?<=""hash"":"").*?(?="")").Match(uploadItemInfo).ToString();
            project.SendWarningToLog("Забираем данные для отправки фото:" +Environment.NewLine+
                "Фото id: "+photo_id +Environment.NewLine+
                "Сервер: "+server +Environment.NewLine+
                "Хэш: "+hash);

            //Сохраняем фото на стену
            project.SendInfoToLog("Третий  этап - получаем адрес сервера для загрузки фото",true);
            project.SendInfoToLog("Взяли для описания: " + strCaption);
            //Формируем запрос для сохранения на стену
            string PostRequestUrl = String.Format("https://api.vk.com/method/photos.saveWallPhoto?access_token={0}&group_id={1}&photo={2}&server={3}&hash={4}&caption={5}&v=5.69",
                strAccess_token,strGroupId,photo_id,server,hash,TextProcessing.UrlEncode(strCaption));

            string PostRequest =  ZennoPoster.HttpGet(PostRequestUrl);

            project.SendInfoToLog("photos.saveWallPhoto " + PostRequest);
            //Забираем ссылку на запись на стену PostRequest
            string PhotoToWall = new Regex(@"(?<=\{""response"":\[\{""id"":)[\w\W]*?(?=,"")").Match(PostRequest).ToString();
            string Owner_id = new Regex(@"(?<=owner_id"":)[\w\W]*?(?=,)").Match(PostRequest).ToString();
            project.SendInfoToLog("id фото для размещения на стене " + PostRequest);
            project.SendInfoToLog("photos.saveWallPhoto " + PhotoToWall);

            string attach ="photo"+Owner_id+"_"+PhotoToWall;

            //Формируем запрос для постинга на стену
            //Берем текст поста
            string PostText = TextProcessing.UrlEncode(strCaption);
            //Формируем запрос для размещения поста
            string PostUrlWallGet = String.Format("https://api.vk.com/method/wall.post?"+
                "access_token={0}"+
                "&owner_id=-{1}"+
                "&friends_only=0"+
                "&from_group=1"+
                "&attachments={2}"+
                "&signed=0"+
                "&message={3}"+
                "&mark_as_ads=0"+
                "&v=5.69",
                strAccess_token,strGroupId,attach,PostText);
            //Отправляем запрос
            string PostId = ZennoPoster.HttpGet(PostUrlWallGet);
            //Пауза 1 сек.
            Thread.Sleep(1000);
            //Забираем i поста из ответа PostId
            string PostIdOnly = new Regex(@"(?<=""post_id"":).*?(?=}})").Match(PostId).ToString();

            //Перемещаем использованный файл в папку used
            File.Move(lstListFotoFiles[0],project.Directory+"/foto used/"+FileName);
            //======+++Тут процес постинга закончен
            //Формируем ссылку на пост
            string FinishPostUrlForCheck = String.Format(@"https://vk.com/club{0}?w=wall-{0}_{1}",strGroupId,PostIdOnly);
            project.SendInfoToLog("Ссылка на пост: " + FinishPostUrlForCheck, true);
        }

    }
}
Вот так сниппет
C#:
//Эти две строки обязательно прописать во всех сниппетах.
Tech.project = project;
Tech.instance = instance;
//а эта строчка постит фото на стену группы
Poster.ApiVkPhotoPost();
 

Вложения

Последнее редактирование:

Astraport

Client
Регистрация
01.05.2015
Сообщения
3 817
Благодарностей
2 808
Баллы
113

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
Ну если этот проект рассматривать как постер картинок, то смысла нет. Ту вы правы. А вот для большого проекта, где размещаются не только фото и со своими алгоритмами, общий код, на мой взгляд, более полезен.
Но это сугубо мое мнение.
 

Astraport

Client
Регистрация
01.05.2015
Сообщения
3 817
Благодарностей
2 808
Баллы
113
Ну если этот проект рассматривать как постер картинок, то смысла нет. Ту вы правы. А вот для большого проекта, где размещаются не только фото и со своими алгоритмами, общий код, на мой взгляд, более полезен.
Но это сугубо мое мнение.
Для социалок, где постоянно что-то меняется и отваливается, важен удобный дебаг. Запихнуть весь код в общий и потом страдать?
В больших проектах наоборот стараешься в кубиках C# не более 100 строк делать для удобства и разбивать их.
В общий только часто используемые в неск. кубиках надежные утилиты ИМХО.
 

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
Для социалок, где постоянно что-то меняется и отваливается, важен удобный дебаг. Запихнуть весь код в общий и потом страдать?
В больших проектах наоборот стараешься в кубиках C# не более 100 строк делать для удобства и разбивать их.
В общий только часто используемые в неск. кубиках надежные утилиты ИМХО.
Ну тут используется официальное API VK и тема не спамная. Соответственно изменения делаются очень редко.
Что касается количества строк, тут вы абсолютно правы и это касается не только кубиков, но и методов в общем коде.
Тут я нарочно пошел на нарушение этого правила, исключительно для демострации сути работы с объектами простым способом.

В моем комбайне такие модули также не содержат более 100 строк кода.

Про дебаг. Поскольку работа идет с апи, то можно использовать Visual Studio.
 

inilim

Client
Регистрация
16.09.2017
Сообщения
327
Благодарностей
106
Баллы
43
Не все поймут. zennoposter в сторонке.
 

AZANIR

Client
Регистрация
09.06.2014
Сообщения
376
Благодарностей
171
Баллы
43
в общий код есть смысл выносить то что повторяется часто, очень часто , а как познавательная статья очень даже неплохо.
 
  • Спасибо
Реакции: Advert31337

surrealmix

Client
Регистрация
07.03.2013
Сообщения
720
Благодарностей
397
Баллы
63
При работе с общим кодом есть также нюанс – это объекты instance и project. Их нет в общем коде и их надо подключить.
Для этого в классе Tech создаем глобальные переменные:
public static IZennoPosterProjectModel project;
public static Instance instance;
Если шаблон предназначен для многопоточного выполнения, то так делать категорически нельзя.
 
  • Спасибо
Реакции: doc

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
а как познавательная статья очень даже неплохо.
Спасибо, вы уловили самую суть)))

Если шаблон предназначен для многопоточного выполнения, то так делать категорически нельзя.
В многопоток пока еще особо не вникал - не смогу прокомментировать. Данный шаблон выбрал исключительно для примера, на мой взгляд, достаточно простого и понятного.
Опять же можно создать классы в которых нет надобности использовать project и instance.
 

doc

Client
Регистрация
30.03.2012
Сообщения
7 754
Благодарностей
3 836
Баллы
113
Нужно использовать instance или project - просто пропиши эти переменные в методах и передавай туда эти объекты при вызове
 
  • Спасибо
Реакции: Advert31337

nvmds

Client
Регистрация
04.05.2016
Сообщения
55
Благодарностей
3
Баллы
8
А сколько времени в итоге ушло? на кубиках такое накидать 10 мин макс
 

Advert31337

Client
Регистрация
18.12.2016
Сообщения
51
Благодарностей
36
Баллы
18
А сколько времени в итоге ушло? на кубиках такое накидать 10 мин макс
Поскольку я изучаю C# с нуля, то долго.
Разумеется я не предлагаю немедленно бросить кубики и бежать осваивать свой код)
И все таки, для более сложных проектов комфортнее работать с кодом, а не с покрывалом из простых кубиков.
А данный простой шаблон по функционалу предназначен для наглядного примера.
 

radv

Client
Регистрация
11.05.2015
Сообщения
927
Благодарностей
459
Баллы
63

iBotovod

Client
Регистрация
01.07.2017
Сообщения
53
Благодарностей
17
Баллы
8
Годно. Узнал несколько новых вещей для себя в работе с токенами и файлОм. Спасибо.
PS: Сиборра рулез :-)
 
  • Спасибо
Реакции: Advert31337

Belias

Client
Регистрация
25.06.2013
Сообщения
12
Благодарностей
6
Баллы
3
Отличная статья, для начинающих самое то.
 
  • Спасибо
Реакции: Advert31337

Кто просматривает тему: (Всего: 2, Пользователи: 1, Гости: 1)