Недавно решил написать программу, с помощью которой можно будет постить новости с картинкой в группе ВКонтакте. Поискав в интернете чьи-нибудь работы, я нашел куски кода на php, а на C# ничего не было. Нашел библиотеку для работы с VK API на C#, но там не было нужных для меня API. Я решил, что самому будет проще написать, чем искать, заодно и поделюсь с тем, кого это интересует.
Для этого нам понадобиться: standalone-приложение и токен для этого приложения.
Зарегистрируем standalone-приложение и получаем токен:
Приступим к самой программе. Для программы нам понадобиться библиотека Json.Net (можно скачать в NuGet).
Для этого нам понадобиться: standalone-приложение и токен для этого приложения.
Зарегистрируем standalone-приложение и получаем токен:
- Внизу сайта заходим в раздел «Разработчикам»;
- Жмем кнопку «Создать приложение»;
- Вводим название приложение и выбираем «Standalone-приложение»;
- После создания заходим на вкладку «Настройки» и копируем «ID приложения»;
- Затем переходим по ссылке:
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); - Копируем из адресной строки браузера адрес и оттуда сохраняем access_token. С помощью этого токена мы сможем получить доступ к API.
Приступим к самой программе. Для программы нам понадобиться библиотека Json.Net (можно скачать в NuGet).
- Скачаем Json.Net через NuGet;
- Создадим класс «vkWallPost», подключим пространство имен «Newtonsoft.Json.Linq» и «System.IO», добавим в него поле token и конструктор (при создании объекта класса vkWallPost будет передавать токен, который получили в пункте 4);
Кодclass vkWallPost { string token; public vkWallPost(string token) { this.token = token; } }
- Добавим в класс метод 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; }
- Добавим в класс метод 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 }
- Добавим в класс метод 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; }
- Добавляем метод 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 }
- Создадим метод 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); }
- Теперь добавим последний метод, который будет собирать все, что надо и добавлять новость в группу. Название 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>
Надеюсь, что статья оказалась полезной для тех, кто искал информацию на эту тему.