diff options
author | David Phillips <david@sighup.nz> | 2018-09-21 21:29:17 +1200 |
---|---|---|
committer | David Phillips <david@sighup.nz> | 2018-09-21 21:32:28 +1200 |
commit | 0475f0bb2fa7ee2f211c67f8df68b014c7fbd213 (patch) | |
tree | 5d40897f5508f6c681d93145506d1e4fa0ebd53a | |
parent | f2812c477b230a1407381bfbbb393119c7280076 (diff) | |
download | idalius-0475f0bb2fa7ee2f211c67f8df68b014c7fbd213.tar.xz |
Add runtime module {,un}loading
-rw-r--r-- | Plugin.pm | 34 | ||||
-rw-r--r-- | Plugin/Admin.pm | 65 | ||||
-rw-r--r-- | Plugin/DevNull.pm | 4 | ||||
-rw-r--r-- | Plugin/Echo.pm | 2 | ||||
-rw-r--r-- | Plugin/Introspect.pm | 24 | ||||
-rw-r--r-- | Plugin/Map.pm | 2 | ||||
-rw-r--r-- | Plugin/Ping.pm | 2 | ||||
-rw-r--r-- | Plugin/Random.pm | 4 | ||||
-rw-r--r-- | Plugin/Source.pm | 2 | ||||
-rw-r--r-- | Plugin/Thanks.pm | 8 | ||||
-rw-r--r-- | Plugin/Timezone.pm | 2 | ||||
-rwxr-xr-x | idalius.pl | 33 |
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; } @@ -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( \®ister_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 |