package UDPBot; # Package for CCR bots that do UDP. Implements one standard UDP protocol. # Variables: # UDPmsg parsed udp message (set in doInput()) # UDPAliases hash table mapping aliases -> object names # version version of your own bot: used for ping/pong # Functions # lookupUDPAlias return the object of the given alias # addUDPAlias add an alias # removeUDPAlias remove an alias. # sendMessageToObject lowest level UDP send, to object # sendMessageToAlias sends message to alias/object. # emitAliases emit the alias database # pingAlias send a ping to an alias # pongAlias send a pong to an alias (not usually by hand) use TalkBot; @ISA = qw(TalkBot); @EXPORT = (@TalkBot::EXPORT, qw(%UDPAliases %UDPmsg $version lookupUDPAlias addUDPAlias removeUDPAlias sendMessageToObject sendMessageToAlias emitAliases pingAlias pongAlias)); %UDPAliases = {}; %UDPmsg = {}; $version = 'unset version string'; # lookupUDPAlias(aliasname) # downcase the string. sub lookupUDPAlias { my $key = $_[0]; $key =~ tr/A-Z/a-z/; return $UDPAliases{$key}; } # addAlias(aliasname, objectname) sub addUDPAlias { my $key = $_[0]; $key =~ tr/A-Z/a-z/; $UDPAliases{$key} = $_[1]; } sub removeUDPAlias { my $key = $_[0]; $key =~ tr/A-Z/a-z/; if ($UDPAliases{$key}) { delete $UDPAliases{$key}; return 1; } else { return 0; } } # sendTextToObject(objid, message) # this is the lowlevel UDP send. Note that we just send it off and don't # worry about whether it got there - not robust at all. sub sendMessageToObject { ccrl("[udpsend at \"$_[1]\" to $_[0]]"); } # sendTextToAlias(alias, message) # alias is either a :objid, or else it is interpreted as an alias. # returns 1 if the destination was resolvable, 0 if not. sub sendMessageToAlias { $dest = $_[0]; $message = $_[1]; if ($dest =~ /^:/) { # object id? sendMessageToObject($dest, $message); return 1; } elsif ($objId = lookupUDPAlias($dest)) { sendMessageToObject($objId, $message); return 1; } else { return undef; } } # Print out the alias database. # Thanks to adam for pointing out how to do keys. sub emitAliases { foreach $s (keys(%UDPAliases)) { ::emit("$s => $UDPAliases{$s}"); } 1; } # base UDP protocol support - pings. # pingAlias(alias, sender name) sub pingAlias { if (sendMessageToAlias($_[0], "bu ping ($_[1]) ($version)")) { } else { ::emit("Failed to ping $_[0]"); } 1; } # pongAlias(alias, sender name) sub pongAlias { if (sendMessageToAlias($_[0], "bu pong ($_[1]) ($version)")) { } else { ::emit("Failed to pong $_[0]"); } 1; } # what to do when a ping is received - speak it out, and pong. sub handlePingBaseUDP { ::emit("$1 pinged me from $UDPmsg{From} ($2). Responding."); pongAlias($UDPmsg{From}, $name); 1; } # what to do when a pong is received - speak it out. sub handlePongBaseUDP { ::emit("Received pong from $UDPmsg{From} ($1 $2)."); 1; } # This table defines the "base UDP" protocol - ping and pong, right now. e.g. # bu ping (:nelson) (radio 0.4) # bu pong (:radio) (radio 0.4) %funcs = ('^bu ping \(([^\)]*)\) \(([^\)]*)\)$' => \&handlePingBaseUDP, '^bu pong \(([^\)]*)\) \(([^\)]*)\)$' => \&handlePongBaseUDP ); $baseUDPFunctions = \%funcs; # override TalkBot::doInput(). If the thing we've received is a UDPmsg, # parse it into UDPmsg. Furthermore, if it matches /^bu /, then handle # it via the baseUDP protocol. sub doInput { my ($rv, $foo); $rv = TalkBot::doInput(); # return value. if ($rv eq '/UDPReceive' && # UDP message for us $args{Object} =~ /$ccrName/i) { ($foo, %UDPmsg) = parseccrl($args{Message}); if ($UDPmsg{Data} =~ /^bu /) { # base UDP protocol if (!ApplyTable::applytable($UDPmsg{Data}, $baseUDPFunctions)) { ::emit("Unknown base UDP command ::$UDPmsg{Data}::"); } return '/Handled'; } else { # some other UDP msg, return $rv; # just return. } } else { # not a UDP msg, so return $rv; # just return. }; } 1;