忍者ブログ
a pot of tea,
プログラミング勉強中。備忘録や、つくったものの紹介を書いています。openFrameworks(ofxiPhone)/Perl/PHP/as3(flash,AIR)などなど。
Admin / Write
2024/03/29 (Fri) 03:10
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

2011/03/07 (Mon) 22:21
第6回というか、第2部というか。

ひさびさにperlと格闘しました。
先日公開された、公式リズムシbot(@rhythmushi_bot)のプログラムを担当しました。
リズムシ作者さんの公式HPはこちら:オトノアソビバ

機能は、
・定時ツイート
・リプライへの返事
・フォローされたらリフォロー&リプライ送信
おおまかにこの3つ。

今回はお見せできない部分もあるのですが、以下ソースコードです。

@4/19 追記
コードを大幅にいじりました。
比較のためにこちらのコードも残しておきますが、よりよい(と思われる)最新版はこちら








#!/usr/bin/perl
use warnings;
use strict;
use CGI::Carp qw(fatalsToBrowser);

# モジュールのパスを追加
use lib qw(/パス);

# Net::Twitter::Lite、Data::Dumperモジュールを使用
use Net::Twitter::Lite;
use Data::Dumper;

# utf8エンコードを使用
use utf8;
use Encode;
use JSON 'decode_json';
binmode(STDOUT, ":utf8");

# HTML出力
print "Content-Type: text/html\n\n";

# twitter認証
my %RAP_CONSUMER_TOKENS = (
consumer_key => 'コンシューマトークンのキー',
consumer_secret => 'コンシューマトークンのパスワード');

my $RAP_ACCESS_TOKEN = 'アクセストークンのキー';
my $RAP_ACCESS_TOKEN_SECRET = 'アクセストークンのパスワード';

# 呼び出し、トークンセット
my $rapTweet = Net::Twitter::Lite->new(%RAP_CONSUMER_TOKENS);
$rapTweet->access_token($RAP_ACCESS_TOKEN);
$rapTweet->access_token_secret($RAP_ACCESS_TOKEN_SECRET);

######################

## 定時ツイート ##

# localtime()関数は、秒、分、時、日にち、月、年、曜日の配列になっている
# ※年は1900をプラス、月は1をプラスして使う
(my $sec, my $min, my $hour,
my $mday, my $mon, my $year, my $wday) = localtime();

# $min=分が10分未満のとき=毎時間実行
if($min < 10){
	my $rnd = int(rand(2));
	if($rnd == 0){
		my $kotobaResult;
		
		# サブルーチン"pattGenarate"を実行
		$kotobaResult = pattGenerate();
		
		$rapTweet->update($kotobaResult);
	}
}

sub pattGenerate{
	
	# 非公開です!ごめんなさい。
	
	return $result;
}

######################

## リプライ返し ##

# 自分へのリプライを取得
my $rapParam = $rapTweet->mentions();

# 結果を書き出すテキストファイル
my $rapFile = '.txt';

# 書き出しに使用
my @rapFlags;
my @rapStatus;
my @rapIds;

# リプライの内容の配列
my @replyStatus = ("リプライの内容");

foreach my $str (@$rapParam){
	# 投稿する文章を格納
	my $s;
	
	# パターンをランダムで選択
	# rand(整数) -> 0から指定した整数までの数をランダムで出力(小数)
	# int() -> 数値の整数部を取り出し(=切り捨て)
	my $kRand = int(rand(整数));
	
	# $kRand番目にあたる文字列を取得
	$s = $replyStatus[$kRand];
	
	# @ユーザ名 発言の形に
	$s = join('', "@",$str->{'user'}{'screen_name'}, " ", $s);
	
	# 配列に格納
	push @rapStatus, $s;
	push @rapIds, $str->{'id'};
}

# ログファイルを共用読み取りでオープン
open (my $fh, '+<', $rapFile)
or die "Can't open file : $!";

for(my $i=0; $i<@rapIds; $i++){ 
	while( my $line = <$fh> ){
		
		# ファイルの中にidがあるかチェック
		if($line =~ /$rapIds[$i]/){
			$rapFlags[$i] = 0;
			last;
		}
		else{
			$rapFlags[$i] = 1;
		}
	}
}


