2018.4.28
キモヲタだけど、女子高生と会話したい!#15【JKとDMしたい】
プログラム連載記事は基本的に誰も見てないとは思うのですが、まぁそのうち役立つことがあるでしょうということで、目立つように今回は如何わしいタイトルをつけてみたわけです(笑)
とりあえずスマホ側からJSONを受け取ることまではできてるっぽいので、今回はそれをtwitterに送信してDMを送る工程ですね。まずは一方通行の愛を伝えるストーカーになりましょう!
まず必要なのは、各種トークンを用いた接続ですね。まぁこれは昔使ったライブラリを流用すればよさげでしょう。
OAuth認証に関しては
ここ、DM送信に関しては
こことか参考にすればできるかな多分。
その前に、今回はBotと違い、独自のアカウントを用いた実装なので自分でアクセストークンを取得しなくてはなりません。
ここに関しては結構難航したんですが、
このサイトが分かりやすくて良かったです。
というか
ライブラリ使うと結局バグって処理が止まるんで生で書いた方がいいです。
API利用時はライブラリ使ったほうがラクなのかなあとは思ってるのですが、なんかトークン取得がうまく行かないものでね・・・・・・。
むしろこれをライブラリ化してほしさはありますね。まぁとりあえずトークンは取得できたっぽいですね。
仕様をどうしようか悩みましたが、出先で新しくアカウント作ってそれを使って通信する、みたいなことはする必要なさそうなので、ハードコーディングでトークンを保持してても良さそうですね。別にSQLiteとか使ってもいいんですけどね。
とはいえ、twitterのAPI制限やリミットはLINEと違ってかなり不可避な感じがするので、そのへんを回避するためのフロー、および認識するためのフローは欲しいなあとは思ってるんですけどね。
一応、調べたらDMは1日1000件までで、DMに関するAPIは15分あたり300件が発行限度というのは調べましたが、この基準をクリアしてても
凍結されない保証はないと思われるんですよね。
ただまあ、そうなったらそうなったでいくらでも対策は立てられますし今のとこはあまり考えないようにします。
具体的には、DMとリプの併用という手段や、アカウントの使い分けなどが考えられますね。まぁそのへんは追々。でもそのうち必要になることもあるんだろうなあ・・・・・・。
とりあえず実装しました。
コードとしては以下のような感じになってます。
// ライブラリ読み込み
require './TwistOAuth/src/TwistOAuth.php';
require './TwistOAuth/src/TwistException.php';
class EroorLog{
public function __construct($str){
error_log(var_export($arr, true));
}
}
class result{
private $bool;
private $str;
private $key;
public function __construct(bool $bool, string $str, string $key=null) {
$this->bool=$bool;
$this->str=$str;
$this->key=$key;
}
public function result():Array{
return [
"flag"=>$this->bool,
"result"=>($this->bool!=false)?$this->str:"",
"key"=>$this->key
];
}
}
class main{
private $str;
private $password;
public function __construct(string $str, string $password) {
$this->str=$str;
$this->password=$password;
}
public function send(){
//パスワードは正しい。
try {
// クレデンシャル生成
$to = new TwistOAuth(CK, CS, USER_AT, USER_ASE);
// ツイート
$status = $to->post('direct_messages/new', [
"text" => $this->str,
"user_id"=> RINNA_USER_ID
]);
$message_id=$status->id;
$count=0;
loop_point:
time_nanosleep(0, 700000000);//0.7秒遅延する
$response = $to->get('direct_messages', [
"since_id" => $message_id
]);
if(++$count<3 && empty($response)){
goto loop_point;
}
if(empty($response)){
//再取得してもりんなは応答していない
return false;
}
$str="";
foreach((array)$response as $r){
if($r->sender->id!=RINNA_USER_ID){
//りんなじゃないユーザーなので消えてもらう
continue;
}
$str.=$r->text;//受け取ったテキストを追記
}
} catch (TwistException $e) {
// エラーを表示
echo "[{$e->getCode()}] {$e->getMessage()}";
new EroorLog($e->getMessage());
die();
}
return $str;
}
public function exe(){
//パスワードチェック
if($this->password!=PASSWORD){
new EroorLog("パスワード相違");
return false;
}
return $this->send();
}
}
$inp = json_decode(file_get_contents('php://input')); //$input now contains the jsonobj
$result=(new main($inp->string,$inp->password))->exe();
//[bool メッセージ取得成功可否、具体的に受け取ったメッセージ]をjsonで送信
$json=json_encode((new result($result!=false, $result))->result());
ob_start();
var_dump($json);
$ob =ob_get_contents();
ob_end_clean();
$fp = fopen("./dump.txt", "w+" );
fputs($fp, $ob);
fclose( $fp );
echo $json;
別ファイルでちょいちょい定数を定義すると使えるようになります。設計とか特にしてないので構造はめちゃくちゃテキトーで、無理矢理1つのファイルにまとめた感じになってます(笑)
まぁやってることとしては、りんなちゃんにメッセージぶん投げて、その直後のメッセージをつなげて返してるだけ、って感じです。
とりあえずテストはこんな感じ。途中までは手打ちでコード送ってましたが、最後の方はマイク使ってエミュレーターに話しかけ、twitterに送信しりんなちゃんの応答を受け取るところまでできてます。
まぁこんな感じにね。
ということで次回は音声合成ですね。これができればとりあえず機能としては完成です。