Created
October 13, 2012 03:39
-
-
Save kazy111/3883139 to your computer and use it in GitHub Desktop.
Twitter API 1.1てきとう対応
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//====================================================================== | |
//EasyBotter Ver2.05+ | |
//updated 2012/10/22 | |
//====================================================================== | |
class EasyBotter | |
{ | |
private $_screen_name; | |
private $_consumer_key; | |
private $_consumer_secret; | |
private $_access_token; | |
private $_access_token_secret; | |
private $_replyLoopLimit; | |
private $_footer; | |
private $_dataSeparator; | |
private $_tweetData; | |
private $_replyPatternData; | |
private $_repliedReplies; | |
private $_logDataFile; | |
private $_latestReply; | |
function __construct() | |
{ | |
$dir = getcwd(); | |
$path = $dir."/PEAR"; | |
set_include_path(get_include_path() . PATH_SEPARATOR . $path); | |
$inc_path = get_include_path(); | |
chdir(dirname(__FILE__)); | |
date_default_timezone_set("Asia/Tokyo"); | |
require_once("setting.php"); | |
$this->_screen_name = $screen_name; | |
$this->_consumer_key = $consumer_key; | |
$this->_consumer_secret = $consumer_secret; | |
$this->_access_token = $access_token; | |
$this->_access_token_secret = $access_token_secret; | |
$this->_replyLoopLimit = $replyLoopLimit; | |
$this->_footer = $footer; | |
$this->_dataSeparator = $dataSeparator; | |
$this->_repliedReplies = array(); | |
$this->_logDataFile = "log.dat"; | |
$this->_latestReply = file_get_contents($this->_logDataFile); | |
require_once 'HTTP/OAuth/Consumer.php'; | |
$this->consumer = new HTTP_OAuth_Consumer($this->_consumer_key, $this->_consumer_secret); | |
$http_request = new HTTP_Request2(); | |
$http_request->setConfig('ssl_verify_peer', false); | |
$consumer_request = new HTTP_OAuth_Consumer_Request; | |
$consumer_request->accept($http_request); | |
$this->consumer->accept($consumer_request); | |
$this->consumer->setToken($this->_access_token); | |
$this->consumer->setTokenSecret($this->_access_token_secret); | |
$this->printHeader(); | |
} | |
function __destruct(){ | |
$this->printFooter(); | |
} | |
//どこまでリプライしたかを覚えておく | |
function saveLog(){ | |
rsort($this->_repliedReplies); | |
return file_put_contents($this->_logDataFile,$this->_repliedReplies[0]); | |
} | |
//表示用HTML | |
function printHeader(){ | |
$header = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'; | |
$header .= '<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">'; | |
$header .= '<head>'; | |
$header .= '<meta http-equiv="content-language" content="ja" />'; | |
$header .= '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />'; | |
$header .= '<title>EasyBotter</title>'; | |
$header .= '</head>'; | |
$header .= '<body><pre>'; | |
print $header; | |
} | |
//表示用HTML | |
function printFooter(){ | |
echo "</body></html>"; | |
} | |
//ランダムにポスト | |
function postRandom($datafile = "data.txt"){ | |
$status = $this->makeTweet($datafile); | |
if(empty($status)){ | |
$message = "投稿するメッセージがないようです。<br />"; | |
echo $message; | |
return array("error"=> $message); | |
}else{ | |
//idなどの変換 | |
if(preg_match("@{.+?}@",$status) == 1){ | |
$status = $this->convertText($status); | |
} | |
$response = $this->setUpdate(array("status"=>$status)); | |
//print $status; | |
return $this->showResult($response); | |
} | |
} | |
//順番にポスト | |
function postRotation($datafile = "data.txt", $lastPhrase = FALSE){ | |
$status = $this->makeTweet($datafile,0); | |
if($status !== $lastPhrase){ | |
$this->rotateData($datafile); | |
if(empty($status)){ | |
$message = "投稿するメッセージがないようです。<br />"; | |
echo $message; | |
return array("error"=> $message); | |
}else{ | |
//idなどの変換 | |
if(preg_match("@{.+?}@",$status) == 1){ | |
$status = $this->convertText($status); | |
} | |
$response = $this->setUpdate(array("status"=>$status)); | |
return $this->showResult($response); | |
} | |
}else{ | |
$message = "終了する予定のフレーズ「".$lastPhrase."」が来たので終了します。<br />"; | |
echo $message; | |
return array("error"=> $message); | |
} | |
} | |
//リプライする | |
function reply($cron = 2, $replyFile = "data.txt", $replyPatternFile = "reply_pattern.php"){ | |
$replyLoopLimit = $this->_replyLoopLimit; | |
//リプライを取得 | |
$response = $this->getReplies(); | |
$response = $this->getRecentTweets($response, $cron * $replyLoopLimit * 3); | |
$replies = $this->getRecentTweets($response, $cron); | |
$replies = $this->selectTweets($replies); | |
$replies = $this->removeRepliedTweets($replies); | |
if(count($replies) != 0){ | |
//ループチェック | |
$replyUsers = array(); | |
foreach($response as $r){ | |
$replyUsers[] = (string)$r->user->screen_name; | |
} | |
$countReplyUsers = array_count_values($replyUsers); | |
$replies_ = array(); | |
foreach($replies as $r){ | |
$userName = (string)$r->user->screen_name; | |
if($countReplyUsers[$userName] < $replyLoopLimit){ | |
$replies_[] = $r; | |
} | |
} | |
//古い順にする | |
$replies = array_reverse($replies_); | |
if(count($replies) != 0){ | |
//リプライの文章をつくる | |
$replyTweets = $this->makeReplyTweets($replies, $replyFile, $replyPatternFile); | |
foreach($replyTweets as $re){ | |
$value = array("status"=>$re["status"],'in_reply_to_status_id'=>$re["in_reply_to_status_id"]); | |
$response = $this->setUpdate($value); | |
$result = $this->showResult($response); | |
$results[] = $result; | |
if($response->in_reply_to_status_id){ | |
$this->_repliedReplies[] = (string)$response->in_reply_to_status_id; | |
} | |
} | |
} | |
}else{ | |
$message = $cron."分以内に受け取った@はないようです。<br /><br />"; | |
echo $message; | |
$results[] = $message; | |
} | |
if(!empty($this->_repliedReplies)){ | |
$this->saveLog(); | |
} | |
return $results; | |
} | |
//タイムラインに反応する | |
function replyTimeline($cron = 2, $replyPatternFile = "reply_pattern.php"){ | |
//タイムラインを取得 | |
$timeline = $this->getFriendsTimeline(); | |
$timeline = $this->getRecentTweets($timeline, $cron); | |
$timeline = $this->selectTweets($timeline); | |
$timeline = $this->removeRepliedTweets($timeline); | |
$timeline = array_reverse($timeline); | |
if(count($timeline) != 0){ | |
//リプライを作る | |
$replyTweets = $this->makeReplyTimelineTweets($timeline, $replyPatternFile); | |
if(count($replyTweets) != 0){ | |
foreach($replyTweets as $re){ | |
$value = array("status"=>$re["status"],'in_reply_to_status_id'=>$re["in_reply_to_status_id"]); | |
$response = $this->setUpdate($value); | |
$result = $this->showResult($response); | |
$results[] = $result; | |
if($response->in_reply_to_status_id){ | |
$this->_repliedReplies[] = (string)$response->in_reply_to_status_id; | |
} } | |
}else{ | |
$message = $cron."分以内のタイムラインに反応する単語がないようです。<br /><br />"; | |
echo $message; | |
$results = $message; | |
} | |
} | |
if(!empty($this->_repliedReplies)){ | |
$this->saveLog(); | |
} | |
return $results; | |
} | |
//発言を作る | |
function makeTweet($file, $number = FALSE){ | |
if(empty($this->_tweetData[$file])){ | |
$this->_tweetData[$file] = $this->readDataFile($file); | |
} | |
//発言をランダムに一つ選ぶ | |
if($number === FALSE){ | |
$status = $this->_tweetData[$file][array_rand($this->_tweetData[$file])]; | |
}else{ | |
$status = $this->_tweetData[$file][$number]; | |
} | |
return $status; | |
} | |
//リプライを作る | |
function makeReplyTweets($replies, $replyFile, $replyPatternFile){ | |
if(empty($this->_replyPatternData[$replyPatternFile]) && !empty($replyPatternFile)){ | |
$this->_replyPatternData[$replyPatternFile] = $this->readPatternFile($replyPatternFile); | |
} | |
$replyTweets = array(); | |
foreach($replies as $reply){ | |
$status = ""; | |
//リプライパターンと照合 | |
if(!empty($this->_replyPatternData[$replyPatternFile])){ | |
foreach($this->_replyPatternData[$replyPatternFile] as $pattern => $res){ | |
if(preg_match("@".$pattern."@u",$reply->text, $matches) === 1){ | |
$status = $res[array_rand($res)]; | |
for($i=1;$i <count($matches);$i++){ | |
$p = "$".$i; | |
$status = str_replace($p,$matches[$i],$status); | |
} | |
break; | |
} | |
} | |
} | |
//パターンになかった場合はランダムに | |
if(empty($status) && !empty($replyFile)){ | |
$status = $this->makeTweet($replyFile); | |
} | |
if(empty($status) || $status == "[[END]]"){ | |
continue; | |
} | |
if(preg_match("@{.+?}@",$status) == 1){ | |
$status = $this->convertText($status, $reply); | |
} | |
$reply_name = (string)$reply->user->screen_name; | |
$in_reply_to_status_id = (string)$reply->id; | |
$re["status"] = "@".$reply_name." ".$status; | |
$re["in_reply_to_status_id"] = $in_reply_to_status_id; | |
$replyTweets[] = $re; | |
} | |
return $replyTweets; | |
} | |
//タイムラインへの反応を作る | |
function makeReplyTimelineTweets($timeline, $replyPatternFile){ | |
if(empty($this->_replyPatternData[$replyPatternFile])){ | |
$this->_replyPatternData[$replyPatternFile] = $this->readPatternFile($replyPatternFile); | |
} | |
$replyTweets = array(); | |
foreach($timeline as $tweet){ | |
$status = ""; | |
$re = array(); | |
$text = (string)$tweet->text; | |
//リプライパターンと照合 | |
foreach($this->_replyPatternData[$replyPatternFile] as $pattern => $res){ | |
if(preg_match("@".$pattern."@u",$text, $matches) === 1 && !preg_match("/\@/i",$text)){ | |
$status = $res[array_rand($res)]; | |
for($i=1;$i <count($matches);$i++){ | |
$p = "$".$i; | |
$status = str_replace($p,$matches[$i],$status); | |
} | |
break; | |
} | |
} | |
if(empty($status)){ | |
continue; | |
} | |
if(preg_match("@{.+?}@",$status) == 1){ | |
$status = $this->convertText($status, $tweet); | |
} | |
$reply_name = (string)$tweet->user->screen_name; | |
$in_reply_to_status_id = (string)$tweet->id; | |
$re["status"] = "@".$reply_name." ".$status; | |
$re["in_reply_to_status_id"] = $in_reply_to_status_id; | |
$replyTweets[] = $re; | |
} | |
return $replyTweets; | |
} | |
//ログの順番を並び替える | |
function rotateData($file){ | |
$tweetsData = file_get_contents($file); | |
$tweets = explode("\n", $tweetsData); | |
$tweets_ = array(); | |
for($i=0;$i<count($tweets) - 1;$i++){ | |
$tweets_[$i] = $tweets[$i+1]; | |
} | |
$tweets_[] = $tweets[0]; | |
$tweetsData_ = ""; | |
foreach($tweets_ as $t){ | |
$tweetsData_ .= $t."\n"; | |
} | |
$tweetsData_ = trim($tweetsData_); | |
$fp = fopen($file, 'w'); | |
fputs($fp, $tweetsData_); | |
fclose($fp); | |
} | |
//タイムラインの最近20件の呟きからランダムに一つを取得 | |
function getRandomTweet(){ | |
$response = $this->getFriendsTimeline(); | |
for($i=0;$i<99;$i++){ | |
$randomTweet = $response->status[rand(0,count($response->status))]; | |
if($randomTweet->user->screen_name != $this->_screen_name){ | |
return $response->status[rand(0,count($response->status))]; | |
} | |
} | |
return false; | |
} | |
//つぶやきの中から$minute分以内のものと、最後にリプライしたもの以降のものだけを返す | |
function getRecentTweets($response,$minute){ | |
$tweets = array(); | |
$now = strtotime("now"); | |
$limittime = $now - $minute * 70; //取りこぼしを防ぐために10秒多めにカウントしてる | |
foreach($response as $tweet){ | |
//var_dump($tweet); | |
$time = strtotime($tweet->created_at); | |
// echo $time." = ".$limittime."<Br />"; | |
$tweet_id = (string)$tweet->id; | |
if($limittime <= $time && $this->_latestReply < $tweet_id && !$tweet->retweeted){ | |
$tweets[] = $tweet; | |
}else{ | |
break; | |
} | |
} | |
return $tweets; | |
} | |
//必要なつぶやきのみに絞る | |
function selectTweets($response){ | |
$replies = array(); | |
foreach($response as $reply){ | |
//自分自身のつぶやきを除外する | |
$replyName = (string)$reply->user->screen_name; | |
if($this->_screen_name == $replyName){ | |
continue; | |
} | |
//RT, QTを除外する | |
$text = (string)$reply->text; | |
if(strpos($text,"RT") != FALSE || strpos($text,"QT") != FALSE){ | |
continue; | |
} | |
$replies[] = $reply; | |
} | |
return $replies; | |
} | |
//リプライ一覧から自分が既に返事したものを除く | |
function removeRepliedTweets($response){ | |
$replies = array(); | |
foreach($response as $reply){ | |
$id = (string)$reply->id; | |
if(in_array($id, $this->_repliedReplies) === FALSE){ | |
$replies[] = $reply; | |
} | |
} | |
return $replies; | |
} | |
//自動フォロー返し | |
function autoFollow(){ | |
$response = $this->getFollowers(); | |
$followList = array(); | |
foreach($response as $user){ | |
$follow = (boolean)$user->following; | |
if($follow != True){ | |
$followList[] = (string)$user->screen_name; | |
} | |
} | |
foreach($followList as $screen_name){ | |
$response = $this->followUser($screen_name); | |
} | |
} | |
//つぶやきデータを読み込む | |
function readDataFile($file){ | |
if(preg_match("@\.php$@", $file) == 1){ | |
require_once($file); | |
return $data; | |
}else{ | |
$tweets = file_get_contents($file); | |
$tweets = trim($tweets); | |
$tweets = preg_replace("@".$this->_dataSeparator."+@",$this->_dataSeparator,$tweets); | |
$data = explode($this->_dataSeparator, $tweets); | |
return $data; | |
} | |
} | |
//リプライパターンデータを読み込む | |
function readPatternFile($file){ | |
$data = array(); | |
require_once($file); | |
if(count($data) != 0){ | |
return $data; | |
}else{ | |
return $reply_pattern; | |
} | |
} | |
//文章を変換する | |
function convertText($text, $reply = FALSE){ | |
$text = str_replace("{year}",date("Y"),$text); | |
$text = str_replace("{month}",date("n"),$text); | |
$text = str_replace("{day}",date("j"),$text); | |
$text = str_replace("{hour}",date("G"),$text); | |
$text = str_replace("{minute}",date("i"),$text); | |
$text = str_replace("{second}",date("s"),$text); | |
//ランダムな一人のfollowingデータを取る | |
if(strpos($text, "{following_id}") !== FALSE){ | |
$response = $this->getFriends(); | |
$id = $response[rand(0,count($response->user)-1)]->screen_name; | |
$text = str_replace("{following_id}",$id,$text); | |
} | |
if(strpos($text, "{following_name}") !== FALSE){ | |
$response = $this->getFriends(); | |
$name = $response[rand(0,count($response->user)-1)]->name; | |
$text = str_replace("{following_name}",$name,$text); | |
} | |
//ランダムな一人のfollowerデータを取る | |
if(strpos($text,"{follower_id}") !== FALSE){ | |
$response = $this->getFollowers(); | |
$id = $response[rand(0,count($response->user)-1)]->screen_name; | |
$text = str_replace("{follower_id}",$id,$text); | |
} | |
if(strpos($text, "{follower_name}") !== FALSE){ | |
$response = $this->getFollowers(); | |
$name = $response[rand(0,count($response->user)-1)]->name; | |
$text = str_replace("{follower_name}",$name,$text); | |
} | |
//タイムラインからランダムに最近発言した人のデータを取る | |
if(strpos($text,"{timeline_id}") !== FALSE){ | |
$randomTweet = $this->getRandomTweet(); | |
$text = str_replace("{timeline_id}", $randomTweet->user->name,$text); | |
} | |
if(strpos($text, "{timeline_name}") !== FALSE){ | |
$randomTweet = $this->getRandomTweet(); | |
$text = str_replace("{timeline_name}",$randomTweet->user->screen_name,$text); | |
} | |
//使うファイルによって違うやつ | |
//リプライの場合は相手のid、そうでなければfollowしているidからランダム | |
if(strpos($text,"{id}") !== FALSE){ | |
if(!empty($reply)){ | |
$text = str_replace("{id}",$reply->user->screen_name,$text); | |
}else{ | |
$randomTweet = $this->getRandomTweet(); | |
$text = str_replace("{id}",$randomTweet->user->screen_name,$text); | |
} | |
} | |
if(strpos($text,"{name}") !== FALSE){ | |
if(!empty($reply)){ | |
$text = str_replace("{name}",$reply->user->name,$text); | |
}else{ | |
$randomTweet = $this->getRandomTweet(); | |
$text = str_replace("{name}",$randomTweet->user->name,$text); | |
} | |
} | |
if(strpos($text,"{tweet}") !== FALSE && !empty($reply)){ | |
$tweet = preg_replace("@\.?\@[a-zA-Z0-9-_]+\s@u","",$reply->status); | |
$text = str_replace("{tweet}",$tweet,$text); | |
} | |
//フッターを追加 | |
$text .= $this->_footer; | |
return $text; | |
} | |
//結果を表示する | |
function showResult($response){ | |
if(!$response->error){ | |
$message = "Twitterへの投稿に成功しました。<br />"; | |
$message .= "@<a href='http://twitter.com/".$response->user->screen_name."' target='_blank'>".$response->user->screen_name."</a>"; | |
$message .= "に投稿したメッセージ:".$response->text; | |
$message .= " <a href='http://twitter.com/".$response->user->screen_name."/status/".$response->id."' target='_blank'>http://twitter.com/".$response->user->screen_name."/status/".$response->id."</a><br /><br />"; | |
echo $message; | |
//var_dump($response); | |
return array("result"=> $message); | |
}else{ | |
$message = "Twitterへの投稿に失敗しました。<br />"; | |
$message .= "ユーザー名:@<a href='http://twitter.com/".$this->_screen_name."' target='_blank'>".$this->_screen_name."</a><br /><br />"; | |
echo $message; | |
var_dump($response); | |
return array("error" => $message); | |
} | |
} | |
//基本的なAPIを叩く | |
function _setData($url, $value = array()){ | |
$response = $this->consumer->sendRequest($url, $value, "POST"); | |
$response = $this->json_decode($response->getBody()); | |
return $response; | |
} | |
function _getData($url){ | |
$response = $this->consumer->sendRequest($url, array(), "GET"); | |
$response = $this->json_decode($response->getBody()); | |
return $response; | |
} | |
function setUpdate($value){ | |
$url = "https://api.twitter.com/1.1/statuses/update.json"; | |
return $this->_setData($url, $value); | |
} | |
function getFriendsTimeline(){ | |
$url = "https://api.twitter.com/1.1/statuses/home_timeline.json"; | |
return $this->_getData($url); | |
} | |
function getReplies($page = false) | |
{ | |
$url = "https://api.twitter.com/1.1/statuses/mentions_timeline.json"; | |
if ($page) { | |
$url .= '?page=' . intval($page); | |
} | |
return $this->_getData($url); | |
} | |
function getFriends($id = null) | |
{ | |
static $cache = NULL; | |
if ($cache === NULL) { | |
$url = "https://api.twitter.com/1.1/friends/ids.json"; | |
$res = $this->_getData($url); | |
$url = "https://api.twitter.com/1.1/users/lookup.json"; | |
$data = array(); | |
$data['user_id'] = implode(',', $res->ids); | |
$cache = $this->_setData($url, $data); | |
} | |
return $cache; | |
} | |
function getFollowers() | |
{ | |
static $cache = NULL; | |
if ($cache === NULL) { | |
$url = "https://api.twitter.com/1.1/followers/ids.json"; | |
$res = $this->_getData($url); | |
$url = "https://api.twitter.com/1.1/users/lookup.json"; | |
$data = array(); | |
$data['user_id'] = implode(',', $res->ids); | |
$cache = $this->_setData($url, $data); | |
} | |
return $cache; | |
} | |
function followUser($screen_name) | |
{ | |
$url = "https://api.twitter.com/1.1/friendships/create.json"; | |
$data = array(); | |
$data['user_id'] = $screen_name; | |
return $this->_setData($url, $data); | |
} | |
function json_decode($json) { | |
if (function_exists('json_decode')) { | |
return json_decode($json); | |
} | |
else { | |
// Anonymous, 03-Nov-2010, http://www.php.net/manual/en/function.json-decode.php#100740 | |
$comment = false; | |
$out = '$x='; | |
for ($i=0; $i<strlen($json); $i++) { | |
if (!$comment) { | |
if (($json[$i] == '{') || ($json[$i] == '[')) $out .= ' array('; | |
elseif (($json[$i] == '}') || ($json[$i] == ']')) $out .= ')'; | |
elseif ($json[$i] == ':') $out .= '=>'; | |
else $out .= $json[$i]; | |
} | |
else $out .= $json[$i] == '$' ? '\$' : $json[$i]; | |
if ($json[$i] == '"' && $json[($i-1)]!="\\") $comment = !$comment; | |
} | |
eval($out. ';'); | |
return $x; | |
} | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment