Введение.
У многих, наверное, есть группы или сообщества на сайте vk.com. Многое, для удобного администрирования предусмотрели разработчики: и статистика в удобном виде, и возраст аудитории, и забанить нерадивого юзера можно. Но вот что нельзя - так это просмотреть тех, кто нарушил правила (Первое правило Бойцовского клуба: не упоминать о Бойцовском клубе.) сообщества и вышел. Ведь их нужно забанить! Зачем? Объясню на примере. У нас есть небольшая группа, народ постоянно как вступает, так и выходит. В группе я оказываю некоторую бесплатную помощь людям, и вступая в сообщество, они подписываются под правилом - остаться в нём. Конечно же есть те, кто воспользовавшись помощью - вышел. Лично мне их категорически нужно забанить. Зачем? Народ постоянно прибывает, и те, кто когда-то вышел, могут зайти снова, воспользоваться и выйти. А нам оно надо? Конечно нет.
В статистике указано, сколько человек покинули сообщество, но не указано - кто. Когда в сообществе 100 человек - реально отследить вышедших и злостно покарать баном. Когда 200 - сложновато. А когда 1000 - почти невозможно. Покопавшись в подобном софте (который умеет с группами работать), ничего путнего я не нашёл. А если я не нашёл то, что мне требовалось - я это напишу :).
Определяемся с целью.
Показать, как разработать приложение, способное отслеживать, кто вышел и пришёл в группу, уведомлять об этом и банить автоматом тех, вышел. То есть сделаем то, о чём не позаботились разработчики vk, а что порой так нужно. Смысл в том, что я лишь покажу основной код, а все плюшки (вроде упоминалку из трее, время упоминания и файл настроек) - крутите вы сами. Ну или, если кому-то понадобится, выложу уже готовую, получившуюся у меня.
На чём пишем: Делфи.
К делу.
Алгоритм работы программы в 2-х пунктах:
1) При первой авторизации и указании группы, спарсить список всех пользователей и сохранить их в заданную дирректорию.
2) Далее, посапывая в трее, через указанный интервал просыпаться и сканировать пользователей. Сверять их с первоначальным листом. Изменения есть? Уведомлять! Кто-то ушёл? Банить! Кто-то пришёл? Ура. Все действия писать в журнал (если последний нужен пользователю). Ну и заменить исходный список на спарсенный заново, если есть изменения.
Вот и вся логика. Поехали.
Вы любите дизайн?
А я на него срал!
Стране нужны паровозы! Нам нужен металл!
Это говорит о том, что с формой я определюсь в последний момент. Пока пишем движок. Перейдём в код, там зададим небольшую процедурку:
function tuc: TStringList;
var
reg: TregExpr; //В uses - RegExpr. Переменная типа регулярных выражений (TregExpr).
mas_all: array [1..1000] of string; //Стринговый массив
i: integer;
s: string;
data, list_new: TStringlist; //Стринг-листы (говори массивы)
begin
{Всеобщая инициализация}
reg:= TregExpr.Create;
list_new:= TStringlist.Create;
data:= TStringlist.Create;
{Шлём запрос с функцией groups.getMembers}
data.Text:= http.Get('https://api.vk.com/method/groups.getMembers?group_id=ID_группы&sort=id_asc&offset=0&count=1000&v=5.5');
//Сортировка
reg.InputString:= data.Text; //Данные, где регулярить :)
reg.Expression:= '[\d](.*?),'; // Регулярка
if reg.Exec(data.Text) then
repeat
n:= n+1;
mas_all[n]:= reg.Match[0]; //В массив кладём первое (оно и так одно) совпадение.
until (not reg.ExecNext);
{удаляем запятые}
for i := 1 to n do begin
if pos(',', mas_all[i]) <> 0 then delete (mas_all[i], pos(',', mas_all[i]), 1);
end;
{убираем 1-ую строку (в ней число, но оно обозначает не id пользователя, а количество участников)}
for I := 1 to n do
begin
if i = n then break;
mas_all[i]:= mas_all[i+1];
end;
{записываем всё в StringList и присваиваем результат}
for i := 1 to n-1 do
list_new.Add(mas_all[i]);
Result:= list_new;
end;
Начну с запроса. API-функция groups.getMembers возвращает список всех участников сообщества. Её параметры:
group_id - идентификатор сообщества
sort - сортировка пользователей (id_asc, id_desc, time_asc, time_desc. )
offset - смещение (укажете 100 - будет выводить, начиная с 100-ого пользователя)
count - количество (max - 100. затем ставим смещение на 1001 и выводим ещё 1000. И т.д.)
Запрос вернёт нам такой вид:
response: {
count: 279017,users: [4525, 4568, 4615, 4617, 4731, 4751, 4812, 4923, 5047, 5131]
}
Как понятно - надо парсить. Процесс парсинга и сортировки - закомментировал как мог.
Именно эта функция - основной костяк программы. Она будет получать самые свежие списки пользователей (а верней их (пользователей) ID).
Теперь сохраняем файл - я пока сделал отдельную кнопку, куда, на событие onclick разместил такой код:
var
filee: TextFile;
list: TStringlist;
i: integer;
path,s: string;
begin
list:= TstringList.Create;
if not form2.sd1.Execute then exit else path:= sd1.FileName;
AssignFile(filee, path);
Rewrite(filee);
list:= tuc; //Получаем в стринглист LIST данные, которые вернёт нам наша прекрасная функция, что выше.
for i := 1 to list.Count-1 do
begin
s:= list.Strings[i];
writeln (filee, s); //Записываем в файл
end;
CloseFile(filee);
end;
П.с: Переменную, в которой лежит путь, рекомендую сделать публичной. Т.к. загружать файл для сравнения нам ещё предстоит.
Всё, в файл запилили. Что дальше?
Дальше на 3-ю кнопку забиндим самое святое, что будет в программе - отлов вышедших и зашедших:
var
list_old, list_new: TStringlist;
i: Integer;
j,n,k,index: Integer;
news,old: array[1..1000] of string;
st: integer;
begin
list_old:= TStringList.Create;
list_new:= TStringlist.Create;
list_new:= tuc; //Получаем список юзеров группы
n:=0; k:=0; index:=0;
list_old.LoadFromFile(path); // Вот поэтому я и говорил - "Сохрани в публичную переменную ключ, мать твою!"
if list_old.Count = list_new.Count then ShowMessage('Изменений нет') else // Если выгруженный лист = только что полученному, то изменений нет
if list_old.Count < list_new.Count then //Если полученный>старого, то есть пополнение!
begin
MessageBox(handle, Pchar('Есть пополнение!'), Pchar('Ура!!'), mb_ok);
for i := 0 to list_new.Count-1 do
begin
if Pos (list_new.Strings[i], list_old.Text) = 0 then
begin
k:= k+1;
news[k]:= list_new.Strings[i]; //Запись всех тех, кто пришёл.
end;
end;
end else
if list_old.Count > list_new.Count then //если же наоборот, то кто-то вышел.
begin
MessageBox(handle, Pchar('Есть вышедшие пользователи'), Pchar('Убить и изнасиловать!!'), mb_ok);
for i := 0 to list_old.Count-1 do
begin
if Pos (list_old.Strings[i], list_new.Text) = 0 then
begin
k:= k+1;
old[k]:= list_old.Strings[i]; //Запись в массив old всех тех, кто посмел выйти.
data.Text:= http.Get('https://api.vk.com/method/groups.banUser?group_id=ID_группы&user_id=old[k]&reason=0&comment=totoje!&v=5.7&token=ТОКЕН'); //Забанили засранца
end;
end;
end;
end;
В FormN.Create у меня прописана инициализация и создание idhttp:
http:= TidHTTP.Create(nil);
http.HandleRedirects:= true;
http.IOHandler:= form2.IdSSLIOHandlerSocketOpenSSL1;
Собственно всё - это и есть основной код, движок, программки. Я, для своей, планирую допилить удобную оповещалку, файл настроек и конечно же оптимизировать код (синзронизировать всё между собой). Как закончу - выложу, может кому пригодится.
Спасибо за внимание.