Пост новостей с фотографией в группу ВКонтакте (C#)

Недавно решил написать программу, с помощью которой можно будет постить новости с картинкой в группе ВКонтакте. Поискав в интернете чьи-нибудь работы, я нашел куски кода на php, а на C# ничего не было. Нашел библиотеку для работы с VK API на C#, но там не было нужных для меня API. Я решил, что самому будет проще написать, чем искать, заодно и поделюсь с тем, кого это интересует.

Для этого нам понадобиться: standalone-приложение и токен для этого приложения.

Зарегистрируем standalone-приложение и получаем токен:
  1. Внизу сайта заходим в раздел «Разработчикам»;
  2. Жмем кнопку «Создать приложение»;
  3. Вводим название приложение и выбираем «Standalone-приложение»;
  4. После создания заходим на вкладку «Настройки» и копируем «ID приложения»;
  5. Затем переходим по ссылке:
    oauth.vk.com/authorize?client_id=[ID]&scope=wall,photos,audio,video,docs,notes,groups,messages,notifications,stats,ads,notify,friends,offline&redirect_uri=http://oauth.vk.com/blank.html&display=page&response_type=token

    , где [ID] – id, который мы скопировали в пункте 4);
  6. Копируем из адресной строки браузера адрес и оттуда сохраняем access_token. С помощью этого токена мы сможем получить доступ к API.

