#!/usr/bin/perl
# $Id: pidgin2gmail.pl,v 1.1 2008/09/09 08:08:21 ecu Exp ecu $
# pidgin2imap - Store pidgin logs in gmail account
# Nicolas Jombart <ecu@200ok.org>
# BSD License, but I will not copy/paste the whole upcase thing

use strict;
use warnings;
use Mail::IMAPClient;
use IO::Socket::SSL;
use File::Find;
use DateTime::Format::Mail;
use DB_File;
use Fcntl;
use Date::Parse;

# Configuration
my $dir = shift;
my $gmail_user = 'yourname@gmail.com';
my $gmail_password = "xxxxxx";
my $gmail_folders = "imlogs";
my $dbfile = "pidgin2imap.db";
my @forget = ('aolsystemmsg', 'skdjskdj');
my $debug_imap = 0;
my $midleft = "something.domain.com";
my $tz = "Europe/Paris";

### DO NOT EDIT BELOW THERE

# Damn it, I used strict!
my $proto = "";
my $account = "";
my $buddy = "";
my %seen = ();
my @logs = ();
my $uid = "";

# What to do with log file
sub parse_message {
	my $file = shift;
	my $msg = "";
	my $date = "";
	my $ac = "";
	my $from = "";
	open(FH,$file) or die "Can't open $file: $!";
	while(<FH>) {
		if(/^Conversation with (\S+) at (.*) on (\S+) \((\S+)\)/) {
			$ac = $3;
			$from = $1;
			my ($year, $month, $day, $hh, $mm, $ss) = $file =~ /.*\/(\d{4})-(\d{2})-(\d{2})\.(\d{2})(\d{2})(\d{2}).*\.txt$/;
			my $dt = DateTime->new(
				year => $year, month => $month, day => $day, 
				hour => $hh, minute => $mm, second => $ss,
				time_zone => $tz
			);
			$date = DateTime::Format::Mail->format_datetime( $dt );
			$msg = "Message-Id: $1-$3-$4-".int(rand(1000))."\@$midleft\n";
			$msg .= "From: $from (Pidgin2IMAP IM Logs)\nTo: $ac\n";
			$msg .= "Subject: Conversation with $from at $hh:$mm\nDate: $date\n";
			$msg .= "MIME-Version: 1.0\nContent-Type: text/html\n\n";
			$msg .= "<html><body>";
		}
		else {
			chomp;
			if(/^([()0-9:]+) (\S+): (.*)$/) {
				$msg .= "$from <font color=\"";
				if($2 eq $ac) { $msg .= "red"; } else { $msg .= "blue"; }
				$msg .= "\">$2</font>: $3<br>\n";
			}
			else { 
				$msg .= $_ . "<br>"; 
			}
		}
	}
	$msg .= "</body></html>\n\n";
	return ($date,$msg);
}

tie (%seen, 'DB_File', $dbfile) or die ("Cannot open $dbfile: $!\n");

# IMAP connection
print "Connecting to Gmail...";

my	$socket = IO::Socket::SSL->new(
	PeerAddr => 'imap.gmail.com',
	PeerPort => 993,
	)
	|| die "socket(): $@";

my $client = Mail::IMAPClient->new(
             Socket   => $socket,
             User     => $gmail_user,
             Password => $gmail_password,
             Debug    => $debug_imap,
             )
             || die "new(): $@";

print "OK!\n" if $client->IsAuthenticated();

# walk files and process
find sub {
	return unless -f;
	my($proto,$account,$buddy,$log) = $File::Find::name =~ m/$dir\/?(\S+)\/(\S+)\/(\S+)\/(\S+)$/;
	return unless defined $log;
	return if($buddy =~ '\.system'); # we don't keep system logs
	return if($account eq $buddy); # chat with yourself?
	foreach (@forget) { return if($_ eq $buddy); }
	if( exists $seen{"$account:$buddy:$log"} ) {
		return;
	} else {
		print "processing chat $log with $buddy ($proto) in $gmail_folders ... ";
		$client->select("$gmail_folders/$proto") or die "Cannot select folder: $@\n";
		my @tmp =  &parse_message("$dir/$proto/$account/$buddy/$log");
		my ($tmpd, $tmpm) = @tmp;
		return unless defined $tmpd;
		# RFC2060 dd-Mon-yyyy hh:mm:ss +0000
		$tmpd =~ s/(\S+), (\d{2}) (\S{3}) (\d{4})/$2-$3-$4/;
		if($client->append_string("$gmail_folders/$proto", $tmpm, '\Seen', $tmpd)) {
			print "OK\n";
			$seen{"$account:$buddy:$log"} = 1;
		}
		else { warn "Couldn't append: $@";}
	}
}, $dir;

$client->logout();
untie(%seen);


