# $Id: url2html.pl,v 1.0 01/08/2010 Pieter Exp $
#
# This script is a code fork of Jean-Yves Lefort's url.pl, version 0.54
# and Hugo Haas his burl.pl v1.7
# See: http://void.adminz.be/
#      http://larve.net/people/hugo/2003/02/burl.pl
# 
# Changed by Pieter to fill his needs :-)
# http://pieter.blinkenshell.org
# 30/07/2010 
#
#

use Irssi();
use URI::Escape;
use HTML::Entities;
$VERSION = "1.0";
%IRSSI = (
	  authors     => 'Pieter',
	  contact     => 'pieter\@blinkenshell.org',
	  name        => 'url2html',
	  description => 'URL logger for Irssi',
	  license     => 'BSD',
	  changed     => '$Date: 2010/07/30 17:37:30 $ ',
	  modules     => 'URI::Escape HTML::Entities',
	  commands    => 'url2html'
);

# description:
#
#	url2html.pl grabs URLs in messages writes them in a HTML file.
#
# /set's:
#
#	url_grab_level
#
#		message levels to take in consideration
#		example: PUBLICS ACTIONS
#
#	url_redundant
#
#		whether to assign same URL a new number or not
#		example: ON
#
#	url_verbose_grab
#
#		whether to grab verbosely or not
#		example: OFF
#
#	url_hilight
#
#		whether to hilight the URLs in the text or not
#		example: OFF
#
#	url_file
#
#		where to write the URL list
#		example: ~/.irssi-urls.html
#
# commands
#
#	/URL [-clear]
#
#		-clear will clear the URL list.
#
#		If no argument is specified, a HTML file containing all
#		grabbed URLs will be written to the path in url_file.
#
# events
#
#    quit
#
#       When you type the /quit command this script will 
#       write the urls to the url_file
#

use strict;
use POSIX qw(strftime);

my @items;

sub expand {
  my ($string, %format) = @_;
  my ($len, $attn, $repl) = (length $string, 0);
  
  $format{'%'} = '%';

  for (my $i = 0; $i < $len; $i++) {
    my $char = substr $string, $i, 1;
    if ($attn) {
      $attn = undef;
      if (exists($format{$char})) {
	$repl .= $format{$char};
      } else {
	$repl .= '%' . $char;
      }
    } elsif ($char eq '%') {
      $attn = 1;
    } else {
      $repl .= $char;
    }
  }
  
  return $repl;
}

sub split_and_insert {
    my ($target, $text, $stripped) = @_;

    if ($stripped =~ /[a-zA-Z0-9+-.]+:\/\/[^ \t\<\>\"]+/o) {
	my $num = -1;
	if (! Irssi::settings_get_bool('url_redundant')) {
	    my $n = 1;
	    foreach (@items) {
		if ($_->{url} eq $&) {
		    $num = $n;
		    last;
		}
		$n++;
	    }
	}

	if ($num == -1) {
	    push @items,
	    {
		time => time,
		target => $target,
		pre_url => "$`",
		url => "$&",
		post_url => "$'"
		};
	    $num = @items;
	    Irssi::print('Added item #' . $num . ' to URL list')
		if Irssi::settings_get_bool('url_verbose_grab');
	}

	my $url_pos = index $text, $&;
	my $left = substr($text, $url_pos + length $&);
	$stripped = substr($stripped, index($stripped, $&) + length $&);

	if (Irssi::settings_get_bool('url_hilight')) {
	    $text =  substr($text, 0, $url_pos) .
		'' . $num . ':<' . $& . '>';
	}
	return($text, $left, $stripped);
    } {
	return ($text, '', '');
    }
}

my $inprogress = 0;

sub print_text {
  my ($textdest, $t, $stripped) = @_;
  
  return if ($inprogress);

  if (Irssi::level2bits(Irssi::settings_get_str('url_grab_level'))
      & $textdest->{level}) {

      my $s = $stripped;
      my $text;

      my $l;
      $l = $t;
      while($l ne '') {
	  my $r;
	  ($r, $l, $s) = &split_and_insert($textdest->{target}, $l, $s);
	  $text .= $r;
      }

      if (($text ne $t) && Irssi::settings_get_bool('url_hilight')) {
	  $inprogress = 1;
	  Irssi::signal_emit('print text', $textdest,
			     $text, $stripped);
	  $inprogress = 0;
	  Irssi::signal_stop();
      }
  }
}

sub write_file {
 my $file = shift;
 # What I would like to see is 2010.08.01.20:31_url2html.html
  my $now = strftime("%Y.%m.%d.%R", localtime(time)); 
  open(FILE, ">$file$now.html") or return $!;

  print FILE <<'EOF' or return $!;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>IRC URL list</title></head>
<body>
<center style="font-family: Arial;">IRC URL list
<table border="0" cellpadding="5" cellspacing="0">
  <tbody>
    <tr><td>Time</td><td>Target</td><td>Message</td></tr>
EOF

  foreach (@items) {
    my $timestamp = strftime('%Y-%m-%d %H:%M%Z', localtime $_->{time});
    print FILE
	"	<tr><td>$timestamp</td><td>$_->{target}</td><td>$_->{pre_url}<a href='"
	. HTML::Entities::encode(uri_escape($_->{url}, "^-A-Za-z0-9./:")) . "'>"
	. HTML::Entities::encode($_->{url}) . "</a>$_->{post_url}</td></tr>\n"
	or return $!;
  }
  
  print FILE <<'EOF' or return $!;
      </table>
    </center>
    <hr>
    <center style="font-family: Arial;">Generated by url2html.pl</center>
  </body>
</html>
EOF

  close(FILE) or return $!;

  return undef;
}

sub url {
  my ($args, $server, $item) = @_;

  my ($file) = glob Irssi::settings_get_str('url_file');

  if ($args ne '') {
    if (lc $args eq '-clear') {
      @items = ();
      Irssi::print('URL list cleared');
    } elsif ($args =~ /^[0-9]+$/) {
      if ($args > 0 && $items[$args - 1]) {
	 Irssi::print(' >> URL list is written!');
      } else {
	Irssi::print("URL #$args not found");
      }
    } else {
      Irssi::print('Usage: /URL [-clear|<number>]', MSGLEVEL_CLIENTERROR);
    }
  } else {
    if (@items) {
      my $error;
      if ($error = write_file($file)) {
	Irssi::print("Unable to write $file: $error", MSGLEVEL_CLIENTERROR);
      } else  {
	Irssi::print(' >> URL list is written!');  
      }
    } else {
      Irssi::print('URL list is empty');
    }
  }
}

sub cmd_quit {
  # when irssi quits write to file
  system(url);
}
Irssi::settings_add_str('url2html', 'url_grab_level','PUBLIC TOPICS ACTIONS MSGS DCCMSGS');
Irssi::settings_add_bool('url2html', 'url_verbose_grab', undef);
Irssi::settings_add_bool('url2html', 'url_hilight', 1);
Irssi::settings_add_bool('url2html', 'url_redundant', 0);
Irssi::settings_add_str('url2html', 'url_file', '~/url2html.html');

Irssi::signal_add('print text', \&print_text);

Irssi::command_bind('url', \&url);
Irssi::command_bind('quit', 'cmd_quit');
