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

Advert31337

Client
Регистрация
18.12.2016
Сообщения
53
Реакции
38
Баллы
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);

Ну вот вроде все.
 
Номер конкурса статей
  1. Девятый конкурс статей
Тема статьи
  1. Соц. сети
Последнее редактирование:
Вот так выглядит общий код:
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();
 

Вложения

Последнее редактирование:
C#:
Развернуть Свернуть Копировать
[CODE=Csharp]
 
  • Спасибо
Реакции: Advert31337
Ну если этот проект рассматривать как постер картинок, то смысла нет. Ту вы правы. А вот для большого проекта, где размещаются не только фото и со своими алгоритмами, общий код, на мой взгляд, более полезен.
Но это сугубо мое мнение.
 
Ну если этот проект рассматривать как постер картинок, то смысла нет. Ту вы правы. А вот для большого проекта, где размещаются не только фото и со своими алгоритмами, общий код, на мой взгляд, более полезен.
Но это сугубо мое мнение.
Для социалок, где постоянно что-то меняется и отваливается, важен удобный дебаг. Запихнуть весь код в общий и потом страдать?
В больших проектах наоборот стараешься в кубиках C# не более 100 строк делать для удобства и разбивать их.
В общий только часто используемые в неск. кубиках надежные утилиты ИМХО.
 
Для социалок, где постоянно что-то меняется и отваливается, важен удобный дебаг. Запихнуть весь код в общий и потом страдать?
В больших проектах наоборот стараешься в кубиках C# не более 100 строк делать для удобства и разбивать их.
В общий только часто используемые в неск. кубиках надежные утилиты ИМХО.
Ну тут используется официальное API VK и тема не спамная. Соответственно изменения делаются очень редко.
Что касается количества строк, тут вы абсолютно правы и это касается не только кубиков, но и методов в общем коде.
Тут я нарочно пошел на нарушение этого правила, исключительно для демострации сути работы с объектами простым способом.

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

Про дебаг. Поскольку работа идет с апи, то можно использовать Visual Studio.
 
Не все поймут. zennoposter в сторонке.
 
в общий код есть смысл выносить то что повторяется часто, очень часто , а как познавательная статья очень даже неплохо.
 
  • Спасибо
Реакции: Advert31337
При работе с общим кодом есть также нюанс – это объекты instance и project. Их нет в общем коде и их надо подключить.
Для этого в классе Tech создаем глобальные переменные:
public static IZennoPosterProjectModel project;
public static Instance instance;
Если шаблон предназначен для многопоточного выполнения, то так делать категорически нельзя.
 
  • Спасибо
Реакции: doc
а как познавательная статья очень даже неплохо.
Спасибо, вы уловили самую суть)))

Если шаблон предназначен для многопоточного выполнения, то так делать категорически нельзя.
В многопоток пока еще особо не вникал - не смогу прокомментировать. Данный шаблон выбрал исключительно для примера, на мой взгляд, достаточно простого и понятного.
Опять же можно создать классы в которых нет надобности использовать project и instance.
 
А сколько времени в итоге ушло? на кубиках такое накидать 10 мин макс
 
А сколько времени в итоге ушло? на кубиках такое накидать 10 мин макс
Поскольку я изучаю C# с нуля, то долго.
Разумеется я не предлагаю немедленно бросить кубики и бежать осваивать свой код)
И все таки, для более сложных проектов комфортнее работать с кодом, а не с покрывалом из простых кубиков.
А данный простой шаблон по функционалу предназначен для наглядного примера.
 
Годно. Узнал несколько новых вещей для себя в работе с токенами и файлОм. Спасибо.
PS: Сиборра рулез :)
 
  • Спасибо
Реакции: Advert31337
Отличная статья, для начинающих самое то.
 
  • Спасибо
Реакции: Advert31337

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