From: Christian Garbs Date: Fri, 26 Dec 2008 21:45:13 +0000 (+0100) Subject: add plugin system X-Git-Url: https://git.camperquake.de/gitweb.cgi?p=xmlrtorrent.git;a=commitdiff_plain;h=a4e872193217ce3466cffc6bd05ad6b2afb3b586 add plugin system heavily copied from videosite.pl currently a big no-op, just empty framework --- diff --git a/xmlrtorrent.pl b/xmlrtorrent.pl index d3e4f81..71b3b3e 100644 --- a/xmlrtorrent.pl +++ b/xmlrtorrent.pl @@ -13,9 +13,12 @@ use File::Spec; use List::Util qw(max); use xmlrtorrent; +my @talkers; +my $talker; my $conf; my $conffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'xmlrtorrent.xml'); my $scriptdir = File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts'); +my $plugindir = File::Spec->catfile($scriptdir, 'xmlrtorrent'); my %torrentlist = (); my $torrentindex = 1; my $rtorrent; @@ -30,7 +33,7 @@ my $PARAMS = { }; # activate debug here -my $debug = 0; +my $debug = 1; # "message public", SERVER_REC, char *msg, char *nick, char *address, char *target signal_add_last("message public" => sub {check_for_link(\@_,1,4,2,0);}); @@ -334,6 +337,64 @@ sub sig_command_script_unload { } } +sub ploader { + + my $dir = shift; + my $pattern = shift; + my $type = shift; + my @list; + my $p; + my $g; + my @g = (); + + opendir(D, $dir) || return (); + @list = grep {/$pattern/ && -f File::Spec->catfile($dir, $_) } readdir(D); + closedir(D); + + foreach $p (@list) { + write_debug('Trying to load %s:', $p); + $p =~ s/\.pm$//; + eval qq{ require xmlrtorrent::$p; }; + if ($@) { + write_irssi('Failed to load plugin: %s', "$@"); + next; + } + + $g = eval qq{ xmlrtorrent::$p->new(); }; + if ($@) { + write_irssi('Failed to instanciate: %s', "$@"); + delete($INC{$p}); + next; + } + + write_debug('found %s %s', $g->{'TYPE'}, $g->{'NAME'}); + if ($type eq $g->{'TYPE'}) { + push(@g, $g); + $g->setio(sub {Irssi::print(shift)}); + } else { + write_irssi('%s has wrong type (got %s, expected %s)', $p, $g->{'TYPE'}, $type); + delete($INC{$p}); + } + } + + write_debug('Loaded %d plugins', $#g+1); + + return @g; +} + +sub _load_modules($) { + + my $path = shift; + + foreach (keys(%INC)) { + if ($INC{$_} =~ m|^$path|) { + write_debug('Removing %s from $INC', $_); + delete($INC{$_}); + } + } + @talkers = ploader($path, '.*Talker\.pm$', 'talker'); +} + sub init_xmlrtorrent { my $bindings = shift; @@ -350,6 +411,23 @@ sub init_xmlrtorrent { } } + _load_modules($plugindir); + + unless (defined(@talkers)) { + write_irssi('No talkers found, can not proceed.'); + return; + } + + $talker = $talkers[0]; + foreach $p (@talkers) { + if ($conf->{'xmlrtorrent'}->{'talker'} eq $p->{'NAME'}) { + $talker = $p; + } + } + write_debug(undef, 'Selected %s as talker', $talker->{'NAME'}); + $conf->{'videosite'}->{'talker'} = $talker->{'NAME'}; + + # Restore the queue %torrentlist = %{$conf->{'xmlrtorrent'}->{'_QUEUE'}}; %torrentlist = map { my $a = substr($_, 1); ("$a" => $torrentlist{$_}) } keys(%torrentlist); diff --git a/xmlrtorrent/Base.pm b/xmlrtorrent/Base.pm new file mode 100644 index 0000000..aa9e348 --- /dev/null +++ b/xmlrtorrent/Base.pm @@ -0,0 +1,173 @@ +# (c) 2007 by Ralf Ertzinger +# licensed under GNU GPL v2 + +package xmlrtorrent::Base; + +use strict; +use Data::Dumper; + +sub new { + my $class = shift; + my $self = {'_DEBUG' => 0, '_OUT' => sub {print shift}}; + + bless($self, $class); + + $self->_prepare_parameters(); + + return $self; +} + +sub error { + my $self = shift; + my $t; + + $t = sprintf(shift(@_), @_); + $t =~ s/%/%%/g; + $self->{'_OUT'}($t); +} + +sub debug { + my $self = shift; + my @data = @_; + + $data[0] = "DEBUG: " . $data[0]; + if ($self->{'_DEBUG'} != 0) {$self->error(@data)}; +} + +sub mergeconfig { + my $self = shift; + my $c = shift; + my $o; + + return $self->{'_CONFIG'} unless defined($c); + + foreach $o (keys(%{$c->{'option'}})) { + if (exists($self->{'_CONFIG'}->{'option'}->{$o})) { + $self->{'_CONFIG'}->{'option'}->{$o}->{'content'} = $c->{'option'}->{$o}->{'content'}; + } + } + + return $self->{'_CONFIG'}; +} + +sub _prepare_parameters { + my $self = shift; + my $p; + + $self->{'_CONFIG'} = {'option' => {'enabled' => {'content' => '1'}}}; + + foreach $p (keys(%{$self->{'_PARAMS'}})) { + $self->{'_CONFIG'}->{'option'}->{$p}->{'content'} = $self->{'_PARAMS'}->{$p}->[0]; + } +} + +sub _getval { + my $self = shift; + my $key = shift; + my $val; + + $val = $self->{'_CONFIG'}->{'option'}->{$key}->{'content'}; + $self->debug('Returning %s=%s', $key, $val); + + return $val; +} + +sub setval { + my $self = shift; + my $key = shift; + my $val = shift; + + if (exists($self->{'_CONFIG'}->{'option'}->{$key})) { + $self->{'_CONFIG'}->{'option'}->{$key}->{'content'} = $val; + } else { + $self->error('Module %s does not have a parameter named %s', $self->{'NAME'}, $key); + } +} + +sub setio { + my $self = shift; + my $io = shift; + + $self->{'_OUT'} = $io; +} + +sub getconfstr { + my $self = shift; + my $s = 'Options for ' . $self->{'NAME'} . ":\n"; + my $k; + my $p; + + foreach $k (keys(%{$self->{'_CONFIG'}->{'option'}})) { + $p = $self->{'_CONFIG'}->{'option'}->{$k}->{'content'}; + $p =~ s/%/%%/g; + $s .= sprintf(" %s: %s", $k, $p); + if ($self->{'_CONFIG'}->{'option'}->{$k}->{'content'} eq $self->{'_PARAMS'}->{$k}->[0]) { + $s .= " (default)\n"; + } else { + $s .= "\n"; + } + } + + return $s; +} + +# Return a list of the parameters supported by the module +# Does not return the 'enabled' parameter +sub getparamlist { + my $self = shift; + my $word = shift; + + return grep {$_ ne 'enabled' && /^$word/} keys %{$self->{'_PARAMS'}}; +} + +# Return a list of valid parameter values, if the parameter has +# such a list. +sub getparamvalues { + my $self = shift; + my $param = shift; + my $word = shift; + + unless(exists($self->{'_PARAMS'}->{$param}->[2])) { + return (); + } else { + return grep {/^$word/} keys %{$self->{'_PARAMS'}->{$param}->[2]}; + } +} + + +sub gethelpstr { + my $self = shift; + my $s = 'Help for ' . $self->{'NAME'} . ":\n"; + my $k; + my $p; + + if (exists($self->{'DESC'})) { + $s .= "Description:\n " . $self->{'DESC'}; + } + + $s .= " Options:\n"; + foreach $k (keys(%{$self->{'_CONFIG'}->{'option'}})) { + $p = $self->{'_PARAMS'}->{$k}->[0]; + $p =~ s/%/%%/g; + if (exists($self->{'_PARAMS'}->{$k}->[2])) { + # The parameter has a list of allowed values. Add the keys and their help + $s .= sprintf(" %s: %s (default: %s)\n", $k, $self->{'_PARAMS'}->{$k}->[1], $p); + foreach (sort keys(%{$self->{'_PARAMS'}->{$k}->[2]})) { + $s .= sprintf(" %s: %s\n", $_, $self->{'_PARAMS'}->{$k}->[2]->{$_}); + } + } else { + # The parameter just has a default value and a help text + $s .= sprintf(" %s: %s (default: %s)\n", $k, $self->{'_PARAMS'}->{$k}->[1], $p); + } + } + + return $s; +} + +sub setdebug { + my $self = shift; + + $self->{'_DEBUG'} = shift; +} + +1; diff --git a/xmlrtorrent/HTTPTalker.pm b/xmlrtorrent/HTTPTalker.pm new file mode 100644 index 0000000..612d9fc --- /dev/null +++ b/xmlrtorrent/HTTPTalker.pm @@ -0,0 +1,27 @@ +# Talker using RPC over HTTP +# +# (c) 2008 by Ralf Ertzinger +# licensed under GNU GPL v2 + +package xmlrtorrent::HTTPTalker; +use xmlrtorrent::TalkerBase; +@ISA = qw(xmlrtorrent::TalkerBase); + +use Data::Dumper; + +use strict; + +sub new { + my $class = shift; + my $self = $class->SUPER::new(); + + $self->{'NAME'} = 'http'; + + bless($self, $class); + + $self->_prepare_parameters(); + + return $self; +} + +1; diff --git a/xmlrtorrent/TalkerBase.pm b/xmlrtorrent/TalkerBase.pm new file mode 100644 index 0000000..d1fa7c8 --- /dev/null +++ b/xmlrtorrent/TalkerBase.pm @@ -0,0 +1,20 @@ +# (c) 2007 by Ralf Ertzinger +# licensed under GNU GPL v2 + +package xmlrtorrent::TalkerBase; +use xmlrtorrent::Base; +@ISA = qw(xmlrtorrent::Base); + +use strict; + +sub new { + my $class = shift; + my $self = $class->SUPER::new(); + + $self = {%{$self}, + TYPE => 'talker', + }; + return bless($self, $class); +} + +1;