С каждым днём в рядах программистов происходит пополнение. Кто-то всегда хотел этим заняться и вдруг решился, кто-то внезапно решил поменять сферу деятельности и изучить программирование, а кому-то это требуется, к примеру, для выполнения своих рабочих обязанностей. Так или иначе, всегда легче обучаться по готовым примерам, когда все самые трудные вопросы изучены за вас, а вам предоставляется урок, изложенный в довольно упрощённой форме. Именно такой урок ждёт вас сегодня.

Цель урока
Цель этого урока – написать простейшую программу для ВКонтакте, которая будет спустя минуту после запуска публиковать пост в указанное сообщество от имени администратора, удаляя при этом предыдущий пост, если таковой имеется.
В целях написания данной программы было использовано программное обеспечение Embarcadero RAD Studio с Delphi XE6 на борту. Вы можете использовать это ПО или любую другую версию.
Приступим
Процесс создания спамера заключается в написании кода в несколько этапов, на каждом из которых пишется какая-то часть спамера. Урок предполагает, что у вас уже есть базовые знания в языке программирования Delphi, и направлен скорее на демонстрацию работы с API ВКонтакте. Ничего кардинально сложного здесь нет, поэтому просто следуйте инструкции.
- Запускаем Delphi, создаём новый проект и добавляем на форму поля, необходимые для простейшего спамера:

