#!/usr/bin/env perl
#
# twitterupdates.pl: Xchat plugin to fetch twitter updates for a given user.
# Copyright (C) 2010 P J P <pj.pandit@yahoo.co.in>
#
# `twitterupdates' is a free software; you can redistribute it and/or modify
# it under the terms of GNU General Public License as published by the Free
# Software Foundation; either version 3 of the license, or(at your option) any
# later version.
#
# `twitterupdates' is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# `twitterupdates'; if not, see: <http://www.gnu.org/licenses>.
#
# twitterupdates.pl uses XML::LibXML
#
#   -> $ yum install perl-XML-LibXML
#   -> http://cpan.uwinnipeg.ca/htdocs/XML-LibXML
#

use strict;
use warnings;
use XML::LibXML::Reader;

my ($prog, $VERSION) = ("", "0.8");
my ($twuser, $twpass, $tmout) = ("<TWITTER-NAME>", "<PASSWORD>", 60);
my ($twurl) = ("http://twitter.com/statuses/friends_timeline.xml");

my ($twfile, $twmode, $twcount, %tweets) = ("", 0, 0, ());


sub read_updates
{
    my $TWIT = undef;

    if ($twmode < 2)
    {
        $twfile = sprintf ("/tmp/tu%ld", time());
        my $cmmd = "curl -su $twuser\:$twpass -o $twfile $twurl";
        system ($cmmd);
    }

    open ($TWIT, "<", $twfile) or die ("$prog: could not open file: $twfile\n");
    my $reader = new XML::LibXML::Reader (IO => $TWIT);

    $twcount = 0;
    while ($reader->nextElement ("status"))
    {
        my ($usr, $msg) = ("", "");

        if ($reader->nextElement ("text"))
        {
            $reader->read ();
            chomp ($msg = $reader->value ());
            $msg = join (' ', split('\n', $msg));
        }
        if ($reader->nextElement ("screen_name"))
        {
            $reader->read ();
            $usr = $reader->value ();
        }
        $tweets{$twcount++} = [ $usr, $msg ];
    }
    $reader->close();

    close ($TWIT);
    unlink ($twfile) if ($twmode < 2);

    return;
}


sub to_xchat
{
    my ($tab_focus) = (0);

    if ($twuser eq "" || $twuser =~ m/user-name/i)
    {
        Xchat::print ("invalid twitter name: $twuser\n");
        return;
    }

    read_updates ();
    srand (time () ^ $$);

    $tab_focus = Xchat::get_prefs ("tab_new_to_front");
    Xchat::command ("set -quiet tab_new_to_front 0");
    Xchat::command ("query -nofocus $twuser");

    for (my $k = $twcount - 1; $k >= 0; $k--)
    {
        my ($msg, $fmt) = ("", "\012\003%02d%s: \00301%s");

        if ($tweets{$k}[1] =~ m/\@$twuser/i)
        {
            $tweets{$k}[1] = "\cB".$tweets{$k}[1]."\cB";
        }
        $msg = sprintf ($fmt, int(rand(31)), $tweets{$k}[0], $tweets{$k}[1]);

        Xchat::print ($msg, $twuser);
    }

    undef %tweets;
    Xchat::hook_timer (($tmout * 60 * 1000), "to_xchat");
    Xchat::command ("set -quiet tab_new_to_front $tab_focus");

    return;
}


sub to_console
{
    if ($twuser eq "" || $twuser =~ m/user-name/i)
    {
        printf ("%s: invalid twitter name: `%s'\n", $prog, $twuser);
        return;
    }

    read_updates ();
    for (my $k = $twcount - 1; $k >= 0; $k--)
    {
        printf ("%15s: %s\n", $tweets{$k}[0], $tweets{$k}[1]);
    }
    undef %tweets;

    return;
}


sub basename
{
    my @formal = @_;

    my ($slash, $pos) = ("/", 0);
    my ($path, $prg) = ($formal[0], "");

    $slash = "\\" if ($^O eq "MSWin32");
    $pos = rindex $path, $slash;
    chomp ($prg = substr ($path, $pos + 1));

    return $prg;
}


sub usage
{
    printf ("Usage: %s [OPTION]\n", $prog);
    return;
}


sub printh
{
    my $fmt = " %-23s %s\n";

    usage ();

    printf ("\n");
    printf ("Get twitter updates every %d mins.\n", $tmout);

    printf ("\n");
    printf ("Options: \n");

    printf ("\n");
    printf ($fmt, "  -c --console", "work in the console mode");
    printf ($fmt, "  -f --file <name>", "specify XML file to read");
    printf ($fmt, "  -h --help", "show this help");
    printf ($fmt, "  -v --version", "show version");

    printf ("\n");
    printf ("Report bugs to <pj.pandit\@yahoo.co.in>\n");

    return;
}


sub check_options
{
    my ($i, $arg) = (0, "");

    for ($i = 0; $i < @ARGV; $i++)
    {
        $arg = $ARGV[$i];
        if ($arg eq "-c" || $arg eq "--console")
        {
            $twmode = 1;
        }
        elsif ($arg eq "-f" || $arg eq "--file")
        {
            die ("$prog: filename missing\n") if ($arg eq $ARGV[-1]);
            if ($ARGV[$i + 1] =~ /^\-{1,}\w*/)
            {
                printf ("$prog: invalid filename: `%s'\n", $ARGV[$i + 1]);
                exit 1;
            }

            $twmode = 2;
            $twfile = $ARGV[++$i];
        }
        elsif ($arg eq "-h" || $arg eq "--help")
        {
            printh ();
            exit 0;
        }
        elsif ($arg eq "-v" || $arg eq "--version")
        {
            printf ("%s %s\n", $prog, $VERSION);
            exit 0;
        }
        elsif ($arg =~ /^\-{1,}\w*/)
        {
            printf ("%s: invalid option: `%s'\n", $prog, $arg);
            exit 1;
        }
    }
    shift @ARGV while ($i-- > 0);

    return;
}


#
# main ()
{
    $prog = basename ($0);
    check_options();

    if (!$twmode)
    {
        Xchat::register ("Twitter updates", $VERSION,
                         "Twitter updates every $tmout mins.", "");
        to_xchat ()
    }

    to_console () if ($twmode);
}
