Останнім часом, за даними різних спостережень, все більше переважає тенденція написання різних бойових роботів (war bots), у функції яких зазвичай входить масові DDoS атаки, спам або накрутка лічильників і т. п. Створення таких армій, справа, звичайно, «благе», ніхто не сперечається, тим більше що їх цілком можна пустити і в більш благі цілі, які залежать лише від того, хто стоїть біля керма». На hackzonae є кілька статей, присвячених цьому питанню, тому (і не тільки), ми його розглядати не будемо. Давайте розглянемо більш культурні, перспективні, затребувані проекти, іменовані бот-сервісами. Назва терміна говорить сама за себе (service — послуга). Допомога такого сервісу може бути неоціненною, так само як і марною. Фантазія і нагальні потреби в цій справі вирішують багато чого. Як приклад, ми будемо створювати бот-сервіс для IRC-мереж, який повинен бути, або може бути корисний програмісту. Писати будемо на Delphi, тому господа сишники можуть з радістю припинити читання, і скролити в самий низ, щоб поставити уїдливий коментар.

Почнемо, як не дивно, зі створення нового проекту, і додання формі необхідного контенту, для функціонування. До речі, форма тут потрібна більше для наочності, ніж для функціональності. І так, по порядку. По-перше нам потрібна область для виводу прийнятої інформації, отже більшу частину нашої форми займає компонент Memo, або його аналог. Панель з кнопками в кол-ве 2х штук буде включати функцію підключення і відключення від сервера. І компонент, що вказує активностьнеактивность функції бота. Я використовував для цих цілей CheckBox. 4 компонента типу Edit будуть служити для того, щоб ми могли варіювати сервера, порт, id, і автозаход на канал. StatusBar буде служити для виведення поточного часу, а також часу сеансу, тому додамо Timer з вкладки System. Щоб не було незрозумілих моментів, я розмістив посилання на исходник і бінарники в кінці статті. Основним компонентом в нашому проекті, як ви здогадуєтеся буде IdIRC з вкладки Indy Client.

Пробігшись поглядом по інспектору об’єктів, з виділеним IdIRC, ви можете побачити, що, в принципі, всі властивості і події позначені досить ясно і чітко. Host сервер, Nick, Password, Port. Введемо в інспекторі об’єктів нік боту, на наш розсуд. Тепер опрацюємо події OnClick обох кнопок. Процедури приймуть такий вигляд:

procedure TMain.Button1Click(Sender: TObject);
begin
randomize;
If ld1.text” then
idIRC1.Host:=ld1.Text
else begin
messagebox(0,’Ви не вказали сервер…’,’error’,mb_ok);
exit;
end;
If ld2.Text” then
try
idIRC1.Port:=StrToInt(ld2.Text);
except begin
ShowMessage(‘Port є числовим значенням!’);
exit;
end;
end
else begin
ShowMessage(‘Ви не вказали порт…’);
exit;
end;
If ld3.Text” then
idIRC1.Username:=ld3.Text
else idIRC1.Username:=IntToStr(random(999));
try
idIRC1.Connect();
except begin
messagebox(1,’Перевірте підключення до Інтернет або налаштування FireWall…’,’Підключення скасовано’,mb_ok);
exit;
end;
end;
idIRC1.Raw(‘mode ‘+idIRC1.Nick+’ +x’);
If ld4.Text” then
idIRC1.Join(ld4.Text);
Button2.Enabled:=true;
end;

procedure TMain.Button2Click(Sender: TObject);
begin
idIRC1.Quit(‘…’);
end;

Спробуйте запустити програму, і ви побачите, що по натисненню на кнопку Connect, з’єднання з вказаним вами сервером сталося. При натисканні на Quit бот покинув сервер. Тепер давайте розглянемо процедури уважніше. На початку ми надаємо властивостей компонента IdIRC зазначені значення. Ld компонент LabeledEdit, перейменований для стислості. Зверніть увагу, що перевірка введених значень йде на всіх рівнях, щоб не допустити введення некоректних даних. Що стосується ID клієнта, то він, у разі, якщо ми залишимо поле порожнім прийме значення випадково згенерованої рядки, в межах числового значення 998. Тепер саме час… з’єднається з сервером: idIRC1.Connect(), у разі якщо спроба буде вдалою виконається функція шифрування ніка і автозахода на канал. Однак ми не можемо спостерігати за цими діями з вікна нашої програми, успіх мені довелося фіксувати з вікна свого клієнта irc. Давайте виправимо цей недолік, обробивши подія OnRaw. Для початку, процедура прийме такий вигляд:

