--- ChivanetModcon/modcon	2025/01/31 15:39:06	1.3
+++ ChivanetModcon/modcon	2025/01/31 19:41:00	1.4
@@ -4,13 +4,16 @@
 # ChivaNet Moderator Console
 #  Copyright (C) 2025 Coherent Logic Development LLC
 #
-# $Id: modcon,v 1.3 2025/01/31 15:39:06 snw Exp $
+# $Id: modcon,v 1.4 2025/01/31 19:41:00 snw Exp $
 #
 # Author: Serena Willis <snw@coherent-logic.com>
 #
 # Licensed AGPL-3.0
 #
 # $Log: modcon,v $
+# Revision 1.4  2025/01/31 19:41:00  snw
+# Move to a UNIX UI paradigm
+#
 # Revision 1.3  2025/01/31 15:39:06  snw
 # Minor fixes
 #
@@ -24,59 +27,45 @@
 
 use REST::Client;
 use JSON;
-use Getopt::Long;
 use Data::Dumper;
 use Term::ReadKey;
+use Getopt::Long;
 
-my $rasurl = '';
+my $sso_account = '';
 my $apikey = '';
 my $online = 0;
 my $modcon_version = '0.0.1';
 my $cnclient = '';
-my $rasclient = '';
 my $wchar = '';
 my $hchar = '';
 my $wpixels = '';
 my $hpixels = '';
 my $account = '';
+my $mode = '---';
+my $user = '---';
+$site = '';
+
+sub list_directories {
+    return ('sso', 'ras');
+}
 
 sub list_sso_users {
-    $cnclient->GET("/chivanet/users");
-    my $ct = 0;
-    
+    $cnclient->GET("/chivanet/users");       
     my $json = $cnclient->responseContent();
     my $hashref = decode_json($json);
 
     if($hashref->{ok} == 1) {
         my $arrayref = $hashref->{users};
-        my @users = sort(@{$arrayref});
-        
-        foreach my $user (@users) {
-            print "$user\n";
-            $ct = $ct + 1;
-
-            if($ct > $hchar - 2) {
-                print "ENTER to continue, Q to quit...";
-                my $resp = <STDIN>;
-                chomp($resp);
-                if($resp eq "Q") {
-                    return;
-                }
-                elsif($resp eq "q") {
-                    return;
-                }
-                $ct = 0;
-            }
-        }
+        my @users = @{$arrayref};
+
+        return @users;
     }
     else {
         print "RPC error\n";
+        return ();
     }
 }
 
-sub list_ras_users {
-
-}
 
 sub select_sso_user {
     my($id) = @_;
@@ -90,11 +79,10 @@ sub select_sso_user {
         $cnclient->GET("/chivanet/user?id=$id");
         my $json = $cnclient->responseContent();
         $account = decode_json($json);
-        
+
         return $id;
     }
     else {
-        print ">>> invalid SSO user $id [$hashref->{error}]\n";
         return "---";
     }            
 }
@@ -110,7 +98,6 @@ sub select_ras_user {
         return $id;
     }
     else {
-        print ">>> invalid RAS screen name $id\n";
         return "---";
     }
 }
@@ -162,57 +149,17 @@ sub list_ras_screennames {
     my($id) = @_;
     
     $cnclient->GET("/chivanet/ras_screen_names?id=$id");
-
     my $json = $cnclient->responseContent();
     my $hashref = decode_json($json);
     my $arrayref = $hashref->{screen_names};
-    my $ct = 0;
-    my $total = 0;
-
-    print "\n";
     
-    foreach my $sn (@{$arrayref}) {
-        my $name = "$sn->{screen_name}\n";
-        chomp($name);
-
-        my $bot = '';
-        my $public = '';
-        
-        if($sn->{bot_sn} eq 1) {
-            $bot = "bot";
-        }
-        else {
-            $bot = "human";
-        }
-
-        if($sn->{public_sn} eq 1) {
-            $public = "public";
-        }
-        else {
-            $public = "unlisted";
-        }
-
-        print "$name:  $public $bot; created $sn->{create_ts}\n";
-        
-        $ct = $ct + 1;
-        $total = $total + 1;
-        
-        if($ct > $hchar - 2) {
-            print "ENTER to continue, Q to quit...";
-            my $resp = <STDIN>;
-            chomp($resp);
-            if($resp eq "Q") {
-                return;
-            }
-            elsif($resp eq "q") {
-                return;
-            }
-            $ct = 0;
-        }
-    }
+    return @{$arrayref};   
+}
 
