#!/usr/bin/perl # =============================================================== # Twitterを携帯とかでスマートに使おうかなとか思って # でっちあげたPerlスクリプト # # "Twimp" v0.9 by iMp / SOU1 $version ="0.9"; # # =============================================================== # -------------------------------------- # 以下、通常ユーザー設定項目 # -------------------------------------- # Twitterのアカウント情報 $user = "(Twitterのユーザー名を入力)"; $pass = "(Twitterのパスワードを入力)"; # 画面表示時刻のタイムゾーン $timezone = 'JST'; # 画面に表示するメッセージ数(最大20) $msgnum = 10; # 時刻・名前表示の背景色 $name_bg = "#3377AA"; # 時刻・名前表示の文字色 $name_color = "#FFFFFF"; # ユーザー名のリンクで返信(@〜 )自動追加 : 1で有効/0で無効 $use_reply = 0; # ユーザー画像 : 1で有効/0で無効 $use_img = 0; # Status末尾の "from 〜" 表示 # 0 = Twimp # 1 = web $stat_from = 0; # 返信自動追加有効時、BODYタグのリンク色設定 $link ="#88CCFF"; $alink ="#88CCFF"; $vlink ="#88CCFF"; # -------------------------------------- # 以上、ユーザー設定項目 # -------------------------------------- # Twitter投稿先URL $readuri = "http://twitter.com/statuses/friends_timeline.xml"; $posturi = "http://twitter.com/statuses/update.json"; # Twimp User-Agent $agent = "twimp/".$version; # モジュール宣言 use Jcode; use LWP::UserAgent; use XML::Simple; use Data::Dumper; use HTTP::Date; # 機種依存文字変換テーブル作成 &init_table; # スクリプトのファイル名取得 $ENV{'SCRIPT_FILENAME'} =~ /\/([^\/]+)$/; $filename = $1; # FORMデータ取得 if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $post_buffer, $ENV{'CONTENT_LENGTH'}); } $buffer = $ENV{'QUERY_STRING'} . '&' . $post_buffer; @pairs = split(/&/,$buffer); # FORMデータ分割 foreach $pair(@pairs) { ($name,$value) = split(/=/,$pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value = &gaiji_conv($value); Jcode::convert(\$value,'utf8','sjis'); $FORM{$name} = $value; } # ----- POST呼び出しの場合→Twitter投稿 if($ENV{'REQUEST_METHOD'} eq "POST") { # FORMデータ確認 if ($FORM{'message'} eq "") { &error('メッセージが未記入です'); } # --- from [appname] の表示内容 if($stat_from == 1) { $update_source = "web"; } else { $update_source = "twimp"; } # メッセージをURLエンコード $enc_message = url_encode($FORM{'message'}); # ----- LWPを使った投稿処理 # ※twmailを参考にさせて頂きました # http://polaire.org/r-top/mob/archives/2007/04/twitterperl.html $req = HTTP::Request->new( POST => $posturi ); $req->authorization_basic( $user, $pass ); if ($FORM{'replyuid'} ne "") { $req->content("source=" . $update_source . "&status=" . $enc_message . "&in_reply_to_user_id=" . $FORM{'replyuid'} . "&in_reply_to_status_id=" . $FORM{'replymsgid'} ); } else { $req->content("source=" . $update_source . "&status=" . $enc_message); } $req->header("X-Twitter-Client" => "Twimp"); $req->header("X-Twitter-Client-Version" => $version); $req->header("X-Twitter-Client-URL" => "http://callusnext.com/twimp.xml"); $ua = LWP::UserAgent->new( agent => $agent, keepalive => 4 ); $res = $ua->request( $req ); $status = $res->status_line; # HTTP Status確認 if ($status !~ m/^200/i) { &error('取得に失敗しました
ステータス : '.$status); } # ----- 成功メッセージ出力 # HTTPヘッダ &http_header(); # HTML本体 print "\n"; print "投稿しました。
\n"; print "ステータス:$status
\n"; print "[戻る]
\n"; print "\n"; exit; } # 返信先ユーザー名格納 $reply_uid = ""; $reply_msgid = ""; $reply_name = $FORM{'reply'}; if( $reply_name ne "" ) { Jcode::convert(\$reply_name,'sjis'); $reply_disp = sprintf("@%s ",$reply_name); $reply_uid = $FORM{'uid'}; $reply_msgid = $FORM{'msgid'}; } # ----- friends_timeline取得 # LWPを使った取得処理 $req = HTTP::Request->new( GET => $readuri ); $req->authorization_basic( $user, $pass ); $req->header("X-Twitter-Client" => "Twimp"); $req->header("X-Twitter-Client-Version" => $version); $req->header("X-Twitter-Client-URL" => "http://callusnext.com/twimp.xml"); $ua = LWP::UserAgent->new( agent => $agent, keepalive => 4 ); $res = $ua->request( $req ); $status = $res->status_line; $content = $res->content; # HTTP Status確認 if ($status !~ m/^200/i) { &error('取得に失敗しました
ステータス : '.$status); } # XMLパーサ処理(XML::Simple使用) $xmlparser = XML::Simple->new; $xmldata = $xmlparser->XMLin($content); # エントリIDの取得・ソート @entries_id = sort {$b cmp $a} keys %{$xmldata->{status}}; # ----- HTML出力 # HTTPヘッダ &http_header(); # HTML本体 print "Twimp\n"; }else { print "\n"; } print "[リロード]
\n"; print "
\n"; print "\n"; if( $reply_name ne "" ) { print "\n"; print "\n"; } print "
\n"; print "
\n"; # メッセージ出力 foreach $id (@entries_id) { # メッセージ数判定 $msgnum--; if($msgnum < 0) { last; } # ----- メッセージ整形出力 $uid = $xmldata->{status}->{$id}->{user}->{id}; $text = $xmldata->{status}->{$id}->{text}; $name = $xmldata->{status}->{$id}->{user}->{screen_name}; $img = $xmldata->{status}->{$id}->{user}->{profile_image_url}; $createtime = $xmldata->{status}->{$id}->{created_at}; $createtime =~ s/\+0000/GMT/g; $createtime = HTTP::Date::str2time($createtime,$timezone); ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($createtime); $disptime = sprintf("%02d:%02d",$hour,$min); $text = &wave_conv($text); Jcode::convert(\$text,'sjis','utf8'); $name = &wave_conv($name); Jcode::convert(\$name,'sjis','utf8'); if( $use_reply == 1 ) { print "

