I've written up an example socket bot that will connect to a server (just the one -- multiserver is more complex) and respond to certain events.
This is just to show you how socket bots work. It is in no way a complete of even very functional bot.
The bot has a built in identd server so you can respond to identd requests with it.
Commands:
/bot connect <server> <port> (to connect the bot to a server)
/bot disconnect (to disconnect the bot)
/bot send (to send data to the server)
/bot sendln (to send data to the server follows by a CRLF)
/bot debug (to open a window which shows all incoming/outgoing data and allows you to send data to the server by typing commands out)
/bot identresponse <data> (to respond to ident requests) -- you won't need this, I've already scripted the ident response but you can see how to do it at least
I have also added a small /test alias that will open up the debug window and connect you a server. You will want to make use of the debug window whilst you're writing the bot. You'll need to change the test alias to connect to a server/port of your choice.
When commands are received from the server it will throw off signals that you can respond to using the ON SIGNAL event. For the time being all signals will be echoed to the status window so that you can see what the signals look like and choose how to respond to each one.
At the moment the bot doesn't join any channels automatically but you can make it join a channel by typing "JOIN #channel" in the debug window without the quotes.
The bot keeps a list of channels it has joined, it keeps track of its own nickname and it keeps track of a nicklist for each channel, however I have only incorporated the JOIN, PART, NICK and QUIT events for the nicklist tracking.. you will need to add support for on KICK. This is just an example bot, after all.
If you look towards the end of the script you will see how to respond to the signal events that are thrown.
For example:
elseif ($1 == IRCEVENT.PART) {
if ($trimnick($2) == $bme) hdel bot.channels $3
else hdel bot.nicklist. $+ $3 $trimnick($2)
}
; /names list.
elseif ($1 == IRCEVENT.RAW.353) {
var %hash = bot.nicklist. $+ $4
tokenize 32 $mid($5-,2)
while ($1 != $null) {
hadd -m %hash $trimstatus($1) $trimstatus($1)
tokenize 32 $2-
}
}
The first event above is the part that updates the nicklist when somebody leaves a channel.
The second event above is the part that fills the nicklist when a /names list is received back from the server (usually when you first join a channel).
Anyway, that's the example. If you're serious about making this I suggest you study the code and play around with the signals, and try to get things done. If you get stuck I'll be willing to help you with more questions but I'm not going to write the entire thing for you
Without further ado, here's the code.
alias -l err {
echo -ac info $1-
halt
}
alias -l bclose {
if ($window(@bot.debug)) echo $v1 4*** Disconnected ***
sockclose bot*
hfree -w bot*
}
alias -l trimaddress return $gettok($1,2-,33)
alias -l trimnick return $trimstatus($mid($gettok($1,1,33),2))
alias -l trimstatus return $regsubex($1,/^[@%\+]+/,)
alias test {
close -@ @bot.debug
bot debug
bot connect <your server> <your port>
}
alias -l menubchannel {
if ($istok(begin end,$1,32)) return -
var %c = $hget(bot.channels,$1).item
return %c : viewnlist %c
}
alias -l viewnlist {
var %h = bot.nicklist. $+ $1, %i = 1
echo @bot.debug 7*** Nicklist for $1:
while ($hget(%h,%i).item != $null) {
echo @bot.debug 7 $+ $v1 ( $+ $hget(%h,%i).data $+ )
inc %i
}
}
alias bchannel return $hget(bot.channels,$1).item
alias bme return $hget(bot,nick)
alias bot {
if ($1 == connect) {
if ($sock(bot)) err * /bot: already connected.
if ($0 < 3) err * /bot: insufficient parameters.
if ($3 !isnum 1-65535) err * /bot: invalid port specified.
sockopen bot $2-3
}
elseif ($istok(send sendln,$1,32)) {
if (!$sock(bot)) err * /bot: not connected.
if ($0 < 2) err * /bot: insufficient parameters.
if ($window(@bot.debug)) echo @bot.debug 5>>> $2- $+ $iif($1 == sendln,\r\n)
sockwrite $iif($1 == sendln,-n) bot $2-
}
elseif ($1 == disconnect) {
if (!$sock(bot)) err * /bot: not connected.
bclose
}
elseif ($1 == identresponse) {
if ($0 < 4) err * /bot: insufficient parameters.
if (!$sock(bot.identd.client)) err * /bot: no ident request in progress.
sockwrite -n bot.identd.client $2-3 : USERID : UNIX : $4
}
elseif ($1 == debug) && (!$window(@bot.debug)) window -e @bot.debug
}
on *:input:@bot.debug: bot sendln $1-
menu @bot.debug {
Quit: bot sendln QUIT
Disconnect: bot disconnect
View channels:{
var %i = 1
while ($hget(bot.channels,%i).item) {
tokenize 32 $1- $v1
inc %i
}
echo -a 7* ON CHANNELS: $1-
}
View nicklist
.$submenu($menubchannel($1))
}
on *:sockopen:bot:{
if ($sockerr) {
bclose
err * /bot: socket error ( $+ $sock(bot).wserr $+ : $sock(bot).wsmsg $+ )
}
socklisten bot.identd 113
.signal -n bot CONNECT
}
on *:socklisten:bot.identd: sockaccept bot.identd.client
on *:sockread:bot.identd.client:{
var %data
sockread %data
.signal -n bot IDENT %data
}
on *:sockwrite:bot.identd.client: sockclose bot.identd*
on *:sockread:bot:{
var %data
sockread %data
tokenize 32 %data
if ($window(@bot.debug)) echo @bot.debug 3<<< $1-\r\n
if ($2 isnum) {
if ($2 == 005) .signal -n bot LOGON $3-
.signal -n bot IRCEVENT.RAW. $+ $2-
}
elseif ($1 == PING) .signal -n bot IRCEVENT.PING $2-
elseif ($1 == ERROR) .signal -n bot IRCEVENT.ERROR $2-
else .signal -n bot IRCEVENT. $+ $2 $1 $3-
}
on *:sockclose:bot: bclose
on *:signal:bot:{
echo -s SIGNAL: $1-
if ($1 == IDENT) bot identresponse $2-3 bot
elseif ($1 == CONNECT) {
bot sendln NICK botty_
bot sendln USER botty_ 8 * :bot
}
elseif ($1 == LOGON) {
hadd -m bot nick $2
hadd -m bot serversupports $3-
}
elseif ($1 == IRCEVENT.PING) bot sendln PONG $2-
elseif ($1 == IRCEVENT.JOIN) {
if ($trimnick($2) == $bme) hadd -m bot.channels $mid($3,2) $ticks
else hadd -m bot.nicklist. $+ $mid($3,2) $trimnick($2) $mid($2,2)
}
elseif ($1 == IRCEVENT.NICK) {
if ($trimnick($2) == $bme) hadd -m bot nick $mid($3,2)
else {
var %i = 1, %c
while ($bchannel(%i)) {
%c = $v1
if ($hget(bot.nicklist. $+ %c,$trimnick($2))) {
hdel bot.nicklist. $+ %c $trimnick($2)
hadd -m bot.nicklist. $+ %c $mid($3,2) $+($mid($3,2),!,$trimaddress($2))
}
inc %i
}
}
}
elseif ($1 == IRCEVENT.QUIT) {
if ($trimnick($2) == $bme) bclose
else {
var %i = 1, %c
while ($bchannel(%i)) {
%c = $v1
if ($hget(bot.nicklist. $+ %c,$trimnick($2))) hdel bot.nicklist. $+ %c $trimnick($2)
inc %i
}
}
}
elseif ($1 == IRCEVENT.PART) {
if ($trimnick($2) == $bme) hdel bot.channels $3
else hdel bot.nicklist. $+ $3 $trimnick($2)
}
; /names list.
elseif ($1 == IRCEVENT.RAW.353) {
var %hash = bot.nicklist. $+ $4
tokenize 32 $mid($5-,2)
while ($1 != $null) {
hadd -m %hash $trimstatus($1) $trimstatus($1)
tokenize 32 $2-
}
}
}
Hope this helps