Diff for /ChivanetConvoBot/convobot between versions 1.3 and 1.6

version 1.3, 2025/02/03 15:38:12 version 1.6, 2025/02/05 01:03:18
Line 9 Line 9
 # Licensed AGPL-3.0  # Licensed AGPL-3.0
 #  #
 # $Log$  # $Log$
   # Revision 1.6  2025/02/05 01:03:18  snw
   # Fix invite and seen commands to support screen names with spaces
   #
   # Revision 1.5  2025/02/03 18:14:15  snw
   # Further work on bot
   #
   # Revision 1.4  2025/02/03 17:31:28  snw
   # Further MySQL work
   #
 # Revision 1.3  2025/02/03 15:38:12  snw  # Revision 1.3  2025/02/03 15:38:12  snw
 # Begin SQL work  # Begin SQL work
 #  #
Line 38  my $dbname = ''; Line 47  my $dbname = '';
 my $dbusername = '';  my $dbusername = '';
 my $dbpw = '';  my $dbpw = '';
 my $dbconn = '';  my $dbconn = '';
   my $autogreet = 'off';
   
 my $chatroom = '';  my $chatroom = '';
 my $online = 0;  my $online = 0;
 my $chat_idle_seconds = 0;  my $chat_idle_seconds = 0;
 my $last_chat_received = time();  my $last_chat_received = time();
 my $start_time = time();  my $start_time = time();
   my $dbh = '';
   my $dsn = '';
   
 my @congregants = ();  my @congregants = ();
 my %seen = ();  
   
 GetOptions("aimsn=s" => \$botsn,  
            "aimhost=s" => \$botsrv,  
            "aimpw=s" => \$botpw,  
            "idlemax=s" => \$idlemax,  
            "chatroom=s" => \$chatroom,  
            "dbhost=s" => \$dbhost,  
            "dbname=s" => \$dbname,  
            "dbusername=s" => \$dbusername,  
            "dbpw=s" => \$dbpw);  
             or die("error in command line arguments");  
   
 %signon = (  
     screenname => $botsn,  
     password => $botpw,  
     host => $botsrv,  
 );   
   
 $oscar = Net::OSCAR->new();  $oscar = Net::OSCAR->new();
 my $dbh = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost",  
                        "$dbusername", "$dbpw",  
                        {'RaiseError' => 1});  
   
 sub get_seen_status {  sub get_seen_status {
       my($sn, $chat) = @_;
   
       my $sth = $dbh->prepare("SELECT * FROM seen WHERE aim_server=? AND aim_sn=? AND aim_chatroom=? AND sn=?");
       $sth->execute($botsrv, $botsn, $chatroom, $sn);
   
       if($sth->rows > 0) {
           my $hashref = $sth->fetchrow_hashref();
           $chat->chat_send("I last saw <strong>$sn</strong> on $hashref->{seen_time}.");
       }
       else {
           $chat->chat_send("I have never seen <strong>$sn</strong>.");
       }
       
   }
   
   sub update_seen_status {
     my($sn) = @_;      my($sn) = @_;
   
       my $del = $dbh->prepare("DELETE FROM seen WHERE aim_server=? AND aim_sn=? AND aim_chatroom=? AND sn=?");
       $del->execute($botsrv, $botsn, $chatroom, $sn) or die "error DBI->errstr()";
           
       my $ins = $dbh->prepare("INSERT INTO seen (aim_server, aim_sn, aim_chatroom, sn, seen_time) VALUES (?, ?, ?, ?, ?)");
       my $seentime = localtime();
       $ins->execute($botsrv, $botsn, $chatroom, $sn, $seentime) or die "error DBI->errstr()";        
 }  }
   
 sub signon_done {  sub signon_done {
     print "[OK]\n";      print "[OK]\n";
       print "convobot:  joining $chatroom...";
     $oscar->chat_join($chatroom, 5);         $oscar->chat_join($chatroom, 5);   
       print "[OK]\n";
     $online = 1;      $online = 1;
 }  }
   
   sub oscar_error {
       my($oscar, $connection, $error, $description, $fatal) = @_;
   
       if($fatal != 0) {
           die "\nconvobot:  fatal OSCAR error:  $description\n";        
       }
       else {
           print "\nconvobot:  recoverable OSCAR error: $description\n";
       }
      
   }
   
 sub chat_joined {  sub chat_joined {
     my($oscar, $chatname, $chat) = @_;      my($oscar, $chatname, $chat) = @_;
   
       print "bot:  chat joined [$chatname]\n";
       
     $room = $chat;      $room = $chat;
     bless $room, "Net::OSCAR::Connection::Chat";      bless $room, "Net::OSCAR::Connection::Chat";
   
       print "convobot:  connecting to database $dbname\@$dbhost...";
   
       $dsn = "DBI:mysql:database=$dbname;host=$dbhost;port=3306;mysql_connect_timeout=5;";
       $dbh = DBI->connect($dsn, $dbusername, $dbpw, {RaiseError => 1});
       die "convobot:  failed to connect to MySQL database: DBI->errstr()" unless $dbh;
   
       print "[OK]\n";
   
       $oscar->set_callback_chat_buddy_in(\&chat_buddy_in);
       $oscar->set_callback_chat_buddy_out(\&chat_buddy_out);
 }  }
   
 sub chat_buddy_in {  sub chat_buddy_in {
     my ($oscar, $who, $chat, $buddy) = @_;      my ($oscar, $who, $chat, $buddy) = @_;
   
     $seen{$who} = localtime();      update_seen_status($who);
           
     if($who ne $botsn) {      if($who ne $botsn) {
         push(@congregants, $who);          push(@congregants, $who);
         print "[$who] has joined\n";                  print "convobot:  [$who] has joined\n";        
     }      }
     else {      else {
         print "[$who] has joined (ignoring bot)\n";          print "convobot:  [$who] has joined (ignoring bot)\n";
     }      }
   
     if(time() - $start_time > 2) {  
         my @phrases = ('Welcome to [room], [user]! :-)',      if($autogreet eq "on") {
                        'How\'s it going, [user]?',          if(time() - $start_time > 2) {
                        'Hey [user]! Bring any snacks?',              my @phrases = ('Welcome to [room], [user]! :-)',
                        'Heya [user]! Hope your day is going well!',                             'How\'s it going, [user]?',
                        'Ooo, [user] has joined [room]! Now the party can start!');                             'Hey [user]! Bring any snacks?',
                                              'Heya [user]! Hope your day is going well!',
         my $phrase = $phrases[rand @phrases];                             'Ooo, [user] has joined [room]! Now the party can start!');
         $phrase =~ s/\[user\]/$who/g;              
         $phrase =~ s/\[room\]/$chatroom/g;                     my $phrase = $phrases[rand @phrases];
         my $phrasefix = "<div id=convobot></div>$phrase";              $phrase =~ s/\[user\]/$who/g;
         $chat->chat_send($phrasefix);              $phrase =~ s/\[room\]/$chatroom/g;       
     }              my $phrasefix = "<div id=convobot></div>$phrase";
     else {              $chat->chat_send($phrasefix);
         print "Not sending greeting for 2 seconds after startup\n";          }
           else {
               print "convobot:  not sending greeting for 2 seconds after startup\n";
           }
     }      }
 }  }
   
