{"id":11,"date":"2008-09-01T10:50:48","date_gmt":"2008-09-01T16:50:48","guid":{"rendered":"http:\/\/xux.in\/blog\/post\/perl-irc-bot-goki-chanop-plugin\/"},"modified":"2008-09-22T12:33:42","modified_gmt":"2008-09-22T17:33:42","slug":"perl-irc-bot-goki-chanop-plugin","status":"publish","type":"post","link":"http:\/\/xux.in\/blog\/post\/perl-irc-bot-goki-chanop-plugin\/","title":{"rendered":"Perl IRC Bot (Goki) + ChanOp plugin"},"content":{"rendered":"<p>Goki is an IRC Bot written in perl, very easy to install, use and develop. One of the best things about Goki is it doesn&#8217;t require any additional modules, just give it a try <a href=\"http:\/\/goki.sf.net\" target=\"_blank\">http:\/\/goki.sf.net<\/a>.<\/p>\n<p>Since Goki has no authentication yet, I did a small plugin which will handle a very primitive user&#8217;s access list and a few basic channel operator&#8217;s commands, nothing more but what you are reading \ud83d\ude09<\/p>\n<p>Follow the instructions:<\/p>\n<p>&#8211; Create a file plugin\/chanop.pm (or whatever you want)<br \/>\n&#8211; Paste the following code:<\/p>\n<pre lang=\"perl\">package chanop; \r\n#use warnings; # we don't need warnings, we know it's dirty code ;) \r\n \r\n# Module wide variables \r\n \r\n# add as many nicks as you want, and remember, in order to authenticate  \r\n# you need to have the same nick name (not case sensitive) \r\nmy %chanops = ( \r\n'xUx' => '12345', \r\n'demonick' => 'demopass', \r\n'nick2' => 'somethinghere' \r\n); \r\n \r\n# careful, moving things here could make the bot crash :) \r\nmy %chdata = (); # hash that will hold all data \r\n \r\nforeach $key (sort keys %chanops) { \r\n%{$chdata{lc($key)}} = ('nick' => lc($key), 'pass' => $chanops{$key}); \r\n} \r\n \r\n# Module load functions. Set default values here. \r\nBEGIN { \r\nour $VERSION = 0.4; \r\n$irc = main::IRC; \r\n# private events \r\n$irc->add_handler('privcmd auth','do_auth'); \r\n$irc->add_handler('privcmd who','do_who'); \r\n$irc->add_handler('privcmd join','do_join'); \r\n$irc->add_handler('privcmd part','do_part'); \r\n$irc->add_handler('privcmd kick','do_kick'); \r\n$irc->add_handler('privcmd ban','do_ban'); \r\n$irc->add_handler('privcmd voice','do_voice'); \r\n$irc->add_handler('privcmd devoice','do_devoice'); \r\n$irc->add_handler('privcmd op','do_op'); \r\n$irc->add_handler('privcmd deop','do_deop'); \r\n$irc->add_handler('privcmd sh','do_sh'); \r\n$irc->add_handler('privcmd say','do_say'); \r\n} \r\n \r\nsub do_say { \r\nmy ( $nick, $hostmask, $text ) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nmy $msg = join(\" \",@args[1 .. scalar(@args)-1]); \r\nmain::plog \"Message sent from $nick to $args[0]\\n\"; \r\n$irc->say($args[0],$msg); \r\n} \r\n \r\nsub do_sh { \r\nmy ( $nick, $hostmask, $text ) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmain::plog \"Exec attempt by $nick\\n\"; \r\nmy @output = `$text`; \r\nmy $line; \r\nforeach $line (@output) { \r\n$irc->say($nick, $line); \r\n} \r\n} \r\n \r\nsub do_deop { \r\n# deop #channel nick \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Deop on $args[0] to $args[1] by $nick\\n\"; \r\n$irc->deop($args[0],$args[1]); \r\n} \r\n \r\nsub do_op { \r\n# op #channel nick \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Op on $args[0] to $args[1] by $nick\\n\"; \r\n$irc->op($args[0],$args[1]); \r\n} \r\n \r\nsub do_devoice { \r\n# devoice #channel nick \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\n$irc->devoice($args[0],$args[1]); \r\n} \r\n \r\nsub do_voice { \r\n# voice #channel nick \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Voice on $args[0] to $args[1] by $nick\\n\"; \r\n$irc->voice($args[0],$args[1]); \r\n} \r\n \r\nsub do_ban { \r\n# ban #channel nick|hostmask \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Ban on $args[0] to $args[1] by $nick\\n\"; \r\n$irc->mode($args[0],\"+b\",$args[1]); \r\n} \r\n \r\nsub do_kick { \r\n# kick #channel nick reason \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmy $reason = join(\" \",@args[2 .. scalar(@args)-1]) || $args[1]; \r\nmain::plog \"Kick on $args[0] to $args[1] ($reason) by $nick\\n\"; \r\n$irc->kick($args[0],$args[1],$reason); \r\n} \r\n \r\nsub do_part { \r\n# part #channel \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Parting $args[0] by $nick\\n\"; \r\n$irc->part($args[0]); \r\n} \r\n \r\nsub do_join { \r\n# join #channel \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nmy @args = split(\" \",$text); \r\nif ($args[0] !~ \/^\\#\/) { $args[0] = \"#\" . $args[0]; } \r\nmain::plog \"Joining $args[0] by $nick\\n\"; \r\n$irc->join($args[0]); \r\n} \r\n \r\nsub do_who { \r\nmy ($nick,$hostmask,$text) = @_; \r\nif (!&do_auth_check($nick,$hostmask)) { return; } \r\nforeach my $key (sort keys %chdata) { \r\nif (exists($chdata{$key}{'hostmask'})) { \r\n$irc->say($nick, $chdata{$key}{'nick'} . \" (\". $chdata{$key}{'hostmask'}.\")\"); \r\n} \r\n} \r\nreturn; \r\n} \r\n \r\nsub do_auth_check { \r\nmy ($nick,$hostmask) = @_; \r\nmy $tmphostmask = (split(\"\\!\",$hostmask))[1]; \r\nif (!exists($chdata{lc($nick)}{'hostmask'})) { \r\nmain::plog \"Unauthorized access from $hostmask\\n\"; \r\nreturn 0; \r\n} \r\nif ($chdata{lc($nick)}{'hostmask'} eq $tmphostmask) { return 1; } \r\nreturn 0; \r\n} \r\n \r\nsub do_auth { \r\nmy ($nick,$hostmask,$text) = @_; \r\nmy $tmphostmask = (split(\"\\!\",$hostmask))[1]; \r\nif (!exists($chdata{lc($nick)})) { \r\nmain::plog \"Invalid user tried to AUTH: $nick ($tmphostmask)\\n\"; \r\nreturn; \r\n} \r\nmy @args = split(\" \",$text); \r\nif ($chdata{lc($nick)}{'pass'} ne $args[0]) { \r\nmain::plog \"Invalid Login attemp from $nick ($tmphostmask)\\n\"; \r\n$irc->notice($nick,\"Invalid Password, attemp logged!\"); \r\nreturn; \r\n} \r\nif (exists($chdata{lc($nick)}{'hostmask'})) { \r\nmain::plog \"RE-AUTH from $nick from \".$chdata{lc($nick)}{'hostmask'}.\" to $tmphostmask\\n\"; \r\n} \r\nelse { main::plog \"AUTH from $nick from $tmphostmask\\n\"; } \r\n$chdata{lc($nick)}{'hostmask'} = $tmphostmask; \r\n$irc->notice($nick, \"Authentication Succesful!\"); \r\n} \r\n \r\nreturn 1; \r\n \r\n# Module unload functions, free memory and close open filehandles here \r\nEND { \r\n# Does not currently work, but is here for future compatibility \r\n# $irc->del_handler( '', '' ); \r\n} \r\n<\/pre>\n<p>&#8211; Edit file conf\/plugin.conf and make it load your plugin by adding a line with the word &#8220;chanop&#8221; (or the first part of your thanemayoupicked.pm)<br \/>\n&#8211; Start your bot and have fun \ud83d\ude09<\/p>\n<p>For future reference and user&#8217;s comments go to <a href=\"http:\/\/sourceforge.net\/forum\/forum.php?thread_id=2185241&#038;forum_id=621728\" target=\"_blank\">http:\/\/sourceforge.net\/forum\/forum.php?thread_id=2185241&#038;forum_id=621728<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Goki is an IRC Bot written in perl, very easy to install, use and develop. One of the best things about Goki is it doesn&#8217;t require any additional modules, just give it a try http:\/\/goki.sf.net. Since Goki has no authentication yet, I did a small plugin which will handle a very primitive user&#8217;s access list [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,8,5],"tags":[22,4,16],"class_list":["post-11","post","type-post","status-publish","format-standard","hentry","category-code","category-linux","category-software","tag-irc","tag-perl","tag-snippet"],"_links":{"self":[{"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/posts\/11","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/comments?post=11"}],"version-history":[{"count":2,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/posts\/11\/revisions"}],"predecessor-version":[{"id":31,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/posts\/11\/revisions\/31"}],"wp:attachment":[{"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/media?parent=11"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/categories?post=11"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/xux.in\/blog\/wp-json\/wp\/v2\/tags?post=11"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}