for(my $j=0; $j<@rapIds; $j++){

	# フラグが1=新しい場合のみ、発言を投稿、IDをログに書きこむ
	if($rapFlags[$j] == 1){
		$rapTweet->update($rapStatus[$j]);
		print $fh $rapIds[$k];
		print $fh "\n";
	}
}

# ファイルクローズ
close $fh;

######################

## フォロー返し ##

#followers(フォローされている)、friends(フォローしている)を取得
my $rapFollowers = $rapTweet->followers();
my $rapFriends = $rapTweet->friends();
my @followName;
my @friendsName;
my @protect;

foreach my $desc (@$rapFollowers){
	
	# ユーザ名とプロテクト(鍵つきアカウント)かどうかを配列にプッシュ
	my $follow = $desc->{'screen_name'};
	push @followName, $follow;
	my $bProt = $desc->{'protected'};
	push @protect, $bProt;
}
foreach my $desc (@$rapFriends){
	
	# フォロワーのユーザ名をプッシュ
	my $friend = $desc->{'screen_name'};
	push @friendsName, $friend;
}


my $mutchFlag = 0;
for (my $i = 0; $i < @followName; $i++) {
	for (my $j = 0; $j < @friendsName; $j++) {
		if($friendsName[$j] =~ /$followName[$i]/){
			
			# マッチした=既にフォローしているので、内側のループを抜ける
			$mutchFlag = 1;
			last;
		}
	}
	# flagを0にして、次へ
	if($mutchFlag == 1){
		$mutchFlag = 0;
	}
	else {
		# 鍵付きアカウントでない場合
		if($protect[$i] =~ /false/){
			
			# フォローに失敗するとエラーが吐かれるので、
			# それをキャッチ/プログラムを終了させないために、evalを使用
			eval{
				$rapTweet->create_friend($followName[$i])
			};
			if($@){
				# "$@"にエラー内容が格納される
				print $@, "\n
";
			}
			else {
				# エラーが出なかったので、新しいフォロワーにリプライ
				my $s;
				
				# @ユーザ名 発言 の形に
				$s = join('', "@", $followName[$i], " リプライ内容");
				
				#ツイート
				$rapTweet->update($s);
			}
		}
	}
}

exit;
__END__

以上です。
いろいろ削ったりしていますが、だいたいこんなかんじ。
ご質問ご意見お待ちしてます。

Net::Twitter::Liteでどんな値が取れるのかは、
Net-Twitter-Lite - search.cpan.org
こちらで確認ができます。
->{'user'}{'screen_name'}なんていうように、パラメータが入れ子になっていたりいなかったりするので、一番大きい枠を(たとえばmentions())取ったら、
my $tweet = Net::Twitter::Lite->new(%_CONSUMER_TOKENS);
my $param = $tweet->mentions();
print Dumper $param;
このようにダンプすれば、中の各パラメータが表示されるので、そこから当たりをつけるというのもあり。


以下ぼやき。
フォロー返しのしくみは、たぶんこのやり方でいいんだと思います。
最初は鍵つきさんのことをまったく考えてなくって、数人にリプライを送り続けるという失敗をかましました。申し訳ありません。
あとはリムーブされたらこちらもリムーブ、をやろうと思っているんですが、まあ、もうちょっと後でもいいかな。
フォロー>>>フォロワーくらいになったらやります。

相変わらずelse ifって書いちゃうくせが抜けません。
for文の書き方もas3、C、perlでちょっとずつ違ってこんがらがります。

あ、あと、perlではif($val == true)とかができないんですね。
undifinedは偽、それ以外が真。
なので、ここでも
if($protect[$i] =~ /false/){

このように取ってます。



拍手

PR
Comment
Name
Title
Mail
URL
Comment
Pass   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
  HOME   28  25  24  23  22  21  20  19  18  17  16 
最新コメント
[02/22 通りすがり]
[10/05 ar_tama]
[10/02 すぎゃーん]
[10/02 すぎゃーん]
最新トラックバック
プロフィール
twitter
follow me!
@ar_tama


ar_tama / Makoto Arata
東京のはしっこでプログラミング、ときどきコンピュータ音楽。
音大生。
にゃんこともちもちが好き。
詳細

contact:arata.makoto(at)gmail.com
(at)->@
バーコード
ブログ内検索
__
忍者ブログ [PR]