html/openurl.pl


   1 # OpenURL by Stefan'tommie' Tomanek
   2 #
   3 # 05.06.2002
   4 # * complete rewrite
   5 
   6 use strict;
   7 
   8 use vars qw($VERSION %IRSSI);
   9 $VERSION = "20030208";
  10 %IRSSI = (
  11     authors     => "Stefan 'tommie' Tomanek",
  12     contact     => "stefan\@pico.ruhr.de",
  13     name        => "OpenURL",
  14     description => "Stores URLs in a list and launches mail, web or ftp software",
  15     license     => "GPLv2",
  16     url         => "http://scripts.irssi.org",
  17     changed     => "$VERSION",
  18     commands	=> "openurl"
  19 );
  20 
  21 use Irssi 20020324;
  22 use Irssi::TextUI;
  23 use Irssi::UI;
  24 
  25 use vars qw(@urls %urltypes $recent);
  26 $recent = 1;
  27 
  28 # RegExp & defaultcommands
  29 %urltypes = ( http => { regexp => qr#((?:https?://[^\s<>"]+|www\.[-a-z0-9.]+)[^\s.,;<">\):])#, cmd => 'w3m "$1"' },
  30               ftp  => { regexp => qr#((?:ftp://[^\s<>"]+|ftp\.[-a-z0-9.]+)[^\s.,;<">\):])#, cmd => 'ncftp "$1"' },
  31 	      mail => { regexp => qr#([-_a-z0-9.]+\@[-a-z0-9.]+\.[-a-z0-9.]+)#, cmd => 'mutt "$1" -s "$2"' },
  32 	    );
  33 
  34 sub draw_box ($$$$) {
  35     my ($title, $text, $footer, $colour) = @_;
  36     my $box = '';
  37     $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
  38     foreach (split(/\n/, $text)) {
  39         $box .= '%R|%n '.$_."\n";
  40     }                                                                               $box .= '%R`--<%n'.$footer.'%R>->%n';
  41     $box =~ s/%.//g unless $colour;
  42     return $box;
  43 }
  44 
  45 sub show_help() {
  46     my $help=$IRSSI{name}." ".$VERSION."
  47 /openurl
  48         List the saved URLs
  49 /openurl <number> <number>...
  50         Load the corresponding URLs in your browser/mailer
  51 /openurl paste <number> <number>...
  52         Paste the selected URLs to the current channel/query
  53 /openurl topics
  54         Look for URLs in channel topics
  55 /openurl clear
  56         Clear all URLs
  57 /openurl help
  58         Display this help
  59 ";
  60     my $text = '';
  61     foreach (split(/\n/, $help)) {
  62         $_ =~ s/^\/(.*)$/%9\/$1%9/;
  63 	$text .= $_."\n";
  64     }
  65     print CLIENTCRAP draw_box($IRSSI{name}." help", $text, "help", 1) ;
  66 }
  67 
  68 sub list_urls {
  69     my $string = '';
  70     my $i = 1;
  71     foreach (@urls) {
  72 	my $text = $_->{url};
  73 	my $url = $_->{url};
  74 	$text = $_->{text} if Irssi::settings_get_bool('openurl_display_context');
  75 	$url =~ s/%/%%/g;
  76 	$text =~ s/%/%%/g;
  77 	$text =~ s/\Q$url/%U$url%U/;
  78 	if ($recent-1 == $i) {
  79 	    $string .= '%B»%n';
  80 	} else {
  81 	    $string .= ' ';
  82 	}
  83 	$string .= '%r['.$i.']%n ';
  84 	$string .= '<'.$_->{channel};
  85 	$string .= '/'.$_->{nick} unless $_->{nick} eq "";
  86 	$string .= '> ';
  87 	$string .= $text." %n\n";
  88 	$i++;
  89     }
  90     print CLIENTCRAP draw_box("OpenURL", $string, "URLs", 1);
  91 }
  92 
  93 sub event_private_message {
  94     my ($server, $text, $nick, $address) = @_;
  95     process_line($server, $nick, $nick, $text);
  96 }
  97 sub event_public_message {
  98     my ($server, $text, $nick, $address, $target) = @_;
  99     process_line($server, $target, $nick, $text);
 100 }
 101 sub event_topic_changed {
 102     my ($channel) = @_;
 103     process_line($channel->{server}, $channel->{name}, "", $channel->{topic});
 104 }
 105 
 106 sub process_line ($$$$) {
 107     my ($server, $target, $nick, $line) = @_;
 108     my $url = get_url($line);
 109     if ($url) {
 110 	my $type = url_type($url);
 111 	return unless Irssi::settings_get_bool('openurl_watch_'.$type);
 112 	new_url($server, $target, $nick, $line, $url);
 113     }
 114 }
 115 
 116 sub get_url ($) {
 117     my ($text) = @_;
 118     foreach (keys %urltypes) {
 119 	return $1 if ($text =~ /$urltypes{$_}->{regexp}/);
 120     }
 121 }
 122 
 123 sub url_type ($) {
 124     my ($url) = @_;
 125     foreach (keys %urltypes) {
 126 	return $_ if ($url =~ /$urltypes{$_}->{regexp}/);
 127     }
 128 }
 129 
 130 sub launch_url ($) {
 131     my ($url) = @_;
 132     my $type = url_type($url);
 133     my $address = $url;
 134     my $suffix= "";
 135     if ($type eq "mail") {
 136 	$address = $1 if $url =~ /(.*?@.*?)($|\?)/;
 137 	$suffix = $2 if $url =~ /(.*?@.*?)\?subject=(.*)/;
 138     }
 139     my $command = Irssi::settings_get_str("openurl_app_".$type);
 140     $command =~ s/\$1/$address/;
 141     $command =~ s/\$2/$suffix/;
 142     system($command);
 143 }
 144 
 145 sub new_url ($$$$$) {
 146     my ($server, $channel, $nick, $text, $url) = @_;
 147     $recent = 1 if ($recent > Irssi::settings_get_int('openurl_max_urls'));
 148     # Check for existance of URL
 149     my $i = 1;
 150     foreach (@urls) {
 151 	if ($text eq $_->{text} && $channel eq $_->{channel}) {
 152 	    my $note_id = add_note($server, $channel, $i);
 153 	    push @{$_->{notes}}, $note_id;
 154 	    return();
 155 	}
 156 	$i++;
 157     }
 158     if (defined $urls[$recent-1]) {
 159 	del_notes($recent);
 160     }
 161     $urls[$recent-1] = {channel => $channel,
 162                         text    => $text,
 163 			nick    => $nick,
 164 			url     => $url,
 165 			notes   => [],
 166 			};
 167     my $note_id = add_note($server, $channel, $recent);
 168     push @{$urls[$recent-1]{notes}}, $note_id;
 169     $recent++;
 170 }
 171 
 172 
 173 sub del_notes ($) {
 174     my ($num) = @_;
 175     my $view;
 176     my $witem = Irssi::window_item_find($urls[$num-1]->{channel});
 177     if (defined $witem) {
 178 	$view =  $witem->window()->view();
 179     }
 180     if (defined $view) {
 181 	foreach (@{$urls[$num-1]->{notes}}) {
 182 	    my $line = $view->get_bookmark($_);
 183 	    $view->remove_line($line) if defined $line;
 184 	    $view->set_bookmark($_, undef);
 185 	}
 186 	@{$urls[$num-1]->{notes}} = ();
 187 	$view->redraw();
 188     }
 189 }
 190 
 191 sub add_note ($$$) {
 192     my ($server, $target, $num) = @_;
 193     my $witem;
 194     if (defined $server) {
 195 	$witem = $server->window_item_find($target);
 196     } else {
 197 	$witem = Irssi::window_item_find($target);
 198     }
 199     if (defined $witem) {
 200 	$witem->print("%R>>%n OpenURL ".$num, MSGLEVEL_CLIENTCRAP);
 201 	# create a unique ID for the mark
 202 	my $foo = time().'-'.int(rand()*1000);
 203 	$witem->window()->view()->set_bookmark_bottom("openurl_".$num.'-'.$foo);
 204 	return("openurl_".$num.'-'.$foo);
 205     }
 206     return(undef);
 207 }
 208 
 209 sub clear_urls {
 210     del_notes($_) foreach (0..scalar(@urls)-1);
 211     pop(@urls) foreach (1..scalar(@urls));
 212     $recent = 1;
 213     print CLIENTCRAP '%R>>%n URLs cleared';
 214 }
 215 
 216 sub cmd_openurl ($$$) {
 217     my ($arg, $server, $witem) = @_;
 218     my @args = split(/ /, $arg);
 219     if (scalar(@args) == 0) {
 220 	list_urls;
 221     } elsif ($args[0] eq 'clear') {
 222 	clear_urls;
 223     } elsif ($args[0] eq 'topics') {
 224     	event_topic_changed($_) foreach (Irssi::channels());
 225     } elsif ($args[0] eq 'help') {
 226 	show_help();
 227     } elsif ($args[0] eq 'open') {
 228 	launch_url($args[1]);
 229     } else {
 230 	my $paste = 0;
 231 	if ($args[0] eq 'paste') {
 232 	    $paste = 1;
 233 	    shift(@args);
 234 	}
 235 	foreach (@args) {
 236 	    next unless /\d+/;
 237 	    next unless defined $urls[$_-1];
 238 	    my $url = $urls[$_-1]->{url};
 239 	    if ($paste == 1) {
 240 		if (ref $witem && ($witem->{type} eq "CHANNEL" || $witem->{type} eq "QUERY")) {
 241 		    $witem->command("MSG ".$witem->{name}." ".$url);
 242 		}
 243 	    } else {
 244 		launch_url($url);
 245 	    }
 246 	}
 247     }
 248 }
 249 
 250 foreach (keys %urltypes) {
 251     Irssi::settings_add_str($IRSSI{'name'}, 'openurl_app_'.$_, "screen ".$urltypes{$_}->{cmd});
 252     Irssi::settings_add_bool($IRSSI{'name'}, 'openurl_watch_'.$_, 1);
 253 }
 254 Irssi::settings_add_int($IRSSI{'name'}, 'openurl_max_urls', 20);
 255 Irssi::settings_add_bool($IRSSI{'name'}, 'openurl_display_context', 1);
 256 
 257 Irssi::signal_add_last("message private", "event_private_message");
 258 Irssi::signal_add_last("message public", "event_public_message");
 259 Irssi::signal_add_last("channel topic changed", "event_topic_changed");
 260 
 261 #Irssi::signal_add('open url', \&launch_url);
 262 
 263 foreach my $cmd ('topics', 'clear', 'paste', 'help') {
 264     Irssi::command_bind('openurl '.$cmd => sub {
 265 	cmd_openurl("$cmd ".$_[0], $_[1], $_[2]); });
 266 }
 267 Irssi::command_bind('openurl', 'cmd_openurl');
 268 
 269 print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /openurl help for help';