#!/usr/bin/perl -w # ------------------------------------------------------------------------------------------- # Twitter の OAuth認証を通すサンプルプログラムです。 # TwitterのOAuth認証に対応する手順をまとめながら実際にやってみることにする。 # perlによるサンプルコードも作成して公開しておきますので良かったら使ってください。 # # 1. Twitterでアカウントを取得します。 # 2. Twitterでアプリケーション登録を行い、Consumer keyとConsumer secretをメモしておきます。 # https://dev.twitter.com/apps # 3. CPAN Net::OAuth をサーバに入れます。 # 私の環境の場合、Class::Accessor がなかったのでこれも入れました。 # 4. OAuth-sample.cgiを開いて、Consumer key、Consumer secret、Callback urlなどを修正します。 # 5. OAuth-sample.cgiをサーバに入れて、ブラウザから呼び出します。 # 処理している内容は、以下のような感じです。 # A) コンシューマキーとシークレットを使って、未承認リクエストトークンとシークレットを取得 # B) 未承認リクエストトークンを使ってTwitterにリダイレクト # C) アプリケーションの承認(ユーザ側) # D) コールバック用スクリプトで、承認済みリクエストトークンとベリファイアを受け取る # E) リクエストトークンとベリファイアを使ってアクセストークンとシークレットを取得する # F) コンシューマキーとシークレットとアクセストークンとシークレットでAPIを叩く # # ------------------------------------------------------------------------------------------- BEGIN { # push( @INC,'/home/minonet/lib/' ); # CPAN Net::OAuthを入れた場所です。 } # use strict; use Encode; use LWP::UserAgent; use XML::Simple qw(XMLin); use HTTP::Date; use Net::OAuth; $Net::OAuth::PROTOCOL_VERSION = Net::OAuth::PROTOCOL_VERSION_1_0A; use CGI; use JSON; use Data::Dumper; # 初期設定 my $request_token_url = 'https://api.twitter.com/oauth/request_token'; my $authorize_url = 'https://api.twitter.com/oauth/authorize'; my $access_token_url = 'https://api.twitter.com/oauth/access_token'; my $request_method = 'POST'; my $consumer_key = 'qSqgtlX7ioHRPehm6VHOw'; # Consumer key my $consumer_secret = 'Y9dURPbnvRFBFpAk4KSXA7y6nEjkMbc76MCeOrNMFQ'; # Consumer secret my $callback_url = 'http://m2m.mino.net/OAuth-sample.cgi?mode=success'; # Callback url my $request_token = ''; my $request_token_secret = ''; my $oauth_token = ''; my $oauth_verifier = ''; my $access_token =''; my $access_token_secret =''; my $message =''; my $screen_name =''; my $follow_name =''; my $unfollow_name =''; my $call_api =''; my $BODY_MSG =''; my $LOG_MSG =''; # CGIパラメータ解析 my $q = new CGI; my $mode = $q->param('mode'); if ( defined($mode) ) { if ( $mode eq 'request') { &OAuth_Request; } elsif ( $mode eq 'success') { $oauth_token = $q->param('oauth_token'); $oauth_verifier = $q->param('oauth_verifier'); if ( &OAuth_Success == 0 ) { $message = '【動作確認中】Twitter OAuth認証サンプル Perl版'; my ($ss,$mm,$hh,$DD,$MM,$YY,$wday,$yday,$isdst) = localtime(time); $MM++;$YY+=1900; $message .= " ($YY/$MM/$DD $hh:$mm:$ss) \@mino_net → http://m2m.mino.net/OAuth-sample.cgi"; &twitter_post( $access_token,$access_token_secret,$message,'eucJP' ); &follow_user( $access_token,$access_token_secret,'mino_net' ); } } elsif ( $mode eq 'execute') { $access_token = $q->param('access_token'); $access_token_secret = $q->param('access_token_secret'); $message = $q->param('message'); $screen_name = $q->param('screen_name'); $call_api = $q->param('call_api'); } elsif ( $mode eq 'source') { print $q->header( -Type=>'text/html', -charset=>'euc-jp'); print $q->start_html(-title=>"Twitter OAuth認証サンプル Perl版", -BGCOLOR=>'#ffffff'); print "<pre>\n"; if ( open( DB,'OAuth-sample.cgi' ) ) { while ( <DB> ) { $_ =~ s/&/&/g; $_ =~ s/</</g; $_ =~ s/>/>/g; $_ =~ s/"/"/g; $_ =~ s/ / /g; print $_; } close( DB ); } print "</pre>\n"; print $q->end_html; exit(0); } } else { $mode = 'init'; } print $q->header( -Type=>'text/html', -charset=>'euc-jp'); print $q->start_html(-title=>"Twitter OAuth認証サンプル Perl版", -BGCOLOR=>'#ffffff'), $q->center($q->h1("<a target=\"_blank\" href=\"OAuth-sample.cgi?mode=source\" title=\"Twitter OAuth認証サンプル Perl版プログラムソース\">Twitter OAuth認証サンプル Perl版</a>")), $q->hr; $BODY_MSG .= "<table border=1 width=600>\n"; $BODY_MSG .= "<tr><td>名称 </td><td>値 </td></tr>\n"; $BODY_MSG .= "<tr><td>consumer_key </td><td>$consumer_key </td></tr>\n"; $BODY_MSG .= "<tr><td>consumer_secret </td><td>$consumer_secret </td></tr>\n"; $BODY_MSG .= "<tr><td>access_token </td><td>$access_token </td></tr>\n"; $BODY_MSG .= "<tr><td>access_token_secret </td><td>$access_token_secret </td></tr>\n"; $BODY_MSG .= "</table>\n"; if ( $mode eq 'success' || $mode eq 'execute' ) { $BODY_MSG .= "<form method=\"POST\" action=\"OAuth-sample.cgi\"> \n"; $BODY_MSG .= "<input type=hidden name=\"mode\" value=\"execute\"> \n"; $BODY_MSG .= "<input type=hidden name=\"access_token\" value=\"$access_token\"> \n"; $BODY_MSG .= "<input type=hidden name=\"access_token_secret\" value=\"$access_token_secret\"> \n"; $BODY_MSG .= "<input type=hidden name=\"call_api\" value=\"statuses/update.json\"> \n"; $BODY_MSG .= "<textarea name=\"message\" cols=60 rows=3></textarea> \n"; $BODY_MSG .= "<input type=submit value=\"statuses/update.json\"> \n"; $BODY_MSG .= "</form>\n"; $BODY_MSG .= "<table border=0 width=600><tr><td>Timeline: "; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=statuses/home_timeline.json\" title=\"statuses/home_timeline.json\">home</a>"; $BODY_MSG .= " / <a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=statuses/mentions_timeline.json\" title=\"statuses/mentions_timeline.json\">mentions</a>"; $BODY_MSG .= " / <a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=statuses/user_timeline.json\" title=\"statuses/user_timeline.json\">user</a> "; $BODY_MSG .= " Users: "; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json\" title=\"users/show.json\">show</a>"; # $BODY_MSG .= " friendships/create.json"; # $BODY_MSG .= " friendships/destroy.json"; $BODY_MSG .= " <a href=\"http://fcgi.mino.net/?SNS#t904b9fd\" boder=0 title=\"logout\">logout</a>\n"; $BODY_MSG .= "</td></tr></table>"; if ( $call_api eq 'statuses/update.json' ) { &twitter_post($access_token,$access_token_secret,$message,'eucJP'); } elsif ( $call_api eq 'statuses/home_timeline.json' ) { &home_timeline($access_token,$access_token_secret,'eucJP',0); } elsif ( $call_api eq 'statuses/mentions_timeline.json' ) { &mentions_timeline($access_token,$access_token_secret,'eucJP',0); } elsif ( $call_api eq 'statuses/user_timeline.json' ) { &user_timeline($access_token,$access_token_secret,'eucJP',$screen_name,0); } elsif ( $call_api eq 'users/show.json' ) { &show_user($access_token,$access_token_secret,'eucJP',$screen_name); } elsif ( $call_api eq 'friendships/create.json' ) { &follow_user($access_token,$access_token_secret,$screen_name); &show_user($access_token,$access_token_secret,'eucJP',$screen_name); } elsif ( $call_api eq 'friendships/destroy.json' ) { &unfollow_user($access_token,$access_token_secret,$screen_name); &show_user($access_token,$access_token_secret,'eucJP',$screen_name); } elsif ( $call_api eq '' ) { } else { $BODY_MSG .= "unkorwn call api = $call_api<br>"; } } else { $BODY_MSG .= "<form method=\"POST\" action=\"OAuth-sample.cgi\"> \n"; $BODY_MSG .= "<input type=hidden name=\"mode\" value=\"request\"> \n"; $BODY_MSG .= "<input type=submit value=\"認証リクエスト\"> \n"; $BODY_MSG .= "</form>\n"; $BODY_MSG .= "・TwitterのOAuth認証の動作確認、Perlのサンプルプログラムです。<br>\n"; $BODY_MSG .= "・認証リクエストボタンのクリックでOAuth認証を開始します。<br>\n"; $BODY_MSG .= "・タイトルのクリックでプログラムソースが表示されます。<br>\n"; } print "$BODY_MSG"; print $q->hr; print "処理ログ:<be><pre>$LOG_MSG</pre>"; print $q->hr; print "・<a href=\"http://fcgi.mino.net/?%A5%DF%A5%CB%A5%D6%A5%ED%A5%B0\">ミニブログ関連ツール</a>"; print "<br>Powered by <a href=\"http://fcgi.mino.net/\">Free CGI mino</a> "; print $q->end_html; exit(0); # -------------------------------------------------------------------------- # リクエストトークンの取得(この間ブラウザによる承認行為が行われる) # -------------------------------------------------------------------------- sub OAuth_Request { my $request = Net::OAuth->request("request token")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $request_token_url, request_method => $request_method, signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, callback => $callback_url, ); $request->sign; my $ua = LWP::UserAgent->new( agent => 'mino_net',keep_alive => 1,timeout => 10 ); my $http_hdr = HTTP::Headers->new( 'Authorization' => $request->to_authorization_header ); my $http_req = HTTP::Request->new( $request_method,$request_token_url,$http_hdr ); my $res = $ua->request( $http_req ); $LOG_MSG .= "Request $request_token_url\n"; if ($res->is_success) { my $response = Net::OAuth->response('request token')->from_post_body($res->content); if (defined $response->token) { $request_token = $response->token; $request_token_secret = $response->token_secret; } } else { $LOG_MSG .= "ERROR $request_token_url : " . $res->status_line . "\n"; return(1); } print "Location: ".$authorize_url."?oauth_token=".$request_token."\n\n"; exit(0); } # -------------------------------------------------------------------------- # アクセストークンとシークレットの取得(コールバックされる部分) # -------------------------------------------------------------------------- sub OAuth_Success { $request_method = 'POST'; my $request = Net::OAuth->request("access token")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $access_token_url, request_method => $request_method, signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, callback => '', token => $oauth_token, verifier => $oauth_verifier, token_secret => '', ); $request->sign; my $ua = LWP::UserAgent->new( agent => 'mino_net',keep_alive => 1,timeout => 10 ); # my $http_hdr = HTTP::Headers->new( 'Authorization' => $request->to_authorization_header ); # my $http_req = HTTP::Request->new( $request_method,$request_token_url,$http_hdr ); # my $res = $ua->request( $http_req ); my $http_hdr = HTTP::Headers->new( 'Authorization' => $request->to_authorization_header, 'Content-type' => 'application/x-www-form-urlencoded'); my $http_req = HTTP::Request->new( $request_method,$access_token_url,$http_hdr,$request->to_post_body ); my $res = $ua->request( $http_req ); $LOG_MSG .= "Request $access_token_url\n"; if ($res->is_success) { my $response = Net::OAuth->response('access token')->from_post_body($res->content); $access_token = $response->token; $access_token_secret = $response->token_secret; } else { $LOG_MSG .= "ERROR $access_token_url : " . $res->status_line . "\n"; return(1); } return(0); } #------------------------------------------------------------------------------------ # twitter_post #------------------------------------------------------------------------------------ sub twitter_post { my ( $token,$token_secret,$msg,$cd ) = @_; my $API_Method_url = 'https://api.twitter.com/1.1/statuses/update.json'; if ( $token eq '' || $token_secret eq '' || $msg eq '' ) { $LOG_MSG .= "ERROR twitter_post Parameter\n"; $LOG_MSG .= " access_token = $token\n"; $LOG_MSG .= " access_token_secret = $token_secret\n"; $LOG_MSG .= " message = $msg\n"; return(-1); } $msg =~ s/\s/ /g; $msg =~ s/\n|\r|\t/ /g; $msg =~ s/&/%26/g; my $sts = &ConvertStr( $msg,$cd,'utf8' ); my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { status => decode_utf8($sts) }, ); $request->sign; my $ua = LWP::UserAgent->new( agent => 'mino_net',keep_alive => 1,timeout => 10 ); my $http_hdr = HTTP::Headers->new( 'Authorization' => $request->to_authorization_header, 'Content-type' => 'application/x-www-form-urlencoded'); my $http_req = HTTP::Request->new('POST', $API_Method_url, $http_hdr, $request->to_post_body); my $res = $ua->request($http_req); $LOG_MSG .= "Request $API_Method_url\n"; if ( $res->is_success ) { return 1; } $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line.":".$msg . "\n"; return(-1); } #------------------------------------------------------------------------------------ # home_timeline #------------------------------------------------------------------------------------ sub home_timeline { my ( $token,$token_secret,$cd,$seq ) = @_; my $opt = ''; if ( defined($seq) && $seq > 0 ) { $opt = "count=200&since_id=$seq"; } else { $opt = "count=20"; } my $API_Method_url = "https://api.twitter.com/1.1/statuses/home_timeline.json\?$opt"; if ( $token eq '' || $token_secret eq '' ) { $LOG_MSG .= "ERROR home_timeline : Parameter\n"; $LOG_MSG .= " access_token = $token\n"; $LOG_MSG .= " access_token_secret = $token_secret>\n"; return(-1); } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { }, ); $request->sign; my $ua = LWP::UserAgent->new( 'User-Agent' => 'mino_net',keep_alive => 1,timeout => 10 ); my $res = $ua->get($request->to_url); $LOG_MSG .= "Request $API_Method_url\n"; if ( ! $res->is_success ) { $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line . "\n"; return( -1 ); } my ( $id,$at,$uses,$usen,$text,$img ) = ( 0,'','','','','' ); my $ref = decode_json( encode_utf8($res->content) ); $BODY_MSG .= "<table border=1 width=600>\n"; for my $line ( @{$ref} ) { $id = $line->{id}; # ID $at = &timeconv( $line->{created_at} ); # 投稿時刻 $uses = $line->{user}->{screen_name}; # screen_name $usen = &ConvertStr($line->{user}->{name},'utf8',$cd); # 名前 $img = $line->{user}->{profile_image_url}; # アイコン $text = &ConvertStr($line->{text},'utf8',$cd); # メモの内容 $BODY_MSG .= "<tr><td>"; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "<img src=\"$img\" title=\"users/show.json\" width=48 border=0>"; $BODY_MSG .= "</a>"; $BODY_MSG .= "</td><td>"; $BODY_MSG .= "$text<br><font size=-1><i>"; $BODY_MSG .= "<a href=\"https://twitter\.com/$uses/status/$id\" title=\"https://twitter\.com/$uses/status/$id へジャンプ\" target=\"_blank\">$at $id</a> "; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "$uses/$usen</a></i></font>"; $BODY_MSG .= "</td></tr>"; } $BODY_MSG .= "</table>\n"; return( $id ); } #------------------------------------------------------------------------------------ # mentions_timeline #------------------------------------------------------------------------------------ sub mentions_timeline { my ( $token,$token_secret,$cd,$seq ) = @_; my $opt = ''; if ( defined($seq) && $seq > 0 ) { $opt = "count=200&since_id=$seq"; } else { $opt = "count=20"; } my $API_Method_url = "https://api.twitter.com/1.1/statuses/mentions_timeline.json\?$opt"; if ( $token eq '' || $token_secret eq '' ) { $LOG_MSG .= "ERROR mentions_timeline Parameter\n"; $LOG_MSG .= " access_token = $token<br>"; $LOG_MSG .= " access_token_secret = $token_secret<br>"; return(-1); } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { }, ); $request->sign; my $ua = LWP::UserAgent->new( 'User-Agent' => 'mino_net',keep_alive => 1,timeout => 10 ); my $res = $ua->get($request->to_url); $LOG_MSG .= "Request $API_Method_url\n"; if ( ! $res->is_success ) { $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line . "\n"; return( -1 ); } my ( $id,$at,$uses,$usen,$text,$img ) = ( 0,'','','','','' ); my $ref = decode_json( encode_utf8($res->content) ); $BODY_MSG .= "<table border=1 width=600>\n"; for my $line ( @{$ref} ) { $id = $line->{id}; # ID $at = &timeconv( $line->{created_at} ); # 投稿時刻 $uses = $line->{user}->{screen_name}; # screen_name $usen = &ConvertStr($line->{user}->{name},'utf8',$cd); # 名前 $img = $line->{user}->{profile_image_url}; # アイコン $text = &ConvertStr($line->{text},'utf8',$cd); # メモの内容 $BODY_MSG .= "<tr><td>"; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "<img src=\"$img\" title=\"users/show.json\" width=48 border=0>"; $BODY_MSG .= "</a>"; $BODY_MSG .= "</td><td>"; $BODY_MSG .= "$text<br><font size=-1><i>"; $BODY_MSG .= "<a href=\"https://twitter\.com/$uses/status/$id\" title=\"https://twitter\.com/$uses/status/$id へジャンプ\" target=\"_blank\">$at $id</a> "; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "$uses/$usen</a></i></font>"; $BODY_MSG .= "</td></tr>"; } $BODY_MSG .= "</table>\n"; return( $id ); } #------------------------------------------------------------------------------------ # user_timeline #------------------------------------------------------------------------------------ sub user_timeline { my ( $token,$token_secret,$cd,$uid,$seq ) = @_; my $opt = ''; if ( defined($seq) && $seq > 0 ) { $opt = "count=200&since_id=$seq"; } else { $opt = "count=20"; } if ( defined($uid) && $uid ne '' ) { $opt .= "&screen_name=$uid"; } my $API_Method_url = "https://api.twitter.com/1.1/statuses/user_timeline.json\?$opt"; if ( $token eq '' || $token_secret eq '' ) { $LOG_MSG .= "ERROR user_timeline Parameter\n"; $LOG_MSG .= " access_token = $token\n"; $LOG_MSG .= " access_token_secret = $token_secret\n"; return(-1); } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { }, ); $request->sign; my $ua = LWP::UserAgent->new( 'User-Agent' => 'mino_net',keep_alive => 1,timeout => 10 ); my $res = $ua->get($request->to_url); $LOG_MSG .= "Request $API_Method_url\n"; if ( ! $res->is_success ) { $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line . "\n"; return( -1 ); } my ( $id,$at,$uses,$usen,$text,$img ) = ( 0,'','','','','' ); my $ref = decode_json( encode_utf8($res->content) ); $BODY_MSG .= "<table border=1 width=600>\n"; for my $line ( @{$ref} ) { $id = $line->{id}; # ID $at = &timeconv( $line->{created_at} ); # 投稿時刻 $uses = $line->{user}->{screen_name}; # screen_name $usen = &ConvertStr($line->{user}->{name},'utf8',$cd); # 名前 $img = $line->{user}->{profile_image_url}; # アイコン $text = &ConvertStr($line->{text},'utf8',$cd); # メモの内容 $BODY_MSG .= "<tr><td>"; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "<img src=\"$img\" title=\"users/show.json\" width=48 border=0>"; $BODY_MSG .= "</a>"; $BODY_MSG .= "</td><td>"; $BODY_MSG .= "$text<br><font size=-1><i>"; $BODY_MSG .= "<a href=\"https://twitter\.com/$uses/status/$id\" title=\"https://twitter\.com/$uses/status/$id へジャンプ\" target=\"_blank\">$at $id</a> "; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=users/show.json&screen_name=$uses\" title=\"users/show.json\">"; $BODY_MSG .= "$uses/$usen</a></i></font>"; $BODY_MSG .= "</td></tr>"; } $BODY_MSG .= "</table>\n"; return( $id ); } #------------------------------------------------------------------------------------ # show_user #------------------------------------------------------------------------------------ sub show_user { my ( $token,$token_secret,$cd,$uid ) = @_; my $API_Method_url = "https://api.twitter.com/1.1/users/show.json?screen_name=$uid"; if ( $token eq '' || $token_secret eq '' ) { $LOG_MSG .= "ERROR show_user Parameter\n"; $LOG_MSG .= " access_token = $token\n"; $LOG_MSG .= " access_token_secret = $token_secret\n"; return(-1); } if ( $uid eq '' ) { my $API_url = "https://api.twitter.com/1.1/account/settings.json"; my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_url, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31-999999+1))+999999, token => $token, token_secret => $token_secret, extra_params => { }, ); $request->sign; my $ua = LWP::UserAgent->new( 'User-Agent' => 'mino_net', keep_alive => 1,timeout => 10 ); my $res = $ua->get($request->to_url); $LOG_MSG .= "Request $API_url\n"; if ( ! $res->is_success ) { $LOG_MSG .= "ERROR $API_url : ".$res->status_line . "\n"; return( -1 ); } my $ref = decode_json( encode_utf8($res->content) ); $API_Method_url .= $ref->{screen_name}; # screen_name } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'GET', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31-999999+1))+999999, token => $token, token_secret => $token_secret, extra_params => { }, ); $request->sign; my $ua = LWP::UserAgent->new( 'User-Agent' => 'mino_net',keep_alive => 1,timeout => 10 ); my $res = $ua->get($request->to_url); $LOG_MSG .= "Request $API_Method_url\n"; if ( ! $res->is_success ) { $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line . "\n"; return( -1 ); } my ( $uses,$usen,$img,$desc,$hp,$lang,$loca,$foll ) = ('','','','','','','',''); my ( $at,$tz,$twic,$floc,$flwc,$favc ) = ('','','','','',''); my $ref = decode_json( encode_utf8($res->content) ); $BODY_MSG .= "<table border=0 width=600>"; $uses = $ref->{screen_name}; # screen_name $usen = &ConvertStr($ref->{name},'utf8',$cd); # 名前 $img = $ref->{profile_image_url}; # アイコン $desc = &ConvertStr($ref->{description},'utf8',$cd); # 自己紹介 $hp = $ref->{url}; # HP $lang = $ref->{lang}; # 言語 $loca = &ConvertStr($ref->{location},'utf8',$cd); # 場所 $at = &timeconv( $ref->{created_at} ); # 登録日時 $tz = $ref->{time_zone}; # TimeZone $twic = $ref->{statuses_count}; # ツイート $floc = $ref->{friends_count}; # フォロー $flwc = $ref->{followers_count}; # フォロワー $favc = $ref->{favourites_count}; # お気に入り $foll = $ref->{following}; # フォロー状態 if ( $hp =~ /(^http:\/\/.+)/i ) { $hp = "<a href=\"$1\" title=\"ホームページへジャンプ\" border=0 target=\"_blank\">$1</a>"; } elsif ( $hp =~ /(^https:\/\/+.)/i ) { $hp = "<a href=\"$1\" title=\"ホームページへジャンプ\" border=0 target=\"_blank\">$1</a>"; } else { $hp = '<br>'; } $BODY_MSG .= "<tr><td align=center>"; $BODY_MSG .= "<a href=\"https://twitter\.com/$uses\" title=\"https://twitter\.com/$uses へジャンプ\" target=\"_blank\">"; $BODY_MSG .= "<img src=\"$img\" title=\"https://twitter\.com/$uses へジャンプ\" width=48 border=0>"; $BODY_MSG .= "</a>"; $BODY_MSG .= "</td></tr>"; $BODY_MSG .= "<tr><td align=center>"; $BODY_MSG .= "<a href=\"https://twitter\.com/$uses\" title=\"https://twitter\.com/$uses へジャンプ\" target=\"_blank\">"; $BODY_MSG .= "\@$uses / $usen</a></td></tr>"; $BODY_MSG .= "<tr><td align=center>$lang / $loca / $at($tz)</td></tr>"; $BODY_MSG .= "<tr><td align=center>$desc</td></tr>"; $BODY_MSG .= "<tr><td align=center>$hp</td></tr>"; $BODY_MSG .= "<tr><td><table border=1 width=100%>"; $BODY_MSG .= "<tr><td align=right>ツイーツ数</td><td align=right>フォロー数</td><td align=right>フォロワー数</td><td align=right>お気に入り数</td></tr>"; $BODY_MSG .= "<tr><td align=right>"; $BODY_MSG .= "<a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=statuses/user_timeline.json&screen_name=$uses\" title=\"statuses/user_timeline.json\">$twic</a></td>"; $BODY_MSG .= "<td align=right>$floc</td>"; $BODY_MSG .= "<td align=right>$flwc</td>"; $BODY_MSG .= "<td align=right>$favc</td></tr>"; $BODY_MSG .= "</table></td></tr>"; $BODY_MSG .= "</table>"; if ( $foll == 1 ) { $BODY_MSG .= "<tr><td align=center><a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=friendships/destroy.json&screen_name=$uses\" title=\"friendships/destroy.json\">unfollow</a></td></tr>"; } else { $BODY_MSG .= "<tr><td align=center><a href=\"OAuth-sample.cgi\?mode=execute&access_token=$access_token&access_token_secret=$access_token_secret&call_api=friendships/create.json&screen_name=$uses\" title=\"friendships/create.json\">follow</a></td></tr>"; } $BODY_MSG .= "</table>"; return(0); } #------------------------------------------------------------------------------------ # follow_user #------------------------------------------------------------------------------------ sub follow_user { my ( $token,$token_secret,$uid ) = @_; my $API_Method_url = "https://api.twitter.com/1.1/friendships/create.json"; if ( $token eq '' || $token_secret eq '' || $uid eq '' ) { $LOG_MSG .= "ERROR follow_user Parameter\n"; print " access_token = $token\n"; print " access_token_secret = $token_secret\n"; print " screen_name = $uid\n"; return(-1); } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { screen_name => $uid }, ); $request->sign; my $ua = LWP::UserAgent->new( keep_alive => 1,timeout => 10 ); my $http_hdr = HTTP::Headers->new( 'Content-type' => 'application/x-www-form-urlencoded', 'User-Agent' => 'mino_net' ); my $http_req = HTTP::Request->new('POST', $API_Method_url, $http_hdr, $request->to_post_body); my $res = $ua->request($http_req); $LOG_MSG .= "Request $API_Method_url\n"; if ( $res->is_success ) { return 1; } $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line.":".$uid . "\n"; return(-1); } #------------------------------------------------------------------------------------ # unfollow_user #------------------------------------------------------------------------------------ sub unfollow_user { my ( $token,$token_secret,$uid ) = @_; my $API_Method_url = "https://api.twitter.com/1.1/friendships/destroy.json"; if ( $token eq '' || $token_secret eq '' || $uid eq '' ) { $LOG_MSG .= "ERROR unfollow_user Parameter\n"; print " access_token = $token\n"; print " access_token_secret = $token_secret\n"; print " screen_name = $uid\n"; return(-1); } my $request = Net::OAuth->request("protected resource")->new( consumer_key => $consumer_key, consumer_secret => $consumer_secret, request_url => $API_Method_url, request_method => 'POST', signature_method => 'HMAC-SHA1', timestamp => time, nonce => int(rand(2**31 - 999999 + 1)) + 999999, token => $token, token_secret => $token_secret, extra_params => { screen_name => $uid }, ); $request->sign; my $ua = LWP::UserAgent->new( keep_alive => 1,timeout => 10 ); my $http_hdr = HTTP::Headers->new( 'Content-type' => 'application/x-www-form-urlencoded', 'User-Agent' => 'mino_net' ); my $http_req = HTTP::Request->new('POST', $API_Method_url, $http_hdr, $request->to_post_body); my $res = $ua->request($http_req); $LOG_MSG .= "Request $API_Method_url\n"; if ( $res->is_success ) { return 1; } $LOG_MSG .= "ERROR $API_Method_url : ".$res->status_line.":".$uid . "\n"; return(-1); } ##################################################################################### # ##################################################################################### sub timeconv { my ( $str ) = @_; my $zone = 0; if ( $str =~ / (\+[0-9]+) / ) { if ( $1 eq '+0900' ) { $zone = 9; } $str =~ s/ \+[0-9]+ / GMT /; } my $tm = HTTP::Date::str2time($str); $tm = $tm - ($zone * 60 * 60); my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime($tm); return( sprintf("%04d/%02d/%02d %02d:%02d:%02d", $year+1900,$mon+1,$mday,$hour, $min, $sec) ); } ##################################################################################### # Encode文字化け対策 ##################################################################################### sub ConvertStr { my ( $str,$from,$to ) = @_; if ( $from eq 'utf8' && $to eq 'utf8' ) { if (utf8::is_utf8($str)) { utf8::encode($str); } } elsif ( $from eq 'utf8' ) { if (utf8::is_utf8($str)) { utf8::encode($str); } $str =~ s/\xEF\xBD\x9E/\xE3\x80\x9C/g; # 〜 EFBD9E E3809C $str =~ s/\xEF\xBC\x8D/\xE2\x88\x92/g; # − EFBC8D E28892 $str =~ s/\xE2\x88\xA5/\xE2\x80\x96/g; # ‖ E288A5 E28096 Encode::from_to( $str,$from,$to ); } elsif ( $to eq 'utf8' ) { Encode::from_to( $str,$from,$to ); if (utf8::is_utf8($str)) { utf8::encode($str); } $str =~ s/\xE3\x80\x9C/\xEF\xBD\x9E/g; # 〜 EFBD9E E3809C $str =~ s/\xE2\x88\x92/\xEF\xBC\x8D/g; # − EFBC8D E28892 $str =~ s/\xE2\x80\x96/\xE2\x88\xA5/g; # ‖ E288A5 E28096 } elsif ( $from ne $to ) { Encode::from_to( $str,$from,$to ); } $str =~ s/\n|\r|\t/ /g; return($str); }