/** * docomoの対話APIを叩いてレスポンスを貰ってくる * * @param string $apikey docomoAPIキー * @param string $context 会話のコンテキストID(API仕様参照) * @param string $mode 会話のモード(API仕様参照 * @param string $nickname 会話している人間側の名前 * @param string $text 人間側の入力テキスト * @return stdClass レスポンスのJSONをデコードしたオブジェクト * @throws \Exception サーバとの通信に失敗した場合 */ private function getData($apikey, $context, $mode, $nickname, $text) { $userData = ['utt' => (string) $text, 'context' => (string) $context, 'nickname' => (string) $nickname, 'mode' => (string) $mode]; $url = sprintf('https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=%s', rawurlencode($apikey)); Log::info("docomo対話APIを呼び出します"); Log::info("URL: " . $url); Log::info("パラメータ:"); Log::info($userData); $curl = new Curl(); $curl->setHeader('Content-Type', 'application/json; charset=UTF-8'); $ret = $curl->post($url, json_encode($userData)); if ($curl->error) { Log::error(sprintf("docomo対話APIの呼び出しに失敗しました: %d: %s", $curl->error_code, $curl->error_message)); throw new \Exception('docomo dialogue error: ' . $curl->error_code . ': ' . $curl->error_message); } Log::info("docomoからのデータ:"); Log::info($ret); if (is_object($ret) && isset($ret->utt)) { if ($ret->utt == '') { Log::warning(" docomo 指示文章が空です"); } else { Log::success(" docomo 指示文章: " . $ret->utt); } return $ret; } Log::error("docomoから受け取ったデータが期待した形式ではありません:"); Log::error($ret); throw new \Exception('Received an unexpected data from docomo server'); }
/** * 現在の天気の情報を問い合わせる * * @return \bot\weather\yahoocom\Response * @throws \Exception 問い合わせに失敗した場合 */ public function query() { $queryUri = self::buildQueryUrl(['q' => $this->buildYql($this->city), 'format' => 'json', 'env' => 'store://datatables.org/alltableswithkeys']); Log::info(__METHOD__ . ': Query URL: ' . $queryUri); $curl = new Curl(); $curl->get($queryUri); if ($curl->error) { $msg = 'YQL Query Error: ' . $curl->error_code . ': ' . $curl->error_message; Log::error(__METHOD__ . ': ' . $msg); Log::error($curl->raw_response); throw new \Exception($msg); } return new Response($curl->raw_response); }
/** * ツイートを投稿する関数 * * @param object $connection 投稿に使用する TwitterOAuth のインスタンス * @param array $param Twitter に送信するパラメータ * @param int $retryLimit 最大再試行回数 * @return bool 投稿に成功すれば true、失敗すれば false */ public static function postTweet(TwitterOAuth $connection, array $param, $retryLimit = 3) { Log::info("Twitter に tweet を POST します:"); Log::info($param); for ($retry = 0; $retry < $retryLimit; ++$retry) { if ($retry > 0) { sleep(1); } $result = $connection->post('statuses/update', $param); if (is_object($result) && isset($result->id_str) && isset($result->text)) { Log::success("Tweet を投稿しました"); Log::success(['id' => $result->id_str, 'text' => $result->text]); return true; } Log::warning("Tweet の投稿に失敗しました"); } Log::error("Tweet を投稿できませんでした"); Log::error($param); return false; }
use chomado\bot\format\WeatherFormatter; use chomado\bot\weather\yahoocom\Client as WeatherClient; // bootstrap require_once __DIR__ . '/vendor/autoload.php'; Log::setErrorHandler(); // ファイルの行をランダムに抽出 $randomComments = new RandomSentenceList(__DIR__ . '/tweet_content_data_list/list.txt'); Log::trace("list.txtは" . count($randomComments) . "行です"); $timeZoneJst = new DateTimeZone('Asia/Tokyo'); $now = new MyDateTime('now', $timeZoneJst); // 天気情報 $weather = (new WeatherClient('tokyo'))->query(); $formattedWeather = WeatherFormatter::formatForWeatherTweet($weather, '東京', $timeZoneJst); // 呟く文成形 // ============================================================================ // (*゚▽゚* っ)З ちょまぎょ! // // 現在時刻は17:55です。 // 東京の17:30現在の天気は、にわか雨(7.2℃)です。 // 明日はところにより曇り(昼)で、最高気温12.8℃、最低気温3.3℃です。 // ============================================================================ $message = sprintf("%s\n\n%s\n%s", $randomComments->get(), '現在時刻は' . $now->format('H:i') . 'です。', $formattedWeather); // Twitterに接続 $config = Config::getInstance(); $connection = new TwitterOAuth($config->getTwitterConsumerKey(), $config->getTwitterConsumerSecret(), $config->getTwitterAccessToken(), $config->getTwitterAccessTokenSecret()); $param = ['status' => $message]; Log::info("Twitter に tweet を POST します:"); Log::info($param); // 投稿 $ret = TwitterUtil::postTweet($connection, $param); exit($ret ? 0 : 1);
exit(0); } Log::success("Twitter からメンション一覧を取得しました。新着は " . count($res) . " 件です。"); // 最終投稿IDを書き込む file_put_contents(__DIR__ . '/runtime/last_id.txt', $res[0]->id_str); Log::trace("最終投稿IDを保存しました: " . $res[0]->id_str); $success_count = 0; $failure_count = 0; $chat_context_manager = new ChatContextManager(); foreach ($res as $re) { $param = []; Log::info("届いたメッセージ:"); Log::info(sprintf(" [@%s] %s - %s\n", $re->user->screen_name, $re->user->name, $re->text)); // もし自分自身宛てだったら無視する.(無限ループになっちゃうから) if (strtolower($re->user->screen_name) === strtolower($config->getTwitterScreenName())) { Log::info("投稿ユーザが自分なので無視します"); continue; } // リプライ本文から余計なものを取り除く. // 例: "@chomado_bot こんにちは" → "こんにちは" $text = trim(preg_replace('/@[a-z0-9_]+/i', '', $re->text)); // もし数字だけだったら素数判定処理をする if (filter_var($text, FILTER_VALIDATE_INT)) { $num = intval($text); $message = sprintf('%d の次の素数は %s です。', $num, '[そのうち実装するよ!]'); } else { // botに来たリプライに数字以外のものが含まれていたら // 通常の雑談対話リプライをする $chat = new Chat($config->getDocomoDialogueApiKey(), $chat_context_manager->getContextId($re->user->screen_name), $chat_context_manager->getMode($re->user->screen_name), $re->user->name, $text); $message = sprintf('%s %s%s', $chat->ResText(), $randomFaces->get(), PHP_EOL); }