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