[ /lj/tw/007.txt ]   PHP source

#!/usr/bin/perl # tw # simple twitter reader/writer # # Project #123 # http://umlautllama.com/project.php?ShortName=tw # # 2008-03 Scott Lawrence http://twitter.com/yorgle # yorgle@gmail.com # http://umlautllama.com # usage: # tw displays the most recent twits, newest first # tw my content post "my content" to your twitter account # # Version Info: # # 2008-06-05 v007 added symlink-$0 check tw-mono/tw # # 2008-03-26 v006 Tweaks to send the entire hash, parsing user/ # # 2008-03-23 v005 Link/Twitter response ID extraction # # 2008-03-22 v004 Text line wrapping # # 2008-03-22 v003 Added ANSIColor support. # # 2008-03-22 v002 Rework the tweets into an array, reverse sorting # # 2008-03-21 v001 Initial version, basic tweeting and such # require Term::ANSIColor; use Term::ANSIColor qw(:constants); # do we want to display with colors? my $useColor = 1; # do we want to line break text? my $lineBreak = 1; my $wrapAtCol = 78; # set your username and password here. # remember to chmod 700 this file! my $username = "yourUserName"; my $password = "yourPassWerd"; # the command we use to get the current timeline my $getcmd = "curl -s -u %s:%s http://twitter.com/statuses/friends_timeline.xml"; # the command we use to push a tweet to the server my $putcmd = "curl -s --basic --user \"%s:%s\" --data-ascii \"status=%s\" \"http://twitter.com/statuses/update.json\""; # we'll use these to mash up our returned data into a sortable array my $sep1 = "____Y0RGL3____"; my $sep2 = "____3LGR0Y____"; # webize # Convert special characters to be web form friendly sub webize { my ($text); $text = shift; $text =~ s/(\W)/ sprintf "%%%02lX", ord $1 /eg; return $text; } my @content, @sortedEntries; # take the XML from the server, and work it into our own sortedEntries sub parseResponse { my $line; my $c = 0; my $prepend = ""; # welcome to hacksville.. population ME! my $started = 0; my $ended = 0; # remove the first two lines... $junk = shift @content; $junk = shift @content; # and parse the entire content foreach $line ( @content ) { chomp $line; # first tag on the line $op1 = index( $line, "<" ); $cl1 = index( $line, ">", $op ); if( $op1 > 0 && $cl1 > 0 ) { $firstTagOnLine = substr $line, $op1+1, ($cl1-$op1-1); } else { $firstTagOnLine = ""; } # last tag on the line $op2 = rindex( $line, "<" ); $cl2 = rindex( $line, ">" ); if( $op2 > 0 && $cl2 > 0 ) { $lastTagOnLine = substr $line, $op2+1, ($cl2-$op2-1); } else { $lastTagOnLine = ""; } # if first !+ last, text is in the middle # if first == last, # if[0] == /, text preceeds # else, text follows # otherwise, text is entire line if( $firstTagOnLine ne $lastTagOnLine ) { $text .= " " . substr $line, $cl1+1, $op2-$cl1-1; } elsif( $firstTagOnLine ne "" ) { if( "/" ne substr $firstTagOnLine, 0, 1 ) { $text .= " " . substr $line, $cl1+1; } else { $text .= " " . substr $line, 0, $op2; } } else { $text .= " " . $line; } $text =~ s/^\s+//g; $text =~ s/\s+$//g; # do stuff if( $firstTagOnLine eq "status" ) { $started = 1; } if( $lastTagOnLine eq "/status" ) { $ended = 1; } if( $firstTagOnLine eq "user" ) { $prepend = "user_"; } if( $lastTagOnLine eq "/user" ) { $prepend = ""; } if( $ended ) { # reset $ended = 0; $started = 0; } # see if the last tag on the line is a close tag # if so, store aside the text content for the tag if( "/" eq substr $lastTagOnLine, 0, 1 ) { $entryHash{ $prepend . substr( $lastTagOnLine, 1) } = $text; $text = ""; } if( "/status" eq $lastTagOnLine ) { # reformat and store the record $entry = "order" . $sep2 . (sprintf "%03d", $c++); while (($key,$value) = each( %entryHash )) { $entry .= $sep1 . $key . $sep2 . $value; } push @sortedEntries, $entry; } } } # display an item. # di( colorA, "text a", colorB, "text b" ); # available colors: CLEAR, RESET, BOLD, DARK, UNDERLINE, UNDERSCORE, # BLINK, REVERSE, CONCEALED, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, # ON_BLACK, ON_RED, ON_GREEN, ON_YELLOW, ON_BLUE, ON_MAGENTA, ON_CYAN, # ON_WHITE sub di { my $col1 = shift; my $key = shift; my $col2 = shift; my $val = shift; my @valw = split " ", $val; if( $useColor ) { print $col1; } printf "%5s: ", $key; if( $useColor ) { print $col2; } if( $lineBreak ) { $wc = 8; foreach $word ( @valw ) { if( $wc + (length $word ) > $wrapAtCol ) { printf "\n "; $wc = 8; } elsif ($wc == 8) { # do nothing. } else { print " "; $wc++; } print $word; $wc += length $word; } } else { printf "%s", $val; } if( $useColor ) { print RESET; } printf "\n"; } # dump out a list of links from the post sub dumpLinks { my $color = BLUE; my @words = split " ", shift; my $whichc = 0; my $which; foreach $word ( @words ) { if( "@" eq substr $word, 0, 1 ) { $word =~ s/:.*//g; $word =~ s/'.*//g; $word =~ s/\..*//g; $word =~ s/@//g; if( (lc $word) eq (lc $username) ) { $color = YELLOW; } else { $color = BLUE; } $which = sprintf "%03d", int $whichc++; di( $color, $which, CYAN.UNDERLINE, "http://twitter.com/" . $word ); } if( "http" eq (lc (substr $word, 0, 4)) ) { $which = sprintf "%03d", $which++; di( BLUE, $which, CYAN.UNDERLINE, $word ); } } } # dump out the list of items sub displayResponse { my $entry, @items, %ihash; # available tags: # created_at creation date # id post ID # source posting method # text post content # truncated true/false if shortened # user_description info about the user # user_id user's ID # user_location user's location # user_name user's proper name # user_profile_image_url user's avatar image # user_protected user's protection # user_screen_name user's twitter name # user_url user's hhome url foreach $entry ( @displayEntries ) { $ihash = {}; # first, extract out the hash. @items = split $sep1, $entry; foreach $item ( @items ) { ( $key, $value ) = split $sep2, $item; $ihash{ $key } = $value; } # now pretty print it for ourselves di( BLUE, "Ord", CYAN, (sprintf "%02d", $ihash{ "order" })); di( BLUE, "User", YELLOW, $ihash{ "user_name" } ); if( $ihash{ "user_name" } ne $ihash{ "user_screen_name" } ) { di( BLUE, "Nick", YELLOW, $ihash{ "user_screen_name" } ); } di( BLUE, "Date", GREEN, $ihash{ "created_at" } ); di( BLUE, "ID", CYAN.UNDERLINE, ( sprintf "http://twitter.com/%s/statuses/%s", $ihash{ "user_screen_name" }, $ihash{ "id" })); if( $ihash{ "user_protected" } ne "false" ){ di( BLUE, "Prot", BOLD.RED, "Protected" ); } di( BLUE, "URL", CYAN.UNDERLINE, "http://twitter.com/" . $ihash{ "user_screen_name" }); if( "" ne $ihash{ "location" } ) { di( BLUE, "Loc", CYAN, $ihash{ "user_location" }); } dumpLinks( $ihash{ "text" }); di( BLUE, "Text", WHITE, $ihash{ "text" }); printf "\n"; } } sub checkSelfName { $exename = (split "/", $0)[-1]; if( $exename eq "tw" ) { $useColor = 1; } if( $exename eq "tw-mono" ) { $useColor = 0; } } # do stuff sub main { # check for symlinked self-name checkSelfName(); if( scalar @ARGV == 0 ) { $command = sprintf $getcmd, $username, $password; @content = `$command`; parseResponse(); @displayEntries = reverse @sortedEntries; displayResponse(); } else { $content = join ' ', @ARGV; printf "Tweeting: %s\n", webize( $content ); $command = sprintf $putcmd, $username, $password, webize( $content ); `$command`; } } &main;