-    print "\nSSO user $id has $total screen names\n\n";
+sub list_ras_users {
 
+    return ();
+    
 }
 
 sub print_sso_user {
@@ -298,54 +245,165 @@ sub send_im {
 sub prompt {
     
     my $rawcmd = '';
-    my $mode = '---';
-    my $user = '---';
-
+    my $pmode = $mode;    
+    my @path = ();
+    
     while (1) {
-        print "MODCON [$mode/$user]> ";
+        $pmode = lc $mode;
+        my $prompt = '';
+        if($pmode ne "---") {
+            if($user eq '---') {
+                $prompt = "$sso_account\@$site:[/$pmode]\$ ";
+            }
+            else {
+                $prompt = "$sso_account\@$site:[/$pmode/$user]\$ ";
+            }
+        }
+        else {
+            $prompt = "$sso_account\@$site:[/]\$ ";
+        }
+        print $prompt;
         my $line = <STDIN>;
         chomp($line);
         $rawcmd = $line;
         
         my @cmd = split(' ', $rawcmd);
         
-        if ($cmd[0] eq "quit") {
+        if ($cmd[0] eq "exit" || $cmd[0] eq "logout" || $cmd[0] eq "quit" || $cmd[0] eq "bye") {
             return;
         }
-        elsif ($cmd[0] eq "mode") {
-            if($cmd[1] eq "sso") {
-                $mode = "SSO";
-                $user = "---";
-                $account = '';
-            }
-            elsif ($cmd[1] eq "ras") {
-                $mode = "RAS";
-                $user = "---";
-                $account = '';
-            }
-            else {
-                print "?\n";
-            }
-        }
-        elsif ($cmd[0] eq "select") {
-            if($cmd[1] eq "user") {
-                if($mode eq "SSO") {
-                    $user = select_sso_user($cmd[2]);                    
-                    chomp($user);
-                    print_sso_user;
-                }
-                elsif($mode eq "RAS") {
-                    $user = select_ras_user($cmd[2]);
-                    chomp($user);
-                    print_ras_user $user;
+        elsif ($cmd[0] eq "pwd") {
+            my $pstr = join('/', @path);
+            print "/$pstr\n";        
+        }        
+        elsif ($cmd[0] eq "cd") {
+            my $abspath = false;
+
+            if($cmd[1] eq "..") {
+                if(@path) {
+                    if($#path == 1) {
+                        $user = "---";
+                        @path = ($pmode);
+                    }
+                    elsif($#path == 0) {
+                        $mode = "---";
+                        @path = ();
+                    }
                 }
                 else {
-                    print "?\n";
+                    print "already in root directory\n";
                 }
-            }            
-            else {
-                print "?\n";
             }
+            else {
+                my @oldpath = @path;
+                @path = split('/', $cmd[1]);
+            
+                if(substr($cmd[1], 0, 1) eq '/') {
+                    $abspath = true;
+                    shift @path;                
+                }
+                
+                if($abspath eq true || !@oldpath) {
+                    if($#path == 0) {
+                        # mode, no user
+                        if($path[0] eq "sso") {
+                            $mode = "SSO";
+                            $user = "---";
+                            @path = ('sso');
+                        }
+                        elsif($path[0] eq "ras") {
+                            $mode = "RAS";
+                            $user = "---";
+                            @path = ('ras');
+                        }
+                        else {
+                            print "$path[0]:  no such directory exists\n";
+                            @path = @oldpath;
+                        }
+                    }
+                    elsif($#path == 1) {
+                        # mode and user
+                        if($path[0] eq "sso") {
+                            $user = select_sso_user($path[1]);                          
+                            if($user eq "---") {
+                                print "$path[1]:  no such file exists in $pmode\n";
+                                @path = @oldpath;
+                            }
+                            else {
+                                $mode = "SSO";
+                                @path = ('sso', $user);
+                            }
+                        }
+                        elsif($path[0] eq "ras") {
+                            $user = select_ras_user($path[1]);
+                            if($user eq "---") {
+                                print "$path[1]:  no such file exists in $pmode\n";
+                                @path = @oldpath;
+                            }
+                            else {
+                                $mode = "RAS";
+                                @path = ('ras', $user);
+                            }
+                        }
+                        else {
+                            print "$path[0]:  no such directory exists\n";
+                            @path = @oldpath;
+                        }
+                    }
+                    else {
+                        if($cmd[1] eq '/') {
+                            $mode = '---';
+                            $user = '---';
+                            @path = ();
+                        }
+                        else {
+                            print "cd:  invalid path specification\n";
+                            @path = @oldpath;
+                        }
+                    }
+                }
+                else {
+                    if($#oldpath == 1) {
+                        print "invalid path specification\n";
+                        @path = @oldpath;
+                    }
+                    else {
+                        if($#path == 0) {
+                            if($pmode eq "sso") {
+                                $user = select_sso_user($path[0]);                          
+                                if($user eq "---") {
+                                    print "$path[0]:  no such file exists in $pmode\n";
+                                    @path = @oldpath;
+                                }
+                                else {
+                                    $mode = "SSO";
+                                    @path = ('sso', $user);
+                                }
+                            }
+                            elsif($pmode eq "ras") {
+                                $user = select_ras_user($path[0]);                          
+                                if($user eq "---") {
+                                    print "$path[0]:  no such file exists in $pmode\n";
+                                    @path = @oldpath;
+                                }
+                                else {
+                                    $mode = "SSO";
+                                    @path = ('sso', $user);
+                                }
+                            }
+                            else {
+                                print "$path[0]:  no such directory exists\n";
+                                @path = @oldpath;                            
+                            }
+                        }
+                        else {
+                            print "invalid path specification\n";
+                            @path = @oldpath;
+                        }
+                    }
+                }                                         
+            } # if ..                                    
+            
         }
         elsif ($cmd[0] eq "im") {
             if($mode eq "RAS") {
@@ -355,11 +413,11 @@ sub prompt {
                     send_im($user, $msgbody);
                 }
                 else {
-                    print "?\n";
+                    print "im:  no user selected\n";
                 }
             }
             else {
-                print "?\n";
+                print "im:  invalid command outside of ras directory\n";
             }
         }    
         elsif ($cmd[0] eq "trace") {
@@ -371,97 +429,136 @@ sub prompt {
                     print_sso_user;
                 }
                 else {
-                    print "?\n";
+                    print "trace:  no user select\n";
                 }
             }
             else {
-                print "?\n";
+                print "trace:  invalid command outside of ras directory\n";
             }
         }
         elsif ($cmd[0] eq "field") {
-            if($user ne "---") {
-                my $act = $account->{account};
-                print "$user\-\>$cmd[1]:  $act->{$cmd[1]}\n";
-            }
-            else {
-                print "?\n";
-            }
-        }
-        elsif ($cmd[0] eq "describe") {
-            if($user ne "---") {
-                if($mode eq "SSO") {
-                    print_sso_user;
+            if($mode eq "SSO") {
+                if($user ne "---") {
+                    my $act = $account->{account};
+                    print "$user\-\>$cmd[1]:  $act->{$cmd[1]}\n";
+                }
+                else {
+                    print "field:  no user selected\n";
                 }
-                elsif($mode eq "RAS") {
-                    print_ras_user($user);
-                }                                
             }
             else {
-                print "?\n";
+                print "field:  command invalid outside of ras directory\n";
             }
         }
-        elsif ($cmd[0] eq "list") {
-            if($cmd[1] eq "users") {
-                if($mode eq "SSO") {
-                    list_sso_users();
-                }
-                elsif($mode eq "RAS") {
-                    list_ras_users();
-                }
+        elsif ($cmd[0] eq "ls") {
+            my @entries = ();
+            
+            if($mode eq "---") {
+                @entries = list_directories();
             }
-            elsif($cmd[1] eq "sessions") {
-                if($mode eq "RAS") {
-                    list_ras_sessions();
+            else {
+                if($user ne "---") {
+                    if($mode eq "SSO") {
+                        print_sso_user;
+                    }
+                    elsif($mode eq "RAS") {
+                        print_ras_user($user);
+                    }                                
                 }
                 else {
-                    print "?\n";
-                }
-            }
-            elsif($cmd[1] eq "sn") {
-                if($mode eq "SSO") {
-                    if($user ne "---") {
-                        list_ras_screennames $user;
+                    if($mode eq "SSO") {
+                        @entries = list_sso_users();
                     }
                     else {
-                        print "?\n";
+                        @entries = list_ras_users();
                     }
                 }
-                else {
-                    print "?\n";
-                }
             }
-            else {
-                print "?\n";
+
+            if(@entries) {
+                my $col = 0;
+                my $pstr = join('/', @path);
+                my $pfin = "/$pstr";
+                my @sorted = sort(@entries);
+                my $maxlen = 0;
+                foreach my $entry (@sorted) {
+                    my $len = length($entry);
+                    if ($len > $maxlen) {
+                        $maxlen = $len;
+                    }
+                }
+                $maxlen = $maxlen + 2;
+                my $ct = $#sorted + 1;
+                foreach my $entry (@sorted) {
+                    if($col + $maxlen >= $wchar) {
+                        print "\n";
+                        $col = 0;
+                    }
+                    else {
+                        printf("%-$maxlen\s", $entry);
+                        $col = $col + $maxlen;
+                    }                    
+                }                
+                print "\n\t$ct items in $pfin\n";
             }
+
         }
         else {
-            print "?\n"
+            print "$cmd[0]: command not found\n";
         }
     }
 
 }
 
 sub main {  
-    GetOptions("rasurl=s" => \$rasurl,               
-               "apikey=s" => \$apikey)
-        or die("error in command line arguments");
+    ($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();    
 
-    ($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
+    GetOptions("site=s" => \$site) or die "error in command line arguments";
+    
+    if($site eq "") {
+        print "modcon: must supply -site command-line argument\n";
+        return;
+    }
     
     $cnclient = REST::Client->new({
-        host => 'https://chivanet.org/rest/api',
+        host => "https://$site/rest/api",
         timeout => 10});
-
-    $cnclient->addHeader('Authorization', "Apikey $apikey");
-
-    $rasclient = REST::Client->new({
-        host => $rasurl,
-        timeout => 10});    
     
     print "ChivaNet MODCON $modcon_version\n";
     print " Copyright (C) 2025 Coherent Logic Development LLC\n\n";
+
+    print "username: ";
+    $sso_account = <STDIN>;
+    chomp($sso_account);
+
+    print "password: ";
+    ReadMode('noecho');
+    my $password = <STDIN>;
+    chomp($password);
+    ReadMode('normal');
+
+    
+    my $params = $cnclient->buildQuery([username => $sso_account, password => $password]);
+    my $result = $cnclient->POST("/chivanet/modcon_auth", substr($params, 1), {'Content-type' => 'application/x-www-form-urlencoded'});
+    my $http_response = $result->{_res};
+    my $json = $http_response->{_content};
+    my $apiresult = decode_json($json);
     
-    prompt();
+    if($apiresult->{ok} == 1) {
+        $cnclient->addHeader('Authorization', "Apikey $apiresult->{token}");
+
+        select_sso_user $sso_account;
+        my $act = $account->{account};
+        
+        print "\n\nWelcome to MODCON, $act->{display_name}!\n\n";
+        
+        prompt();
+    }
+    else {
+        print "\nerror: $apiresult->{error}\n";
+        return;
+    }
+
     print "Goodbye.\n"
 }