Line 127  sub chat_buddy_out { Line 169  sub chat_buddy_out {
     $index++ until $congregants[$index] eq $who;      $index++ until $congregants[$index] eq $who;
     splice(@congregants, $index, 1);      splice(@congregants, $index, 1);
   
     print "$who has left\n";      print "convobot:  $who has left\n";
 }  }
   
 sub chat_im_in {  sub chat_im_in {
Line 137  sub chat_im_in { Line 179  sub chat_im_in {
     my $rawcmd = $hs->parse($message);      my $rawcmd = $hs->parse($message);
     my @cmd = split(' ', $rawcmd);      my @cmd = split(' ', $rawcmd);
   
     $seen{$who} = localtime();      update_seen_status($who);
       
     if($cmd[0] eq "!seen") {      if($who ne $botsn) {
         if(exists($cmd[1])) {          if($cmd[0] eq "!seen") {
             if(exists($seen{$cmd[1]})) {              if(exists($cmd[1])) {
                 $chat->chat_send("I last saw $cmd[1] at $seen{$cmd[1]}");                  my @sna = @cmd[1..$#cmd];
             }                  my $ssn = join(' ', @sna);
             else {                  get_seen_status($ssn, $chat);
                 $chat->chat_send("I've never seen $cmd[1]");              }
             }              else {
         }                  $chat->chat_send("Syntax: !seen <em>screenname</em>");
         else {              }
             $chat->chat_send("Syntax: !seen <em>screenname</em>");          }
         }          elsif($cmd[0] eq "!speak") {
               send_idle_message();
           }
           elsif($cmd[0] eq "!quote") {
               my $fortune = `/usr/games/fortune`;
               $room->chat_send($fortune);
           }
           elsif($cmd[0] eq "!invite") {
               if(exists($cmd[1])) {
                   my @sna = @cmd[1..$#cmd];
                   my $ssn = join(' ', @sna);              
                   $chat->invite($ssn, "Please join us in $chatroom! <br><em>Requested by $who</em>");
               }
           }
           elsif($cmd[0] eq "!help") {
               $room->chat_send("You can enter the following commands:");
               $room->chat_send(" <code>!seen <em>screenname</em></code>  (find out when <em>screenname</em> was last in the chat)");
               $room->chat_send(" <code>!invite <em>screenname</em></code>  (invite <em>screenname</em> to the chat)");
               $room->chat_send(" <code>!speak</code>  (send a random message)");
               $room->chat_send(" <code>!quote</code>  (send a quote)");       
           }
     }      }
               
                           
       
     $last_chat_received = time();          $last_chat_received = time();    
   
     print "chat received from $who; resetting idle counter\n";      print "convobot:  chat received from $who; resetting idle counter\n";
           
 }  }
   
Line 182  sub send_idle_message { Line 243  sub send_idle_message {
         $room->chat_send($phrasefix);          $room->chat_send($phrasefix);
         $last_chat_received = time();          $last_chat_received = time();
     }      }
       
 }  }
   
 $oscar->set_callback_signon_done(\&signon_done);  $oscar->set_callback_signon_done(\&signon_done);
 $oscar->set_callback_chat_joined(\&chat_joined);  $oscar->set_callback_chat_joined(\&chat_joined);
 $oscar->set_callback_chat_buddy_in(\&chat_buddy_in);  
 $oscar->set_callback_chat_buddy_out(\&chat_buddy_out);  
 $oscar->set_callback_chat_im_in(\&chat_im_in);  $oscar->set_callback_chat_im_in(\&chat_im_in);
   $oscar->set_callback_error(\&oscar_error);
   
 print "ChivaNet Conversation Bot v0.0.1\n";  print "ChivaNet Conversation Bot v0.0.1\n";
 print " Copyright (C) 2025 Coherent Logic Development LLC\n\n";  print " Copyright (C) 2025 Coherent Logic Development LLC\n\n";
   
 print "bot:  attempting to sign in... ";  GetOptions("aimsn=s" => \$botsn,
              "aimhost=s" => \$botsrv,
              "aimpw=s" => \$botpw,
              "idlemax=s" => \$idlemax,
              "chatroom=s" => \$chatroom,
              "dbhost=s" => \$dbhost,
              "dbname=s" => \$dbname,
              "dbusername=s" => \$dbusername,
              "dbpw=s" => \$dbpw,
              "autogreet=s" => \$autogreet)
       or die("error in command line arguments");
   
   %signon = (
       screenname => $botsn,
       password => $botpw,
       host => $botsrv,
   ); 
   
   print "AIM Server:        $botsrv\n";
   print "AIM Screen Name:   $botsn\n";
   print "Chat Room:         $chatroom\n";
   print "DB Host:           $dbhost\n";
   print "DB Name:           $dbname\n";
   print "DB Username:       $dbusername\n";
   print "Idle before ping:  $idlemax\n";
   print "Auto-Greet:        $autogreet\n\n";
   
   
   print "convobot:  attempting to sign in...";
 $oscar->signon(%signon);  $oscar->signon(%signon);
   
 while(1) {  while(1) {

Removed from v.1.3  
changed lines
  Added in v.1.6


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>