$disptime $name

\n"; }else { print "

$disptime $name

\n"; } if( $use_img == 1 ) { print ""; } print "$text\n"; } print "\n"; exit; # ======================================================================== # 以下サブルーチン # ======================================================================== # ================================ # エラー時処理 # ================================ sub error { # ----- HTML出力 # HTTPヘッダ &http_header(); # HTML本体 print "Twimp:Error\n"; print "エラー : ".$_[0]."
\n"; print "[戻る]
\n"; print ""; exit; } # ================================ # HTTPヘッダ出力 # ================================ sub http_header { print "Content-type: text/html; charset=Shift_JIS\n"; print "Content-Language: ja\n"; print "Pragma: no-cache\n"; print "Cache-Control: no-cache\n\n"; } # ================================ # URLエンコード # ================================ sub url_encode($) { my $str = shift; $str =~ s/([^\w ])/'%'.unpack('H2', $1)/eg; $str =~ tr/ /+/; return $str; } # ================================ # 機種依存文字変換テーブル作成 # ================================ sub init_table { # windows-932 (Japanese Shift-JIS) # Gaiji (Lead Byte = 0x87) to Normal %gaiji_table = ( "\x87\x40" => '(1)', "\x87\x41" => '(2)', "\x87\x42" => '(3)', "\x87\x43" => '(4)', "\x87\x44" => '(5)', "\x87\x45" => '(6)', "\x87\x46" => '(7)', "\x87\x47" => '(8)', "\x87\x48" => '(9)', "\x87\x49" => '(10)', "\x87\x4a" => '(11)', "\x87\x4b" => '(12)', "\x87\x4c" => '(13)', "\x87\x4d" => '(14)', "\x87\x4e" => '(15)', "\x87\x4f" => '(16)', "\x87\x50" => '(17)', "\x87\x51" => '(18)', "\x87\x52" => '(19)', "\x87\x53" => '(20)', "\x87\x54" => 'I', "\x87\x55" => 'II', "\x87\x56" => 'III', "\x87\x57" => 'IV', "\x87\x58" => 'V', "\x87\x59" => 'VI', "\x87\x5a" => 'VII', "\x87\x5b" => 'VIII', "\x87\x5c" => 'IX', "\x87\x5d" => 'X', "\x87\x5f" => 'ミリ', "\x87\x60" => 'キロ', "\x87\x61" => 'センチ', "\x87\x62" => 'メートル', "\x87\x63" => 'グラム', "\x87\x64" => 'トン', "\x87\x65" => 'アール', "\x87\x66" => 'ヘクタール', "\x87\x67" => 'リットル', "\x87\x68" => 'ワット', "\x87\x69" => 'カロリー', "\x87\x6a" => 'ドル', "\x87\x6b" => 'センチ', "\x87\x6c" => 'パーセント', "\x87\x6d" => 'ミリバール', "\x87\x6e" => 'ページ', "\x87\x6f" => 'mm', "\x87\x70" => 'cm', "\x87\x71" => 'km', "\x87\x72" => 'mg', "\x87\x73" => 'kg', "\x87\x74" => 'cc', "\x87\x75" => 'm2', "\x87\x7e" => '平成', "\x87\x80" => '“', "\x87\x81" => '”', "\x87\x82" => 'No.', "\x87\x83" => 'K.K.', "\x87\x84" => 'TEL', "\x87\x85" => '(上)', "\x87\x86" => '(中)', "\x87\x87" => '(下)', "\x87\x88" => '(左)', "\x87\x89" => '(右)', "\x87\x8a" => '(株)', "\x87\x8b" => '(有)', "\x87\x8c" => '(代)', "\x87\x8d" => '明治', "\x87\x8e" => '大正', "\x87\x8f" => '昭和', "\x87\x90" => '≒', "\x87\x91" => '≡', "\x87\x92" => '∫', "\x87\x93" => 'c∫', "\x87\x94" => 'Σ', "\x87\x95" => '√', "\x87\x96" => '⊥', "\x87\x97" => '∠', "\x87\x98" => '└', "\x87\x99" => 'Δ', "\x87\x9a" => '∵', "\x87\x9b" => '∩', "\x87\x9c" => '∪', ); } # ================================ # 機種依存文字変換処理 # from SjisH2Z.pm (c)2005 Niki # ================================ sub gaiji_conv($) { my($string) = @_; my ($j,$c,$c2,@c); my $ctype = '1'; # 1:ASCII K:半角カナ 2:2バイト文字 my $result; my $k; @c = split(//,$string); for( $j = 0; $j <= $#c; $j++ ) { $c = $c[$j]; # ASCIIなら if( $c =~ /[\x00-\x7f]/ ) { $ctype = '1'; $result .= $c; } # 2バイト文字なら elsif( $c =~ /[\x81-\x9f\xe0-\xff]/ ) { last if( ++$j > $#c ); $c2 = $c[$j]; if( $c2 =~ /[\x40-\xfc]/ ) { $ctype = '2'; $result .= $c . $c2; } else { $result .= $c . $c2; } } # それ以外なら else { $ctype = '1'; $result .= $c; } } $ctype = '1'; @c = split(//,$string); $c = '(?:[\x00-\x7F\xA1-\xDF]|[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])'; $result =~ s/($c)/exists $gaiji_table{$1} ? $gaiji_table{$1} : $1/geo; return $result; } # ================================ # 波線処理 # ================================ sub wave_conv($) { my($string) = @_; use bytes; my $wave_length = length("\xEF\xBD\x9E"); while ((my $i = index($string,"\xEF\xBD\x9E",0)) >= 0) { $string = substr($string,0,$i).'~'.substr($string,$i+$wave_length,length($string)-$wave_length) ; } no bytes; return $string; } # End of script