75回生 sashiming
はじめまして、75回生のsashimingです。今回初めて部誌の執筆をします、よろしくお願いします。
今回の部誌では、 Google Apps Script (通称GAS、以下「GAS」と表記)でTwitterのbotを作ることについて書いていきます。
C/C++やJavaなど、他のプログラミング言語で条件分岐、ループ、配列などの基本的なことを知っていることを前提に進めていきます。JavaScriptの基本を知っておくとなおよいです。
今回の部誌で作るbotは以下のようなものです。
図2.1: bot作成例
このようなbotの動作、特にツイートを実行する部分の動作はどのような仕組みになっているのでしょうか。
Twitterには、Twitter APIという仕組みがあり、プログラムからTwitterのサービスを呼び出す事ができます。言うなれば、プログラムとTwitterサービスを繋ぐ存在です。例えば、「『〇〇』という内容をツイートして」というリクエストをプログラムからTwitter APIを通してTwitterのサービスへ送ることで、実際にツイートが実行されます。図に表すと、次のようになります。
図2.2: Twitter botの仕組み
ここで、タイトルにもある「Google Apps Script(GAS)」はどこで使われているのかというと、プログラムの部分で使われています。次の項では、GASとはどういったものなのかを紹介します。
クラウド上でスクリプトを実行することでGoogleのサービスを操作できる、Google公式のサービスです。
GASを使うことでGmailやGoogleドライブなど、様々なサービスを操作することができます。
一般的に、プログラミングでは最初に開発環境を整える必要がありますが、GASの開発環境はGoogle側で用意してくれています。必要なものはPC、ネット環境、Googleアカウントのみです。これらさえあれば、誰でもすぐにGASのプログラミングを始められます。
普通、常に動作しているようなbot等を作る際は常時起動しているPCまたはサーバーを用意する必要がありますが、GASのスクリプトはGoogle側のサーバーで実行してくれます。つまり、自分でサーバー等を準備する必要がありません。
また、GASにはトリガー機能があり、トリガーを設定することで定期的にスクリプトを実行することができます。そのため、スクリプトエディタを起動していなくても自動的にスクリプトを動かすことができます。これは定期実行系のbotを作る際には重宝する機能です。
GASを学ぶメリットとして、JavaScriptが同時に学べることが挙げられます。
GASで書くスクリプトの言語はJavaScriptがベースとなっているので、JavaScriptで使える機能は基本的にGASでも使えます。そのため、GASを学ぶと同時にJavaScriptも学ぶことができます。逆に、JavaScriptを触ったことがあるならJavaScriptを書く感覚でGASを操れます。
GASには、HTTPリクエストを送ってWebページの情報を取得するUrlFetchApp.fetch()
メソッドや、JSON形式のデータを取得できるJSON.parse()
メソッド(こちらはJavaScriptに用意されているメソッドです)などが用意されているので、APIを叩く処理が実装できます。これらのメソッドのおかげでGASでbotが作れるというわけです。
よくある処理だが実装がめんどくさい、といった機能の実装を自力でやるとなるとかなり大変です。そこで、先人の残した知恵を借りてしまいましょう。
GASには、作成した関数を他のプロジェクトからでも使うことの出来る「ライブラリ機能」があります。ライブラリをインポートすれば、普通ならば数十行の実装だって、たった一文で書けてしまいます。
逆に、自分で関数を書いて、ライブラリとして世に送り出すことも出来ます。自分の書いたコードで他人に貢献できるってステキじゃないですか?
うだうだとGASの紹介をしているのも退屈なので、実際にGASを使ってみましょう。ここからはGoogleアカウントを既に取得しているものとして進めていきます。
Googleにログインしている状態で、https://drive.google.com/からGoogleドライブを開きましょう。
次に、画面上の何もないところを右クリックして、「Google スプレッドシート」をクリックしましょう。Googleスプレッドシートが開かれるはずです。
図2.3: スプレッドシート起動
上部メニューから「ツール」→「スクリプト エディタ」をクリックしましょう。次図のような画面になるはずです。
図2.4: スクリプトエディタ起動
このエディタにスクリプトを書く形になります。それでは、実際にコードを書いてみましょう。
GAS(JavaScript)は仕様がかなり複雑な言語です。簡単なプログラムを作る場合には問題はないのですが、JavaScriptの仕様をフルに利用した高度なコード*1を書く場合は十分に注意して実装する必要があります。
ここでは、複雑な仕様に触れない初歩の部分を載せています。僕は、JavaScriptの細かな仕様は実際にbotを作る実践段階で学んでいけばよいと思っています。
[*1] 激うまギャグ
最初は皆さんおなじみHello, Worldから。次のソースコードを書きましょう。
function myFunction(){ Logger.log("Hello, World"); }
コードを書いたら、Ctrl+Sで適当な名前をつけて保存しましょう。保存ができたら、上部メニューの右向き三角形のマークのボタンを押してスクリプトを実行してください。
画面上部のメッセージ「関数myFunctionを実行中...」の表示が消えたら、上部メニューから「表示」→「ログ」をクリックしましょう。Hello, World
が表示されるはずです。これでGASの世界に挨拶することができました。
図2.5: Hello, World実行
GASでも他言語と同じように変数が使えます。変数を宣言する方法は以下の通りです。
var a; // "a"という名前の変数を宣言 var b = 334; // "b"という名前の変数を宣言し、初期値を334にする var c = "Nada Junior and Senior High School"; // 動的型付けなので、いろいろな型のものを入れられます
変数を使ったプログラムを見てみましょう。
function myFunction() { var a; a = "SAIL AWAY"; var b = 73; Logger.log(a); Logger.log(b); b = "Nada School Festival"; Logger.log(b); }
先ほどと同じようにして実行すると、以下のようになります。ログに73ではなく73.0と表示されるのは仕様です。
図2.6: variable.gs実行結果
var a;
で変数a
を宣言し、a = "SAIL AWAY";
で変数a
に文字列"SAIL AWAY"
を代入しています。また、var b = 73;
で宣言と代入を同時におこなっています。
8行目 b = "Nada School Festival";
のように、同じ変数に再び数値や文字列を代入することもできます。
GAS・JavaScriptでの基本演算はC/C++やJavaと同じです。
表2.2: 演算子一覧
演算子 | 説明 |
---|---|
+ | 加算 |
- | 減算 |
* | 乗算 |
/ | 除算(整数切り捨てにはならず、実数値になります) |
% | 剰余 |
以上の演算子のほか、++
でのインクリメントや、--
でのデクリメント、+=
や-=
も使えます。
以下の表のような比較演算子を使うことで2つの変数の値を比較することができます。基本的には他言語と同じですが、GAS・JavaScript特有の比較演算子があります。
表2.2: 比較演算子一覧
比較演算子 | 説明 |
---|---|
> | 左の値が右の値より大きい |
< | 右の値が左の値より大きい |
>= | 左の値が右の値より大きい、もしくは等しい |
<= | 右の値が左の値より大きい、もしくは等しい |
== | 左の値と右の値が等しい |
!= | 左の値と右の値が異なる |
=== | 左の値と右の値の型や内容、すべてが同一である(== より厳しい比較) |
!== | 左の値と右の値の型や内容が同一ではない |
注意点として、GAS・JavaScriptでは==
と===
で違いがあります。例えば
123 == "123"
はtrue
ですが、123 === "123"
はfalse
です。これらのことを確かめるにはLogger.log(123 == "123");
などとするとするとよいです。
条件分岐をおこなうif文の構文は、C/C++やJavaと同じです。
if(条件式1) { // 条件式1がtrueならこの部分を実行 } else if(条件式2) { // 条件式1がfalseで、条件式2がtrueのときにこの部分を実行 } else { // 条件式1, 2ともにfalseのときにこの部分を実行 }
以下は、if文を使ったコードの例です。
function myFunction() { var a = 1333; if(a == 1333) { Logger.log("a is 1333"); } else { Logger.log("a is not 1333"); } if(a > 1024) { Logger.log("a is greater than 1024"); } if(a < 1024) { Logger.log("a is less than 1024"); } }
実行すると、以下の通りになります。
a is 1333
a is greater than 1024
a == 1333
はtrue
なので、4行目が実行され、6行目は実行されません。また、a > 1024
はtrue
なので9行目が実行されますが、a < 1024
はfalse
なので12行目は実行されません。
ここで、2行目のa = 1333
をa = 753
に変えてみます。すると、実行結果は以下の通りになります。
a is not 1333
a is less than 1024
a == 1333
はfalse
なので、4行目が実行されず、6行目が実行されます。a > 1024
はfalse
なので9行目は実行されませんが、a < 1024
はtrue
なので12行目は実行されます。
for文は、繰り返し回数が決まっているときに使う構文です。
for(初期値; 条件式; 増減式) { // 増減式の最後にはセミコロンはつけません // 繰り返す処理 // 条件式がtrueである限りこの部分は実行されます // 処理が終わるごとに増減式を実行します }
以下は、for文を使ったコードの例です。
function myFunction() { var a = 10; for(var i = 0; i < a; ++i) { Logger.log(i); } }
実行結果は以下の通りです。
0.0
1.0
2.0
3.0
4.0
5.0
6.0
7.0
8.0
9.0
for文は、後ほど紹介する配列の要素を参照するときによく使われます。
何回繰り返すか分かっていないときはwhile文を使いましょう。while文を書くときは、無限ループになっていないか十分に確認をしましょう。さもないと、兵庫県警に逮捕されます。*2
リスト2.1: while文.gs
while(条件式) { // 条件式の最後にはセミコロンはつけません // 繰り返す処理 // 条件式がtrueである限りこの部分は実行されます // 繰り返す処理の最後には必ず増減式を書きましょう }
以下は、while文を使ったコードの例です。
function myFunction() { var a = 0; while(a < 10) { Logger.log(a); a += 2; } }
実行結果は以下の通りです。
0.0
2.0
4.0
6.0
8.0
for文やwhile文のループ処理の中でbreak;
を入れると、完全にループから抜け出します。以下はコード例です。
function myFunction() { var a = 10; for(var i = 0; i < a; ++i) { if(i > 5) break; Logger.log(i); } }
実行結果は以下の通りです。
0.0
1.0
2.0
3.0
4.0
5.0
i
が6
のときにbreak;
が実行され、for文を抜け出しています。
ループ処理の中でcontinue;
を使うと、そこから後の処理は行われず、次のループに移ります。
以下はコード例です。
リスト2.2: continue_example.gs
1 2 3 4 5 6 7 | function myFunction() { var a = 10; for(var i = 1; i <= a; ++i) { if(i % 2 == 1) continue; Logger.log(i); } } |
実行結果は以下の通りです。
2.0
4.0
6.0
7.0
10.0
1から10までの偶数を出力するプログラムです。i
が奇数のときはcontinue;
が実行され、次のループに移ります。
空の配列の初期化のしかたは、次の通りです。
var arr = [];
配列を作成するには、角括弧を使います。
初期値をもつ配列の作り方は、次の通りです。
var arr = [33, 4, 57, 114, 514, 810];
初期値はもたないが要素数が定まっている配列の作り方は、次の通りです。
// 長さ 575 の配列を作る var arr = Array(575);
実際に長さ575の配列を作れているかどうか確認してみましょう。
function myFunction() { var arr = Array(575); Logger.log(arr.length); }
実行結果は次のようになります。
575.0
(配列名).length
で配列の長さを求めることができます。
配列の後ろに要素を追加するには、push()
を使います。使用例は次の通りです。
function myFunction() { var arr = [33, 4, 114, 514, 1919]; arr.push(810); Logger.log(arr); }
実行結果は次のようになります。
[33.0, 4.0, 114.0, 514.0, 1919.0, 810.0]
配列[33, 4, 114, 514, 1919]
の後ろに810
が追加され、[33, 4, 114, 514, 1919, 810]
になりました。
逆に、配列の先頭に要素を追加するには、unshift()
を使います。使用例は次の通りです。
function myFunction() { var arr = ['b', 'c', 'd', 'e']; arr.unshift('a'); Logger.log(arr); }
実行結果は次のようになります。
[a, b, c, d, e]
配列['b', 'c', 'd', 'e']
の先頭に'a'
が追加され、['a', 'b', 'c', 'd', 'e']
になりました。
配列の末尾の要素を削除するには、pop()
を使います。使用例は次の通りです。
function myFunction() { var arr = ['a', 'b', 'c', 'p']; arr.pop(); Logger.log(arr); }
実行結果は次のようになります。
[a, b, c]
配列['a', 'b', 'c', 'p']
の末尾の要素'p'
が削除され、['a', 'b', 'c']
になりました。
逆に、配列の先頭の要素を削除するには、shift()
を使います。使用例は次の通りです。
リスト2.3: array_shift.gs
function myFunction() { var arr = ['a', 'b', 'c']; arr.shift(); Logger.log(arr); }
実行結果は次のようになります。
[b, c]
配列['a', 'b', 'c']
の先頭の要素'a'
が削除され、['b', 'c']
になりました。
配列の値を参照するには、他言語と同じように、添字をつけます。添字は1から始まる(1-indexed)のではなく、0から始まる(0-indexed)ので気をつけましょう。
以下は使用例です。
リスト2.4: array_index.gs
function myFunction() { var arr = ['a', 'b', 'c', 'd', 'e']; Logger.log(arr[3]); // 4 番目の値が出力されます Logger.log(arr[0]); // 1 番目の値が出力されます }
実行結果は以下の通りです。
d
a
配列とfor文を組み合わせて、配列の全要素にアクセスすることもできます。
以下は、配列とfor文を組み合わせた例です。
リスト2.5: array_for.gs
function myFunction() { var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var sum = 0; for(var i = 0; i < arr.length; ++i) { sum += arr[i]; } Logger.log(sum); }
配列に格納された数値の総和を求めるプログラムです。
実行結果は次の通りです。
55.0
通常の配列とは違った配列として、連想配列があります。
連想配列とは、キーを指定して値を紐づけることができる配列です。C++でいうところのstd::map
、JavaでいうところのHashMap
です。
通常の配列では、添字は0から始まる数値ですが、連想配列では文字列のキーを指定して、そのキーに対応する値を代入します。
連想配列の初期化のしかたは、次の通りです。配列では角括弧を使いましたが、連想配列では波括弧を使います。
var hash = {};
初期値をもつ連想配列をつくるには、次のようにします。
var hash = { red: "赤色", blue: "青色", green: "緑色" };
コロンの左にキー名、右に値を書きます。
連想配列に要素を追加するには、連想配列名.キー = 値
や、連想配列名["キー"] = 値
などとします。
var hash = {}; hash.red = "赤色"; hash["blue"] = "青色";
連想配列の要素の参照は連想配列名.キー
や、連想配列名["キー"]
などとするとよいです。
連想配列の全要素を表示するには、for-in文を使います。
リスト2.6: hash_allshow
var hash = { red: "赤色", blue: "青色", green: "緑色", yellow: "黄色", orange: "橙色" }; for(var key in hash) { Logger.log(key + " の値: " + hash[key]); }
実行結果は以下の通りです。
red の値: 赤色
blue の値: 青色
green の値: 緑色
yellow の値: 黄色
orange の値: 橙色
連想配列の要素を削除するには、delete
を使います。
var hash = { red: "赤色", blue: "青色", orange: "橙色", green: "緑色" }; delete hash["orange"]; for(var key in hash) { Logger.log(key + " の値: " + hash[key]); }
実行結果は以下の通りです。
red の値: 赤色
blue の値: 青色
green の値: 緑色
ちゃんとorange
がキーとなる要素が削除されているのが分かります。
JavaScriptでの関数の書き方は次の通りです。
function 関数名 (引数1, 引数2, ...) { // 処理 return 返り値; }
引数がない場合は空白にしても構いません。また、返り値がない場合はreturn~の文は書かなくて構いません。
関数は、同じ処理を何回も実行するときに役に立ちます。
以下は、関数を使ったコードの例です。
リスト2.7: function_example
function rating(money) { var res; if(money < 400) res = "You are gray coder"; else if(money < 800) res = "You are brown coder"; else if(money < 1200) res = "You are green coder"; else if(money < 1600) res = "You are cyan coder"; else if(money < 2000) res = "You are blue coder"; else if(money < 2400) res = "You are yellow coder"; else if(money < 2800) res = "You are orange coder"; else res = "You are red coder"; return res; } function main() { var rate = 1305; Logger.log(rating(rate)); rate = 2810; Logger.log(rating(rate)); rate = 421; Logger.log(rating(rate)); }
AtCoder*3のレーティングから色分けを出力するプログラムです。実行結果は以下の通りです。
You are cyan coder
You are red coder
You are brown coder
[*3] https://atcoder.jp/
一通りGASを触ってみたら、いよいよ本題です。Twitter botを作る準備をしましょう。
Twitter botを作るためには、Twitter APIのAPIキーを取得しなければいけません。Twitter APIを叩くことで、スクリプトからツイートを送信したり、Twitterの様々なコンテンツ (ツイート、タイムライン、フォロワーなど)を取得したりできます。
Twitter APIのAPIキーは、以前はhttps://apps.twitter.com/から簡単に取得できましたが、2018年7月からAPIの使用条件が厳格になり、Twitterアカウントとは別にhttps://developer.twitter.com/からの開発者アカウントの登録が必須になりました。しかも、この開発者アカウントの登録が面倒で、Twitter APIを使う目的を英語で300文字以上書かされたりします。botを作る前段階の時点で初心者殺しですね。*4
[*4] 実は少し前までは開発者アカウントの登録にはTwitter側による審査が必要で、長い時間をかけないと登録ができない鬼畜仕様でした
それでは、この面倒な開発者アカウントの登録をやっていきましょう。
まず、Twitterの通常のアカウントを用意しましょう。登録手順は省略します。
次に、https://developer.twitter.com/にアクセスしてください。
ページ右上の「Apply」をクリックした後、「Apply for a developer account」をクリックしましよう。
図2.7: 開発者アカウント登録手順_01
Twitterアカウントに携帯電話番号を紐づけていないと以下のような画面になるので、「Add a valid phone number」から携帯電話番号を登録しましょう。すでに携帯電話番号を紐づけている場合は「Add a valid phone number」の部分が「Continue」になっているので、そこをクリックしましょう。
図2.8: 開発者アカウント登録手順_02
Twitter APIを利用するアカウントの詳細情報を入力します。
図2.9: 開発者アカウント登録手順_03
Twitter APIの使用用途にチェックを入れます。
図2.10: 開発者アカウント登録手順_04
Twitter APIをどのように使用するかを詳細に記載します。英語で300文字以上書かないといけません。頑張って書きましょう。
図2.11: 開発者アカウント登録手順_05
APIで入手した情報を政府機関が利用できるか確認されます。個人利用なのでもちろん「No」を選びましょう。
図2.12: 開発者アカウント登録手順_06
利用規約に同意して、開発者アカウントの登録申請をしましょう。
図2.13: 開発者アカウント登録手順_07
図2.14: 開発者アカウント登録手順_08
「あなた宛にメールを送信したよ!」という画面になり、Twitterからメールが送信されます。
図2.15: 開発者アカウント登録手順_09
送信されたメールの内容です。「Confirm your email」をクリックしましょう。
図2.16: 開発者アカウント登録手順_10
僕の場合、この時点でTwitter APIを使用できる状態になっていましたが、もし「審査中です」というような画面になっていた場合、審査が終わるまで待ちましょう。Twitter側からメールが来た場合、要求されている内容を英語で書いて返信してください。承認されれば、ようやく開発者アカウントの登録は終わりです。
Get Started(https://developer.twitter.com/en/account/get-started)のページから、「Create an app」をクリックしましょう。
図2.17: APIキー取得_01
「Create an app」をクリックします。
図2.18: APIキー取得_02
以下の画像の通りに必要事項を入力しましょう。
図2.19: APIキー取得_03
図2.20: APIキー取得_04
図2.21: APIキー取得_05
「Callback URLs」には次のURLを指定してください。角括弧は必要ありません。
https://script.google.com/macros/d/[GASのスクリプトID]/usercallback
GASのスクリプトIDは、GASのエディタの上部メニュー「ファイル」→「プロジェクトのプロパティ」を開くことで見ることができます。
図2.22: スクリプトIDの場所
必要事項を記入し終わったら、「Create」をクリックしましょう。その後、APIの使用に関する注意が出るので、一読してから「Create」をクリックしましょう。
図2.23: API使用に関する注意画面
これでAppを作成できました。今回のbot作成では、「Key and tokens」から見られる、2つのConsumer API keysを使います。
図2.24: Key and tokensをクリック
図2.25: 今回使うConsumer API keys
これで、APIキーを取得することができました。
これでようやくAPIキーを取得することができました。あともう一息です。
今度は、GASのライブラリ「TwitterWebService」*5を導入します(公式のものではありません)。TwitterWebServiceライブラリを導入することで、OAuth認証の処理が楽になります。
GASのエディタを開いて、上部メニュー「リソース」から、「ライブラリ」を選択してください。次に、「ライブラリの追加」の欄に以下に示すプロジェクトキーを入力し、「追加」ボタンをクリックしてください。
プロジェクトキー:1rgo8rXsxi1DxI_5Xgo_t3irTw1Y5cxl2mGSkbozKsSXf2E_KBBPC3xTF
以下のような画面になるので、バージョンを「2」に合わせて、「保存」を押してください。
図2.26: ライブラリ追加
図2.27: バージョンを2に合わせて保存
これでTwitterWebServiceライブラリを導入することができました。
以下のソースコードを書いてください。3・4行目には、先ほど取得したConsumer API keysのAPI keyとAPI secret keyを入れてください。
リスト2.8: TwitterHello.gs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // 認証用のインスタンス var twitter = TwitterWebService.getInstance( " (Consumer API keysのAPI key) ", " (Consumer API keysのAPI secret key) " ); // 認証 function authorize(){ twitter.authorize(); } // 認証解除 function reset(){ twitter.reset(); } // 認証後のコールバック function authCallback(request){ return twitter.authCallback(request); } // ここから上は変えないようにしてください function postTweet(){ var service = twitter.getService(); var message = "Hello, World!"; var response = service.fetch("https://api.twitter.com/1.1/statuses/update.json", { method: "post", payload: { status: message } }); } |
ソースコードを書いたら、まずauthorize関数を実行しましょう。authorize関数の走らせ方は以下の画像の通りです。
図2.28: authorize関数実行手順
実行が終わったら、ログを表示させます。以下の画像のようにURLが表示されますので、ブラウザの別タブでそのURLに飛びましょう。
図2.29: 認証ページのURL
すると、ツイ廃にとってはおなじみの画面が表示されました。「連携アプリを認証」をクリックしましょう。
図2.30: おなじみの認証画面
「Success」の表示が出れば、認証成功です。このタブは閉じても構いません。ちなみに、2回目以降の実行では、以上の認証作業は必要ありません。
認証が終わったので、ようやくツイート処理がおこなえます。それでは、先ほどauthorize関数を実行したのと同じようにして、postTweet関数を実行してみましょう。
実行が終了した後、Twitterを開いて確認してみましょう。ちゃんと「Hello, World!」という内容のツイートが送信されています。
図2.31: ツイート送信完了
この記事の冒頭で紹介した、明日の天気を発信するお天気botを、実際に作ってみましょう。
お天気botを作るためには、明日の天気情報をどこかから入手する必要があります。今回は、Livedoorの天気API(http://weather.livedoor.com/weather_hacks/webservice)を利用します。これは、地域を指定するとその地域の今日・明日・明後日の天気・最高気温・最低気温のデータをJSON形式で取得できるというものです。
手っ取り早く作りたいという方のために、先にソースコードを載せておきます。コード解説は後ほど。
リスト2.9: weatherbot.gs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | // 認証用のインスタンス var twitter = TwitterWebService.getInstance( " (Consumer API keysのAPI key) ", " (Consumer API keysのAPI secret key) " ); // 認証 function authorize(){ twitter.authorize(); } // 認証解除 function reset(){ twitter.reset(); } // 認証後のコールバック function authCallback(request){ return twitter.authCallback(request); } // ここから上は変えないようにしてください function weatherTweet(){ var tweet; var weatherJSON = JSON.parse(UrlFetchApp.fetch("http://weather.livedoor.com/forecast/webservice/json/v1?city=270000").getContentText()); var weather = weatherJSON["forecasts"][1]["telop"]; var maxtemp = weatherJSON["forecasts"][1]["temperature"]["max"]["celsius"]; var mintemp = weatherJSON["forecasts"][1]["temperature"]["min"]["celsius"]; var tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); var datestr = String(tomorrow.getMonth()+1) + '月' + String(tomorrow.getDate()) + '日'; tweet = "明日("+datestr+")の大阪の天気は "+weather+" の予想です。\n最高気温は "+maxtemp+"℃、最低気温は"+ mintemp+"℃ の予想です。"; twitter.getService().fetch("https://api.twitter.com/1.1/statuses/update.json", { method: "post", payload: { status: tweet } }); } |
大阪市の天気情報を http://weather.livedoor.com/forecast/webservice/json/v1?city=270000 から入手し(UrlFetchApp.fetch(url)
)、それをJSON形式のデータとして扱えるようにしています(JSON.parse()
)。
入手したJSON形式のデータの構造の概略は次の画像の通りです。JSON形式のデータは階層構造でデータが格納されています。
図2.32: 天気JSONデータの構造
JSON形式のデータでは、連想配列と同じようにして特定のデータにアクセスすることができます。
27行目では明日の天気、
28行目では明日の最高気温、
29行目では明日の最低気温
を参照しています。
31行目では、日付情報を格納するDate型を使い、今日の日付情報(new Date()
)を変数tomorrow
に代入しています。
32行目では、変数tomorrow
が今日の日付情報になっているのを明日の日付情報に直しています。
33行目では、明日の日付を「○月○日」の形の文字列として変数datestr
に代入しています。tomorrow.getMonth()
で返ってくる値は実際の月より1小さいので(例えば5月なら4が返ってきます)、実際の月に直すために1を足しています。
tweet
をつくる文字列では、+
を使うと文字列同士の結合ができます。また、String()
を使うと、数値型のものを文字列型にキャストすることができます。
Hello, Worldのツイートを送信したときと同じように、「変数tweet
をツイート内容にしてツイートして」というリクエストを送っています。
実装をしただけでは、まだ自動実行するbotとはいえません。最後の仕上げとして、このスクリプトを定期的に実行するようにしましょう。
この記事の最初のほうに書いたGASの紹介で、トリガー機能について述べました。今回は、このトリガー機能を使って自動実行させるようにします。
まず、エディタの上部メニュー「編集」→「現在のプロジェクトのトリガー」を押しましょう。別タブが開くはずです。
次に、ページ右下の「トリガーを追加」を押して、次の画像のように設定してください。「時刻の選択」は自分の好きな時間帯にして構いません。「エラー通知設定」についても、自由に設定して構いません。
図2.33: トリガーの設定
設定が終わったら、下部の「保存」を押しましょう。次の画像のような表示になれば、トリガーの設定は成功です。
図2.34: トリガー設定完了
実際に、「時刻の選択」で設定した時間帯になると自動的にツイートが実行されるかと思います。これでようやくお天気botの完成です!
今回作ったお天気botは実装が楽な部類のもので、JavaScriptの関数をもっと学べばさらに高度なbotを作ることができます。また、GASにはスプレッドシートなどと連携した機能があるので、変数データをスプレッドシートに保存しておくといった使い方もできます。
JavaScriptのリファレンスはネットにたくさん転がっており、GAS特有の関数についてもGoogle公式によるリファレンスが(英語ですが)あります。
GASリファレンス:https://developers.google.com/apps-script/reference/
これらを読んで、あなたも便利な機能をもったbotを作りましょう!