TCL скрипты для eggdrop и windrop (часть 2)

Четверг, 26 Июль 2007

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

Основным событием, к которому привязывают процедуры, является публичное выражение, наверное, вы не раз видели, как кто-то пишет на канале «!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
 
proc msg:op {nick host hand text} {
  set chan [lindex $text 0]
  if {[matchattr $hand o $chan]} {
    putserv "mode $chan +o $nick"
    return
  } else {
    putserv "NOTICE $nick :Извините, но вы не являетесь моим оператором на канале $chan" 
    return
  }
}

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" — сообщаем ему, что он зря старается

Вот так выгляди т скрипт, чуть более серьезный, чем в рассмотренной ранее статье. А вот, допустим, бот не является оператором канала $chan, спросите вы. Ну что же, тогда бот зря старается сделать вас оператором, но если вы хотите, чтобы бот вам говорил, что он не оператор, то следует поставить условие:

 
if {![botisop $chan]} { 
  putserv "NOTICE $nick :Извините, но я не оператор на канале $chan."
  return
}

if {![botisop $chan]} { — это означает « если бот не оператор на канале $chan». Чтобы было понятней, объясняю, многие функции возвращают либо 0, либо 1, а восклицательный знак перед скобками выполняет логическую операцию «не». Если вы изучали раньше программирование, то вам должно быть известно, что любое условие тоже своего рода процедура, которая возвращает 1, если условие верно и 0 в противном случае. Этот кусок скрипта надо вставить сразу за строкой set chan [lindex $text 0].

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

bind mode - * mode:bot
proc mode:bot {nick host hand chan mc {victim ""}} { 
  global botnick 
  if {$mc == "-o"} { 
    if {$victim == $botnick || $victim == [getchanhost $botnick $chan]} {
      putserv "PRIVMSG chanserv :op $chan $botnick"
      return
    }
  }
return
}

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 — заканчиваем процедуру

Тут встретилась неизвестная функция getchanhost. Эта функция возвращает хост, с которого зашёл в IRC $nick, а переменная $chan в этой функции говорит, что хост надо смотреть на канале $chan, если эта переменная опущена, то бот будет искать этот $nick на всех каналах, а когда найдёт — «посмотрит» его хост. Эту переменную лучше указывать, потому, что если вдруг этот скрипт будет ещё и наказывать, т.е. допустим, банить обидчика, и нечаянно в случае какой-либо ошибки скрипт получит неправильный ник, то может пострадать невиновный человек, которого на этом канале и нет вообще.

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

Ключевое слово gobal получает значения глобальных переменных, установленных вне какой-либо процедуры, в данном случае ник бота. Можно указывать несколько глобальных переменных, например: global arg1 arg2 arg3 arg4 — получит значения четырех глобальных переменных.

Ну, естественно, что вы не постоянно следите за ботом, за его действиями на всех каналах, где он находится, поэтому иногда очень полезно почитать лог бота, а вот все действия, производимые ботом можно записывать так:

putlog "$nick получил оператора на $chan"

Это соответственно значит, что $nick получил статус оператора канала $chan. Это просто бывает полезным, когда вашего бота обвиняют в каких-либо действиях, которые противоречат правилам канала, ведь на каждом канале свои правила.

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

Последнее обновление ( Суббота, 22 Сентябрь 2007 )
< Пред.   След. >