Среда, 15.05.2024, 04:21
Приветствую Вас, Гость | RSS
Категории раздела
Мини-чат
200
Главная » Статьи » Мои статьи

TCL для Eggdrop и Windrop
TCL для Eggdrop и Windrop

Многие из вас, наверное, знают, что такое IRC, если нет, то дальше читать бессмыссленно.
А если вы всё-таки знаете, то нскорее всего встречались с таким тёмным понятием как "Бот".
Что он? Или кто он? Объясняю, бот-это такая программа, одна часть которой работает как IRC
клиент, а другая выполняет некоторые действия в IRC сети.

Если объяснять ещё более доступным языком, то это опять-же программа, которая выглядит на
канале в IRC как обыкновенный пользователь, но действиями которого управляет другая программа,
называемая скриптом.
Вот теперь по моему уже понятней. Ботом может быть как обычный IRC клиент, такой
как mIRC или BitchX, так и специализированная программа, самой известной из которых является eggdrop.
А теперь я говорю абсолютно конкретно - вот о нём дальше речь и пойдёт. Если вы
никогда раньше не пользовались eggdrop-ом (дальше для краткости егг), То дальше
опять-же нет смысла читать, я не буду рассказывать как его устанавливать и настраивать,
может чуть позже в этом-же цикле статей, но не в этой это точно.
Все скрипты на егга пишутся на языке шелл программирования для *nix - TCL,
дополненном специфическими командами, облегчающими жизнь нам, простым
скриптописателям для егга. Синтаксис языка очень простой, и по ходу
чтения статьи вы с ним полностью разберётесь, и научитесь писать простенькие
скрипты для егга. В следующих статьях я, наверное, напишу о более сложных
вещах, таких как взаимодействие егга с MySQL, чтение и запись файлов
на диске и наверное затрону такую тему, как написание собственных модулей для егга на языке С.
А теперь начнём рассмотрение базовых основ скриптинга для егга.
Основное сокращение применяемое мной это будет комментарий,
который будет ограничиваться символами #! и !# (это не общепринятый
комментарий в скриптах, такое отделение, даже не будет восприниматься
как комментарий ботом).
Всегда, когда вы хотите что ваш бот как-то реагировал на происходящее
на канале, например на слово !bot, стоящее в начале строки он просто
что-нибудь делал, ваш скрипт должен содержать строку:

bind pub !bot -|- pub:bot

Объясняю по словам: команда bind означает привязку к определённому
происшествию, в данном случае к сказанному на канале(pub) слову !bot,
и боту не должно быть важно, кто это сказал (-|-) но зато он
выполняет процедуру pub:bot (это просто имя процедуры, и вы
можете выбирать его сами).
Следуя негласному кодексу скриптописателей для егга, все
привязки обычно идут в самом начале скрипта.
Привязать можно очень ко многим действиям, и в добавок некоторые
действия имеют два разных слова для привязки, например pub и pubm,
основное отличие между ними состоит в том, что привязка типа pub
не распознаёт масок (* ?) и соответственно выглядит как написанный
выше пример, но если вы хотите чтоб бот реагировал на любую строку,
где например встречается сочетание букв "фыв"(очень часто это применяется
для скрипта наказания за нецензурные выражения на канале), то
выглядеть это должно так:

pind pubm "*фыв*" -|- pubm:bot
После такой привязки надо написать процедуру, которую бот будет выполнять.

