Instantly share code, notes, and snippets.

Embed
What would you like to do?
Chat responder with multiple responses support - script for the Globster direct connect client
#!/usr/bin/perl
use strict;
use warnings;
use Net::DBus::Reactor;
use Net::DBus;
use XML::Simple;
# create xml object
my $xml = new XML::Simple;
# read XML file
my $config = $xml->XMLin($ARGV[0], ForceArray => ['hub', 'bottalkresponse', 'botmuteresponse', 'responder', 'response'], SearchPath => [ '/etc/globster' ]);
$ENV{DBUS_SESSION_BUS_ADDRESS} = $config->{'dbusaddr'} ? $config->{'dbusaddr'} : $ENV{DBUS_SESSION_BUS_ADDRESS};
# Hubs to link (Globster hub ids)
my @hubs = @{$config->{'hub'}};
my $g = Net::DBus->find->get_service("net.blicky.Globster")->get_object("/net/blicky/Globster");
my %objs = map +($_->{'hubid'}, $g->get_child_object("/Hub/$_->{'hubid'}")), @hubs;
my @ignored;
my @resplast;
my @msgqueue;
sub is_authority {
my ($user, $array) = @_;
for my $item (@{$array}) {
if ($item eq $user) {
return 1;
}
}
return 0;
}
sub is_ignored {
my $found = 0;
my ($user, $hubid, $array) = @_;
for my $item (@{$array}) {
if ($item->{'user'} eq $user && $item->{'hubid'} == $hubid && $item->{'expiry'} > time) {
$found = 1;
last;
}
}
return $found;
}
sub ignored_cleanup {
my $ignorelist = $_[0];
my $offset = 0;
for my $item (@{$ignorelist}) {
$offset++ if $item->{'expiry'} <= time;
}
splice(@{$ignorelist}, 0, $offset);
}
sub send_reply {
my($hubid, $reply) = @_;
$objs{$hubid}->SendChat(-1, $reply, 0);
}
sub send_msg_queue {
my $mq = shift;
for my $item (@{$mq}) {
if ($item->{'time'} <= time) {
send_reply $item->{'hub'}, $item->{'message'};
}
}
}
sub msg_queue_cleanup {
my $mq = $_[0];
my $offset = 0;
for my $item (@{$mq}) {
$offset++ if $item->{'time'} <= time;
}
splice(@{$mq}, 0, $offset);
}
for my $hub (@hubs) {
$resplast[$hub->{'hubid'}]{'username'} = '';
$resplast[$hub->{'hubid'}]{'keyword'} = '';
$resplast[$hub->{'hubid'}]{'count'} = 0;
$objs{$hub->{'hubid'}}->connect_to_signal('ReceiveChat', sub {
my($group, $user, $message, $me) = @_;
return if $group != -1 || $user == -1 || !$user; # Do not reply to own messages
my $username = [$objs{$hub->{'hubid'}}->UserInfo($user, [ 1 ])]->[1]{$user}[0];
my $rr = '';
my @botauthority = split(',', $hub->{'botauthority'});
if ($message =~ /$hub->{'bottalk'}/ && is_authority($username, \@botauthority)) {
$hub->{'state'} = 1;
my @bottalkresponses = @{$hub->{'bottalkresponse'}};
$rr = $bottalkresponses[rand @bottalkresponses];
}
if ($message =~ /$hub->{'botmute'}/ && is_authority($username, \@botauthority)) {
$hub->{'state'} = 0;
my @botmuteresponses = @{$hub->{'botmuteresponse'}};
$rr = $botmuteresponses[rand @botmuteresponses];
}
if ($hub->{'state'} == 1 && !is_ignored($username, $hub->{'hubid'}, \@ignored)) {
my @responders = @{$hub->{'responder'}};
for my $responder (@responders) {
my $str = $responder->{'keyword'};
if ($message =~ /$str/) {
if ($str eq $resplast[$hub->{'hubid'}]{'keyword'} && $username eq $resplast[$hub->{'hubid'}]{'username'}) {
$resplast[$hub->{'hubid'}]{'counter'}++;
} else {
$resplast[$hub->{'hubid'}]{'keyword'} = $str;
$resplast[$hub->{'hubid'}]{'username'} = $username;
$resplast[$hub->{'hubid'}]{'counter'} = 0;
}
if ($resplast[$hub->{'hubid'}]{'counter'} > $hub->{'maxrepeat'} - 1) {
$rr = $hub->{'repeatresponse'};
my %ignored_user;
$ignored_user{'user'} = $username;
$ignored_user{'expiry'} = time + $hub->{'ignoretime'};
$ignored_user{'hubid'} = $hub->{'hubid'};
push(@ignored, \%ignored_user);
$resplast[$hub->{'hubid'}]{'counter'} = 0;
} else {
my @responses = @{$responder->{'response'}};
$rr = $responses[rand @responses];
}
last;
}
}
}
if ($rr ne '') {
$rr =~ s/%\[userNI\]/$username/g;
my $delay = $hub->{'respdelay'} ? $hub->{'respdelay'} : 0;
my %qr;
$qr{'message'} = $rr;
$qr{'time'} = time + $delay;
$qr{'hub'} = $hub->{'hubid'};
push(@msgqueue, \%qr);
}
});
}
my $reactor = Net::DBus::Reactor->main;
$reactor->add_timeout(1000, Net::DBus::Callback->new( method => sub {
send_msg_queue(\@msgqueue);
msg_queue_cleanup(\@msgqueue);
ignored_cleanup(\@ignored);
}));
$reactor->run;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment