Google App Scriptでtwitterの天気予報botを作る

先日heroku+pythontwitterの天気予報botを作成したのだが(こちらを参照)、herokuはクレジットカードを登録しないと月550時間しか起動できないのを完全にうっかりしていたのでプラットフォームを変更する必要が生じた。よくよく考えたら一日一回のcron jobくらいならGoogle App Script(GAS)で十分なのではないかという結論に至ったため、今回は既存の問題点を改善しつつGASでやり直してみることとする。完成したコードは末尾にまとめて載せてあるので良ければどうぞ。なお、作成したbotは、

  1. 毎朝6:04にウェザーニュースからgmailに天気予報メールが届くので、その本文を取得してツイートする文字列を生成、ツイートする
  2. 1の内容に応じてbotのアイコンを変更する

という動作を毎朝6:30に行うものである。

実装手順

GASの下準備

Google App Scriptの導入に関しては以下のページが参考になる。web上のコンソールにコードを打ち込むだけであり、開発環境に依存せずややこしいデプロイなども必要ないためかなりお手軽である。何よりクレジットカードの登録が必要ないため学生に優しい。

https://kijtra.com/article/cron-by-google-apps-script/

また、今回はGASでtwitterを用いるため以下のページのStep1, 2, 4を完了させておく。なお、ここでのproject keyは廃止されたので代わりにscript IDを用いることになったが作業としては特に変わらない。

https://kijtra.com/article/twitter-api-for-google-apps-script-without-oauthconfig/

天気予報の取得

openweathermapの精度があまりにアレなので(やたら雨を降らせたがる上に気温が異様に低い)3時間予報は潔く諦め日本のサービスを利用することにした。私はウェザーニュースの朝刊メールサービスを購読しているため、「【京都版】ウェザーニュース朝刊」という題名で毎朝6時過ぎに以下のようなメールがgmailに届く。

今日の京都は、

11/26(日) 晴れのち曇り

最高気温 16℃
(前日比 +3℃)

今日は日差しが届いても段々と雲が優勢に。ニワカ雨の可能性があるため、折りたたみ傘がお守りです。昼間は寒さ控えめでも朝晩は冷えるため、湯冷めにご注意を。

このメールの内容をGASで取得し、ツイート内容を生成する。実際にすることといえば、こちらを参考に

var strTerms = '("ウェザーニュース朝刊")';
var myThread = GmailApp.search(strTerms, 0, 1);
var myMessage = GmailApp.getMessagesForThreads(myThread);
var content = myMessage[0][0].getPlainBody();
var arrayOfStrings = content.split(/\r?\n/g);
var tweet = arrayOfStrings[2] + "\n" + arrayOfStrings[4] + arrayOfStrings[5] + "\n" + arrayOfStrings[7];

GmailApp.searchgmailを検索し(2番目の引数には最初のスレッドのインデックスを、3番目の引数には返すべきスレッド数の最大値を指定する)、改行によって文字列を分割、再度結合させてツイートを作成している。

ツイートする

postする関数の引数処理を少し変えたくらいでほぼこちらをコピペした。なお、初回にtwitterのアプリ認証が求められるため、作業を行うブラウザのtwitterbotのアカウントでログインしておくとスムーズである。

Twitterのアイコンを天気に応じて変更する

web上の画像へのリンクから画像を取得、アイコンを変更している。

function changeIcon(url) {
    var service = getService();
    var getImage = UrlFetchApp.fetch(url);
    var image = getImage.getBlob();
    var resp_64 = Utilities.base64Encode(image.getBytes());//TwitterAPI送信用にbase64にエンコード
    if (service.hasAccess()) {
        var url = 'https://api.twitter.com/1.1/account/update_profile_image.json';
        var payload = {
            image: resp_64
        };
        var response = service.fetch(url, {
            method: 'post',
            payload: payload
        });
        var result = JSON.parse(response.getContentText());
        Logger.log(JSON.stringify(result, null, 2));
    } else {
        var authorizationUrl = service.authorize();
        Logger.log('Open the following URL and re-run the script: %s',
                authorizationUrl);
    }
} 

ついでに降雨をラインにも通知する

前回同様、雨や雪が降りそうな時にLine Notifyに通知が来るようにする。コードはほぼ以下のコピペ。

https://qiita.com/tadaken3/items/5f916a12587e42ece814

決まった時間に実行する

GASでは、毎日の定時処理が「6時〜7時」というかなりアバウトな時間帯の間でしか指定できない。これは以下のようにトリガー自体を定時処理させるという巧妙な方法により回避できる。

https://qiita.com/sumi-engraphia/items/465dd027e17f44da4d6a

最終的なコード

以下に完成したコードを載せておく。ちなみに今回作成したbot@kyoto__weatherである。

gistae417abb6caa8ecf45454fb338ad7224?ts=4