procedure TMain.IdIRC1Raw(Sender: TObject; AUser: TIdIRCUser; ACommand,
AContent: String; var Suppress: Boolean);
begin
log.Lines.Add(AUser.Nick+’ ‘+Acommand+’ ‘+AContent);
end;

Тепер, ми можемо навіч переконатися, що з’єднання з сервером йде, як заплановано, і якщо щось піде не так аналізуючи лог лист ми про це дізнаємося. Тепер саме час спробувати навчити бота розмовляти. Однак обробляти подія OnMessage ми не будемо, і взагалі постараємося не зачіпати його жодним чином. Прийняті повідомлення, в OnRaw після невеликої обробки візьмуть цілком прийнятний вигляд. Давайте нарешті напишемо обробку команди від користувача. В якості прикладу, запропоную реалізувати видачу основних 11 пунктів правил каналу #hackzona на однойменному сервері. Для цього помістимо їх в текстовий файл, наприклад «rul.txt», зберігши його в каталог з програмою. Повернемося в процедуру idIRC1Raw і додамо перед begin 2 змінні типу String (target і content), змінну x, зберігає числове значення одну змінну F типу TStringlist:
var target,content:string;
F:TStringList;
x:integer;
потім, нічого не змінюючи, нижче рядка «log.Lines.Add(AUser.Nick+’ ‘+Acommand+’ ‘+AContent);» напишемо наступне:
target:=ansileftstr(Acontent,pos(‘:’,Acontent)-2);
content:=ansirightstr(Acontent,Length(Acontent)-(Length(target)+2));
Тепер наш Raw буде оброблятися, і ділитися на ключові для нас моменти: «Мета» і «Зміст». Якщо ви після додавання цих рядків при спробі запуску програми, прочитаєте помилку типу: «[Error] Unit1.pas(98): Undeclared identifier: ‘ansileftstr’», просто додайте в Uses модуль StrUtils, що містить опис цих функцій. Тепер, власне, сама обробка команди, назвемо її «!rul», там же у Raw:
If (UpperCase(content)=’!RUL’) then begin
F:=Tstringlist.Create;
F. LoadFromFile(‘rul.txt’);
repeat
x:=0;
idIRC1.Say(Auser.Nick,f.Strings[x]);
f.Delete(x);
Sleep(100);
until f.Count=0;
F. Free;
end;

Як ви бачите, ми зводимо оброблену рядок RaW, а саме підрядок content у верхній регістр, порівнюємо. Потім створюємо об’єкт СтрингЛист і в циклі repeatuntil виводимо по черзі вміст файлу, запит користувачу. В кінці процедури, звільняємо об’єкт. В принципі макет створений, подальші команди залежать тільки від ваших потреб. Наприклад, всім відомі процедури роботи з рядками можуть бути дуже корисні для пермоментного використання на каналі. Їх можна продовжити в OnRaw трохи нижче. Наприклад настільки прості, але настільки корисні функції:

if (Pos(‘!LEN ‘,UpperCase(content)) =1) then
idIRC1.Say(Auser.Nick’Довжина рядка: ‘+IntToStr(Length(ansirightstr(content,length(content)-5)))+’ символів.’);
if (Pos(‘!REV ‘,UpperCase(content)) =1) then
idIRC1.Say(Auser.Nick,ReverseString((ansirightstr(content,length(content)-5))));

В нашому випадку, «!Len рядок» поверне довжину рядка, а !rev 123 переверне рядок (321). Що стосується того, навіщо нам потрібна була мінлива target, вона знадобиться якщо наш бот присутній на кількох каналах, і виконує різні функції. Змінна буде містити ім’я каналу, або нік бота (В тому випадку, якщо команди були подані в приват). Працездатність програми, в залежності від встановленого прапора CheckBox1, також слід налаштувати за необхідності. Вихідний код разом з готовим додатком доступний за адресою: (http://ifolder.ru/5579852 226кб).

Більш вдосконалений бот-сервіс такого роду може бути дуже корисний адміністрації деяких порталів, відвідувачі якого, спілкуються за допомогою IRC-каналів, наприклад повідомляючи оперативні дані про зареєстрованих учасників, останніх темах, кол-ве відвідувачів і т. п… Також хочу попередити, що хоч в полях програми за замовчуванням стоять установки на портал ХакЗона, згідно з пунктом 10 правил каналу #hackzona (http://hackzona.ru/hz.php?name=Content&pa=showpage&pid=784 ви можете бути забанені, за використання ботів на даному каналі без узгодження з адміністрацією. Мені доводилося писати ботів на канали, які не підходили під певні шаблони, що виключало використання ботів, наприклад eggdrop, особливо коли мова йде про ігрові каналах (щось типу Мафія), тому постараюся, по можливості, допомогти з виниклими проблемами або питаннями (icq, e-mail).

Happy Coding!