2015-09-07 07:52:39 +02:00
|
|
|
# File: Plugins.pm
|
2015-09-07 07:17:07 +02:00
|
|
|
# Author: pragma-
|
|
|
|
#
|
2015-09-07 07:52:39 +02:00
|
|
|
# Purpose: Loads and manages plugins.
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2017-03-05 22:33:31 +01:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
package PBot::Plugins;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2019-07-11 03:40:53 +02:00
|
|
|
use feature 'unicode_strings';
|
|
|
|
|
2015-09-07 07:17:07 +02:00
|
|
|
use File::Basename;
|
|
|
|
use Carp ();
|
|
|
|
|
|
|
|
sub new {
|
2019-05-28 18:19:42 +02:00
|
|
|
if (ref($_[1]) eq 'HASH') {
|
2015-09-07 07:17:07 +02:00
|
|
|
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
|
|
|
|
}
|
|
|
|
|
|
|
|
my ($class, %conf) = @_;
|
|
|
|
|
|
|
|
my $self = bless {}, $class;
|
|
|
|
$self->initialize(%conf);
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub initialize {
|
|
|
|
my ($self, %conf) = @_;
|
|
|
|
|
|
|
|
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
|
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{plugins} = {};
|
2015-09-07 07:17:07 +02:00
|
|
|
|
|
|
|
$self->{pbot}->{commands}->register(sub { $self->load_cmd(@_) }, "plug", 90);
|
|
|
|
$self->{pbot}->{commands}->register(sub { $self->unload_cmd(@_) }, "unplug", 90);
|
2019-05-09 06:06:56 +02:00
|
|
|
$self->{pbot}->{commands}->register(sub { $self->reload_cmd(@_) }, "replug", 90);
|
2015-09-07 07:17:07 +02:00
|
|
|
$self->{pbot}->{commands}->register(sub { $self->list_cmd(@_) }, "pluglist", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub autoload {
|
2015-09-07 07:39:40 +02:00
|
|
|
my ($self, %conf) = @_;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-09-01 20:01:18 +02:00
|
|
|
return if $self->{pbot}->{registry}->get_value('plugins', 'noautoload');
|
|
|
|
|
2019-12-22 04:01:59 +01:00
|
|
|
my $path = $self->{pbot}->{registry}->get_value('general', 'plugin_dir') // 'Plugins';
|
2019-12-29 07:18:32 +01:00
|
|
|
my $data_dir = $self->{pbot}->{registry}->get_value('general', 'data_dir');
|
2019-09-01 20:01:18 +02:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Loading plugins ...\n");
|
|
|
|
my $plugin_count = 0;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-12-22 00:26:01 +01:00
|
|
|
my $fh;
|
2019-12-29 07:18:32 +01:00
|
|
|
if (not open $fh, "<$data_dir/plugin_autoload") {
|
|
|
|
$self->{pbot}->{logger}->log("warning: file $data_dir/plugin_autoload does not exist; skipping autoloading of Plugins\n");
|
2019-12-22 00:26:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
chomp(my @plugins = <$fh>);
|
|
|
|
close $fh;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
foreach my $plugin (sort @plugins) {
|
|
|
|
$plugin = basename $plugin;
|
|
|
|
$plugin =~ s/.pm$//;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-12-29 07:28:39 +01:00
|
|
|
# do not load plugins that begin with a comment
|
|
|
|
next if $plugin =~ m/^\s*#/;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$plugin_count++ if $self->load($plugin, %conf)
|
2015-09-07 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("$plugin_count plugin" . ($plugin_count == 1 ? '' : 's') . " loaded.\n");
|
2015-09-07 07:17:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub load {
|
2015-09-07 07:52:39 +02:00
|
|
|
my ($self, $plugin, %conf) = @_;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->unload($plugin);
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-09-01 20:01:18 +02:00
|
|
|
return if $self->{pbot}->{registry}->get_value('plugins', 'disabled');
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-12-22 04:01:59 +01:00
|
|
|
my $path = $self->{pbot}->{registry}->get_value('general', 'plugin_dir') // 'Plugins';
|
2019-09-01 20:01:18 +02:00
|
|
|
|
|
|
|
if (not grep { $_ eq $path } @INC) {
|
|
|
|
unshift @INC, $path;
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->{pbot}->{refresher}->{refresher}->refresh_module("$path/$plugin.pm");
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2019-06-26 18:34:19 +02:00
|
|
|
my $ret = eval {
|
2019-12-22 04:33:53 +01:00
|
|
|
require "$path/$plugin.pm";
|
2015-09-07 07:17:07 +02:00
|
|
|
|
|
|
|
if ($@) {
|
|
|
|
chomp $@;
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Error loading $plugin: $@\n");
|
2015-09-07 07:17:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Loading $plugin\n");
|
2019-12-22 04:33:53 +01:00
|
|
|
my $class = "Plugins::$plugin";
|
2015-09-07 07:39:40 +02:00
|
|
|
my $mod = $class->new(pbot => $self->{pbot}, %conf);
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{plugins}->{$plugin} = $mod;
|
2019-09-01 20:01:18 +02:00
|
|
|
$self->{pbot}->{refresher}->{refresher}->update_cache("$path/$plugin.pm");
|
2015-09-07 07:17:07 +02:00
|
|
|
return 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
if ($@) {
|
|
|
|
chomp $@;
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Error loading $plugin: $@\n");
|
2015-09-07 07:17:07 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub unload {
|
2015-09-07 07:52:39 +02:00
|
|
|
my ($self, $plugin) = @_;
|
2015-09-07 07:17:07 +02:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
if (exists $self->{plugins}->{$plugin}) {
|
2015-09-07 07:17:07 +02:00
|
|
|
eval {
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{plugins}->{$plugin}->unload;
|
|
|
|
delete $self->{plugins}->{$plugin};
|
2015-09-07 07:17:07 +02:00
|
|
|
};
|
|
|
|
if ($@) {
|
|
|
|
chomp $@;
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Warning: got error unloading plugin $plugin: $@\n");
|
2015-09-07 07:17:07 +02:00
|
|
|
}
|
2016-02-14 03:37:53 +01:00
|
|
|
|
2019-12-22 04:01:59 +01:00
|
|
|
my $path = $self->{pbot}->{registry}->get_value('general', 'plugin_dir') // 'Plugins';
|
2019-09-01 20:01:18 +02:00
|
|
|
my $class = $path;
|
|
|
|
$class =~ s,[/\\],::,g;
|
|
|
|
|
|
|
|
$self->{pbot}->{refresher}->{refresher}->unload_module($class . '::' . $plugin);
|
|
|
|
$self->{pbot}->{refresher}->{refresher}->unload_subs("$path/$plugin.pm");
|
2016-02-14 03:37:53 +01:00
|
|
|
|
2015-09-07 07:52:39 +02:00
|
|
|
$self->{pbot}->{logger}->log("Plugin $plugin unloaded.\n");
|
2015-09-07 07:17:07 +02:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-09 06:06:56 +02:00
|
|
|
sub reload_cmd {
|
|
|
|
my ($self, $from, $nick, $user, $host, $arguments) = @_;
|
|
|
|
|
|
|
|
if (not length $arguments) {
|
|
|
|
return "Usage: replug <plugin>";
|
|
|
|
}
|
|
|
|
|
|
|
|
my $unload_result = $self->unload_cmd($from, $nick, $user, $host, $arguments);
|
|
|
|
my $load_result = $self->load_cmd($from, $nick, $user, $host, $arguments);
|
|
|
|
|
|
|
|
my $result = "";
|
|
|
|
$result .= "$unload_result " if $unload_result =~ m/^Unloaded/;
|
|
|
|
$result .= $load_result;
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2015-09-07 07:17:07 +02:00
|
|
|
sub load_cmd {
|
|
|
|
my ($self, $from, $nick, $user, $host, $arguments) = @_;
|
|
|
|
|
|
|
|
if (not length $arguments) {
|
|
|
|
return "Usage: plug <plugin>";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($self->load($arguments)) {
|
|
|
|
return "Loaded $arguments plugin.";
|
|
|
|
} else {
|
2015-09-07 07:22:37 +02:00
|
|
|
return "Plugin $arguments failed to load.";
|
2015-09-07 07:17:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub unload_cmd {
|
|
|
|
my ($self, $from, $nick, $user, $host, $arguments) = @_;
|
|
|
|
|
|
|
|
if (not length $arguments) {
|
|
|
|
return "Usage: unplug <plugin>";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($self->unload($arguments)) {
|
|
|
|
return "Unloaded $arguments plugin.";
|
|
|
|
} else {
|
2020-01-31 04:44:40 +01:00
|
|
|
return "Plugin $arguments is not loaded.";
|
2015-09-07 07:17:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub list_cmd {
|
|
|
|
my ($self, $from, $nick, $user, $host, $arguments) = @_;
|
|
|
|
|
|
|
|
my $result = "Loaded plugins: ";
|
|
|
|
my $count = 0;
|
|
|
|
my $comma = '';
|
|
|
|
|
2017-04-11 04:55:52 +02:00
|
|
|
foreach my $plugin (sort keys %{ $self->{plugins} }) {
|
2015-09-07 07:17:07 +02:00
|
|
|
$result .= $comma . $plugin;
|
|
|
|
$count++;
|
|
|
|
$comma = ', ';
|
|
|
|
}
|
|
|
|
|
|
|
|
$result .= 'none' if $count == 0;
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|