Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jul 7th, 2013  |  syntax: Perl  |  size: 20.56 KB  |  views: 31  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/perl -w
  2. use strict;
  3. use feature "state";
  4. use Data::Dumper;
  5. use Storable;
  6. use DateTime;
  7. use Switch;
  8. use Time::Format;
  9. use WebService::GData::YouTube;
  10. use LWP::Simple;
  11. use Data::Validate::URI qw(is_web_uri);
  12. use POE;
  13. use POE::Component::IRC;
  14. use POE::Component::IRC::Plugin::Console;
  15. use POE::Component::IRC::Plugin::NickServID;
  16. use POE::Component::IRC::Plugin::BotAddressed;
  17. use POE::Component::IRC::Plugin::Logger;
  18. use WWW::Wikipedia;
  19. use WWW::YouTube::Info;
  20. use Google::Search;
  21. use DBI;
  22.  
  23. my $dbh = DBI->connect("dbi:SQLite:dbname=raven.db","","") or die $DBI::errstr;
  24. my @tables = $dbh->tables();
  25. my @help = (
  26.         ['.8ball','Predict the future with yes/no questions. - ex. .8ball Is Raven awesome?'],
  27.         ['.tell','Leave a message for a user - ex. .tell user The server is down again.'],
  28.         ['.google','Search Google and return the first result'],
  29.         ['.youtube','Search YouTube and return the first result'],
  30.         ['.wiki','Search for a wiki on the selected topic'],
  31.         ['.down','Check if a website is down.'],
  32.         ['.quote','Record or play back a quote. ".quote" random quote from any user, ".quote user" random quote for the user, ".quote user Message to be quoted" save a new quote'],
  33.         ['.info','Record or play back stored info'],
  34.         ['.define','Look up a definition of a word'],
  35.         ['.urban','Search the Urban Dictionary'],
  36.         ['.devbukkit','Search dev.bukkit.org for plugins'],
  37.         ['.seen','Show last activity for a user'],
  38. );
  39. my @ophelp = (
  40.         ['join','Join a channel'],
  41.         ['part','Leave a channel'],
  42.         ['op','Add an op'],
  43.         ['deop','Remove an op'],
  44.         ['speakas','Make the bot say something in a channel or to a user - ex. /msg RavenBot #MyChannel What are you doing, Dave?'],
  45.         ['emoteas','Make the bot perform a CTCP ACTION [/me] in a channel or to a user chat'],
  46.         ['shutdown','Terminate the bot'],
  47. );
  48.  
  49. my $URLValidator = Data::Validate::URI->new();
  50. # Create tables (if they don't exist)
  51. $dbh->do("CREATE TABLE IF NOT EXISTS Channels(name)");
  52. $dbh->do("CREATE TABLE IF NOT EXISTS Ops(name)");
  53. $dbh->do("CREATE TABLE IF NOT EXISTS Tells(sender, rcpt, channel, message)");
  54. $dbh->do("CREATE TABLE IF NOT EXISTS Info(key PRIMARY KEY, data)");
  55. $dbh->do("CREATE TABLE IF NOT EXISTS Quotes(user, data)");
  56. $dbh->do("CREATE TABLE IF NOT EXISTS LastSeen(user PRIMARY KEY, timestamp)");
  57. # Prepare Database statements
  58. my $addQuote = $dbh->prepare("INSERT INTO Quotes(user, data) VALUES (?, ?);");
  59. my $getUserQuote = $dbh->prepare("SELECT data FROM Quotes WHERE user = ? ORDER BY RANDOM () LIMIT 1;");
  60. my $getAnyQuote = $dbh->prepare("SELECT user, data FROM Quotes ORDER BY RANDOM () LIMIT 1;");
  61. my $updateLastSeen = $dbh->prepare("REPLACE INTO LastSeen(user, timestamp) VALUES (?, ?);");
  62. my $getLastSeen = $dbh->prepare("SELECT timestamp FROM LastSeen WHERE user = ?;");
  63. my $updateInfo = $dbh->prepare("REPLACE INTO Info(key, data) VALUES (?, ?);");
  64. my $getInfo = $dbh->prepare("SELECT data FROM Info WHERE key = ?;");
  65. my $addTell = $dbh->prepare("INSERT INTO Tells(sender, rcpt, channel, message) VALUES (?, ?, ?, ?);");
  66. my $getTells = $dbh->prepare("SELECT rowid, sender, channel, message FROM Tells WHERE rcpt = ?;");
  67. my $removeTells = $dbh->prepare("DELETE FROM Tells WHERE rcpt = ?;");
  68. my $addChannel = $dbh->prepare("REPLACE INTO Channels (name) VALUES (?);");
  69. my $removeChannel = $dbh->prepare("DELETE FROM Channels WHERE name = ?;");
  70. my $addOp = $dbh->prepare("REPLACE INTO Ops (name) VALUES (?);");
  71. my $removeOp = $dbh->prepare("DELETE FROM Ops WHERE name = ?;");
  72. # Finished setup
  73.  
  74. # Color contants
  75. my $WHITE = "\x0300";
  76. my $BLACK = "\x0301";
  77. my $BLUE = "\x0302";
  78. my $GREEN = "\x0303";
  79. my $RED = "\x0304";
  80. my $BROWN = "\x0305";
  81. my $PURPLE = "\x0306";
  82. my $ORANGE = "\x0307";
  83. my $YELLOW = "\x0308";
  84. my $LIGHT_GREEN = "\x0309";
  85. my $TEAL = "\x0310";
  86. my $LIGHT_CYAN = "\x0311";
  87. my $LIGHT_BLUE = "\x0312";
  88. my $PINK = "\x0313";
  89. my $GREY = "\x0314";
  90. my $LIGHT_GREY = "\x0315";
  91. my $NORMAL = "\x0f";
  92.  
  93. my @magic8ball = (
  94.         qq<$GREEN Signs point to yes.>,
  95.         qq<$GREEN Yes.>,
  96.         qq<$YELLOW Reply hazy, try again.>,
  97.         qq<$GREEN Without a doubt.>,
  98.         qq<$RED My sources say no.>,
  99.         qq<$GREEN As I see it, yes.>,
  100.         qq<$GREEN You may rely on it.>,
  101.         qq<$YELLOW Concentrate and ask again.>,
  102.         qq<$RED Outlook not so good.>,
  103.         qq<$GREEN It is decidedly so.>,
  104.         qq<$YELLOW Better not tell you now.>,
  105.         qq<$RED Very doubtful.>,
  106.         qq<$GREEN Yes - definitely.>,
  107.         qq<$GREEN It is certain.>,
  108.         qq<$YELLOW Cannot predict now.>,
  109.         qq<$GREEN Most likely.>,
  110.         qq<$YELLOW Ask again later.>,
  111.         qq<$RED My reply is no.>,
  112.         qq<$GREEN Outlook good.>,
  113.         qq<$RED Do not count on it.>,
  114. );
  115.  
  116. my ($irc) = POE::Component::IRC->spawn();
  117. my @channels = &LoadChannels;
  118. my @ops = &LoadOps;
  119.  
  120. POE::Session->create(
  121.         inline_states => {
  122.                 _start => \&bot_start,
  123.                 irc_001 => \&on_connect,
  124.                 irc_public => \&on_public,
  125.                 irc_msg => \&on_private,
  126.                 irc_join => \&on_join,
  127.                 irc_bot_mentioned => \&on_mention,
  128.                 irc_kick => \&on_kick,
  129.                 irc_disconnected => \&on_disconnect,
  130.         },
  131. );
  132.  
  133. sub bot_start {
  134.         $irc->yield(register => "all");
  135.         my $nick = "RavenBot";
  136.         $irc->yield(connect => {
  137.                         Nick => $nick,
  138.                         Username => 'ravenbot',
  139.                         Ircname => q{MCPortCentral's RavenBot},
  140.                         Server => 'irc.esper.net',
  141.                         Port => '6667',
  142.                         Flood => 'true',
  143.                 }
  144.         );
  145. #$irc->plugin_add( 'Console', POE::Component::IRC::Plugin::Console->new( bindport => 1234, password => 'test' ));
  146.         $irc->plugin_add( 'NickServID', POE::Component::IRC::Plugin::NickServID->new( Password => 'Raven!@)(' ) );
  147.         $irc->plugin_add( 'BotAddressed', POE::Component::IRC::Plugin::BotAddressed->new() );
  148.         $irc->plugin_add( 'Logger', POE::Component::IRC::Plugin::Logger->new( Path => '/opt/RavenBot/ravenbot/logs', DCC => 0, Private => 1, Public => 1, ) );
  149. }
  150.  
  151. sub on_connect {
  152.         $irc->yield(join => $_) for @channels;
  153.         return;
  154. }
  155.  
  156. sub on_disconnect {
  157.         &bot_start;    
  158.         return;
  159. }
  160.  
  161. sub on_public {
  162.         my ($kernel, $who, $where, $msg) = @_[KERNEL, ARG0, ARG1, ARG2];
  163.         my $nick = (split /!/, $who)[0];
  164.         my $channel = $where->[0];
  165.         my $dt = DateTime->now( time_zone=> 'UTC' );
  166.         my $ts = $dt->epoch;
  167.         my $isOp = 0;
  168.         if ($msg =~ /youtube\.com/) {
  169.                 my @matches = ($msg =~ m/v\=.*/g);
  170.                 my $videoid = substr($matches[0],2,11);
  171.                 my $yt = new WebService::GData::YouTube();
  172.                 $yt->query->q($videoid)->limit(1,0);
  173.                 my $videos = $yt->search_video();
  174.                 if (!(defined $videos)) { return }
  175.                 my $length = $$videos[0]->{_feed}{'media$group'}{'yt$duration'}{'seconds'};
  176.                 my $time = &ConvertFromSeconds($length);
  177.                 my $url = $$videos[0]->{_feed}{link}[0]{href};
  178.                 $url =~ s/\&feature=youtube_gdata//g;
  179.                 my $uploader = $$videos[0]->{_feed}{'media$group'}{'media$credit'}[0]{'yt$display'};
  180.                 my $uploadedon = substr($$videos[0]->{_feed}{'media$group'}{'yt$uploaded'}{text}, 0, 10);
  181.                 my $views = &AddCommas($$videos[0]->{_feed}{'yt$statistics'}{viewCount});
  182.                 eval{ $irc->yield(privmsg => $channel, $nick . qq<: \x02> . $$videos[0]->title . qq<\x02 - length: \x02> . $time . qq<\x02 - > . $url . qq< - \x02> . $views  . qq<\x02 views - uploaded by: \x02> . $uploader . qq<\x02 on \x02> . $uploadedon . qq<\x02> ); };
  183.                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  184.         }
  185.         foreach (@ops) {
  186.                 if ( $nick eq $_ ) { $isOp = 1; }
  187.         }
  188.         $getTells->execute($nick);
  189.         while (my $row = $getTells->fetchrow_hashref){
  190.                 $irc->yield(notice => $nick, $$row{'sender'} . ' in ' . $$row{'channel'} . '> ' . $$row{'message'});
  191.                 $dbh->do("DELETE FROM Tells where rowid = " . $$row{'rowid'} . ";");
  192.         }
  193.         $updateLastSeen->execute($nick, $ts);
  194.         if ($msg =~ /^\./) {
  195.                 my ($command, @cmdargs) = (split / /, $msg);
  196.                 switch ($command)
  197.                 {
  198.                         case '.8ball' {
  199.                                 my $response = $magic8ball[rand @magic8ball];
  200.                                 my $question = "";
  201.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  202.                                         $question .= $cmdargs[$i] . " ";
  203.                                 }
  204.                                 chop($question);
  205.                                 $irc->yield(privmsg => $channel, $nick . q< asked "> . $question . q<" - > . $response);
  206.                         }
  207.                         case /\.t($|ell$)/ {
  208.                                 my $numArgs = @cmdargs;
  209.                                 if ($numArgs == 0) {
  210.                                         $irc->yield(privmsg => $channel, qq<$nick: Who did you want to tell and what?>);
  211.                                         return;
  212.                                 }
  213.                                 if ($numArgs == 1) {
  214.                                         $irc->yield(privmsg => $channel, qq<$nick: What did you want to tell that user?>);
  215.                                 } else {
  216.                                         my $rcpt = $cmdargs[0];
  217.                                         my $msg = "";
  218.                                         for (my $i =1; $i <= $#cmdargs; $i++) {
  219.                                                 $msg .= $cmdargs[$i] . " ";
  220.                                         }
  221.                                         chop($msg);
  222.                                         $addTell->execute($nick, $rcpt, $channel, $msg);
  223.                                         $irc->yield(privmsg => $channel, qq<$nick: \x02$rcpt\x02 will be notified on their next activity.>);
  224.                                 }
  225.                         }
  226.                         case /\.g($|oogle$)/ {
  227.                                 my $query = "";
  228.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  229.                                         $query .= $cmdargs[$i] . " ";
  230.                                 }
  231.                                 chop($query);
  232.                                 my $search = Google::Search->Web( query => $query );
  233.                                 eval{
  234.                                         my $result = $search->first;
  235.                                         my $content;
  236.                                         if (defined $result) {
  237.                                                 $content = $result->content;
  238.                                         } else {
  239.                                                 $content = "No results found";
  240.                                         }
  241.                                         $content =~ s|<.+?>||g;
  242.                                         $irc->yield(privmsg => $channel, $nick . q<: > . $result->unescapedUrl . qq< - \x02> . $result->titleNoFormatting . qq<\x02: "> . $content . q<">);
  243.                                 };
  244.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  245.                         }
  246.                         case /\.(yt$|youtube$)/ {
  247.                                 my $yt = new WebService::GData::YouTube();
  248.                                 my $query = "";
  249.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  250.                                         $query .= $cmdargs[$i] . " ";
  251.                                 }
  252.                                 chop($query);
  253.                                 eval{
  254.                                         $yt->query->q($query)->limit(1,0);
  255.                                         my $videos = $yt->search_video();
  256.                                         my $length = $$videos[0]->{_feed}{'media$group'}{'yt$duration'}{'seconds'};
  257.                                         my $time = &ConvertFromSeconds($length);
  258.                                         my $url = $$videos[0]->{_feed}{link}[0]{href};
  259.                                         $url =~ s/\&feature=youtube_gdata//g;
  260.                                         my $uploader = $$videos[0]->{_feed}{'media$group'}{'media$credit'}[0]{'yt$display'};
  261.                                         my $uploadedon = substr($$videos[0]->{_feed}{'media$group'}{'yt$uploaded'}{text}, 0, 10);
  262.                                         my $views = &AddCommas($$videos[0]->{_feed}{'yt$statistics'}{viewCount});
  263.                                         $irc->yield(privmsg => $channel, $nick . qq<: \x02> . $$videos[0]->title . qq<\x02 - length: \x02> . $time . qq<\x02 - > . $url . qq< - \x02> . $views  . qq<\x02 views - uploaded by: \x02> . $uploader . qq<\x02 on \x02> . $uploadedon . qq<\x02> );
  264.                                 };
  265.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  266.                         }
  267.                         case ".wiki" {
  268.                                 my $query = "wiki ";
  269.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  270.                                         $query .= $cmdargs[$i] . " ";
  271.                                 }
  272.                                 chop($query);
  273.                                 eval{
  274.                                         my $search = Google::Search->Web( query => $query );
  275.                                         my $result = $search->first;
  276.                                         my $content = $result->content;
  277.                                         $content =~ s|<.+?>||g;
  278.                                         $irc->yield(privmsg => $channel, $nick . q<: > . $result->unescapedUrl . qq< - \x02> . $result->titleNoFormatting . qq<\x02: "> . $content . q<">);
  279.                                 };
  280.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  281.                         }                      
  282.                         case ".down" {
  283.                                 my $url = $cmdargs[0];
  284.                                 if ($URLValidator->is_web_uri( $url )) {
  285.                                         my $status = "";
  286.                                         if (! head($url) ){
  287.                                                 $status = "$url appears to be " . $RED . "down" . $NORMAL . "!";
  288.                                         } else {
  289.                                                 $status = "$url appears to be " . $GREEN . "up" . $NORMAL . "!";
  290.                                         }
  291.                                         $irc->yield(privmsg => $channel, $nick . qq<: $status>);
  292.                                 } else {
  293.                                         $irc->yield(privmsg => $channel, $nick . qq<: $url does not appear to be a valid URL.>);
  294.                                 }
  295.                         }
  296.                         case /\.q($|uote$)/ {
  297.                                 my $numArgs = @cmdargs;
  298.                                 if ($numArgs == 0) {
  299.                                         $getAnyQuote->execute;
  300.                                         my $result = $getAnyQuote->fetchrow_hashref;
  301.                                         $irc->yield(privmsg => $channel, '<' . $$result{'user'} . '> ' . $$result{'data'});
  302.                                         return;
  303.                                 }
  304.                                 if ($numArgs == 1) {
  305.                                         $getUserQuote->execute($cmdargs[0]);
  306.                                         my $result = $getUserQuote->fetch;
  307.                                         if (!(defined $result)) {
  308.                                                 $irc->yield(privmsg => $channel, 'No quotes found for ' . $cmdargs[0] . '.');
  309.                                                 return;
  310.                                         }
  311.                                         $irc->yield(privmsg => $channel, '<' . $cmdargs[0] . '> ' . $$result[0]);
  312.                                 } else {
  313.                                         my $user = $cmdargs[0];
  314.                                         my $quote = "";
  315.                                         for (my $i =1; $i <= $#cmdargs; $i++) {
  316.                                                 $quote .= $cmdargs[$i] . " ";
  317.                                         }
  318.                                         chop($quote);
  319.                                         $addQuote->execute($user, $quote);
  320.                                         $irc->yield(privmsg => $channel, qq<$nick: Quote added to database.>);
  321.                                 }
  322.                         }
  323.                         case /\.i($|nfo$)/ {
  324.                                 my $numArgs = @cmdargs;
  325.                                 if ($numArgs == 0) {
  326.                                         $irc->yield(privmsg => $channel, qq<$nick: No key specified.>);
  327.                                         return;
  328.                                 }
  329.                                 if ($numArgs == 1) {
  330.                                         $getInfo->execute($cmdargs[0]);
  331.                                         my $result = $getInfo->fetch;
  332.                                         $irc->yield(privmsg => $channel, qq<\x02> . $cmdargs[0] . qq<\x02 - > . $$result[0]);
  333.                                 } else {
  334.                                         my $key = $cmdargs[0];
  335.                                         my $data = "";
  336.                                         for (my $i = 1; $i <= $#cmdargs; $i++) {
  337.                                                 $data .= $cmdargs[$i] . " ";
  338.                                         }
  339.                                         chop($data);
  340.                                         $updateInfo->execute($key, $data);
  341.                                         $irc->yield(privmsg => $channel, qq<$nick: Value set.>);
  342.                                 }
  343.                         }
  344.                         case ".define" {
  345.                                 my $query = "define:";
  346.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  347.                                         $query .= $cmdargs[$i] . " ";
  348.                                 }
  349.                                 chop($query);
  350.                                 eval{
  351.                                         my $search = Google::Search->Web( query => $query );
  352.                                         my $result = $search->first;
  353. #print Dumper($result);
  354.                                         my $content = $result->content;
  355.                                         $content =~ s|<.+?>||g;
  356.                                         $irc->yield(privmsg => $channel, $nick . q<: > . $result->unescapedUrl . qq< - \x02> . $result->titleNoFormatting . qq<\x02: "> . $content . q<">);
  357.                                 };
  358.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  359.                         }
  360.                         case ".urban" {
  361.                                 my $query = "site:urbandictionary.com ";
  362.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  363.                                         $query .= $cmdargs[$i] . " ";
  364.                                 }
  365.                                 chop($query);
  366.                                 eval{
  367.                                         my $search = Google::Search->Web( query => $query );
  368.                                         my $result = $search->first;
  369.                                         my $content = $result->content;
  370.                                         $content =~ s|<.+?>||g;
  371.                                         $irc->yield(privmsg => $channel, $nick . q<: > . $result->unescapedUrl . qq< - \x02> . $result->titleNoFormatting . qq<\x02: "> . $content . q<">);
  372.                                 };
  373.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  374.                         }
  375.                         case /.(db$|devbukkit$)/ {
  376.                                 my $query = "site:dev.bukkit.org ";
  377.                                 for (my $i = 0; $i <= $#cmdargs; $i++) {
  378.                                         $query .= $cmdargs[$i] . " ";
  379.                                 }
  380.                                 chop($query);
  381.                                 my $search = Google::Search->Web( query => $query );
  382.                                 eval{
  383.                                         my $result = $search->first;
  384.                                         my $content;
  385.                                         if (defined $result) {
  386.                                                 $content = $result->content;
  387.                                         } else {
  388.                                                 $content = "No results found";
  389.                                         }
  390.                                         $content =~ s|<.+?>||g;
  391.                                         $irc->yield(privmsg => $channel, $nick . q<: > . $result->unescapedUrl . qq< - \x02> . $result->titleNoFormatting . qq<\x02: "> . $content . q<">);
  392.                                 };
  393.                                 $irc->yield(privmsg => $channel, $nick . qq<: Error while finding information>) if $@;
  394.                         }
  395.                         case ".seen" {
  396.                                 my $numArgs = @cmdargs;
  397.                                 if ($numArgs >= 1) {
  398.                                         my $user = $cmdargs[0];
  399.                                         $getLastSeen->execute($user);
  400.                                         my $result = $getLastSeen->fetch;
  401.                                         if (!(defined $result)){
  402.                                                 $irc->yield(privmsg => $channel, qq<\x02$user\x02 does not have any known activity.>);
  403.                                                 return;
  404.                                         }
  405.                                         my $time = $$result[0];
  406.                                         my $lastseen = DateTime->from_epoch ( epoch => $time );
  407.                                         my $lsmsg = $lastseen->day . '-' . $lastseen->month_abbr . '-' . $lastseen->year . ' ' . $lastseen->hms . ' UTC';
  408.                                         my $duration = &ConvertFromSeconds(($ts - $time));
  409.                                         $irc->yield(privmsg => $channel, qq<\x02$user\x02 was last seen $lsmsg ($duration ago).>);
  410.                                 }
  411.                         }
  412.                         case /.(brainfuck$|bf$)/ {
  413.                                 $irc->yield(privmsg => $channel, qq<\x02$nick\x02 No esoteric programming languages allowed.>);
  414.                         }
  415.                         case /.help$/ {
  416.                                 for (my $i = 0; $i <= $#help; $i++) {
  417.                                         $irc->yield(notice => $nick, $help[$i][0] . ' - ' . $help[$i][1]);
  418.                                 }
  419.                         }
  420.                 }
  421.         }
  422.         return;
  423. }
  424.  
  425. sub on_private {
  426.         my ($kernel, $from, $to, $msg, $identified) = @_[KERNEL, ARG0, ARG1, ARG2, ARG3];
  427.         my $nick = (split /!/, $from)[0];
  428.         my ($command, @cmdargs) = (split / /, $msg);
  429.         my $isOp = 0;
  430.         foreach (@ops) {
  431.                 if ( $nick eq $_ ) { $isOp = 1; }
  432.         }
  433.         switch ($command) {
  434.                 case 'tables' {
  435.                         if ($isOp == 1) {
  436.                                 $irc->yield(privmsg => $nick, @tables);
  437.                         } else {
  438.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  439.                         }
  440.                 }
  441.                 case 'emoteas' {
  442.                         if ($isOp == 1) {
  443.                                 my $response;
  444.                                 for (my $i = 1; $i <= $#cmdargs; $i++) {
  445.                                         $response .= $cmdargs[$i] . " ";
  446.                                 }
  447.                                 $irc->yield(ctcp => $cmdargs[0], qq<ACTION $response>);
  448.                                 $irc->yield(privmsg => $nick, "Sent!");
  449.                         } else {
  450.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  451.                         }
  452.                 }
  453.                 case 'speakas' {
  454.                         if ($isOp == 1) {
  455.                                 my $response;
  456.                                 for (my $i = 1; $i <= $#cmdargs; $i++) {
  457.                                         $response .= $cmdargs[$i] . " ";
  458.                                 }
  459.                                 $irc->yield(privmsg => $cmdargs[0], $response);
  460.                                 $irc->yield(privmsg => $nick, "Sent!");
  461.                         } else {
  462.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  463.                         }
  464.                 }
  465.                 case 'join' {
  466.                         if ($isOp == 1) {
  467.                                 $irc->yield(join => $cmdargs[0]);
  468.                                 $addChannel->execute($cmdargs[0]);
  469.                         } else {
  470.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  471.                         }
  472.                 }
  473.                 case 'part' {
  474.                         if ($isOp == 1) {
  475.                                 $irc->yield(part => $cmdargs[0]);
  476.                                 $removeChannel->execute($cmdargs[0]);
  477.                         } else {
  478.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  479.                         }
  480.                 }
  481.                 case 'op' {
  482.                         if ($isOp == 1) {
  483.                                 push(@ops, $cmdargs[0]);
  484.                                 $addOp->execute($cmdargs[0]);
  485.                                 $irc->yield(privmsg => $nick, "You have granted op to $cmdargs[0].");
  486.                         } else {
  487.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  488.                         }
  489.                 }
  490.                 case 'deop' {
  491.                         if ($isOp == 1) {
  492.                                 my $index = &Find($cmdargs[0], @ops);
  493.                                 delete $ops[$index];
  494.                                 $removeOp->execute($cmdargs[0]);
  495.                                 $irc->yield(privmsg => $nick, "You have removed op from $cmdargs[0].");
  496.                         } else {
  497.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  498.                         }
  499.                 }
  500.                 case 'shutdown' {
  501.                         if ($isOp == 1) {
  502.                                 $irc->yield(quit => "Nevermore!");
  503.                                 $irc->yield(shutdown => "");
  504.                         } else {
  505.                                 $irc->yield(privmsg => $nick, "You cannot do that.");
  506.                         }
  507.                 }
  508.                 case 'help' {
  509.                         for (my $i = 0; $i <= $#ophelp; $i++) {
  510.                                 $irc->yield(privmsg => $nick, $ophelp[$i][0] . ' - ' . $ophelp[$i][1]);
  511.                         }
  512.                 }
  513.                 else {
  514.                         $irc->yield(privmsg => $nick, "I don't recognize that.");
  515.                 }
  516.         }
  517.         return;
  518. }
  519.  
  520. sub on_join {
  521.  
  522.         return;
  523. }
  524.  
  525. sub on_mention {
  526.         state $lastCall = 0;
  527.         my ($kernel, $who, $where, $msg) = @_[KERNEL, ARG0, ARG1, ARG2];
  528.         my $nick = (split /!/, $who)[0];
  529.         my $channel = $where->[0];
  530.         my $ts = DateTime->now( time_zone => 'UTC' );
  531.         if ($ts->epoch >= ($lastCall + 60) && !($msg =~ /^[\.<]/)) {
  532.                 $irc->yield(ctcp => $channel, "ACTION senses someone talking about it.");
  533.                 $lastCall = $ts->epoch;
  534.         }
  535.         return;
  536. }
  537.  
  538. sub on_kick {
  539.         my ($kernel, $kicker, $where, $kickee, $why) = @_[KERNEL, ARG0, ARG1, ARG2, ARG3];
  540.         my $nick = (split /!/, $kickee)[0];
  541.         my $channel = $where;
  542.         $irc->yield(privmsg => $channel, "Meh...  I didn't like them anyway. :P");
  543.         return;
  544. }
  545.  
  546. sub irc_console_connect {
  547.         my ($peeradr, $peerport, $wheel_id) = @_[ARG0 .. ARG2];
  548.         return;
  549. }
  550.  
  551. sub irc_console_authed {
  552.         my $wheel_id = $_[ARG0];
  553.         return;
  554. }
  555.  
  556. sub irc_console_close {
  557.         my $wheel_id = $_[ARG0];
  558.         return;
  559. }
  560.  
  561. sub irc_console_rw_fail {
  562.         my ($peeradr, $peerport) = @_[ARG0, ARG1];
  563.         return;
  564. }
  565.  
  566. $poe_kernel->run();
  567. exit 0;
  568.  
  569. sub LoadOps {
  570.         my $results = $dbh->selectall_arrayref("SELECT name FROM Ops;", { Slice => {} });
  571.         my @ops;
  572.         foreach my $entry ( @$results ) {
  573.                 push(@ops, $entry->{name});
  574.         }
  575.         if (!(@ops)) {
  576.                 print "No ops defined.  Please enter name of first op: ";
  577.                 my $firstop = <>;
  578.                 chomp($firstop);
  579.                 push(@ops, $firstop);
  580.         }
  581.         return @ops;
  582. }
  583.  
  584. sub LoadChannels {
  585.         my $results = $dbh->selectall_arrayref("SELECT name FROM Channels;", { Slice => {} });
  586.         my @channels;
  587.         foreach my $entry ( @$results ) {
  588.                 push (@channels, $entry->{name});
  589.         }
  590.         return @channels;
  591. }
  592.  
  593. sub Find($@) {
  594.         my $s = shift;
  595.         $_ eq $s && return @_ while $_=pop;
  596.         -1;
  597. }
  598.  
  599. sub AddCommas {
  600.         local $_ = shift;
  601.         1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
  602.         return $_;
  603. }
  604.  
  605. sub ConvertFromSeconds {
  606.         my $seconds = $_[0];
  607.         my $days = "";
  608.         my $hours = "";
  609.         my $minutes = "";
  610.         if ($seconds > 86400) {
  611.                 $days = int($seconds / 86400) . "d ";
  612.                 $seconds = $seconds % 86400;
  613.         } else {
  614.                 $days = "";
  615.         }
  616.         if ($seconds > 3600) {
  617.                 $hours = int($seconds / 3600) . "h ";
  618.                 $seconds = $seconds % 3600;
  619.         } else {
  620.                 $hours = "";
  621.         }
  622.         if ($seconds > 60) {
  623.                 $minutes = int($seconds / 60) . "m ";
  624.                 $seconds = $seconds % 60;
  625.         } else {
  626.                 $minutes = "";
  627.         }
  628.         if ($seconds > 0) {
  629.                 $seconds .= "s"
  630.         } else {
  631.                 $seconds = "0s";
  632.         }
  633.  
  634.         return ($days . $hours . $minutes . $seconds);
  635. }