Eggdrop Tcl część 2
Z IrcWiki.
Spis treści |
Programowanie bota Eggdrop w języku TCL
Zaczynamy programowanie
Po tym długim wprowadzeniu czas rozpocząć właściwe programowanie. A więc... do dzieła! Uczymy się :)
Pierwsze polecenia
Poznamy najpierw kilka podstawowych poleceń, którymi powinieneś umieć się posługiwać. Wywołania poleceń można pisać bezpośrednio w kodzie skryptu. Zostaną wtedy uruchomione w chwili wczytania skryptu podczas uruchomienia bota, wykonania polecenia .rehash lub .restart.
Niestety, kiedy w tak wpisanym poleceniu jest błąd, wysypie nam się cały Eggdrop. Trzeba wtedy zajrzeć na koniec loga (u mnie eggdrop\logs\eggdrop.log) by dowiedzieć się o przyczynie błędu, naprawić go i ponownie uruchomić bota. Bywa to bardzo uciążliwe. Z czasem jednak przyzwyczaisz się trochę i zmobilizuje cię to do uważania na literówki w kodzie.
Polecenia logujące
Pierwszym, co nauczymy się robić, będzie zapisywanie podanego tekstu do pliku loga. Myliłby się ten kto sądzi, że służy do tego tylko jedno proste polecenie. Możliwości są takie:
putlog <text> putcmdlog <text> putxferlog <text> putloglev <level(s)> <channel> <text>
Nie przerażaj się jednak! Umieściłem tu listę wszystkich dostępnych poleceń logujących tylko po to, by trochę cię nastraszyć :) Tymczasem sprawa jest całkiem prosta. Eggdrop posiada nie jeden log, ale kilka. Różnego rodzaju informacje lądują w różnych logach zależnie od tego, z jakiego kanału pochodzą oraz przede wszystkim jaki mają poziom (ang. "level"). Możesz przypisywać poszczególne poziomy informacji do poszczególnych logów za pomocą pliku konfiguracyjnego. Jeśli uważnie go przerabiałeś to zapewne pamiętasz. Dokładne opisy tych poleceń znajdziesz w oryginalnej dokumentacji języka TCL lub (w tym przypadku) Eggdropa.
Jeśli nie możesz się w tym połapać, nie szkodzi. Wystarczy używać pierwszego z tych poleceń i odczytywać zapisywany przez nie tekst z odpowiedniego pliku.
putlog "First... loaded"
Wywołanie podobne do powyższego (gdzie "First" to nazwa twojego skryptu) umieszcza się zwykle na końcu każdego skryptu. Dzięki temu po każdym uruchomieniu bota wiesz, że twój skrypt został załadowany. Podany w cudzysłowach tekst zapisuje się do loga o poziomie "o" ("misc") oraz na ekranie w sesji Telnet.
Spróbuj napisać skrypt składający się tylko z tej linijki i uruchom go. Nie powinieneś mieć z tym większych problemów.
Do czego służą te polecenia logujące?
Przeznaczone są do zapisywania różnych zdarzeń, które uznasz w swoim skrypcie za istotne. Szczególnie przydatne mogą być w celu debugowania, czyli szukania błędów w kodzie. Wstawiasz polecenia logujące w różne miejsca kodu i analizując log wiesz co, kiedy, ile razy i w jakiej kolejności było wykonywane.
Poza tym log ma tą zaletę, że bot prowadzi go sobie stale w czasie działania. Łącząc się ze swoim kontem shellowym od czasu do czasu możesz dowiedzieć się o wszystkim, co ważnego zaszło pod twoją nieobecność. Uważaj tylko by nie logować zbyt wiele, bo plik urośnie do ogromnych rozmiarów i będą problemy.
Polecenia wyjściowe
Jak się zapewne domyślasz, najważniejsza w programowaniu bota jest możliwość wysyłania różnych informacji na serwer celem ich przekazania jako wypowiedź lub inne polecenie do danej osoby czy na podany kanał.
puthelp <text> putserv <text> putquick <text>
Wydaje się proste, tylko po co aż trzy?
Aby to wyjaśnić, powiedzieć musimy sobie o tym, w jaki sposób Eggdrop wysyła takie komunikaty. Nie są one wysyłane natychmiast, tylko trafiają do specjalnej kolejki. Wiąże się z tym kilka spraw:
- Wysłanie może potrwać kilka sekund, nie wykonuje się natychmiast
- Kolejność wysyłania komunikatów zostaje zachowana
- Powtarzające się komunikaty są usuwane z kolejki (czyli wysyłane tylko raz) nawet, jeśli różnią się wielkością liter
- Wysyłanie zakolejkowanych komunikatów nie zostanie przerwane po wydaniu polecenia .rehash
Szczególną uwagę zwracam na to usuwanie powtarzających się komunikatów. Trzeba o tym pamiętać aby później nie dziwić się, dlaczego ten sam tekst wysyłany wiele razy pojawia się tylko jeden raz.
A teraz zdradzamy całą tajemnicę: Polecenia są aż trzy, ponieważ każde ma swoją kolejkę. Kolejki te różnią się szybkością.
- puthelp
- Działa najwolniej. Nazwa pochodzi zapewne od wyobrażenia bota jako programu wykonującego zaprogramowane czynności w reakcji na odpowiednie polecenia. Jakiekolwiek wysyłanie informacji miałoby wtedy charakter wyświetlania pomocy z opisem dostępnych możliwości. Polecenie to służy więc do normalnego wysyłania wypowiedzi na kanał czy do konkretnej osoby.
- putserv
- Jest trochę wolniejsze. Nazwa tego polecenia również może być trochę myląca. Przecież wszystkie trzy tak samo wysyłają komunikat do serwera. Pochodzi ona najprawdopodobniej od przewidzianego zastosowania do wysyłania komunikatów sterujących dla serwera IRC i nie będących wypowiedziami.
- putquick
- To polecenie jest najszybsze. Sam nigdy go nie używałem.
Ten mętlik jest trochę związany z historią bota, nie byłem od początku przy rozwoju eggdropa, ale wszystko wskazuje na to, że putserv było pierwszym poleceniem. Możliwe, że nie było wtedy nawet żadnej kolejki. Problemy pojawiły się np. przy skryptach które zwracały jakieś informacje po wydanym poleceniu. Pojawiły się osoby które wysyłały to polecenie wiele razy na sekundę (z różnych sesji) przez co boty miały coraz większe lagi, często nawet wylatywały z IRC z poleceniem "Excess flood". puthelp powstało aby wyeliminować ten problem. Ta kolejka ma też najniższy priorytet, wykonywana jest tylko jak bot nic nie ma do roboty. putquick zostało wprowadzone z powodu narzekania na prędkość putserv, powinno się używać do krytycznych poleceń, np. trzeba kogoś wykopać czy zdeopować bo próbuje przejąć kanał itp.)
-- Dariusz Kuliński 23:09, 3 mar 2005 (PST)
No dobrze... ale właściwie co za <text> można wysyłać? Skąd wiadomo, do kogo będzie adresowany?
Ten <text> to nie jest zwykły dowolny łańcuch. To jeden z dostępnych komunikatów IRC. Za ich pomocą możesz robić wszystko, np. pingować osoby czy kanały. Podam tutaj najprostsze zastosowania:
puthelp "PRIVMSG #lamerlandia :Czesc lamerzy!" puthelp "PRIVMSG Lamer :cze Lamer" puthelp "NOTICE Lamer :wassup?"
Polecenie pierwsze wypowiada podany po dwukropku tekst na podanym kanale. Drugie wypowiada podany tekst "na priv" (znany też jako "Query") do podanej osoby. Trzecie zaś wysyła do podanej osoby komunikat (ang. "notice" - to ta funkcja, do której służy polecenie /notice w mIRCu).
Zwróć uwagę, że spacja musi być przed dwukropkiem, a nie za nim.
Procedury
Nie da się napisać niczego sensownego wywołując jedynie kolejne polecenia. W każdym języku programowanie istnieje możliwość tworzenia własnych podprogramów. W TCL nazywamy je zawsze procedurami.
Deklaracja procedury:
proc <nazwa> { [parametry] } {
<kod>
}
Przykład procedury:
proc ZapiszBleDoLoga { } {
putlog "Ble"
}
Procedurę wywołuje się dokładnie tak, jak wbudowane polecenia. Wywołanie składa się z nazwy procedury oraz oddzielonych od niej i od siebie nawzajem odstępami kolejnych parametrów w odpowiedniej ilości.
Kolejność deklaracji procedur nie ma wpływu na możliwość ich wywoływania. Procedura A może wywołać procedurę B nawet, jeśli ta zadeklarowana jest dopiero poniżej.
Parametry
Jako parametry należy podać listę oddzielonych przecinkami nazw. Dzięki nim procedura może odbierać dodatkowe informacje potrzebne do odpowiedniego wywołania. Parametry można wykorzystywać w kodzie procedury pobierając ich wartość za pomocą operatora $.
Przykład wykorzystania parametrów:
proc ZapiszDoLoga {a_sText} {
putlog $a_sText
}
ZapiszBleLoga "Blebleble"
Na końcu listy parametrów mogą się znaleźć parametry domyślne. Deklaruje się je zapisując zamiast samej nazwy parametru taką konstrukcję:
Deklaracja parametru domyślnego:
{<nazwa> <wartość-domyślna>}
Przykład wykorzystania parametrów domyślnych:
proc ZapiszDoLoga2 {a_sText {a_iLiczba 7}} {
putlog "Twoja $a_sText liczba to: $a_iLiczba"
}
Następujące wywołania tej procedury:
Wywołania procedury z parametrem domyślnym:
ZapiszDoLoga2 "szczesliwa" ZapiszDoLoga2 "pechowa" 13
- spowodują dopisanie do loga: eggdrop.log
Twoja szczesliwa liczba to: 7 Twoja pechowa liczba to: 13
Jak widać, parametr domyślny można pominąć w wywołaniu. Za jego wartość przyjęta zostanie wówczas wartość domyślna.
Jest też możliwość tworzenia procedur przyjmujących dowolną liczbę dodatkowych parametrów. Jako nazwę ostatniego parametru podać należy args. Po szczegóły odsyłam do podręcznika języka TCL, pod hasło proc.
Zapamiętaj, że pomiędzy nazwą procedury a nawiasem klamrowym otwierającym listę jej parametrów musi być odstęp!
Zwracanie wartości
Procedura może zwracać wartość, którą można potem wykorzystać dzięki zagnieżdżaniu poleceń. Służy do tego polecenie:
return <wartość>
Wywołanie tego polecenia w dowolnym miejscu kodu procedury powoduje natychmiastowe zakończenie jej działania i wyjście z niej ze zwróceniem podanej wartości. Jeśli procedura zakończy się bez wywołania tego polecenia, jako zwracana wartość przyjęty zostanie łańcuch pusty.
Piszemy procedurę Debug
Nietrudno dojść do wniosku, że ciągłe zaglądanie do logów to nienajlepszy sposób debugowania. Dużo lepiej byłoby mieć polecenie, które niemal natychmiast poinformowałoby nas o tym, o czym chcielibyśmy się dowiedzieć. Idealnie nadaje się do tego przesyłanie prywatnych wiadomości na IRCu. Dlatego stworzyłem sobie kiedyś taką procedurkę:
Procedura Debug
proc Debug {aText} {
puthelp "PRIVMSG Nick :\[DEBUG\] $aText"
}
W miejsce Nick wpisz swoją ksywę z IRCa. Radzę wstawiać tą procedurę na początku każdego pisanego skryptu.
Jej użycie polega na wstawieniu w odpowiednich miejscach kodu jej wywołania z odpowiednim parametrem. Dzięki temu niemal od razu dostaniesz przez IRC od swojego bota prywatną informację, z której dowiesz się co, kiedy, w jakiej kolejności i z jakimi wartościami się w skrypcie wywołało. Pomoże to znajdować i usuwać błędy.
Nie zapomnij, że Eggdrop usuwa z kolejki wyjściowej powtarzające się komunikaty wysyłając je tylko raz!
Nazwy procedur
Nazwy procedur mogą być zupełnie dowolne. Często stosuje się w nich np. dwukropek :. Nazwy procedur z poszczególnych skryptów TCL używanych przez Eggdropa nie kolidują ze sobą.
Tak jak każda instrukcja TCL jest poleceniem, tak samo każdy łańcuch może zawierać znaki specjalne takie, jak [] czy $. Dzięki temu nazwę procedury do uruchomienia można nawet pobrać ze zmiennej czy złożyć z kilku członów. Jeśli zmienna $s1 przechowuje łańcuch Moja, a zmienna $s2 przechowuje łańcuch Procedura to wywołanie:
$s2$s2 "Ble"
- spowoduje wywołanie procedury o nazwie MojaProcedura z parametrem "Ble".
Bindowanie
Teraz, kiedy znamy już procedury, możemy przejść do sedna sprawy. Bindowanie zdarzeń powoduje, że Eggdrop wywoła napisane przez nas procedury w reakcji na poszczególne zdarzenia.
Składnia polecenia do bindowania
bind <type> <flags> <keyword/mask> <proc-name>
- type - To typ zdarzenia np. wypowiedź na kanale, zmiana tematu kanału, wejście kogoś na kanał.
- flags - To flagi, jakie posiadać musi powodujący zdarzenie użytkownik, by zdarzenie zaszło. Przypomnij sobie rozdział o użytkownikach i flagach. Najczęściej używane wartości to:
- n - Zdarzenie może wywołać tylko właściciel (owner) tego bota, czyli ty. Przydatne, kiedy chodzi o jakieś polecenie sterujące botem.
- - - Zdarzenie może wywołać każdy. Przydatne, kiedy chodzi o zwykłe zdarzenia IRC np. zareagowanie na każdą wypowiedź na kanale.
- keyword/mask - To słowo kluczowe lub maska, którego wystąpienie w tekście będzie warunkiem zajścia zdarzenia. Szczegóły zależą od typu zdarzenia. W masce można używać znaków zastępczych (ang. "wildcards"):
- ? - Zastępuje dowolny, pojedynczy znak.
- * - Zastępuje dowolną liczbę (także zero) dowolnych znaków. Często używa się jako maski pojedynczej gwiazdki *, by zdarzenie zaszło dla każdego tekstu. Inne możliwe konstrukcje maski to np. *słowo*, która szuka wystąpienia podanego słowa w dowolnym miejscu tekstu.
- proc-name: To nazwa procedury, która wywoływana będzie w reakcji na dane zdarzenie.
Bindowana procedura musi mieć odpowiednie parametry zależnie od rodzaju bindowanego zdarzenia. Dostępne typy zdarzeń oraz odpowiadające im wymagane parametry procedur znajdziesz w dokumentacji dołączonej do Eggdropa, w dokumencie "Eggdrop TCL Commands", w rozdziale 11.
W dokumentacji niektórych rodzajów zdarzeń pisze (stackable). Oznacza to, że na dane zdarzenie zakładać można wiele bindów, a odkładane będą one na specjalny stos i wywoływane wszystkie po kolei.
Mam jeszcze dobrą wiadomość. Jeśli podczas wykonywania kodu reagującego na zbindowane zdarzenie wystąpi błąd, Eggdrop nie wysypie się. Po prostu wykonywanie kodu zostanie przerwane, a do loga i w sesji Telnet dopisany zostanie komunikat o błędzie. Nie przeszkadza to możliwości dalszego zachodzenia tego samego lub innych zdarzeń.
MSG i PUB
Te zdarzenia służą do wydawania poleceń. Wypowiadany odpowiednio na "priv" lub za pomocą /msg (MSG) oraz publicznie na kanale (PUB) tekst dzielony jest na pierwsze słowo (do pierwszego odstępu) traktowane jako nazwa polecenia oraz pozostałą część traktowaną jako parametry polecenia. Wielkość liter nie ma znaczenia dla rozpoznania lub nierozpoznania danego polecenia.
Przykład dla zdarzenia MSG:
proc OnLoguj {a_sNick a_sUserHost a_hHandle, a_sText} {
putlog $a_sText
}
bind msg n "loguj" OnLoguj
Kiedy napiszesz do swojego bota np. loguj Tralalala, wywołana w reakcji na zdarzenie przypisane poleceniu loguj procedura dopisze do loga tekst Tralalala.
Parametry przekazywane do procedury obsługującego tego rodzaju zdarzenie mają następujące znaczenie (nazwa parametrów nie jest istotna, liczy się tylko kolejność -- Dariusz Kuliński 23:09, 3 mar 2005 (PST)):
- a_sNick
- To nick osoby, która wydała polecenie.
- a_sUserHost
- To łańcuch o budowie <user>@<host> również odnoszący się do osoby wydającej polecenie, np. w moim przypadku jest to ~sawickiap@frodo.i.czest.pl.
- a_hHandle
- Specjalny uchwyt do konta użytkownika, jeśli osoba, która wydała polecenie, zidentyfikowana została przez bota jako jego zarejestrowany użytkownik.
- a_sText
- To parametry polecenia, czyli część wypowiedzianego tekstu rozpoczynająca się po pierwszym odstępie.
MSGM i PUBM
Poprzednie zdarzenia służyły do reagowania na konkretne polecenia. Te natomiast pozwalają reagować na dowolny wypowiadany tekst pasujący do podanej maski. W przypadku PUBM dopasowywany do maski tekst składa się z nazwy kanału oraz następującej po nim pełnej treści wypowiedzi.
Przykład dla zdarzenia PUBM:
proc OnPubm {a_sNick a_sUserHost a_hHandle a_sChannel a_sText} {
puthelp "NOTICE Nick :Hej, na kanale $a_sChannel mowia o tobie!"
}
bind pubm - "*Nick*" OnPubm
W powyższym kodzie w miejsce Nick wstaw swój pseudonim, a będziesz informowany poprzez wiadomość, kiedy na jednym z kanałów, na których przebywa bot, ktoś go wypowie.
TOPC
To zdarzenie zachodzi, kiedy ktoś zmienia temat kanału. Wspomniałem o nim by zaznaczyć, że chcąc katalogować kolejne tematy nie musisz osobno zajmować się tematem, jaki jest w momencie wchodzenia bota na kanał. Zdarzenie to bowiem wykonuje się także w momencie wchodzenia na kanał.
Timery
Timer (lub jak kto woli: licznik, zegar) pozwala wywołać podane polecenie po podanym czasie.
Polecenia do tworzenia timera:
timer <czas> <polecenie> utimer <czas> <polecenie>
Czas to liczba wyrażona w minutach (timer) lub sekundach (utimer). Po podanym czasie jednorazowo wykonane zostanie podane polecenie. Po jego wykonaniu timer znika, a nie wywołuje się cyklicznie co jakiś czas.
Warto podkreślić pewną różnicę: Podczas bindowania zdarzeń jako ostatni parametr podawaliśmy samą nazwę procedury. Procedura musiała mieć odpowiednie parametry i te parametry były wypełniane przez Eggdropa różnymi ciekawymi informacjami. W przypadku timerów podaje się całe polecenie do wykonania. Musi to być sama nazwa procedury, jeśli procedura nie ma parametrów lub wywołanie razem ze wszystkimi potrzebnymi parametrami.
Powyższe funkcje zwracają wartość będącą identyfikatorem utworzonego timera. Timer taki można, o ile nie zdążył jeszcze się wykonać i tym samym nie zniknął, usunąć poleceniem:
Polecenia do usuwania timera
killtimer <TimerID> killutimer <TimerID>
Warto wiedzieć, że są też polecenia timers i utimers, które zwracają listy utworzonych timerów.
Problem
W związku z podawaniem całego polecenia do wykonania istnieje pewien problem. Chodzi o znaki specjalne rozpoznawane w łańcuchach.
Wyobraź sobie, że chciałbyś, aby za jakiś czas wykonana została procedura Costam z parametrem w postaci łańcucha o treści [NIC]. Łańcuch zawiera nawiasy kwadratowe i chcielibyśmy, aby potraktowane zostały jako zwykłe znaki a nie jako znaki specjalne powodujące wykonanie (nieistniejącego przecież) polecenia.
W tym celu polecenie wywoływane przez timer powinno mieć postać: Costam \[NIC\]. Aby jednak ukośnik nie spowodował zintepretowania nawiasów już podczas deklaracji timera i nie w efekcie nie poskutkował zinterpretowaniem tych nawiasów jako znaków specjalnych już podczas wywoływania polecenia przez timer, dołożyć trzeba dodatkowe ukośniki.
Ostatecznie polecenie tworzące timer wyglądałoby więc tak: timer 60 "Costam \\\[NIC\\\]"
Ale to bez sensu! Naprawdę muszę się zajmować takimi głupotami?
Niekoniecznie. Dużo prościej jest wywoływać jako polecenia timera zawsze tylko zwykłe bezparametrowe procedury. Zazwyczaj to wystarcza.
Problem występuje dlatego, że timer dokonuje tzw. ewaluacji aby wykonać polecenie, problem można wyeliminować pisząc timer 60 [list Costam {[NIC]}]. Jeżeli chcemy jednak jako argumenty podać wartości jakiejś zmiennej to polecenie powinno wyglądać tak: timer 60 [list Costam $zmienna1]
-- Dariusz Kuliński 23:09, 3 mar 2005 (PST)
Przykład - cykliczne timery
Spróbujemy teraz zrobić timer, który będzie wykonywał się cyklicznie co minutę. W tym celu trzeba tworzyć nowy timer na końcu procedury wywołanej przez stary.
Przykład timera cyklicznego:
proc SetTimer { } {
timer 1 OnTimer
}
proc OnTimer { } {
Debug "Minela kolejna minuta"
SetTimer
}
SetTimer
Utworzenie timera potrzebne jest w dwóch miejscach: w samej treści skryptu (w momencie jego uruchamiania) oraz na końcu procedury OnTimer. Rozsądne było więc wydzielenie tego kodu do osobnej procedury zamiast jego powielania.
Powyższy przykład posłuży nam do zaznaczenia dwóch istotnych rzeczy. Po pierwsze: Jeśli podczas wykonywania kodu procedury OnTimer (lub dowolnej przez nią wywołanej) wystąpi błąd, Eggdrop podobnie jak w przypadku bidnowanych zdarzeń nie wysypie się, a tylko przerwie wykonywanie tej procedury. Oczywistą konsekwencją będzie niewykonanie ostatniej instrukcji, która tworzy nowy timer. Dzięki temu błędny kod nie będzie więcej razy wykonywany.
Po drugie: Zapamiętać musisz, że timery nie są usuwane po .rehash. Tymczasem ostatnia instrukcja powyższego kodu za każdym razem utworzy nowy. Powstanie wtedy, niestety, wiele cyklicznie wykonujących się timerów. W efekcie procedura OnTimer wywoływana będzie dużo częściej, niż co minutę.
Jak temu zaradzić?
Rozwiązaniem jest usuwanie bieżącego timera przed .rehash. Wymagałoby to jednak zapamiętania jego uchwytu w zmiennej. Zrobimy to, ale w następnej części, jak tylko poznamy zmienne.
Strefy nazw
TCL jest językiem strukturalnym i bardzo brakuje w nim programowania obiektowego. Pewną organizację kodu można sobie jednak zapewnić dzięki strefom nazw (ang. "namespaces").
Deklaracja strefy nazw
Deklaracja strefy nazw:
namespace eval <nazwa> {
<treść>
}
Treścią może być wszystko to, co mogło być napisane w zwykłej treści skryptu. Dopuszczalne są więc wywołania poleceń, a także deklaracje własnych procedur.
Kod (wywołania poleceń) umieszczony bezpośrednio wewnątrz namespace (nie jako treść procedur) zostanie w danym miejscu wywołany tak samo, jak zostałby, gdyby tej strefy w ogóle nie było.
Operator zakresu
Operatorem zakresu pozwalającym na dostęp do składników strefy (procedur i zmiennych) jest tzw. czterokropek zapisywany jako dwa dwukropki ::. Może wydawać się dziwny, ale miłośnicy języka C++ doskonale go znają.
Aby uzyskać dostęp do składnika strefy nazw, trzeba napisać jakby ścieżkę do niego. Namespaces można w sobie zagnieżdżać, więc ścieżka może składać się z szeregu elementów. Zapisujemy ją jako nazwę strefy, operator zakresu, nazwę podstrefy, znowu operator itd., a w końcu po operatorze nazwę elementu, o który nam chodzi. Operator zakresu można też wstawić na początku takiej "ścieżki".
Z kodu procedury zawartej w strefie nazw można bez użycia operatora zakresu wywoływać zarówno inne procedury z tej samej strefy, jak i procedury globalne (nie zawarte w żadnej strefie). Z kodu procedury globalnej można wywołać procedurę zawartą w strefie używając operatora zakresu.
Przykład
Przykład strefy nazw:
namespace eval MyNS {
proc Proc2 { } {
# W procedurze w namespace wywołuję procedurę globalną
Debug "No i sie wykonalo :)"
}
proc Proc1 { } {
# W procedurze w namespace wywołuję procedurę z tej samej namespace
Proc2
}
}
proc OnTest {a_sNick a_sUserHost a_hHandle, a_sText} {
# W procedurze globalnej wywołuję procedurę z namespace
MyNS::Proc1
}
bind msg n "test" OnTest
PROJEKT - identify
Umiemy już wystarczająco dużo, by napisać pierwszy kompletny i naprawdę użyteczny skrypt.
W sieciach IRC posiadających usługi (jak PolNet) nicki można rejestrować. Zarejestrowanego nicka nikt nam nie odbierze, a bycie zarejestrowanym i zidentyfikowanym może być warunkiem otrzymywania auto-opa od ChanServa.
Najpierw trzeba zarejestrować ksywę. Sam nie możesz tego zrobić, musi to zrobić twój bot. W tym celu połącz się do niego Telnetem i wydaj polecenie podobne do tego:
Bot rejestruje swój nick
.msg NickServ register moje-haslo
Teraz pora napisanie właściwego skryptu. Jego zadaniem będzie identyfikacja bota po każdym uruchomieniu.
Jest jeszcze jedna sprawa. Chcielibyśmy, by bot dzięki byciu zidentyfikowanym mógł dostać auto-opa po wejściu na twój kanał. Problem w tym, że wchodzenie na zapisane w konfiguracji kanały oraz wykonywanie skryptów dzieje się jednocześnie i nigdy nie wiadomo, co będzie pierwsze. Zapewne zależy to od fazy księżyca :) Tak więc może się zdarzyć, że w chwili wchodzenia na kanał bot nie będzie jeszcze zidentyfikowany.
Jak sobie z tym poradzić?
Możnaby pomyśleć coś w kierunku wyjścia i ponownego wejścia na kanał, ale to chyba raczej na pewno nienajlepsze rozwiązanie :) Dużo lepiej wydać po zidentyfikowaniu się polecenie przyznania opa przez ChanServa. Jeśli bot nie miał opa, to go wtedy dostanie.
identify.tcl:
bind evnt - init-server identify
proc identify {a_sType} {
putserv "PRIVMSG NickServ :identify moje-haslo"
putserv "PRIVMSG ChanServ :op #moj-kanal"
}
dopisek
Jest prostsze rozwiazanie problemu. W pliku konfiguracyjnym mamy wpis:
set servers {
server:6667
}
Wystarczy drobna modyfikacja, a bot sie sam loguje :)
set servers {
server:6667:pass
}
Oświadczam, że jestem autorem dopisku i udostepniam go na licencji CC-BY. Marcimon 05:42, 23 maj 2007 (PDT)
Ten tutorial został wprowadzony tutaj za zgodą oryginalnego autora:
Adam Sawicki "Regedit"
http://www.programex.prv.pl