Приступим к самой программе. Для программы нам понадобиться библиотека Json.Net (можно скачать в NuGet).
  1. Скачаем Json.Net через NuGet;
  2. Создадим класс «vkWallPost», подключим пространство имен «Newtonsoft.Json.Linq» и «System.IO», добавим в него поле token и конструктор (при создании объекта класса vkWallPost будет передавать токен, который получили в пункте 4);
    Код
    class vkWallPost
    {
            string token;
            public vkWallPost(string token)
            {
                this.token = token;
            }
    }
    
  3. Добавим в класс метод Response с модификатором доступа private. Метод будет возвращать нам ответа сервера API в string;
    Код
            private string Response(string request_path)    //на вход подаем URL API, например https://api.vk.com/method/photos.getWallUploadServer?group_id=123
            {
                string response = string.Empty;
                HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(request_path);   //отправление запроса к серверу API
                HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();      //получение ответа от сервера API
                Stream receiveStream = Response.GetResponseStream();
                Encoding encode = System.Text.Encoding.GetEncoding("utf-8");   
                StreamReader readStream = new StreamReader(receiveStream, encode);   
    
                Char[] read = new Char[256];
                int count = readStream.Read(read, 0, 256);
    
                while (count > 0)
                {
                    String line = new String(read, 0, count);
                    response += line + "\r\n";                     
                    count = readStream.Read(read, 0, 256);
                }
    
                Response.Close(); 
                readStream.Close(); 
    
                return response;     
            }
    

  4. Добавим в класс метод photosGetWallUploadServer с модификатором private, чтобы получить URL для загрузки изображения на сервер ВКонтакте. На вход подаем group_id (не важно отрицательный или положительный);
    Код
            private string photosGetWallUploadServer(int group_id)    //получить сервер для загрузки фото на стену (возвращает upload_url)
            {
                string request_path = "https://api.vk.com/method/photos.getWallUploadServer?";    //формируем ссылку с нужными параметрами для запроса к API
                request_path += "group_id" + group_id;
                request_path += "&v=5.21";
                request_path += "&access_token=" + token;
    
                var json = JObject.Parse(Response(request_path));     //json парсер
                return json["response"]["upload_url"].ToString();       //возвращает upload_url
            }
    

  5. Добавим в класс метод photosUploadPhotoToURL с модификатором private. Метод возвращает объект класса JObject. На вход подаем URL, полученный из метода photosGetWallUploadServer и адрес фото, которое хотим загрузить (например, E:/img.png. Если ввести адрес вида: «www.img.ru/img.png», то работать не будет!);
    Код
            private JObject photosUploadPhotoToURL(string URL, string file_path)    //загрузка фото на сервер
            {
                WebClient myWebClient = new WebClient(); 
                byte[] responseArray = myWebClient.UploadFile(URL, file_path); 
                var json = JObject.Parse(System.Text.Encoding.ASCII.GetString(responseArray));
    
                return json;
            }
    

  6. Добавляем метод photosSaveWallPhoto. Модификатор доступа private, возвращает JObject. Нужен для того, чтобы получить id фотографии и owner_id (id того, кто загрузил). На вход подаем server, photo, hash, полученный из метода photosUploadPhotoToURL;
    Код
            private JObject photosSaveWallPhoto(string server, string photo, string hash)
            {
                string request_path = "https://api.vk.com/method/photos.saveWallPhoto?";
                request_path += "server=" + server;
                request_path += "&photo=" + photo;
                request_path += "&hash=" + hash;
                request_path += "&v=5.21";
                request_path += "&access_token=" + token;
    
                var json = JObject.Parse((Response(request_path).Replace("[", String.Empty)).Replace("]", String.Empty));       //сначала убираем '[' и ']' из ответа сервера, а зачем парсим
                return json;  //возвращаем объект класса JObject
            }
    

  7. Создадим метод wallPost, который будет отправлять команду API серверу, чтобы он добавил пост в группу с соотвествующими введенными данными. На вход подаем owner_id — id группы или пользователя (для группы должен быть отрицательным), по умолчанию посты будут видны всем пользователям и опубликованы от имени группы. Если хотим, чтобы посто был виден только для друзей, то передаем «friends_only: 1» и если не от имени группы, то from_group: 1. Message — сообщение, которое будет добавлено в пост и attachments в виде photoOwnerId_PhotoId, где OwnerId и PhotoId получены из метода photosSaveWallPhoto. publish_date — время, в которое пост будет опубликован (в формате unixtime);
    Код
            private string wallPost(int owner_id, int friends_only = 0, int from_group = 1, string message = "", string attachments = "", long publish_date = 0)                    //пост на стенку
            {
                if (message == "" && attachments == "") return "Error: message and attachments is empty!";                //не вызывать API, если msg and attach пустые
    
                string request_path = "https://api.vk.com/method/wall.post?";     //путь обращения к vk.api
                request_path += "owner_id=" + owner_id;         
                request_path += "&friends_only=" + friends_only;                   
                request_path += "&from_group=" + from_group;             
                if (message != string.Empty) request_path += "&message=" + message;  
                if (attachments != string.Empty) request_path += "&attachments=" + attachments;   
                if (publish_date != 0) request_path += "&publish_date=" + publish_date;     
                request_path += "&v=5.21";
                request_path += "&access_token=" + token;                                                          //токен (задается в конструкторе)
    
                return Response(request_path);
            }
    

  8. Теперь добавим последний метод, который будет собирать все, что надо и добавлять новость в группу. Название AddWallPost, модификатор public. На вход обязательно подаем group_id (gid) должен быть отрицательным, если это группа, message (сообщение, например «Hello, world!»), attachment (вида E:/img.png), если хотим, чтобы пост опубликовался в какое-то определенное время в течении дня, то на вход подаем publish_date в формате 12:30 или 17:03. Округление в большую сторону до числа, кратного 5 т.к. ВКонтакте можно публиковать только во время, кратное 5, например 13:00, 10:05, 11:10. Метод вернет ответ севера с id поста.

    Код
            public string AddWallPost(int gid, string message = "", string attachment = "", string publish_date = "")
            {
                if (message == "" && attachment == "") return "Error";
    
                string response = string.Empty;
                int hour = int.Parse(publish_date.Split(':')[0]);
                int min = int.Parse(publish_date.Split(':')[1]);
                if ((min % 5) != 0) min += 5 - (min % 5);
                if (min == 60)
                {
                    hour++;
                    min = 0;
                }
                    
                DateTime data_time = new DateTime(2014, 5, 30, hour, min, 0);
                long time = (data_time.ToUniversalTime().Ticks - 621355968000000000) / 10000000; //перевод числа в unixtime
    
                if (attachment != "")
                {
                    string img_path = photosGetWallUploadServer(gid);
                    var resp = photosUploadPhotoToURL(img_path, attachment);
                    resp = photosSaveWallPhoto(resp["server"].ToString(), resp["photo"].ToString(), resp["hash"].ToString());
                    attachment = "photo" + resp["response"]["owner_id"] + "_" + resp["response"]["id"];
                }
    
                return wallPost(gid, message: message, attachments: attachment, publish_date: time);
            }
    </spoiler>




  9. Надеюсь, что статья оказалась полезной для тех, кто искал информацию на эту тему.
Tags:
c#, вконтакте api

You can't comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author's username will be hidden by an alias.