--- ChivanetConvoBot/convobot	2025/02/03 04:28:34	1.2
+++ ChivanetConvoBot/convobot	2025/02/03 17:31:28	1.4
@@ -9,6 +9,12 @@
 # Licensed AGPL-3.0
 #
 # $Log: convobot,v $
+# Revision 1.4  2025/02/03 17:31:28  snw
+# Further MySQL work
+#
+# Revision 1.3  2025/02/03 15:38:12  snw
+# Begin SQL work
+#
 # Revision 1.2  2025/02/03 04:28:34  snw
 # Fix syntax message
 #
@@ -22,12 +28,21 @@ use Net::OSCAR;
 use Getopt::Long;
 use Data::Dumper;
 use HTML::Strip;
+use DBI;
 
 my $idlemax = 1800;
 my $botsn = '';
 my $botsrv = '';
 my $botpw = '';
 my $rasurl = '';
+
+my $dbhost = '';
+my $dbname = '';
+my $dbusername = '';
+my $dbpw = '';
+my $dbconn = '';
+my $autogreet = 'off';
+
 my $chatroom = '';
 my $online = 0;
 my $chat_idle_seconds = 0;
@@ -35,30 +50,55 @@ my $last_chat_received = time();
 my $start_time = time();
 
 my @congregants = ();
-my %seen = ();
 
-GetOptions("aimsn=s" => \$botsn,
-           "aimhost=s" => \$botsrv,
-           "aimpw=s" => \$botpw,
-           "idlemax=s" => \$idlemax,
-           "chatroom=s" => \$chatroom)
-            or die("error in command line arguments");
+$oscar = Net::OSCAR->new();
 
-%signon = (
-    screenname => $botsn,
-    password => $botpw,
-    host => $botsrv,
-); 
+sub get_seen_status {
+    my($sn, $chat) = @_;
 
-$oscar = Net::OSCAR->new();
-#$room = Net::OSCAR::Connection::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 $del = $dbh->prepare("DELETE FROM seen WHERE aim_server=? AND aim_sn=? AND aim_chatroom=? AND sn=?");
+    $del->execute($botsrv, $botsn, $chatroom, $sn);
+    
+    my $ins = $dbh->prepare("INSERT INTO seen (aim_server, aim_sn, aim_chatroom, sn, seen_time) VALUES (?, ?, ?, ?, ?");
+    $ins->execute($botsrv, $botsn, $chatroom, $sn, localtime);        
+}
 
 sub signon_done {
     print "[OK]\n";
-    $oscar->chat_join($chatroom, 5);   
+    print "Joining $chatroom...";
+    $oscar->chat_join($chatroom, 5);
+    print "[OK]\n";
     $online = 1;
 }
 
+sub oscar_error {
+    my($oscar, $connection, $error, $description, $fatal) = @_;
+
+    if($fatal != 0) {
+        die "\nFatal OSCAR error:  $description\n";        
+    }
+    else {
+        print "\nRecoverable OSCAR error: $description\n";
+    }
+   
+}
+
 sub chat_joined {
     my($oscar, $chatname, $chat) = @_;
 
@@ -69,7 +109,7 @@ sub chat_joined {
 sub chat_buddy_in {
     my ($oscar, $who, $chat, $buddy) = @_;
 
-    $seen{$who} = localtime();
+    update_seen_status($who);
     
     if($who ne $botsn) {
         push(@congregants, $who);
@@ -79,21 +119,24 @@ sub chat_buddy_in {
         print "[$who] has joined (ignoring bot)\n";
     }
 
-    if(time() - $start_time > 2) {
-        my @phrases = ('Welcome to [room], [user]! :-)',
-                       'How\'s it going, [user]?',
-                       'Hey [user]! Bring any snacks?',
-                       'Heya [user]! Hope your day is going well!',
-                       'Ooo, [user] has joined [room]! Now the party can start!');
-                
-        my $phrase = $phrases[rand @phrases];
-        $phrase =~ s/\[user\]/$who/g;
-        $phrase =~ s/\[room\]/$chatroom/g;       
-        my $phrasefix = "<div id=convobot></div>$phrase";
-        $chat->chat_send($phrasefix);
-    }
-    else {
-        print "Not sending greeting for 2 seconds after startup\n";
+
+    if($autogreet eq "on") {
+        if(time() - $start_time > 2) {
+            my @phrases = ('Welcome to [room], [user]! :-)',
+                           'How\'s it going, [user]?',
+                           'Hey [user]! Bring any snacks?',
+                           'Heya [user]! Hope your day is going well!',
+                           'Ooo, [user] has joined [room]! Now the party can start!');
+            
+            my $phrase = $phrases[rand @phrases];
+            $phrase =~ s/\[user\]/$who/g;
+            $phrase =~ s/\[room\]/$chatroom/g;       
+            my $phrasefix = "<div id=convobot></div>$phrase";
+            $chat->chat_send($phrasefix);
+        }
+        else {
+            print "Not sending greeting for 2 seconds after startup\n";
+        }
     }
 }
 
@@ -114,16 +157,11 @@ sub chat_im_in {
     my $rawcmd = $hs->parse($message);
     my @cmd = split(' ', $rawcmd);
 
-    $seen{$who} = localtime();
+    update_seen_status($who);
     
     if($cmd[0] eq "!seen") {
         if(exists($cmd[1])) {
-            if(exists($seen{$cmd[1]})) {
-                $chat->chat_send("I last saw $cmd[1] at $seen{$cmd[1]}");
-            }
-            else {
-                $chat->chat_send("I've never seen $cmd[1]");
-            }
+            get_seen_status($cmd[1], $chat);
         }
         else {
             $chat->chat_send("Syntax: !seen <em>screenname</em>");
@@ -166,10 +204,46 @@ $oscar->set_callback_chat_joined(\&chat_
 $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_error(\&oscar_error);
 
 print "ChivaNet Conversation Bot v0.0.1\n";
 print " Copyright (C) 2025 Coherent Logic Development LLC\n\n";
 
+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 "Connecting to database $dbname\@$dbhost...";
+
+my $dsn = "DBI:mysql:database=$dbname;host=$dbhost;port=3306;mysql_connect_timeout=5;";
+my $dbh = DBI->connect($dsn, $dbusername, $dbpw, {RaiseError => 1});
+die "Failed to connect to MySQL database: DBI->errstr()" unless $dbh;
+
+print "[OK]\n";
+
 print "bot:  attempting to sign in... ";
 $oscar->signon(%signon);