Архив статей

Все статьи из текущего раздела

Взгляд на ICQ из Delphi

Популярность ICQ все никак не падает, а наоборот, идет огромный поток новых пользователей (русские же сидят обычно на шестизначках). И если несколько лет назад для ICQ существовал только один официальный клиент от умершей нынче Mirabilis (ее поглотила AOL), то теперь их пруд пруди. И, причем, под любую ось, будь то винды, маки или никсы. К чему я это все? :) Просто и мы сегодня напишем своего клиента, пусть не супернавороченного, но клиента.

Ты уже заинтересовался? Отлично, сейчас я быстренько введу тебя в курс дела. Я давно хотел разработать собственный ICQ-клиент, но все времени не было, да и трудоемко это - не хотелось геморроиться с громоздким кодом и т.п. Но потом мне в руки попались два компонента для работы с ICQ. С радостным предвкушением я установил один из них и обломался. За его использование требовали немало буказоидов. Но второй оказался бесплатным! Прочитав инфу, которая и тебе станет доступной чуть позже, я понял, что это именно то, что нужно. Компонент TICQClient оказался очень хорошим инструментом для создания полноценного(!!!) клиента. Он включает все необходимые возможности и при этом прост в использовании. Качай его с http://www.cobans.net/ и устанавливай. На данном этапе проблем возникнуть не должно. Заметь, что к компоненту прилагается ФАК на русском языке, а также два примера. Один из них и есть почти полноценный ICQ-клиент. Обязательно взгляни на него. Там же ты найдешь и инфу по компоненту, протоколу и другим полезным вещам.

Рождаем Асю

Итак, раз клиент у тебя есть, тогда научимся делать нечто большее. Помнишь, Х писал о программе, которая умела рассылать сообщения, находя нужных пользователей по их инфе? Об этом мы сейчас и поговорим.

Что делает наша тулза:

1) Дает возможность выбирать различные параметры поиска (для примера я взял два: страна и возраст - этого хватит).

2) Дает возможность ввести сообщение с последующей вставкой туда ника жертвы.

3) Ищет/рассылает.

Готов? Поехали...

Первым делом создай новый проект и кинь на него компоненты, расположенные как на скриншоте 1.


Edit`ы называй: LoginEdit, PasswordEdit, CountEdit и MessageEdit, соответственно. Два компонента TComboBox так и оставь. Теперь добавь кнопку и TMemo. И самое главное - TICQClient. Все. Получилось? Отлично.

Подводные камни

Создавая эту программу, я столкнулся с рядом трудностей: первая и самая важная - при поиске пользователей мы обращаемся непосредственно к серверу ICQ, а он работает очень странно. Каждый раз выдает не все UIN`ы (вспомни, как ты искал пользователей в своей аське), а при повторном поиске - уже совсем другие (на самом деле частенько бывает так, что в результате поиска найдено очень много пользователей, поэтому сервер и выдает разные юины, чтобы при следующем поиске они не повторялись - прим. ред.). Т.е. нам придется самим задавать примерное количество поисковых сеансов, да еще и отфильтровывать дубликаты! Второе - задание мессаги. Об этом позже.

Поехали!

Открой свойства компонента TICQClient. В поле ICQServer и ICQPort введи login.icq.com и 5190 соответственно. Теперь исправь поле VAR перед кодом, чтобы получилось что-то вроде:

var

Form1: TForm1;

UinS,NickS: TStringList;

Здесь мы создаем два строковых списка. Зачем они нужны, ты узнаешь позже. Теперь мы напишем несколько функций, с которыми будем работать.

Поиск

Эта функция будет необходима для проверки UIN’ов на дубликаты. Работает она очень просто: получая нового пользователя, мы сравниваем с полученными ранее в списке UinS. Если его там нет, то добавляем его, а во второй список (NickS) пишем ник. Глянь на Листинг 1, там все предельно ясно.

Теперь я должен задержаться на моменте добавления новых строк. Нам будут нужны ник и юин для отправки сообщений. Я просто загоняю их в два списка и потом обращаюсь непосредственно к ним. Если в инфе не указан ник, то функция вернет (точнее, запишет) *. Это просто для удобства.

Изменение сообщения

Эта функция необходима для преобразования текста в твоем MessageEdit в новый, с учетом ника. Для примера в этой программе я сделал проверку на вставленные в мессадж "$Nick" - каждое найденное такое сочетание будет заменено на реальный ник пользователя, которому отправляется сообщение (в этом месте автор имел в виду использование небольшого регулярного выражения - прим. ред.). К примеру: "Привет, $NICK". Этот код смотри в Листинге 2.

Основной кодинг

Теперь мы почти готовы, осталось только объявить параметры поиска: добавить еще три функции из модуля ICQWorks, который необходимо дописать в раздел uses твоей программы. Две функции создают в ComboBox1 возрастные критерии (Листинг 3). Там все очень просто, так что я промолчу. Теперь создай обработчик события OnCreate у формы. Впиши туда содержимое Листинга 4. Все! Приготовления окончены!


