perltidy


use strict;
use Irssi;
use Irssi::Irc;
use Net::Twitter;
use HTTP::Date;
use HTML::Entities;
use File::Temp;

use vars qw($VERSION %IRSSI);
use constant { DEBUG => 0 };;

$VERSION = "0.4";
%IRSSI   = (
    authors     => 'Dan Boger',
    contact     => 'zigdon@gmail.com',
    name        => 'twirssi',
    description => 'Send twitter updates using /tweet.  '
      . 'Can optionally set your bitlbee /away message to same',
    license => 'GNU GPL v2',
    url     => 'http://irc.peeron.com/~zigdon/twirssi/',
    changed => 'Mon Dec  1 15:36:01 PST 2008',
);

my $window;
my $twit;
my $user;
my $poll;
my $last_poll = time;

sub cmd_tweet {
    my ( $data, $server, $win ) = @_;

    unless ($twit) {
        $window->print(
            "%R***%n Not logged in!  Use /twitter_login username pass!");
        return;
    }

    $data =~ s/^\s+|\s+$//;
    unless ($data) {
        $window->print("%R***%n Usage: /tweet <update>");
        return;
    }

    unless ($twit->update($data)) {
        $window->print( "%R***%n Update failed", MSGLEVEL_PUBLIC );
        return;
    }

    my $away = 0;
    if (    Irssi::settings_get_bool("tweet_to_away")
        and $data !~ /\@\w/
        and $data !~ /^[dD] / )
    {
        my $server =
          Irssi::server_find_tag( Irssi::settings_get_str("bitlbee_server") );
        if ($server) {
            $server->send_raw("away :$data");
            $away = 1;
        }
        else {
            $window->print( "%R***%n Can't find bitlbee server."
                  . "Update bitlbee_server or disalbe tweet_to_away" );
        }
    }

    if ( $data =~ s/^[dD] // ) {
        $window->print( "%R***%n DM sent", MSGLEVEL_PUBLIC );
    }
    else {
        $window->print(
            "%R***%n Update sent" . ( $away ? " (and away msg set)" : "" ),
            MSGLEVEL_PUBLIC );
    }
}

sub cmd_login {
    my ( $data, $server, $win ) = @_;
    my $pass;
    ( $user, $pass ) = split ' ', $data, 2;

    $twit = Net::Twitter->new(
        username => $user,
        password => $pass,
        source   => "twirssi"
    );

    unless ($twit->verify_credentials()) {
        $window->print( "%R***%n Login failed", MSGLEVEL_PUBLIC );
        $twit = undef;
        return;
    }

    if ($twit) {
        &get_updates;
        Irssi::timeout_remove($poll) if $poll;
        $poll = Irssi::timeout_add( 300 * 1000, \&get_updates, "" );
        $window->print( "%R***%n Logged in as $user", MSGLEVEL_PUBLIC );
    }
    else {
        $window->print( "%R***%n Login failed", MSGLEVEL_PUBLIC );
    }
}

sub get_updates {
    $window =
      Irssi::window_find_name( Irssi::settings_get_str('twitter_window') );
    unless ($window) {
        Irssi::active_win()
          ->print( "Can't find a window named '"
              . Irssi::settings_get_str('twitter_window')
              . "'.  Create it or change the value of twitter_window" );
    }
    unless ($twit) {
        $window->print(
            "%R***%n Not logged in!  Use /twitter_login username pass!");
        return;
    }

    my ($fh, $filename) = File::Temp::tempfile();
    my $pid = fork();

    if ($pid) { # parent
      Irssi::timeout_add_once( 5000, 'monitor_child', [ $filename ]);
    } elsif (defined $pid) { # child
      close STDIN;
      close STDOUT;
      close STDERR;

      my $new_poll = time;

      print scalar localtime, " - Polling for updates" if DEBUG;
      my $tweets =
        $twit->friends_timeline( { since => HTTP::Date::time2str($last_poll) } ) || [];
      foreach my $t ( reverse @$tweets ) {
          my $text = decode_entities( $t->{text} );
          $text =~ s/%/%%/g;
          $text =~ s/\@([-\w]+)/%B\@$1%n/g;
          printf $fh "[%%B\@%s%%n] %s\n", $t->{user}{screen_name}, $text 
      }
      print scalar localtime, " - Polling for DMs" if DEBUG;
      $tweets =
        $twit->direct_messages( { since => HTTP::Date::time2str($last_poll) } ) || [];
      foreach my $t ( reverse @$tweets ) {
          my $text = decode_entities( $t->{text} );
          $text =~ s/%/%%/g;
          $text =~ s/\@([-\w]+)/%B\@$1%n/g;
          printf $fh "[%%B\@%s%%n (%%WDM%%n)] %s\n", $t->{sender_screen_name}, $text;
      }
      print scalar localtime, " - Done" if DEBUG;
      print $fh $new_poll;
      close $fh;
      exit;
    }
}

sub monitor_child {
  my $data = shift;
  my $filename = $data->[0];

  print scalar localtime, " - checking child log at $filename" if DEBUG;
  if (open FILE, $filename) {
    my @lines = <FILE>;
    close FILE;

    if ($lines[-1] =~ /^\d+$/) {
      $last_poll = pop @lines;
      print "new last_poll = $last_poll" if DEBUG;
      foreach my $line (@lines) {
        chomp $line;
        $window->print($line, MSGLEVEL_PUBLIC);
      }
      unlink $filename or warn "Failed to remove $filename: $!";
      return;
    }
  }

  Irssi::timeout_add_once(5000, 'monitor_child', [$filename]);
}

Irssi::settings_add_str( "twirssi", "twitter_window", "twitter" );
Irssi::settings_add_str( "twirssi", "bitlbee_server", "bitlbee" );
Irssi::settings_add_bool( "twirssi", "tweet_to_away", 0 );
$window = Irssi::window_find_name( Irssi::settings_get_str('twitter_window') );
if ($window) {
    Irssi::command_bind( "tweet",           "cmd_tweet" );
    Irssi::command_bind( "twitter_login",   "cmd_login" );
    Irssi::command_bind( "twitter_updates", "get_updates" );
    $window->print(
"%R***%n Twirssi v$VERSION loaded.  Log in with /twitter_login, send updates with /tweet",
        MSGLEVEL_PUBLIC
    );
}
else {
    Irssi::active_win()
      ->print( "Create a window named "
          . Irssi::settings_get_str('twitter_window')
          . " or change the value of twitter_window" );
}