#!/usr/bin/env perl
#
# ChivaNet Moderator Console
# Copyright (C) 2025 Coherent Logic Development LLC
#
# $Id: modcon,v 1.2 2025/01/31 13:38:51 snw Exp $
#
# Author: Serena Willis <snw@coherent-logic.com>
#
# Licensed AGPL-3.0
#
# $Log: modcon,v $
# Revision 1.2 2025/01/31 13:38:51 snw
# Initial basic functions working
#
# Revision 1.1.1.1 2025/01/30 19:16:06 snw
# Initial commit
#
#
use REST::Client;
use JSON;
use Getopt::Long;
use Data::Dumper;
use Term::ReadKey;
my $rasurl = '';
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 = '';
sub list_sso_users {
$cnclient->GET("/chivanet/users");
my $ct = 0;
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;
}
}
}
else {
print "RPC error\n";
}
}
sub list_ras_users {
}
sub select_sso_user {
my($id) = @_;
$cnclient->GET("/chivanet/validate_user?id=$id");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
#print Dumper($hashref);
if($hashref->{exists} == 1) {
$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 "---";
}
}
sub select_ras_user {
my($id) = @_;
$cnclient->GET("/chivanet/validate_sn?id=$id");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
if($hashref->{exists} == 1) {
return $id;
}
else {
print ">>> invalid RAS screen name $id\n";
return "---";
}
}
sub trace_ras_sn {
my($user) = @_;
$cnclient->GET("/chivanet/trace_sn?id=$user");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
my $record = $hashref->{account};
my $result = $record->{id};
print "RAS screen name $user belongs to SSO account $result; switching to SSO mode\n";
return $result;
}
sub list_ras_sessions {
$cnclient->GET("/chivanet/ras_sessions");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
my $sessions = $hashref->{sessions};
my $arrayref = $sessions->{sessions};
my $ct = 0;
foreach my $session (@{$arrayref}) {
print "$session->{screen_name}\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;
}
}
print "$sessions->{count} current sessions\n";
}
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;
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;
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;
}
}
}
sub print_sso_user {
my $act = $account->{account};
print "\n";
print "Username : $act->{id}\n";
print "Real Name : $act->{last_name}, $act->{first_name}\n";
print "Display Name : $act->{display_name}\n";
print "Pronouns : $act->{pronouns}\n";
print "Profile Image : https://chivanet.org$act->{profile_photo}\n";
print "E-Mail Address : $act->{email}\n";
print "Permission Level : $act->{perm_level}\n";
print "Created : $act->{create_ts}\n";
print "Banned : $act->{mod_banned}\n\n";
}
sub print_ras_user {
my($id) = @_;
$cnclient->GET("/chivanet/sn_status?id=$id");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
my $status = $hashref->{status};
my $online = "offline";
if($status->{online} == 1) {
$online = "online";
}
print "\n";
if($online eq "online") {
my $sess = $status->{session};
my $service = 'AIM';
if($sess->{is_icq} == 1) {
$service = 'ICQ';
}
if($sess->{idle_seconds} > 0) {
$online = "idle";
}
print "Screen Name : $id [$online]\n";
print "Service : $service\n";
if($online eq "online") {
print "Time Online (secs): $sess->{online_seconds}\n";
}
else {
print "Time Idle (secs) : $sess->{idle_seconds}\n";
}
print "Away Message : $sess->{away_message}\n\n";
}
else {
print "Screen Name : $id [$online]\n\n";
}
# print Dumper($status);
}
sub send_im {
my($user, $msgbody) = @_;
print "sending message \"$msgbody\" to $user...";
my $msg = "<font color=red><strong>[ChivaNet Support]:</strong></font> $msgbody";
$cnclient->GET("/chivanet/send_im?from=ChivaNet&to=$user&message=$msg");
my $json = $cnclient->responseContent();
my $hashref = decode_json($json);
if($hashref->{status} == 1) {
print "[OK]\n";
}
else {
print "[FAIL]\n";
}
}
sub prompt {
my $rawcmd = '';
my $mode = '---';
my $user = '---';
while (1) {
print "MODCON [$mode/$user]> ";
my $line = <STDIN>;
chomp($line);
$rawcmd = $line;
my @cmd = split(' ', $rawcmd);
if ($cmd[0] eq "quit") {
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;
}
else {
print "?\n";
}
}
else {
print "?\n";
}
}
elsif ($cmd[0] eq "im") {
if($mode eq "RAS") {
if($user ne "---") {
my @msga = @cmd[1..$#cmd];
my $msgbody = join(' ', @msga);
send_im($user, $msgbody);
}
else {
print "?\n";
}
}
else {
print "?\n";
}
}
elsif ($cmd[0] eq "trace") {
if($mode eq "RAS") {
if($user ne "---") {
my $id = trace_ras_sn($user);
$mode = "SSO";
$user = select_sso_user($id);
print_sso_user;
}
else {
print "?\n";
}
}
else {
print "?\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;
}
elsif($mode eq "RAS") {
print_ras_user($user);
}
}
else {
print "?\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[1] eq "sessions") {
if($mode eq "RAS") {
list_ras_sessions();
}
else {
print "?\n";
}
}
elsif($cmd[1] eq "sn") {
if($mode eq "SSO") {
if($user ne "---") {
list_ras_screennames $user;
}
else {
print "?\n";
}
}
else {
print "?\n";
}
}
else {
print "?\n";
}
}
else {
print "?\n"
}
}
}
sub main {
GetOptions("rasurl=s" => \$rasurl,
"apikey=s" => \$apikey)
or die("error in command line arguments");
($wchar, $hchar, $wpixels, $hpixels) = GetTerminalSize();
$cnclient = REST::Client->new({
host => 'https://chivanet.org/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";
prompt();
print "Goodbye.\n"
}
main();
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>