proc pub:bot {nick host hand chan text} #! Это мы описали процедуру, называется она pub:bot и принимает в качестве аргументов ник, который сказал "!bot"(nick), хост этого пользователя(host), его хэндлер(hand), канал, накотором это всё происходило(chan) и текст следующий за словом !bot(которое обязательнго должно стоять в начале строки, при такой организации привязки) !#
{
if {[mathcattr $hand o $chan]} {
putserv "PRIVMSG $chan :Ты мой оператор."
} else {
putserv "PRIVMSG $chan :Ты не являешься моим оператором."
return
}

Этот скрипт производит следующие действия (с подробным описанием комманд):

if {[matchattr $hand o $chan]} { #! Эта строка проверяет соответствует ли этому хэндлеру флаг "о"(О флагах читай в статье посвящённой флагам, думаю она будет называться "управление eggdrop-ом"), и если это так то бот напишет на канал такую строку "Ты мой оператор". Если вызов команды происходит где-нибудь в середине строки, или в еёё конце то команда заключается в квадратные скобки [].Вывод осуществляется при помощи команды putserv, эта команда отправляет серверу строку, которая идёт дальше в кавычках. А в кавычках там написанно следующее: "Отправить сообщение на канал $chan(который был передан процедуре как параметр) Ты мой оператор." Думаю тут всё понятно. !#

Так этой командой можно отправлять нотисы(NOTICE $nick(или $chan)), сообщения кому-нибудь в приват(PRIVMSG $nick), и другие действия, про которые будет написанно чуть дальше.

} else {

Ну тут я думаю всё понятно. И одно важное замечание, каждая процедура должна содержать команду return (это даже не обязательно, но быстродействие бота немного повышается в больших процедурах.). Этой командой можно вернуть какое-нибудь значение, которое будет присвоено какой-нибудь переменной, например:

set param [mycommand $string] #! Здесь переменная $string это любая переменная, которая должна быть объявленна раньше, и в результате всей этой строки происходять следующие действия: переменной param присваивается значение, которое вернула процедура mycommand, после определённых манипуляций с переменной string !#

Все процедуры обязательно вызывать со строго заданным количеством переменных,
т.е. процедура mycommand была описана всего с одной переменной, и две переменных
передавать нельзя, иначе это вызовет ошибку, и выполнение всего егга прекратится
(т.е. он закроется, и соответственно отключится от IRC сервера), предавать
множество переменных в процедуру можно так: mycommand $string1 $strin2 $string3.
Но процедура может вернуть всего одну переменную.

К слову о переменных, все переменные в TCL являются строковыми, даже когда
переменной присваивается число командой: set param 1 (это мы присвоили
переменной param значение равное 1), эта единица присваевается в виде
строки. А точнее одного слова. Если вы точно уверенны, что эта переменная
содержит число, то можно производить с ним математические операции
с помощью команды expr, например:set new [expr $param+10].

Команда putserv:

Как было сказанно выше, эта команда отправляет на сервер строку, помещая её в буффер
со средним приоритетом(т.е. приоритет этой строке отдаваться не будет, иногда это
вызывает иллюзию подтормаживания бота, но это только иллюзия, и я рекомендую
пользоваться в основном этой командой.)
Строка может быть любой, в принципе, однако любую строку сервер может не понять,
поэтому основные используемые виды такие:
putserv "PRIVMSG $chan :Целое длинное предложение" #! в результате ваш бот скажет целое длинное предложение на канале $chan!#
putserv "NOTICE $chan :А вот это вы обязательно прочитаете" #! Отправит нотис на канал(что такое нотис, читайте в статьях посвящённых общим вопросам IRC) !#
putserv "PRIVMSG $nick :Привет!" #! Отправит сообщение в приват $nick !#
putserv "NOTICE $nick :Думаю тут всё понятно"
putserv "mode $chan +o $nick" #! В результате ваш бот сделает $nick оператором канала $chan. !#
putserv "mode $chan -o $nick"
Думаю уже стало понятно, что этой командой можно делать всё, что угодно на канале.
Синтаксис строк, отправляеых командой putserv описан в статьях посвящённых общим вопросам IRC.

Так-же эта команда имеет двух своих "братьев" puthelp и putquick,
отличаются они тем, что первая команда отправляет строку с пониженным
приоритетом, т.е. эта строка выведется толь косле того как выведутся
все строки с более высоким приоритетом, а команда putquick отправляет
строку с повышенным приоритетом. Обратите внимание, что скрипт работает
намного быстрее, чем человек может печатать, и в результате, если вы
будете часто пользоваться командой putquick, ваш бот может насильно
выйти из IRC сети по причине флуда на сервер. Так что с этой командой
надобно быть поосторожнее.

Команда set:

В принципе эта комманда очень простая, она присваивает переменной
какое-то значение, будь то постоянной строкой, или результатом
выполнения комманды. Если до выполнения этой комманды переменная
не была объявлена, эта комманда её объявляет, в принципе это
единственная комманда, которая объявляет переменные.

Команда if:

Эта команда имеет следующий синтаксис
if {TRUE} {
#! ваш скрипт, если выражение в скобках верное !#
} else {
#! соответсвенно если не верно !#
}
Выражение могут быть следующими

$var1 == $var2 равно
$var1 != $var2 неравно
$var1 < $var2 меньше
$var1 > $var2 больше
$var1 >= $var2 больше или равно
<$var1 <= $var2меньше или равно

Так-же в этой комманде поддерживаются логические операции ||(или) &&(и).
В языке TCL очень сильно развиты операции со строками:
Вот два основных примера:

set slovo [lindex $string $var] #!Эта строка присваивает переменной $slovo значение слова, которое идёт под номером $var в строке $string (обратите внимание, нумерация начинается с нуля), Если слов в строке больше чем указывает $var, то присвоится пустая строка.
set sl [lrange $string $slovo1 $slovo2] #! В результате переменной $sl присвоится значение, промежутка строки $string со слова $slovo1(число, т.е порядковый номер с какого слова) по $slovo2 (аналогично), если вам надо до конца строки то это выглядит таким образом:
set sl [lrange $string $slovo1 end]

&Для начала вашей скриптописательской карьеры :) этого материала вам будет достаточно, но на этом я свой рассказ не закончил.

В прошлой статье я рассмотрел основу построения скрипта для егга.
В этой я собираюсь рассмотреть различные типы привязки, а точнее
типы событий, и привязку к ним. Заодно познакомлю ещё с парочкой функций.
;Основным событием, к которому привязывают процедуры является
публичное выражение, наверное вы не раз видели как кто-то пишет
на канале "!opme" и бот его делает оператором канала, то что это
бот можете не сомневаться. Так вот данная привязка делается при
помощи слов "pub", или "pubm", основное различие я рассмотрел в прошлой статье.
А допустим вам захотелось написать скрипт, который делал бы вас опом,
на сообщение боту в приват, тут уже словами "pub" "pubm" ну никак
не обойдёшься. Для того чтобы привязать определённый скрипт к
приватному сообщению надо применять такой тип привязки:
bind msg !opme o|o msg:op #! или !#
bind msgm "!op*" o|o msgm:op
;Отличия между "msg" и "msgm" такие-же как и между "pub" и "pubm"(читай предыдущую статью.)
Но вот описание процедуры, которая привязана к приватному сообщению, немного отличается от процедуры, привязанной к публичному сообщению. Так сообщение прозвучало не на канале, бот не может определить, с какого канала, из тех, где он вас видит, пришло сообщение, поэтому описание выглядит следующим образом:
proc msg:op {nick host hand text} { #! тут аналогично с процедурой pub:bot (читай предыдущую статью) передаются следующие параметры: ник пользователя(nick), хост(host), его хэндлер(hand) и собственно слова идущие после слова, вызвавшего данную процедуру(text), к примеру строка выглядела так - "!op me on channel #main", в переменной $text будет содержаться строка - "me on channel #main". !#
    Соответственно каждая процедура должна закрываться фигурной скобкой.
Вот теперь можно построить весь скрипт, который опает вас на указанном канале. Соответственно, если вы не являетесь оператором бота, на этом канале, он вам об этом сообщит.
bind msg !op -|- msg:op #! привязали к личному сообщению боту процедуру msg:op, сообщение должно выглядеть таким образом: "!op #main<", тогда бот сделает вас оператором на канале #main, если вы являетесь оператором бота на этом канале.!#

 proc msg:op {nick host hand text} { #! Описали процедуру msg:op !#
set chan [lindex $text 0] #! Из строки пришедшей в качестве параметра выбрали первое слово, напомню, что нумерация слов в строке начинается с нуля, эта строка написана для того, чтобы бот не попытался проверить, являетесь ли вы оператором на канале например "#main please" :) !#
if {[matchattr $hand o $chan]} #! теперь проверяем, является ли человек написавший боту его оператором на канале $chan, т.е. его хэндлеру должен соответствовать флаг "о" !#
    putserv "mode $chan +o $nick" #! если он оператром, "говорим" серверу, что надо сделать этого человека оператором канала $chan, естесственно имеет смысл если бот сам является оператором на канале $chan !#
return #! Заканчиваем процедуру !#
} else { #! А если всё таки этот человек не оператор бота, ведь бот не должен слушаться всех подряд, то... !#
putserv "NOTICE $nick :Извините, но вы не являетесь моим оператором на канале $chan" #! Сообщаем ему что он зря старается !#
>return #! и завершаем процедуру !#
>}
}
    Вот так выглядит скрипт, чуть более серьёзный, чем в рассмотренной ранее статье. А вот допустим бот не является оператором канала $chan, спросите вы. Ну что-ж, тогда бот зря старается сделать вас оператором, но если вы хотите, что бы бот вам говорил что он не оператор, то следует поставить условие:
    ">if {![botisop $chan]} { #! Если бот не оператор на канале $chan, чтоб было понятней, объясняю, многие функции возвращают либо 0 либо 1, а восклицательный знак перед скобками выполняет логическую операци "не", если вы изучали раньше программирование, то вам должно быть ивестно, что любое условие то-же своего рода процедура, которая возвращает 1 если условие верно и 0 в противном случае.
putserv "NOTICE $nick :Извините, но я не оператор на канале $chan." #! Дальше думаю пояснений уже не требуется !#
return
}
Этот кусок скрипта надо вставить сразу за строкой:
set chan [lindex $text 0]

    Соответственно по образу и подобию вы можете сделать скрипт, который заставлял бы бота банить бы кого-нибудь на канале, или наоборот разбанивать, и делать ещё много других полезных действий. Для написания скрипта на бота выполняющего стандартные команды типа: !opme !deopme !ban !unban - этих знаний уже достаточно. Но вдруг кому-то не понравилось что ваш бот делает что-то по вашему указанию, и он решил лишить вашего бота статуса оператора канала... По моему это самый простой способ лишить бота "подвижности", но ваш бот имеет статус AOP на канале (читай статьи посвящённые общим вопросам IRC). Тогда следует написать скрипт, который защищал бы вашего бота от подобных действий, если логично прикинуть, то противостоять этому нельзя, но можно вернуть оператора канала, при помощи ChanServ-a (Зто для сетеи WeNET, для других сетей я ботов пока не делал.). Выглядит это таким образом:

