« がんばろう、自分。 | メイン | 今までの人生で一番うまかったたいやき »

2007年04月22日

メールでTwitterに投稿するPerlスクリプト


せわしなかった今週末でしたけど、土曜日は久しぶりに趣味のプログラミングができて楽しかったです。
予告どおり、メールでTwitterに投稿するPerlスクリプトを作ってみました。
#!/usr/bin/perl
#
# twmail.pl : Update Twitter via mail
#

use strict;
use Encode qw/from_to/;
use LWP::UserAgent;
use URI::Escape;
use MIME::Parser;
use Net::SMTP;

my $user = "your username";
my $pass = "your password";
my $mail_server = "your mail server";

my $uri = "http://twitter.com/statuses/update.json"; 
my $agent = "twmail/0.1";
my $truncate = 0;

# メールを解析
my $parser = new MIME::Parser;
$parser->output_to_core(1);
my $entity = $parser->parse( \*STDIN );
my ( $from, $charset, $message ) = &parse_mail( $entity );

# メッセージを処理
$message = &encode_message( $message, $charset, $truncate );

# メッセージを投げる
my $status = &submit( $user, $pass, $message, $uri, $agent );

# 失敗したらメールで知らせる
&report_failure( $from, $mail_server, $status, $agent ) if ( $status );

###
sub parse_mail {
    my $ent = shift;
    my $head = $ent->head;
    my $body = $ent->bodyhandle;
    my $from = $head->get( 'From' );
    if ( $from =~ /<(.*?)>/ ) { $from = $1; }
    return ( $from, $head->mime_attr( 'Content-Type.charset' ),
	     $body->as_string
	     );
}

sub encode_message {
    my ( $mes, $char, $t ) = @_;
    $mes =~ s/\s/ /g;
    from_to( $mes, $char, 'utf8' );
    if ( $t ) {
	if ( length( $mes ) > 140 ) {
	    $mes = substr( $mes, 0, 139 );
	}
    }
    return uri_escape( $mes );
}

sub submit {
    my ( $user, $pass, $mes, $url, $agent ) = @_;
    my $req = HTTP::Request->new( POST => $uri );
    $req->authorization_basic( $user, $pass );
    $req->content( "status=" . $mes );
    my $ua = LWP::UserAgent->new( agent => $agent, keepalive => 4 );
    my $res = $ua->request( $req );
    my $status = $res->status_line;
    if ( $res->is_success ) { return 0; }
    else { return $status; }
}

sub report_failure {
    my ( $addr, $server, $status, $agent ) = @_;
    my $smtp = Net::SMTP->new( $server );
    $smtp->mail( $agent );
    $smtp->to( $addr );
    $smtp->data();
    $smtp->datasend( "From: $agent\n" );
    $smtp->datasend( "To: $addr\n" );
    $smtp->datasend( "Subject: twitter submit failed\n" );
    $smtp->datasend( "\n" );
    $smtp->datasend( $status );
    $smtp->dataend();
    $smtp->quit;
}
標準入力からメールを読み込むように、これを .qmail なり .forward なりに仕込めばOK。
.qmailであれば
| preline /path/to/twmail.pl
などとしておきます。

これを作るに当たって、404 Blog Not Foundさんの記事を参考にさせて頂きました。この場を借りてお礼申し上げます。
というか、やってることはほとんど同じなんですよね(苦笑)
わざわざ車輪の再発明をしたのは、

・TwitterのAPIに触る練習
・ホームディレクトリに仕込むファイルをひとつだけにしたかった
・うちの環境にYAMLとかJSONのモジュールが入ってなかった(をい)

という、きわめて個人的な理由から。
あと、メールの解析をMIME::Parserに任せてみたかった、というのもあるかも。
携帯からメールでひと言投稿するというスタイルを仮定しているので、解析のしかたはかなり手抜きですが……。

携帯から投稿するだけでよければ、Webインターフェイスにアクセスするよりメールで投げた方が手軽でいいですね。パケ代も少なくて済みますし(笑)、思いついたときにサッと投稿できるのはなかなか便利だと思います。

投稿者 r-top : 2007年04月22日 23:38

トラックバック

このエントリーのトラックバックURL:
http://polaire.org/r-top_mt/mt-tb_1.pl/669

コメント

コメントしてください




保存しますか?