Создай обработчик события OnClick у первой кнопки. Вставляй туда Листинг 5. Что мы там делаем: берем наш юин и пароль, коннектимся к серваку. Теперь создавай ICQClient OnLogin и пиши туда содержимое Листинга 6. Осталось только добавить код для обработчика события OnUserFound компонента ICQClient1:

if Nick=`` then //если Ника нет, то мы будем вставлять "*"

SearchList(Uin, `*`)

else

SearchList(Uin, Nick); //здесь мы начинаем проверку на дубликаты

Завершение

Вот и все! Теперь ты получил быстро работающую программу. Немного доработай ее, и получишь отличную софтину, которая даст тебе возможность похвастаться перед друзьями и быстро разослать тонну спама. Хочу лишь заметить, что не стоит увлекаться массовой рассылкой... Помни: этот пример не для засорения Сети. Удачи!


function SearchList(SUin:string; SNick:string):string;

var j:integer;

flag: boolean; //эта переменная нам нужна для определения дубликата

begin

flag:=true;

for j:=0 to UinS.Count-1 do //перебираем весь список

begin

if SUin=UinS.Strings[j] then //если новый UIN (юин в дальнейшем) = какой-то строке, то

begin

flag:=false; //флаг возвращает "фальшь":)

end;

end;

if flag then //иначе

UinS.Add(SUin); //добавляем юин и ник под единым номером.

NickS.Add(SNick);

end;

function Replace(ZNick:string; Repl:string):string;//как параметры мы задаем: ник и то, что будем менять
var Poz:integer;

s:string;

begin

s:=Form1.MessageEdit.Text; //задаем строку

Poz:=Pos(Repl, s); //если в тексте присутствует указание на ник, то...

while Poz>0 do //...пока он будет

begin

if Repl=`*` then //если ника нет, то…

begin

Delete(s, Poz, Length(Repl)); //удаляем старое

Insert(` `, s, Poz); //вставляем пробел

end

else

begin

Delete(s, Poz, Length(Repl));

Insert(ZNick, s, Poz); //пишем реальный ник пользователя

end;

Form1.MessageEdit.Text:=s; //готовим мессагу

Poz:=Pos(Repl, s); //переводим поиск на новое место

end;

end;

function TForm1.GetAgeMin: Word;

begin

case ComboBox1.ItemIndex of

1: Result := 18;

2: Result := 23;

3: Result := 30;

4: Result := 40;

5: Result := 50;

6: Result := 60;

else

Result := 0;

end;

end;

function TForm1.GetAgeMax: Word;

begin

case ComboBox1.ItemIndex of

1: Result := 22;

2: Result := 29;

3: Result := 39;

4: Result := 49;

5: Result := 59;

6: Result := $2710;

else

Result := 0;

end;

end;

procedure TForm1.FormCreate(Sender: TObject);

var

i:integer;

begin

UinS:=TStringList.Create; //создаем список

NickS:=TStringList.Create; //аналогично

ComboBox1.Items.Add(``); //выводим возраст

ComboBox1.ItemIndex := 0;

ComboBox1.Items.Add(`18-22`);

ComboBox1.Items.Add(`23-29`);

ComboBox1.Items.Add(`30-39`);

ComboBox1.Items.Add(`40-49`);

ComboBox1.Items.Add(`50-59`);

ComboBox1.Items.Add(`60 and above`);

ComboBox2.Items.Add(``);

ComboBox2.ItemIndex := 0;

for i := Low(Countries) to High(Countries) do //выводим страны

ComboBox2.Items.Add(Countries[i].Value);

end;

if LoginEdit.Text=`` then

ShowMessage(`Error! Enter UIN!`)

else

Memo1.Clear;

ICQClient1.UIN:=StrToInt(LoginEdit.Text);

ICQClient1.Password:=PasswordEdit.Text;

ICQClient1.Login(0); //логинимся к серверу в статусе Online

procedure TForm1.ICQClient1Login(Sender: TObject);

var

i:integer;

begin

for i:=0 to StrToInt(CountEdit.TExt) do //сколько раз искать

begin

ICQClient1.SearchWhitePages(``,``,``,``,GetAgeMin,GetAgeMax,0,``,``,ComboBox2.Items.Strings[ComboBox2.ItemIndex],``,``,``,``,``,``,``,``,``,true); //собственно, функция поиска

end;

for i:=0 to UinS.Count-1 do //далее идет проверка на дубликаты

begin

if i=0 then //если это первый найденый юин, то мы заменяем $Nick на новое значение...

Replace(NickS.Strings[i],`$Nick`)

else

begin

Replace(NickS.Strings[i],NickS.Strings[i-1]); //если же нет, то заменяем следующее предыдущим

end;

ICQClient1.SendMessage(StrToInt(UinS.Strings[i]),MessageEdit.Text); //функция рассылки сообщений

Memo1.Lines.Add(`Послано сообщение на `+UinS.Strings[i]+`: `+MessageEdit.Text); //добавляем инфу о проделанной работе

end;

ICQClient1.Disconnect; //отключаемся

UinS.Free;

NickS.Free;

end;