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