aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Phillips <david@sighup.nz>2018-09-21 21:29:17 +1200
committerDavid Phillips <david@sighup.nz>2018-09-21 21:32:28 +1200
commit0475f0bb2fa7ee2f211c67f8df68b014c7fbd213 (patch)
tree5d40897f5508f6c681d93145506d1e4fa0ebd53a
parentf2812c477b230a1407381bfbbb393119c7280076 (diff)
downloadidalius-0475f0bb2fa7ee2f211c67f8df68b014c7fbd213.tar.xz
Add runtime module {,un}loading
-rw-r--r--Plugin.pm34
-rw-r--r--Plugin/Admin.pm65
-rw-r--r--Plugin/DevNull.pm4
-rw-r--r--Plugin/Echo.pm2
-rw-r--r--Plugin/Introspect.pm24
-rw-r--r--Plugin/Map.pm2
-rw-r--r--Plugin/Ping.pm2
-rw-r--r--Plugin/Random.pm4
-rw-r--r--Plugin/Source.pm2
-rw-r--r--Plugin/Thanks.pm8
-rw-r--r--Plugin/Timezone.pm2
-rwxr-xr-xidalius.pl33
12 files changed, 117 insertions, 65 deletions
diff --git a/Plugin.pm b/Plugin.pm
new file mode 100644
index 0000000..4aba6d2
--- /dev/null
+++ b/Plugin.pm
@@ -0,0 +1,34 @@
+package Plugin;
+
+use strict;
+use warnings;
+
+my $unload_callback;
+
+sub load_plugin {
+ my ($logger, $config, $module) = @_;
+ (my $path = $module) =~ s,::,/,g;
+
+ return "$module is already loaded, no changes made" if grep {$_ eq $module} @{$config->{active_plugins}};
+
+ eval {
+ require $path . ".pm";
+ push @{$config->{active_plugins}}, $module;
+ } or do {
+ chomp $@;
+ $logger->($@);
+ return "Cannot load $module: $!";
+ };
+ return undef;
+}
+
+sub unload_plugin {
+ my ($logger, $config, $module) = @_;
+
+ return "$module is not loaded, no changes made" unless grep {$_ eq $module} @{$config->{active_plugins}};
+
+ my @new_plugins = grep {$_ ne $module} @{$config->{active_plugins}};
+ $config->{active_plugins} = \@new_plugins;
+ return undef;
+}
+1;
diff --git a/Plugin/Admin.pm b/Plugin/Admin.pm
index ff64d83..23f8635 100644
--- a/Plugin/Admin.pm
+++ b/Plugin/Admin.pm
@@ -4,34 +4,42 @@ use strict;
use warnings;
use IdaliusConfig qw/assert_scalar assert_list/;
+use Plugin qw/load_plugin unload_plugin/;
my $config;
+my $root_config;
sub configure {
my $self = shift;
my $cmdref = shift;
shift; # run_command
$config = shift;
+ $root_config = shift;
IdaliusConfig::assert_list($config, $self, "admins");
IdaliusConfig::assert_scalar($config, $self, "must_id");
IdaliusConfig::assert_scalar($config, $self, "quit_msg");
- $cmdref->("say", sub { $self->say(@_); } );
- $cmdref->("action", sub { $self->do_action(@_); } );
+ $cmdref->($self, "say", sub { $self->say(@_); } );
+ $cmdref->($self, "action", sub { $self->do_action(@_); } );
- $cmdref->("nick", sub { $self->nick(@_); } );
- $cmdref->("join", sub { $self->join_channel(@_); } );
- $cmdref->("part", sub { $self->part(@_); } );
- $cmdref->("mode", sub { $self->mode(@_); } );
- $cmdref->("kick", sub { $self->kick(@_); } );
- $cmdref->("topic", sub { $self->topic(@_); } );
- $cmdref->("reconnect", sub { $self->reconnect(@_); } );
+ $cmdref->($self, "nick", sub { $self->nick(@_); } );
+ $cmdref->($self, "join", sub { $self->join_channel(@_); } );
+ $cmdref->($self, "part", sub { $self->part(@_); } );
+ $cmdref->($self, "mode", sub { $self->mode(@_); } );
+ $cmdref->($self, "kick", sub { $self->kick(@_); } );
+ $cmdref->($self, "topic", sub { $self->topic(@_); } );
+ $cmdref->($self, "reconnect", sub { $self->reconnect(@_); } );
- $cmdref->("ignore", sub { $self->ignore(@_); } );
- $cmdref->("don't ignore", sub { $self->do_not_ignore(@_); } );
- $cmdref->("who are you ignoring?", sub { $self->dump_ignore(@_); } );
- $cmdref->("exit", sub { $self->exit(@_); } );
+ $cmdref->($self, "ignore", sub { $self->ignore(@_); } );
+ $cmdref->($self, "don't ignore", sub { $self->do_not_ignore(@_); } );
+ $cmdref->($self, "who are you ignoring?", sub { $self->dump_ignore(@_); } );
+
+ $cmdref->($self, "exit", sub { $self->exit(@_); } );
+
+ $cmdref->($self, "plugins", sub { $self->dump_plugins(@_); } );
+ $cmdref->($self, "load", sub { $self->load_plugin(@_); } );
+ $cmdref->($self, "unload", sub { $self->unload_plugin(@_); } );
return $self;
}
@@ -198,4 +206,35 @@ sub exit {
exit;
}
+sub dump_plugins {
+ my ($self, $irc, $logger, $who, $where, $ided, $rest, @arguments) = @_;
+ return "Active plugins: " . join ", ", @{$root_config->{plugins}};
+}
+
+sub unload_plugin {
+ my ($self, $irc, $logger, $who, $where, $ided, $rest, @arguments) = @_;
+
+ return unless is_admin($logger, $who, $ided);
+ return "Syntax: unload <plugin>" unless @arguments == 1;
+
+ my $module = $arguments[0];
+
+ my $error = Plugin::unload_plugin($logger, $root_config, $module);
+ return $error if $error;
+ return "$module unloaded";
+}
+
+sub load_plugin {
+ my ($self, $irc, $logger, $who, $where, $ided, $rest, @arguments) = @_;
+
+ return unless is_admin($logger, $who, $ided);
+ return "Syntax: load <plugin>" unless @arguments == 1;
+
+ my $module = $arguments[0];
+
+ my $error = Plugin::load_plugin($logger, $root_config, $module);
+ return $error if $error;
+ return "$module loaded";
+}
+
1;
diff --git a/Plugin/DevNull.pm b/Plugin/DevNull.pm
index b1087f1..038929a 100644
--- a/Plugin/DevNull.pm
+++ b/Plugin/DevNull.pm
@@ -10,8 +10,8 @@ sub configure {
my $cmdref = shift;
$run_command = shift;
- $cmdref->("hush", sub { $self->hush(@_); } );
- $cmdref->("devnull", sub { $self->hush(@_); } );
+ $cmdref->($self, "hush", sub { $self->hush(@_); } );
+ $cmdref->($self, "devnull", sub { $self->hush(@_); } );
return $self;
}
diff --git a/Plugin/Echo.pm b/Plugin/Echo.pm
index ba66c48..f5225fe 100644
--- a/Plugin/Echo.pm
+++ b/Plugin/Echo.pm
@@ -7,7 +7,7 @@ sub configure {
my $self = shift;
my $cmdref = shift;
- $cmdref->("echo", sub { $self->echo(@_); } );
+ $cmdref->($self, "echo", sub { $self->echo(@_); } );
return $self;
}
diff --git a/Plugin/Introspect.pm b/Plugin/Introspect.pm
deleted file mode 100644
index 05f338a..0000000
--- a/Plugin/Introspect.pm
+++ /dev/null
@@ -1,24 +0,0 @@
-package Plugin::Introspect;
-
-use strict;
-use warnings;
-
-my $root_config;
-
-sub configure {
- my $self = shift;
- my $cmdref = shift;
- shift; # run_command
- shift; # module config
- $root_config = shift;
-
- $cmdref->("plugins", sub { $self->dump_plugins(@_); } );
-
- return $self;
-}
-
-sub dump_plugins {
- my ($self, $irc, $logger, $who, $where, $ided, $rest, @arguments) = @_;
- return "Plugins: " . join ", ", $root_config->{plugins};
-}
-1;
diff --git a/Plugin/Map.pm b/Plugin/Map.pm
index 42856eb..a0f61ba 100644
--- a/Plugin/Map.pm
+++ b/Plugin/Map.pm
@@ -12,7 +12,7 @@ sub configure {
my $cmdref = shift;
$run_command = shift;
- $cmdref->("map", sub { $self->map(@_); } );
+ $cmdref->($self, "map", sub { $self->map(@_); } );
return $self;
}
diff --git a/Plugin/Ping.pm b/Plugin/Ping.pm
index 602469b..2cf46d5 100644
--- a/Plugin/Ping.pm
+++ b/Plugin/Ping.pm
@@ -7,7 +7,7 @@ sub configure {
my $self = shift;
my $cmdref = shift;
- $cmdref->("ping", sub { $self->ping(@_); } );
+ $cmdref->($self, "ping", sub { $self->ping(@_); } );
return $self;
}
diff --git a/Plugin/Random.pm b/Plugin/Random.pm
index cea65fb..c6ed304 100644
--- a/Plugin/Random.pm
+++ b/Plugin/Random.pm
@@ -9,8 +9,8 @@ sub configure {
my $self = shift;
my $cmdref = shift;
- $cmdref->("shuffle", sub { $self->shuffle(@_); } );
- $cmdref->("choose", sub { $self->choose(@_); } );
+ $cmdref->($self, "shuffle", sub { $self->shuffle(@_); } );
+ $cmdref->($self, "choose", sub { $self->choose(@_); } );
return $self;
}
diff --git a/Plugin/Source.pm b/Plugin/Source.pm
index 6b93979..8719305 100644
--- a/Plugin/Source.pm
+++ b/Plugin/Source.pm
@@ -7,7 +7,7 @@ sub configure {
my $self = shift;
my $cmdref = shift;
my @source_commands = ("guts", "help", "source");
- $cmdref->($_, sub { $self->source(@_); }) for @source_commands;
+ $cmdref->($self, $_, sub { $self->source(@_); }) for @source_commands;
return $self;
}
diff --git a/Plugin/Thanks.pm b/Plugin/Thanks.pm
index 01c52ac..0ccf319 100644
--- a/Plugin/Thanks.pm
+++ b/Plugin/Thanks.pm
@@ -7,10 +7,10 @@ sub configure {
my $self = shift;
my $cmdref = shift;
- $cmdref->("thanks", sub { $self->thanks(@_); } );
- $cmdref->("thanks.", sub { $self->thanks(@_); } );
- $cmdref->("thanks!", sub { $self->thanks(@_); } );
- $cmdref->("thanks?", sub { $self->thanks(@_); } );
+ $cmdref->($self, "thanks", sub { $self->thanks(@_); } );
+ $cmdref->($self, "thanks.", sub { $self->thanks(@_); } );
+ $cmdref->($self, "thanks!", sub { $self->thanks(@_); } );
+ $cmdref->($self, "thanks?", sub { $self->thanks(@_); } );
return $self;
}
diff --git a/Plugin/Timezone.pm b/Plugin/Timezone.pm
index 5e649b1..a8a8fcc 100644
--- a/Plugin/Timezone.pm
+++ b/Plugin/Timezone.pm
@@ -16,7 +16,7 @@ sub configure {
IdaliusConfig::assert_dict($config, $self, "timezone");
- $cmdref->("time", sub { $self->time(@_); } );
+ $cmdref->($self, "time", sub { $self->time(@_); } );
return $self;
}
diff --git a/idalius.pl b/idalius.pl
index 690d5a7..627d91f 100755
--- a/idalius.pl
+++ b/idalius.pl
@@ -8,6 +8,7 @@ use POE::Kernel;
use POE::Component::IRC;
use POE::Component::IRC::Plugin::NickServID;
use IdaliusConfig;
+use Plugin qw/load_plugin/;
use IRC::Utils qw(strip_color strip_formatting);
my $config_file = "bot.conf";
@@ -24,9 +25,7 @@ sub log_info {
eval {
for my $module (@{$config->{_}->{plugins}}) {
- log_info "Loading $module";
- (my $path = $module) =~ s,::,/,g;
- require $path . ".pm";
+ Plugin::load_plugin(\&log_info, $config->{_}, $module);
$module->configure(
\&register_command,
\&run_command,
@@ -39,7 +38,6 @@ eval {
die;
};
-
$| = 1;
my $current_nick = $config->{_}->{nick};
@@ -90,27 +88,32 @@ $poe_kernel->run();
sub module_is_enabled {
my $module = $_[0];
- return grep {$_ eq $module} @{$config->{_}->{plugins}};
+ return grep {$_ eq $module} @{$config->{_}->{active_plugins}};
}
# Register a command name to a certain sub
sub register_command {
- my ($command, $action) = @_;
+ my ($owner, $command, $action) = @_;
$command = lc $command;
- log_info "Registering command: $command";
- $commands{$command} = $action;
+ log_info "Registering command: $command (from $owner)";
+ $commands{$owner}{$command} = $action;
}
sub run_command {
my ($command_string, $who, $where, $ided) = @_;
my @arguments;
+ my $owner;
my $command_verbatim;
my $command;
- for my $c (keys %commands) {
- if (($command_verbatim) = $command_string =~ m/^(\Q$c\E( |$))/i) {
- $command = lc $c;
- last;
+ OUTER: for my $o (keys %commands) {
+ next unless module_is_enabled($o);
+ for my $c (keys %{$commands{$o}}) {
+ if (($command_verbatim) = $command_string =~ m/^(\Q$c\E( |$))/i) {
+ $command = lc $c;
+ $owner = $o;
+ last OUTER;
+ }
}
}
@@ -119,9 +122,9 @@ sub run_command {
my $rest = (split "\Q$command_verbatim", $command_string, 2)[1];
@arguments = split /\s+/, $rest if $rest;
- return ($commands{$command})->($irc, \&log_info, $who, $where, $ided, $rest, @arguments);
+ my $action = $commands{$owner}{$command};
+ return $action->($irc, \&log_info, $who, $where, $ided, $rest, @arguments);
}
-
sub custom_ping {
my ($irc, $heap) = @_[KERNEL, HEAP];
$irc->yield(userhost => $current_nick);
@@ -217,7 +220,7 @@ sub handle_common {
# handler names are defined as being prefixed with on_
$message_type = "on_$message_type";
my $ignore_suffix = "_yes_really_even_from_ignored_nicks";
- for my $module (@{$config->{_}->{plugins}}) {
+ for my $module (@{$config->{_}->{active_plugins}}) {
if (module_is_enabled($module)) {
if (!should_ignore($nick) and $module->can($message_type)) {
# Leave message type unchanged