- 4 поля Edit для логина и пароля, для ID группы-приёмника и прикрепления аттача
- 2 текстовых поля Memo для текста сообщения и лога событий
- 2 кнопки Button для входа в аккаунт и запуска спамера
- Компонент Timer для отправки сообщения спустя некоторый интервал времени
- Компонент HTTP для осуществления GET и POST запросов к ВКонтакте
- Компонент IdSSLIOHandlerSocketOpenSSL для отправки запросов по защищённому соединению HTTPS
- 4 поля Edit для логина и пароля, для ID группы-приёмника и прикрепления аттача
- Приступаем к написанию кода. Для начала опишем авторизацию аккаунта. Для этого создадим процедуру GetToken:
procedure TForm1.GetToken;
var
temp: string;
response: string;
begin
try
// отправка запроса на авторизацию
response := idhttp1.Get('https://oauth.vk.com/token?grant_type=password&client_id=2274003&scope=wall&client_secret=hHbZxrka2uZ6jB1inYsH&username=' + LoginEdit.Text + '&password=' + PassEdit.text);
except
// если что-то пошло не так, выводим в лог информацию об этом
logmemo.Lines.Add('ошибка соединения при получении access token');
end;
// проверяем, если слово token есть в переменной response, значит access_token получен
if Pos('token', response) <> 0 then
begin
// выдергиваем access_token
temp := Copy(response, Pos('access_token":"', response), Pos('","expires_in', response) - 3);
Delete(temp, 1, 15);
// и кладём в переменную token
token := temp;
logmemo.Lines.Add('token получен');
end else
begin
// если token получить не удалось, пишем об этом в логе
logmemo.Lines.Add('token не получен');
end;
end;
Описанный метод авторизации заключается в получении ключа доступа access_token. Если точнее, это так называемая «Прямая авторизация». Прочитать о ней можно здесь: vk.com/dev/auth_direct.
Access_token, или маркер доступа, – программный объект, который содержит информацию по безопасности сеанса и идентифицирует пользователя и его привилегии в социальной сети ВКонтакте.
Позже, при отправке некоторых Get или Post запросов к ВКонтакте, необходимо будет вместе с самими запросами передавать и сгенерированный при авторизации маркер доступа, потому что не все методы API ВКонтакте являются общедоступными и могут требовать от пользователя определённых прав, которые идентифицируются посредством передаваемого access_token.
В запрос для получения маркер доступа access_token в процедуре выше были включены следующие параметры:
- grant_type – тип авторизации, должен быть всегда равен password
- client_id – ID приложения, через которое происходит авторизация
- client_secret – секретный ключ того же приложения
- username – логин от вашего аккаунта ВКонтакте
- password – пароль от вашего аккаунта ВКонтакте
Доступ к этому типу авторизации может быть получен только после предварительного согласования с администрацией ВКонтакте. Но так как это наиболее быстрый и удобный способ авторизации, мы схитрили и для реализации данного типа авторизации в нашей программе использовали в качестве приложения для авторизации данные от официального клиента ВКонтакте для Android (имеются ввиду параметры client_id и client_secret). Поэтому не нужно возиться с созданием нового приложения ВКонтакте и отправкой запроса на одобрение администрацией – для нашего примера можно обойтись и таким вариантом.
- grant_type – тип авторизации, должен быть всегда равен password
- Привяжем созданную процедуру к кнопке «Авторизация», по клику на которую программа будет проходить авторизацию и получать сгенерированный access_token:
procedure TForm1.Button1Click(Sender: TObject);
begin
GetToken;
end;
- Все запросы к ВКонтакте в обязательном порядке выполняются через защищённое соединение. Поэтому обязательно нужно связать компоненты HTTP и IdSSLIOHandlerSocketOpenSSL, а также положить в папку с программой файлы dll-библиотек ssleay32.dll и libeay32.dll, если их там нет.
- Следующий шаг – написание функции, отвечающей за работу спамера по таймеру. Мы уже определились, что программа будет проверять стену сообщества на наличие уже опубликованного поста, удалять его, если он существует, и публиковать новый по таймеру через заданный интервал времени. В нашем случае, через минуту. Для реализации такого алгоритма нам потребуются 3 метода API ВКонтакте со следующими параметрами:
- wall.get – получение записей со стены пользователя или сообщества
Требуемые параметры:
- owner_id – ID сообщества ВКонтакте, записи со стены которого необходимо получить
access_token– маркер доступа здесь необязателен, т.к. метод wall.get – общедоступный
- owner_id – ID сообщества ВКонтакте, записи со стены которого необходимо получить
- wall.delete – удаление записи со стены пользователя или сообщества
Требуемые параметры:
- owner_id – ID сообщества ВКонтакте, запись со стены которого необходимо удалить
- post_id – ID записи на стене сообщества, которую необходимо удалить
- access_token – маркер доступа, полученный при авторизации
- owner_id – ID сообщества ВКонтакте, запись со стены которого необходимо удалить
- wall.post – публикация записи на стену пользователя или сообщества
Требуемые параметры:
- owner_id – ID сообщества ВКонтакте, на стене которого необходимо разместить запись
- from_group – метка, обозначающая, от имени кого публиковать запись. В нашем случае, мы публикуем от имени администратора сообщества, поэтому этот параметр должен быть равен 1
- message – текст сообщения
- attachments – прикрепление по ссылке. Это может быть: фотография, аудио или видеозапись, документ, wiki-страница, заметка, опрос, альбом, товар или подборка товаров
- access_token – маркер доступа, полученный при авторизации
- owner_id – ID сообщества ВКонтакте, на стене которого необходимо разместить запись
Ознакомиться со всеми параметрами используемых методов API ВКонтакте вы можете на страницах документации, но для нашей задачи нам хватит и перечисленных выше параметров.
Объединив эти методы и поколдовав над ними, получилась вот такая простенькая процедура, которую мы связали с событием таймера OnTimer:
procedure TForm1.Timer1Timer(Sender: TObject);
var
response: String;
id: String;
pos1: Integer;
Info: TStringList;
begin
// как только интервал, заданный в таймере, подойдёт к концу, выключаем таймер и выполняем алгоритм
timer1.Enabled := false;
try
// получаем список записей со стены сообщества
// согласно документации API ВКонтакте, метод wall.get – общедоступный, поэтому access_token можно не передавать
response := idhttp1.Get('https://api.vk.com/method/wall.get?owner_id=-' + GroupEdit.text);
except
logmemo.Lines.Add('Ошибка получения ID поста');
end;
// получаем ID последнего поста
id := Pars(response,'"id":', ',"');
sleep(500);
// если пост есть
if Length(id) > 0 then
begin
try
// удаляем его
response := idhttp1.Get('https://api.vk.com/method/wall.delete?owner_id=-' + GroupEdit.text + '&post_id=' + id + '&access_token=' + token);
except
// если что-то пошло не так, сообщаем об этом в логе
logmemo.Lines.Add('Ошибка удаления поста');
end;
end;
sleep(500);
// публикуем новый пост посредством post-запроса
try
response := '';
Info := TStringList.Create;
Info.Add('owner_id=-' + GroupEdit.text);
Info.Add('from_group=1');
Info.Add('access_token=' + token);
Info.Add('message=' + messagememo.text);
Info.Add('attachments=' + attachedit.text);
response := idhttp1.Post('https://api.vk.com/method/wall.post', Info);
except
// если что-то пошло не так, сообщаем об этом в логе
logmemo.Lines.Add('Ошибка создания поста');
end;
// проверяем ответ от сервера: удалось ли опубликовать пост или нет, и выводим соответствующую надпись в лог
if Pos('post_id', response) > 0 then logmemo.Lines.Add('Пост добавлен!') else logmemo.Lines.Add('Пост не добавлен!');
Info.Free;
end;
- wall.get – получение записей со стены пользователя или сообщества
- И опишем функцию Pars, с помощью которой в процедуре выше происходит извлечение ID последнего поста из ответа от сервера:
function TForm1.Pars(st, st_begin, st_end: WideString): WideString;
begin
if Pos(st_begin, st) <> 0 then Delete(st, 1, Pos(st_begin, st) + Length(st_begin) - 1) else
begin
result := '';
exit;
end;
if Pos(st_end, st) <> 0 then Delete(st, Pos(st_end, st), Length(st)) else
begin
result := '';
exit;
end;
result := st;
end;
- В свойствах таймера в блоке Object Inspector нашего Delphi устанавливаем свойство Interval равным 60000 миллисекунд (1 минута). Это будет означать, что после запуска спамера должна будет пройти 1 минута, прежде чем выполнится основной алгоритм программы.
- Далее создаём событие нажатия на кнопку «Запустить». Оно будет по клику запускать таймер, если заранее был получен ключ access_token:
procedure TForm1.StartButtonClick(Sender: TObject);
begin
if Length(token) > 0 then timer1.Enabled := true;
end;
- В итоге, скомпилировав весь этот код и запустив программу, можно насладиться результатом:

