package DXCommandmode;
-use POSIX;
+#use POSIX;
@ISA = qw(DXChannel);
+use POSIX qw(:math_h);
use DXUtil;
use DXChannel;
use DXUser;
use QSL;
use DB_File;
use VE7CC;
+use DXXml;
use strict;
-use vars qw(%Cache %cmd_cache $errstr %aliases $scriptbase $maxerrors %nothereslug $maxbadcount $msgpolltime);
+use vars qw(%Cache %cmd_cache $errstr %aliases $scriptbase $maxerrors %nothereslug
+ $maxbadcount $msgpolltime $default_pagelth $cmdimportdir);
%Cache = (); # cache of dynamically loaded routine's mod times
%cmd_cache = (); # cache of short names
$maxerrors = 20; # the maximum number of concurrent errors allowed before disconnection
$maxbadcount = 3; # no of bad words allowed before disconnection
$msgpolltime = 3600; # the time between polls for new messages
-
+$cmdimportdir = "$main::root/cmd_import"; # the base directory for importing command scripts
+ # this does not exist as default, you need to create it manually
+ #
use vars qw($VERSION $BRANCH);
$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
my $host = $self->{conn}->{peerhost};
$host ||= "AGW Port #$self->{conn}->{agwport}" if exists $self->{conn}->{agwport};
$host ||= "unknown";
- Log('DXCommand', "$call connected from $host");
+ LogDbg('DXCommand', "$call connected from $host");
$self->{name} = $name ? $name : $call;
$self->send($self->msg('l2',$self->{name}));
$self->state('prompt'); # a bit of room for further expansion, passwords etc
$self->{priv} = $user->priv || 0;
$self->{lang} = $user->lang || $main::lang || 'en';
- $self->{pagelth} = $user->pagelth || 20;
+ my $pagelth = $user->pagelth;
+ $pagelth = $default_pagelth unless defined $pagelth;
+ $self->{pagelth} = $pagelth;
($self->{width}) = $line =~ /width=(\d+)/; $line =~ s/\s*width=\d+\s*//;
$self->{width} = 80 unless $self->{width} && $self->{width} > 80;
$self->{consort} = $line; # save the connection type
$self->{priv} = 0 if $line =~ /^(ax|te)/ && !$self->conn->{usedpasswd};
# get the filters
- $self->{spotsfilter} = Filter::read_in('spots', $call, 0) || Filter::read_in('spots', 'user_default', 0);
- $self->{wwvfilter} = Filter::read_in('wwv', $call, 0) || Filter::read_in('wwv', 'user_default', 0);
- $self->{wcyfilter} = Filter::read_in('wcy', $call, 0) || Filter::read_in('wcy', 'user_default', 0);
- $self->{annfilter} = Filter::read_in('ann', $call, 0) || Filter::read_in('ann', 'user_default', 0) ;
+ my $nossid = $call;
+ $nossid =~ s/-\d+$//;
+
+ $self->{spotsfilter} = Filter::read_in('spots', $call, 0)
+ || Filter::read_in('spots', $nossid, 0)
+ || Filter::read_in('spots', 'user_default', 0);
+ $self->{wwvfilter} = Filter::read_in('wwv', $call, 0)
+ || Filter::read_in('wwv', $nossid, 0)
+ || Filter::read_in('wwv', 'user_default', 0);
+ $self->{wcyfilter} = Filter::read_in('wcy', $call, 0)
+ || Filter::read_in('wcy', $nossid, 0)
+ || Filter::read_in('wcy', 'user_default', 0);
+ $self->{annfilter} = Filter::read_in('ann', $call, 0)
+ || Filter::read_in('ann', $nossid, 0)
+ || Filter::read_in('ann', 'user_default', 0) ;
# clean up qra locators
my $qra = $user->qra;
}
$self->tell_login('loginu');
+ $self->tell_buddies('loginb');
# do we need to send a forward/opernam?
my $lastoper = $user->lastoper || 0;
my $info = Route::cluster();
$self->send("Cluster:$info");
- # send prompts and things
+ # send prompts for qth, name and things
$self->send($self->msg('namee1')) if !$user->name;
$self->send($self->msg('qthe1')) if !$user->qth;
$self->send($self->msg('qll')) if !$user->qra || (!$user->lat && !$user->long);
$self->send($self->msg('hnodee1')) if !$user->qth;
$self->send($self->msg('m9')) if DXMsg::for_me($call);
+
+ # send out any buddy messages for other people that are online
+ foreach my $call (@{$user->buddies}) {
+ my $ref = Route::User::get($call);
+ if ($ref) {
+ foreach my $node (@{$ref->parent}) {
+ $self->send($self->msg($node eq $main::mycall ? 'loginb' : 'loginbn', $call, $node));
+ }
+ }
+ }
+
$self->lastmsgpoll($main::systime);
$self->prompt;
}
my @bad;
if (@bad = BadWords::check($l)) {
$self->badcount(($self->badcount||0) + @bad);
- Log('DXCommand', "$self->{call} swore: $l");
+ LogDbg('DXCommand', "$self->{call} swore: $l with words:" . join(',', @bad) . ")");
} else {
for (@{$self->{talklist}}) {
$self->send_talks($_, $l);
my @bad;
if (@bad = BadWords::check($cmdline)) {
$self->badcount(($self->badcount||0) + @bad);
- Log('DXCommand', "$self->{call} swore: $cmdline");
+ LogDbg('DXCommand', "$self->{call} swore: $cmdline with words:" . join(',', @bad) . ")");
} else {
for (@{$self->{talklist}}) {
$self->send_talks($_, $rawline);
# check for excessive swearing
if ($self->{badcount} && $self->{badcount} >= $maxbadcount) {
- Log('DXCommand', "$self->{call} logged out for excessive swearing");
+ LogDbg('DXCommand', "$self->{call} logged out for excessive swearing");
$self->disconnect;
return;
}
return () if length $cmdline == 0;
-
+
+
# split the command line up into parts, the first part is the command
my ($cmd, $args) = split /\s+/, $cmdline, 2;
$args = "" unless defined $args;
if ($cmd) {
# strip out // on command only
$cmd =~ s|//|/|g;
+ $cmd =~ s|^/||g; # no leading / either
+ $cmd =~ s|[^-?\w/]||g; # and no funny characters either
my ($path, $fcmd);
# first expand out the entry to a command
($path, $fcmd) = search($main::localcmd, $cmd, "pl");
- ($path, $fcmd) = search($main::cmd, $cmd, "pl") if !$path || !$fcmd;
+ ($path, $fcmd) = search($main::cmd, $cmd, "pl") unless $path && $fcmd;
if ($path && $cmd) {
dbg("path: $cmd cmd: $fcmd") if isdbg('command');
delete $nothereslug{$k};
}
}
+
+ import_cmd();
}
#
# send info to all logged in thingies
$self->tell_login('logoutu');
+ $self->tell_buddies('logoutb');
- Log('DXCommand', "$call disconnected");
+ LogDbg('DXCommand', "$call disconnected");
$self->SUPER::disconnect;
}
sub prompt
{
my $self = shift;
+
+ return if $self->{gtk}; # 'cos prompts are not a concept that applies here
+
my $call = $self->call;
my $date = cldate($main::systime);
my $time = ztime($main::systime);
return $package;
}
+sub send
+{
+ my $self = shift;
+ if ($self->{gtk}) {
+ for (@_) {
+ $self->SUPER::send(dd(['cmd',$_]));
+ }
+ } else {
+ $self->SUPER::send(@_);
+ }
+}
+
sub local_send
{
my ($self, $let, $buf) = @_;
{
my ($self, $from, $to, $via, $line) = @_;
$line =~ s/\\5E/\^/g;
- $self->local_send('T', "$to de $from: $line") if $self->{talk};
+ if ($self->{talk}) {
+ if ($self->{gtk}) {
+ $self->local_send('T', dd(['talk',$to,$from,$via,$line]));
+ } else {
+ $self->local_send('T', "$to de $from: $line");
+ }
+ }
Log('talk', $to, $from, $via?$via:$main::mycall, $line);
# send a 'not here' message if required
unless ($self->{here} && $from ne $to) {
return if $_[0] ne $main::myalias && $_[0] ne $main::mycall;
}
return if $target eq 'SYSOP' && $self->{priv} < 5;
- my $buf = "$to$target de $_[0]: $text";
- $buf =~ s/\%5E/^/g;
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['ann', $to, $target, $text, @_])
+ } else {
+ $buf = "$to$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send($target eq 'WX' ? 'W' : 'N', $buf);
}
return unless grep uc $_ eq $target, @{$self->{user}->{group}};
$text =~ s/^\#\d+ //;
- my $buf = "$target de $_[0]: $text";
- $buf =~ s/\%5E/^/g;
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['chat', $to, $target, $text, @_])
+ } else {
+ $buf = "$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send('C', $buf);
}
my $buf;
if ($self->{ve7cc}) {
$buf = VE7CC::dx_spot($self, @_);
+ } elsif ($self->{gtk}) {
+ my ($dxloc, $byloc);
+
+ my $ref = DXUser->get_current($_[4]);
+ if ($ref) {
+ $byloc = $ref->qra;
+ $byloc = substr($byloc, 0, 4) if $byloc;
+ }
+
+ my $spot = $_[1];
+ $spot =~ s|/\w{1,4}$||;
+ $ref = DXUser->get_current($spot);
+ if ($ref) {
+ $dxloc = $ref->qra;
+ $dxloc = substr($dxloc, 0, 4) if $dxloc;
+ }
+ $buf = dd(['dx', @_, ($dxloc||''), ($byloc||'')]);
+
} else {
$buf = $self->format_dx_spot(@_);
$buf .= "\a\a" if $self->{beep};
return unless $self->{wwv};
if ($self->{wwvfilter}) {
- ($filter, $hops) = $self->{wwvfilter}->it(@_ );
+ ($filter, $hops) = $self->{wwvfilter}->it(@_[7..$#_] );
return unless $filter;
}
- my $buf = "WWV de $_[6] <$_[1]>: SFI=$_[2], A=$_[3], K=$_[4], $_[5]";
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['wwv', @_])
+ } else {
+ $buf = "WWV de $_[6] <$_[1]>: SFI=$_[2], A=$_[3], K=$_[4], $_[5]";
+ $buf .= "\a\a" if $self->{beep};
+ }
+
$self->local_send('V', $buf);
}
return unless $filter;
}
- my $buf = "WCY de $_[10] <$_[1]> : K=$_[4] expK=$_[5] A=$_[3] R=$_[6] SFI=$_[2] SA=$_[7] GMF=$_[8] Au=$_[9]";
- $buf .= "\a\a" if $self->{beep};
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['wcy', @_])
+ } else {
+ $buf = "WCY de $_[10] <$_[1]> : K=$_[4] expK=$_[5] A=$_[3] R=$_[6] SFI=$_[2] SA=$_[7] GMF=$_[8] Au=$_[9]";
+ $buf .= "\a\a" if $self->{beep};
+ }
$self->local_send('Y', $buf);
}
foreach my $dxchan (DXChannel::get_all) {
next unless $dxchan->{enhanced} && $dxchan->{senddbg};
- $dxchan->send_later('L', $s);
+ if ($dxchan->{gtk}) {
+ $dxchan->send_later('L', dd(['db', $s]));
+ } else {
+ $dxchan->send_later('L', $s);
+ }
}
}
return @out;
}
+# Import any commands contained in any files in import_cmd directory
+#
+# If the filename has a recogisable callsign as some delimited part
+# of it, then this is the user the command will be run as.
+#
+sub import_cmd
+{
+ # are there any to do in this directory?
+ return unless -d $cmdimportdir;
+ unless (opendir(DIR, $cmdimportdir)) {
+ LogDbg('err', "can\'t open $cmdimportdir $!");
+ return;
+ }
+
+ my @names = readdir(DIR);
+ closedir(DIR);
+ my $name;
+ foreach $name (@names) {
+ next if $name =~ /^\./;
+
+ my $s = Script->new($name, $cmdimportdir);
+ if ($s) {
+ LogDbg('DXCommand', "Run import cmd file $name");
+ my @cat = split /[^A-Za-z0-9]+/, $name;
+ my ($call) = grep {is_callsign(uc $_)} @cat;
+ $call ||= $main::mycall;
+ $call = uc $call;
+ my @out;
+
+
+ $s->inscript(0); # switch off script checks
+
+ if ($call eq $main::mycall) {
+ @out = $s->run($main::me, 1);
+ } else {
+ my $dxchan = DXChannel::get($call);
+ if ($dxchan) {
+ @out = $s->run($dxchan, 1);
+ } else {
+ my $u = DXUser->get($call);
+ if ($u) {
+ $dxchan = $main::me;
+ my $old = $dxchan->{call};
+ my $priv = $dxchan->{priv};
+ my $user = $dxchan->{user};
+ $dxchan->{call} = $call;
+ $dxchan->{priv} = $u->priv;
+ $dxchan->{user} = $u;
+ @out = $s->run($dxchan, 1);
+ $dxchan->{call} = $call;
+ $dxchan->{priv} = $priv;
+ $dxchan->{user} = $user;
+ } else {
+ LogDbg('err', "Trying to run import cmd for non-existant user $call");
+ }
+ }
+ }
+ $s->erase;
+ for (@out) {
+ LogDbg('DXCommand', "Import cmd $name/$call: $_");
+ }
+ } else {
+ LogDbg('err', "Failed to open $cmdimportdir/$name $!");
+ unlink "$cmdimportdir/$name";
+ }
+ }
+}
1;
__END__