-use File::Temp qw(tempfile);
-
-my @grabbers;
-my @getters;
-my $getter;
-my $conf;
-my $xmlconffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.xml');
-my $conffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.json');
-my $scriptdir = File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts');
-my $plugindir = File::Spec->catfile($scriptdir, 'videosite');
-my @outputstack = (undef);
-
-# "message public", SERVER_REC, char *msg, char *nick, char *address, char *target
-signal_add_last(_bcs("message public" => sub {check_for_link(@_)}));
-# "message own_public", SERVER_REC, char *msg, char *target
-signal_add_last(_bcs("message own_public" => sub {check_for_link(@_)}));
-
-# "message private", SERVER_REC, char *msg, char *nick, char *address
-signal_add_last(_bcs("message private" => sub {check_for_link(@_)}));
-# "message own_private", SERVER_REC, char *msg, char *target, char *orig_target
-signal_add_last(_bcs("message own_private" => sub {check_for_link(@_)}));
-
-# "message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target
-signal_add_last(_bcs("message irc action" => sub {check_for_link(@_)}));
-# "message irc own_action", SERVER_REC, char *msg, char *target
-signal_add_last(_bcs("message irc own_action" => sub {check_for_link(@_)}));
-
-# For tab completion
-# This does not use BettIrssi (yet)
-signal_add_first('complete word', \&sig_complete);
-
-sub push_output {
- unshift(@outputstack, shift);
-}
-
-sub pop_output {
- shift(@outputstack);
-
- @outputstack = (undef) unless (@outputstack);
-}
-
-my $videosite_commands = {
- 'save' => sub {
- cmd_save();
- },
-
- 'set' => sub {
- cmd_set(@_);
- },
-
- 'show' => sub {
- cmd_show(@_);
- },
-
- 'help' => sub {
- cmd_help(@_);
- },
-
- 'getter' => sub {
- cmd_getter(@_);
- },
-
- 'enable' => sub {
- cmd_enable(@_);
- },
-
- 'disable' => sub {
- cmd_disable(@_);
- },
-
- 'reload' => sub {
- init_videosite(0);
- },
-
- 'mode' => sub {
- cmd_mode(@_);
- },
-
- 'connector' => sub {
- cmd_connector(@_);
- },
-
- 'debug' => sub {
- $debug = 1;
- foreach (@grabbers, @getters) {
- $_->setdebug(1);
- }
- write_irssi('Enabled debugging');
- },
-
- 'nodebug' => sub {
- $debug = 0;
- foreach (@grabbers, @getters) {
- $_->setdebug(0);
- }
- write_irssi('Disabled debugging');
- },
-};
-
-sub write_irssi {
- my @text = @_;
- my $output = $outputstack[0];
-
- my $format = "%%mvideosite: %%n" . shift(@text);
-
- # escape % in parameters from irssi
- s/%/%%/g foreach @text;
-
- if (defined $output) {
- $output->(sprintf($format, @text), MSGLEVEL_CLIENTCRAP);
- } else {
- Irssi::print(sprintf($format, @text));
- }
-
-}
-
-sub write_debug {
- if ($debug) {
- write_irssi(@_);
- }
-}
-
-sub expand_url_shortener {
- my $s = shift;
- my $os = '';
- my @urlshortener = (
- 'is\.gd/[[:alnum:]]+',
- 'otf\.me/[[:alnum:]]+',
- 'hel\.me/[[:alnum:]]+',
- '7ax\.de/[[:alnum:]]+',
- 'ow\.ly/[[:alnum:]]+',
- 'j\.mp/[[:alnum:]]+',
- 'bit\.ly/[[:alnum:]]+',
- 'tinyurl\.com/[[:alnum:]]+',
- 'pop\.is/[[:alnum:]]+',
- 'post\.ly/[[:alnum:]]+',
- '1\.ly/[[:alnum:]]+',
- '2\.ly/[[:alnum:]]+',
- 't\.co/[[:alnum:]]+',
- 'shar\.es/[[:alnum:]]+',
- 'goo\.gl/[[:alnum:]]+',
- );
- my $ua = LWP::UserAgent->new(agent => 'Mozilla', max_redirect => 0, timeout => 5);
- my $i = 10;
-
- OUTER: while (($os ne $s) and ($i > 0)) {
- study($s);
- $os = $s;
- $i--;
-
- foreach my $pattern (@urlshortener) {
- my $p = "https?:\/\/" . $pattern;
-
- write_debug("Matching %s against %s", $p, $s);
- if ($s =~ m|($p)|) {
- my $matched = $1;
- my $res;
-
- write_debug("Found %s", $matched);
- $res = $ua->head($matched);
- if ($res->is_redirect()) {
- my $new = $res->headers()->header("Location");
-
- write_debug("Replacing %s with %s", $matched, $new);
- $s =~ s/$matched/$new/;
- next OUTER;
- } else {
- write_debug("Error resolving %s", $matched);
- }
- }
- }
- }
-
- if ($i == 0) {
- write_debug("Loop terminated by counter");
- }
-
- write_debug("Final string: %s", $s);
-
- return $s;
-}
-
-sub connectorlist {
- my @c;
-
- foreach (@{$conf->{'videosite'}->{'connectorlist'}}) {
- push(@c, $conf->{'videosite'}->{'connectors'}->{$_});
- }
-
- return @c;
-}
-
-
-sub check_for_link {
- my $event = shift;
- my $message = $event->message();
- my $witem = $event->channel();
- my $g;
- my $m;
- my $p;
-
-
- # Look if we should ignore this line
- if ($message =~ m,(?:\s|^)/nosave(?:\s|$),) {
- return;
- }
-
- push_output($event->ewpf);
- $message = expand_url_shortener($message);
-
- study($message);
-
- # Offer the message to all Grabbers in turn
- GRABBER: foreach $g (@grabbers) {
- ($m, $p) = $g->get($message);
- while (defined($m)) {
- write_debug('Metadata: %s', Dumper($m));
- if ('download' eq ($conf->{'videosite'}->{'mode'})) {
- write_irssi('%%R>>> %%NSaving %%Y%s%%N %%G%s', $m->{'SOURCE'}, $m->{'TITLE'});
- unless($getter->get($m)) {
- write_irssi('%%R>>> FAILED');
- }
- } elsif ('display' eq ($conf->{'videosite'}->{'mode'})) {
- write_irssi('%%M>>> %%NSaw %%Y%s%%N %%G%s', $m->{'SOURCE'}, $m->{'TITLE'});
- } else {
- write_irssi('%%R>>> Invalid operation mode');
- }
-
- # Remove the matched part from the message and try again (there may be
- # more!)
- $message =~ s/$p//;
- study($message);
- last GRABBER if ($message =~ /^\s*$/);
-
- ($m, $p) = $g->get($message);
- }
- }
-
- pop_output();
-}
-
-sub cmd_save {
-
- eval {
- my ($tempfile, $tempfn) = tempfile("videosite.json.XXXXXX", dir => Irssi::get_irssi_dir());
- print $tempfile JSON->new->pretty->utf8->encode($conf);
- close($tempfile);
- rename($tempfn, $conffile);
- };
- if ($@) {
- write_irssi('Could not save config to %s: %s', ($conffile, $@));
- } else {
- write_irssi('configuration saved to %s', $conffile);
- }
-}
-
-sub cmd_set {
- my $target = shift;
- my $key = shift;
- my $val = shift;
- my $p;
-
- foreach $p (@getters, @grabbers) {
- if ($p->{'NAME'} eq $target) {
- $p->setval($key, $val);
- return;
- }
- }
- write_irssi('No such module');
-}
-
-
-sub cmd_enable {
- my $target = shift;
- my $p;
-
- foreach $p (@grabbers) {
- if ($p->{'NAME'} eq $target) {
- $p->enable();
- return;
- }
- }
- write_irssi('No such module');
-}
-
-
-sub cmd_disable {
- my $target = shift;
- my $p;
-
- foreach $p (@grabbers) {
- if ($p->{'NAME'} eq $target) {
- $p->disable();
- return;
- }
- }
- write_irssi('No such module');
-}
-
-
-sub cmd_show {
- my $target = shift;
- my $p;
- my $e;
-
- if (defined($target)) {
- foreach $p (@getters, @grabbers) {
- if ($p->{'NAME'} eq $target) {
- write_irssi($p->getconfstr());
- return;
- }
- }
- write_irssi('No such module');
- } else {
- write_irssi('Loaded grabbers (* denotes enabled modules):');
- foreach $p (@grabbers) {
- $e = $p->_getval('enabled');
- write_irssi(' %s%s', $p->{'NAME'}, $e?'*':'');
- };
-
- write_irssi('Loaded getters:');
- foreach $p (@getters) {
- write_irssi(' %s', $p->{'NAME'});
- };
- }
-}
-
-sub cmd_help {
- my $target = shift;
- my $p;
-
- if (defined($target)) {
- foreach $p (@getters, @grabbers) {
- if ($p->{'NAME'} eq $target) {
- write_irssi($p->gethelpstr());
- return;
- }
- }
- write_irssi('No such module');
- } else {
- write_irssi(<<'EOT');
-Supported commands:
- save: save the current configuration
- help [modulename]: display this help, or module specific help
- show [modulename]: show loaded modules, or the current parameters of a module
- set modulename parameter value: set a module parameter to a new value
- getter [modulename]: display or set the getter to use
- enable [modulename]: enable the usage of this module (grabbers only)
- disable [modulename]: disable the usage of this module (grabbers only)
- reload: reload all modules (this is somewhat experimental)
- mode [modename]: display or set the operation mode (download/display)
- connector [subcommand]: manage connectors (proxies)
- debug: enable debugging messages
- nodebug: disable debugging messages
-EOT
- }
-}
-
-sub cmd_getter {
- my $target = shift;
- my $p;
-
- if (defined($target)) {
- foreach $p (@getters) {
- if ($p->{'NAME'} eq $target) {
- $getter = $p;
- $conf->{'videosite'}->{'getter'} = $target;
- write_irssi("Getter changed to %s", $target);
- return;
- }
- }
- write_irssi('No such getter');
- } else {
- write_irssi('Current getter: %s', $conf->{'videosite'}->{'getter'});
- }
-}
-
-sub cmd_mode {
- my $mode = shift;
-
- if (defined($mode)) {
- $mode = lc($mode);
- if (('download' eq $mode) or ('display' eq $mode)) {
- $conf->{'videosite'}->{'mode'} = $mode;
- write_irssi('Now using %s mode', $mode);
- } else {
- write_irssi('Invalid mode: %s', $mode);
- }
- } else {
- write_irssi('Current mode: %s', $conf->{'videosite'}->{'mode'});
- }
-}
-
-sub cmd_connector {
- my $subcmd = shift;
- my $connconf = $conf->{'videosite'}->{'connectors'};
-
- unless(defined($subcmd)) {
- $subcmd = "help";
- }
-
- $subcmd = lc($subcmd);
-
- if ($subcmd eq 'list') {
- write_irssi("Defined connectors");
- foreach (keys(%{$connconf})) {
- write_irssi($_);
- my $schemas = $connconf->{$_}->{'schemas'};
- if (scalar(keys(%{$schemas})) == 0) {
- write_irssi(" No schemas defined");
- } else {
- foreach (keys(%{$schemas})) {
- write_irssi(' %s: %s', $_, $schemas->{$_});
- }
- }
- }
-
- write_irssi();
- write_irssi("Selected connectors: %s", join(", ", @{$conf->{'videosite'}->{'connectorlist'}}));
- } elsif ($subcmd eq 'add') {
- my ($name) = @_;
-
- unless(defined($name)) {
- write_irssi("No name given");
- return;
- }
-
- $name = lc($name);
-
- if (exists($connconf->{$_})) {
- write_irssi("Connector already exists");
- return;
- }
-
- $connconf->{$name} = {'name' => $name, 'schemas' => {}};
- } elsif ($subcmd eq 'del') {
- my ($name) = @_;
-
- unless(defined($name)) {
- write_irssi("No name given");
- return;
- }
-
- $name = lc($name);
-
- unless (exists($connconf->{$name})) {
- write_irssi("Connector does not exist");
- return;
- }
-
- if (exists($connconf->{$name}->{'_immutable'})) {
- write_irssi("Connector cannot be removed");
- return;
- }
-
- delete($connconf->{$name});
-
- # Remove from list of active connectors
- $conf->{'videosite'}->{'connectorlist'} =
- [ grep { $_ ne $name } @{$conf->{'videosite'}->{'connectorlist'}} ];
-
- if (scalar(@{$conf->{'videosite'}->{'connectorlist'}}) == 0) {
- write_irssi("List of selected connectors is empty, resetting to direct");
- $conf->{'videosite'}->{'connectorlist'} = [ 'direct' ];
- }
- } elsif ($subcmd eq 'addschema') {
- my ($conn, $schema, $proxy) = @_;
-
- unless(defined($conn)) {
- write_irssi("No connector name given");
- return;
- }
-
- $conn = lc($conn);
-
- if (exists($connconf->{$conn}->{'_immutable'})) {
- write_irssi("Connector cannot be modified");
- return;
- }