- Введя данные как на скриншоте выше, авторизовавшись и запустив спамер, в итоге мы получили следующий результат:

Ещё раз подчеркнём, что данный вариант программы требует от вашего аккаунта прав администратора для удаления поста со стены и публикации нового поста от имени группы.
Заключение
Конечно, это ещё очень сырой вариант спамера. Для полноценной работы и его применения на постоянной основе его ещё стоит доработать, например:
- Организовать работу спамера по таймеру бесконечно, чтобы пост публиковался и удалялся по кольцу автоматически, а не по нажатию на кнопку «Запуск» снова и снова.
- Доработать удаление поста в группе. Так как наш вариант программы просто удаляет последний пост в группе, то может выйти, что перед удалением старого поста и публикацией нового на стену сообщества был добавлен новый пост (не через нашу программу), который удалится вместо старого рекламного поста.
- Описать адекватное поведение программы при достижении в группе суточного лимита на добавление 50 постов на стену.
- В случае, если цель использования спамера – реклама по определённым ключевым словам, по которым пост можно найти в поиске, можно научить программу при достижении суточного лимита на публикацию постов автоматически создавать новую группу для продолжения работы.
- И многое другое.
На самом деле, это только учебный урок, и программа действительно очень проста. В ней можно сделать множество функциональных доработок, чтобы превратить его в по-настоящему мощный инструмент. Но цель нашего урока – привести пример того, как в целом осуществляется работа в Delphi с API ВКонтакте для написания подобных программ.
Готовый исходный код спамера можно скачать в прикреплении к материалу.