- Add the ability to enable/disable selected grabber modules
[videosite.git] / videosite.pl
1 # autodownload flash videos
2 #
3 # (c) 2007-2008 by Ralf Ertzinger <ralf@camperquake.de>
4 # licensed under GNU GPL v2
5 #
6 # Based on youtube.pl by Christian Garbs <mitch@cgarbs.de>
7 # which in turn is
8 # based on trigger.pl by Wouter Coekaerts <wouter@coekaerts.be>
9
10 use strict;
11 use Irssi 20020324 qw (command_bind command_runsub signal_add_first signal_add_last);
12 use vars qw($VERSION %IRSSI);
13 use XML::Simple;
14 use Data::Dumper;
15 use File::Spec;
16
17 my @grabbers;
18 my @getters;
19 my $getter;
20 my $conf;
21 my $conffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.xml');
22
23 # activate debug here
24 my $debug = 0;
25
26 # "message public", SERVER_REC, char *msg, char *nick, char *address, char *target
27 signal_add_last("message public" => sub {check_for_link(\@_,1,4,2,0);});
28 # "message own_public", SERVER_REC, char *msg, char *target
29 signal_add_last("message own_public" => sub {check_for_link(\@_,1,2,-1,0);});
30
31 # "message private", SERVER_REC, char *msg, char *nick, char *address
32 signal_add_last("message private" => sub {check_for_link(\@_,1,-1,2,0);});
33 # "message own_private", SERVER_REC, char *msg, char *target, char *orig_target
34 signal_add_last("message own_private" => sub {check_for_link(\@_,1,2,-1,0);});
35
36 # "message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target
37 signal_add_last("message irc action" => sub {check_for_link(\@_,1,4,2,0);});
38 # "message irc own_action", SERVER_REC, char *msg, char *target
39 signal_add_last("message irc own_action" => sub {check_for_link(\@_,1,2,-1,0);});
40
41 sub write_irssi {
42     my $witem = shift;
43     my @text = @_;
44
45     $text[0] = 'videosite: ' . $text[0];
46
47     if (defined $witem) {
48         $witem->print(sprintf(shift(@text), @text), MSGLEVEL_CLIENTCRAP);
49     } else {
50         Irssi::print(sprintf(shift(@text), @text));
51     }
52
53 }
54
55 sub write_debug {
56     if ($debug) {
57         write_irssi(shift, @_);
58     }
59 }
60
61 sub check_for_link {
62     my ($signal,$parammessage,$paramchannel,$paramnick,$paramserver) = @_;
63     my $server = $signal->[$paramserver];
64     my $target = $signal->[$paramchannel];
65     my $message = ($parammessage == -1) ? '' : $signal->[$parammessage];
66     my $g;
67     my $m;
68
69
70     my $witem;
71     if (defined $server) {
72         $witem = $server->window_item_find($target);
73     } else {
74         $witem = Irssi::window_item_find($target);
75     }
76
77     # Look if we should ignore this line
78     if ($message =~ m,(?:\s|^)/nosave(?:\s|$),) {
79         return;
80     }
81
82     # Offer the message to all Grabbers in turn
83     foreach $g (@grabbers) {
84         if (defined($m = $g->get($message))) {
85             write_debug($witem, 'Metadata: %s', Dumper($m));
86             write_irssi($witem, '%%R>>> %%NSaving %%Y%s%%N %%G%s', $m->{'SOURCE'}, $m->{'TITLE'});
87             unless($getter->get($m)) {
88                 write_irssi($witem, '%%R>>> FAILED');
89             }
90         }
91     }
92 }
93
94 sub cmd_save {
95
96     eval {
97         open(CONF, '>'.$conffile) or die 'Could not open config file';
98         print CONF XML::Simple::XMLout($conf, KeepRoot => 1, KeyAttr => {'config' => 'module', 'option' => 'key'});
99         close(CONF);
100     };
101     if ($@) {
102         write_irssi(undef, 'Could not save config to %s: %s', ($conffile, $@));
103     } else {
104         write_irssi(undef, 'configuration saved to %s', $conffile);
105     }
106 }
107
108 sub cmd_set {
109     my $target = shift;
110     my $key = shift;
111     my $val = shift;
112     my $p;
113
114     foreach $p (@getters, @grabbers) {
115         if ($p->{'NAME'} eq $target) {
116             $p->setval($key, $val);
117             return;
118         }
119     }
120     write_irssi(undef, 'No such module');
121 }
122
123
124 sub cmd_enable {
125     my $target = shift;
126     my $p;
127
128     foreach $p (@grabbers) {
129         if ($p->{'NAME'} eq $target) {
130             $p->enable();
131             return;
132         }
133     }
134     write_irssi(undef, 'No such module');
135 }
136
137
138 sub cmd_disable {
139     my $target = shift;
140     my $p;
141
142     foreach $p (@grabbers) {
143         if ($p->{'NAME'} eq $target) {
144             $p->disable();
145             return;
146         }
147     }
148     write_irssi(undef, 'No such module');
149 }
150
151
152 sub cmd_show {
153     my $target = shift;
154     my $p;
155     my $e;
156
157     if (defined($target)) {
158         foreach $p (@getters, @grabbers) {
159             if ($p->{'NAME'} eq $target) {
160                 write_irssi(undef, $p->getconfstr());
161                 return;
162             }
163         }
164         write_irssi(undef, 'No such module');
165     } else {
166         write_irssi(undef, 'Loaded grabbers (* denotes enabled modules):');
167         foreach $p (@grabbers) {
168             $e = $p->_getval('enabled');
169             write_irssi(undef, ' %s%s', $p->{'NAME'}, $e?'*':'');
170         };
171
172         write_irssi(undef, 'Loaded getters:');
173         foreach $p (@getters) {
174             write_irssi(undef, ' %s', $p->{'NAME'});
175         };
176     }
177 }
178
179 sub cmd_help {
180     my $target = shift;
181     my $p;
182
183     if (defined($target)) {
184         foreach $p (@getters, @grabbers) {
185             if ($p->{'NAME'} eq $target) {
186                 write_irssi(undef, $p->gethelpstr());
187                 return;
188             }
189         }
190         write_irssi(undef, 'No such module');
191     } else {
192         write_irssi(undef, <<'EOT');
193 Supported commands:
194  save: Save the current configuration
195  help [modulename]: Display this help, or module specific help
196  show [modulename]: Show loaded modules, or the current parameters of a module
197  set modulename parameter value: set a module parameter to a new value
198  getter [modulename]: display or set the getter to use
199  enable [modulename]: enable the usage of this module (grabbers only)
200  disable [modulename]: disable the usage of this module (grabbers only)
201  debug: enable debugging messages
202  nodebug: disable debugging messages
203 EOT
204     }
205 }
206
207 sub cmd_getter {
208     my $target = shift;
209     my $p;
210
211     if (defined($target)) {
212         foreach $p (@getters, @grabbers) {
213             if (($p->{'NAME'} eq $target) && ($p->{'TYPE'} eq 'getter')) {
214                 $getter = $p;
215                 $conf->{'videosite'}->{'getter'} = $target;
216                 return;
217             }
218         }
219         write_irssi(undef, 'No such getter');
220     } else {
221         write_irssi(undef, 'Current getter: %s', $conf->{'videosite'}->{'getter'});
222     }
223 }
224
225
226 # save on unload
227 sub sig_command_script_unload {
228     my $script = shift;
229     if ($script =~ /(.*\/)?videosite(\.pl)?$/) {
230         cmd_save();
231     }
232 }
233
234 sub ploader {
235
236     my $dir = shift;
237     my $pattern = shift;
238     my $type = shift;
239     my @list;
240     my $p;
241     my $g;
242     my @g = ();
243
244     opendir(D, $dir) || return ();
245     @list = grep {/$pattern/ && -f File::Spec->catfile($dir, $_) } readdir(D);
246     closedir(D);
247
248     foreach $p (@list) {
249         write_debug(undef, "Trying to load $p:");
250         $p =~ s/\.pm$//;
251         eval qq{ require $p; };
252         if ($@) {
253             write_debug(undef, "Failed to load plugin: $@");
254             next;
255         }
256
257         $g = eval $p.q{->new();};
258         if ($@) {
259             write_debug(undef, "Failed to instanciate: $@");
260             next;
261         }
262
263         write_debug(undef, "found $g->{'TYPE'} $g->{'NAME'}");
264         if ($type eq $g->{'TYPE'}) {
265             push(@g, $g);
266         } else {
267             write_irssi(undef, '%s has wrong type (got %s, expected %s)', $p, $g->{'TYPE'}, $type);
268         }
269     }
270
271     write_debug(undef, "Loaded %d plugins", $#g+1);
272     
273     return @g;
274 }
275
276 sub init_videosite {
277
278     my $p;
279
280     unless(-r $conffile && defined($conf = XML::Simple::XMLin($conffile, ForceArray => ['config', 'option'], KeepRoot => 1, KeyAttr => {'config' => 'module', 'option' => 'key'}))) {
281         # No config, start with an empty one
282         write_debug(undef, 'No config found, using defaults');
283         $conf = { 'videosite' => { 'getter' => '' }};
284     }
285
286     unshift(@INC, File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts', 'videosite'));
287     @grabbers = ploader(File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts', 'videosite'), '.*Grabber\.pm$', 'grabber');
288     @getters = ploader(File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts', 'videosite'), '.*Getter\.pm$', 'getter');
289
290     unless (defined(@grabbers) && defined(@getters)) {
291         write_irssi(undef, 'No grabbers or no getters found, can not proceed.');
292         return;
293     }
294
295     $getter = $getters[0];
296     foreach $p (@getters) {
297         if ($conf->{'videosite'}->{'getter'} eq $p->{'NAME'}) {
298             $getter = $p;
299         }
300     }
301     write_debug(undef, 'Selected %s as getter', $getter->{'NAME'});
302     $conf->{'videosite'}->{'getter'} = $getter->{'NAME'};
303
304     # Loop through all plugins and load the config
305     foreach $p (@grabbers, @getters) {
306         $conf->{'videosite'}->{'config'}->{$p->{'NAME'}} = $p->mergeconfig($conf->{'videosite'}->{'config'}->{$p->{'NAME'}});
307     }
308
309     Irssi::signal_add_first('command script load', 'sig_command_script_unload');
310     Irssi::signal_add_first('command script unload', 'sig_command_script_unload');
311     Irssi::signal_add('setup saved', 'cmd_save');
312
313
314     Irssi::command_bind('videosite' => \&cmdhandler);
315 }
316
317 sub cmdhandler {
318     my ($data, $server, $item) = @_;
319     my @params = split(/\s+/, $data);
320
321     if ($params[0] eq 'save') {
322         cmd_save();
323     } elsif ($params[0] eq 'set') {
324         shift(@params);
325         cmd_set(@params);
326     } elsif ($params[0] eq 'show') {
327         shift(@params);
328         cmd_show(@params);
329     } elsif ($params[0] eq 'help') {
330         shift(@params);
331         cmd_help(@params);
332     } elsif ($params[0] eq 'getter') {
333         shift(@params);
334         cmd_getter(@params);
335     } elsif ($params[0] eq 'enable') {
336         shift(@params);
337         cmd_enable(@params);
338     } elsif ($params[0] eq 'disable') {
339         shift(@params);
340         cmd_disable(@params);
341     } elsif ($params[0] eq 'debug') {
342         $debug = 1;
343         foreach (@grabbers, @getters) {
344             $_->setdebug(1);
345         }
346         write_irssi(undef, 'Enabled debugging');
347     } elsif ($params[0] eq 'nodebug') {
348         $debug = 0;
349         foreach (@grabbers, @getters) {
350             $_->setdebug(0);
351         }
352         write_irssi(undef, 'Disabled debugging');
353     }
354 }
355
356 init_videosite();