bind mode - * mode:bot #! К любому изменению мода канала привязываем скрипт mode:bot !#

>proc mode:bot {nick host hand chan mc {victim ""}} { #! описываем процедуру mode:bot, которой передаются переменные, о которых говорилось раньше, и две новые - mc(конкретное какое изменение произошло) и victim(жертва этого изменения)
global botnick #! Плучаем ник бота, он устанавливается в кофигурации бота, которая то же выполняется как самый обыкновенный скрипт !#
if {$mc == "-o"} { #! Если изменением послужило лишение кого-либо статуса оператора канала, то идём дальше !#
if {$victim == $botnick || $victim == [getchanhost $botnick $chan]} #! А если жертвой послужил бот, то выполняем следующие действия: !#
putserv "PRIVMSG chanserv :op $chan $botnick" #! Сообщаем чансерву, что надобно бы вернуть статус оператора. !#
return #! и прекращаем выполнение процедуры !#
}
}
return #! А тут прекращаем выполнение процедуры, в случае если жертвой был не бот, или если изменение мода было другим.
}
    Тут встретилась неизвестная функция "getchanhost". Эта функция возвращает хост, с которого зашёл в мирк $nick, а переменная $chan в этой функции говорит что хост надо смотреть на канале $chan, если эта переменная опущена, то бот будет искать этот $nick на всех каналах, а когда найдёт "посмотрит" его хост. Эту переменную лучше указывать, потому, что если вдруг этот скрипт будет ещё и наказывать, т.е. допустим банить обидчика, и нечаянно в случае какой-либо ошибки скрипт получит неправильный ник, то может пострадать невиновный человек. Которого на этом канале и нет вообще.
    Таким образом можно и перехватывать баны, присвоение статуса оператора нежелательным лицам, и все остальные.
    Ключевое слово "gobal" получает значения глобальных перемнных, установленных вне какой-либо процедуры, в данном случае ник бота. Можно указывать несколько глобальных переменных, например: global arg1 arg2 arg3 arg4 - получит значения четырёх глобальных переменных.
    Ну естественно, что вы не постоянно следите за ботом, за его действиями на всех канал, где он находится, поэтому иногда очень полезно почитать лог бота, а вот все действия, производимые ботом можно записывать так: putlog "$nick получил оператора на $chan" - что соответственно значит, что $nick получил статус оператора канала $chan. Это просто бывает полезным, когда вашего бота обвиняют в каких-либо действиях, которые противоречат правилам канала, ведь на каждом канале свои правила.
    Вот теперь вы можете задуматься над попыткой написать набор простейших, но полезных комманд для вашего бота, которые будут упрощать управление ботом с канала, или как-то автоматизируют поведение бота.
    В следующей статье буду рассмотрены основные строковые операции, и управление пользователями и каналами.


Все материалы размещенные на сайте, никакими правами не защищены. Все уже украдено до вас.
Категория: Мои статьи | Добавил: Reflex (08.01.2011)
Просмотров: 906 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Отправка SMS
Форма входа
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0