# OpenURL by Stefan'tommie' Tomanek # # 05.06.2002 # * complete rewrite use strict; use vars qw($VERSION %IRSSI); $VERSION = "20030208"; %IRSSI = ( authors => "Stefan 'tommie' Tomanek", contact => "stefan\@pico.ruhr.de", name => "OpenURL", description => "Stores URLs in a list and launches mail, web or ftp software", license => "GPLv2", url => "http://scripts.irssi.org", changed => "$VERSION", commands => "openurl" ); use Irssi 20020324; use Irssi::TextUI; use Irssi::UI; use vars qw(@urls %urltypes $recent); $recent = 1; # RegExp & defaultcommands %urltypes = ( http => { regexp => qr#((?:https?://[^\s<>"]+|www\.[-a-z0-9.]+)[^\s.,;<">\):])#, cmd => 'w3m "$1"' }, ftp => { regexp => qr#((?:ftp://[^\s<>"]+|ftp\.[-a-z0-9.]+)[^\s.,;<">\):])#, cmd => 'ncftp "$1"' }, mail => { regexp => qr#([-_a-z0-9.]+\@[-a-z0-9.]+\.[-a-z0-9.]+)#, cmd => 'mutt "$1" -s "$2"' }, ); sub draw_box ($$$$) { my ($title, $text, $footer, $colour) = @_; my $box = ''; $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n"; foreach (split(/\n/, $text)) { $box .= '%R|%n '.$_."\n"; } $box .= '%R`--<%n'.$footer.'%R>->%n'; $box =~ s/%.//g unless $colour; return $box; } sub show_help() { my $help=$IRSSI{name}." ".$VERSION." /openurl List the saved URLs /openurl ... Load the corresponding URLs in your browser/mailer /openurl paste ... Paste the selected URLs to the current channel/query /openurl topics Look for URLs in channel topics /openurl clear Clear all URLs /openurl help Display this help "; my $text = ''; foreach (split(/\n/, $help)) { $_ =~ s/^\/(.*)$/%9\/$1%9/; $text .= $_."\n"; } print CLIENTCRAP draw_box($IRSSI{name}." help", $text, "help", 1) ; } sub list_urls { my $string = ''; my $i = 1; foreach (@urls) { my $text = $_->{url}; my $url = $_->{url}; $text = $_->{text} if Irssi::settings_get_bool('openurl_display_context'); $url =~ s/%/%%/g; $text =~ s/%/%%/g; $text =~ s/\Q$url/%U$url%U/; if ($recent-1 == $i) { $string .= '%B»%n'; } else { $string .= ' '; } $string .= '%r['.$i.']%n '; $string .= '<'.$_->{channel}; $string .= '/'.$_->{nick} unless $_->{nick} eq ""; $string .= '> '; $string .= $text." %n\n"; $i++; } print CLIENTCRAP draw_box("OpenURL", $string, "URLs", 1); } sub event_private_message { my ($server, $text, $nick, $address) = @_; process_line($server, $nick, $nick, $text); } sub event_public_message { my ($server, $text, $nick, $address, $target) = @_; process_line($server, $target, $nick, $text); } sub event_topic_changed { my ($channel) = @_; process_line($channel->{server}, $channel->{name}, "", $channel->{topic}); } sub process_line ($$$$) { my ($server, $target, $nick, $line) = @_; my $url = get_url($line); if ($url) { my $type = url_type($url); return unless Irssi::settings_get_bool('openurl_watch_'.$type); new_url($server, $target, $nick, $line, $url); } } sub get_url ($) { my ($text) = @_; foreach (keys %urltypes) { return $1 if ($text =~ /$urltypes{$_}->{regexp}/); } } sub url_type ($) { my ($url) = @_; foreach (keys %urltypes) { return $_ if ($url =~ /$urltypes{$_}->{regexp}/); } } sub launch_url ($) { my ($url) = @_; my $type = url_type($url); my $address = $url; my $suffix= ""; if ($type eq "mail") { $address = $1 if $url =~ /(.*?@.*?)($|\?)/; $suffix = $2 if $url =~ /(.*?@.*?)\?subject=(.*)/; } my $command = Irssi::settings_get_str("openurl_app_".$type); $command =~ s/\$1/$address/; $command =~ s/\$2/$suffix/; system($command); } sub new_url ($$$$$) { my ($server, $channel, $nick, $text, $url) = @_; $recent = 1 if ($recent > Irssi::settings_get_int('openurl_max_urls')); # Check for existance of URL my $i = 1; foreach (@urls) { if ($text eq $_->{text} && $channel eq $_->{channel}) { my $note_id = add_note($server, $channel, $i); push @{$_->{notes}}, $note_id; return(); } $i++; } if (defined $urls[$recent-1]) { del_notes($recent); } $urls[$recent-1] = {channel => $channel, text => $text, nick => $nick, url => $url, notes => [], }; my $note_id = add_note($server, $channel, $recent); push @{$urls[$recent-1]{notes}}, $note_id; $recent++; } sub del_notes ($) { my ($num) = @_; my $view; my $witem = Irssi::window_item_find($urls[$num-1]->{channel}); if (defined $witem) { $view = $witem->window()->view(); } if (defined $view) { foreach (@{$urls[$num-1]->{notes}}) { my $line = $view->get_bookmark($_); $view->remove_line($line) if defined $line; $view->set_bookmark($_, undef); } @{$urls[$num-1]->{notes}} = (); $view->redraw(); } } sub add_note ($$$) { my ($server, $target, $num) = @_; my $witem; if (defined $server) { $witem = $server->window_item_find($target); } else { $witem = Irssi::window_item_find($target); } if (defined $witem) { $witem->print("%R>>%n OpenURL ".$num, MSGLEVEL_CLIENTCRAP); # create a unique ID for the mark my $foo = time().'-'.int(rand()*1000); $witem->window()->view()->set_bookmark_bottom("openurl_".$num.'-'.$foo); return("openurl_".$num.'-'.$foo); } return(undef); } sub clear_urls { del_notes($_) foreach (0..scalar(@urls)-1); pop(@urls) foreach (1..scalar(@urls)); $recent = 1; print CLIENTCRAP '%R>>%n URLs cleared'; } sub cmd_openurl ($$$) { my ($arg, $server, $witem) = @_; my @args = split(/ /, $arg); if (scalar(@args) == 0) { list_urls; } elsif ($args[0] eq 'clear') { clear_urls; } elsif ($args[0] eq 'topics') { event_topic_changed($_) foreach (Irssi::channels()); } elsif ($args[0] eq 'help') { show_help(); } elsif ($args[0] eq 'open') { launch_url($args[1]); } else { my $paste = 0; if ($args[0] eq 'paste') { $paste = 1; shift(@args); } foreach (@args) { next unless /\d+/; next unless defined $urls[$_-1]; my $url = $urls[$_-1]->{url}; if ($paste == 1) { if (ref $witem && ($witem->{type} eq "CHANNEL" || $witem->{type} eq "QUERY")) { $witem->command("MSG ".$witem->{name}." ".$url); } } else { launch_url($url); } } } } foreach (keys %urltypes) { Irssi::settings_add_str($IRSSI{'name'}, 'openurl_app_'.$_, "screen ".$urltypes{$_}->{cmd}); Irssi::settings_add_bool($IRSSI{'name'}, 'openurl_watch_'.$_, 1); } Irssi::settings_add_int($IRSSI{'name'}, 'openurl_max_urls', 20); Irssi::settings_add_bool($IRSSI{'name'}, 'openurl_display_context', 1); Irssi::signal_add_last("message private", "event_private_message"); Irssi::signal_add_last("message public", "event_public_message"); Irssi::signal_add_last("channel topic changed", "event_topic_changed"); #Irssi::signal_add('open url', \&launch_url); foreach my $cmd ('topics', 'clear', 'paste', 'help') { Irssi::command_bind('openurl '.$cmd => sub { cmd_openurl("$cmd ".$_[0], $_[1], $_[2]); }); } Irssi::command_bind('openurl', 'cmd_openurl'); print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /openurl help for help';