ことのはじまり
- TwitterAPIには「いいね!」した人をリストする機能が無い。
- favstarとかもあるけど鍵付きの人は認識できないっぽいし一部有料。
- むしろ「いいね!」でなくていい。欲しい人のTwitterアカウントが認識できればいい。
- 後で集計しやすい形が良い。.csvとか.xlsxとか.jsonとかとか…
- Googleフォームなららくちん! ……でもTwitterID書いて投稿だったら簡単に偽装できる。
- お、コレ行けるんじゃね?→[GAS] Google Apps Script でTwitter複数アカウントを使い分ける
- GoogleAppsScriptならGoogleスプレッドシートに書きだせる!
というわけで作成した時にハマリ所をいくつかピックアップ。
詳しい使い方とかはココで紹介しませんので、各自でQiitってください。
「ええい御託は良い、はやくコードを写さんか!」って人はこちら
ハマり所とテクニック
コールバック
--- コード.gs ---
OAuth1.getCallbackUrl = function(scriptId) {
return Utilities.formatString(
'https://script.google.com/macros/s/%s/exec', scriptId);
}
~
// getServiceを上書き、スクリプトIDを手動設定に変更
twitter.getService = function() {
~
.setScriptId(PropertiesService.getScriptProperties().getProperty("OPENED_SCRIPT_ID"))
~
function doGet(e) {
if (e && e.parameter.oauth_verifier)
~
--- プロジェクトのプロパティ ---
OPENED_SCRIPT_ID : ********************************************************
一番悩んだところ。
デフォルトのプロパティではhttps://script.google.com/macros/s/スクリプトID/usercallback
に飛ぶのだが、このページに飛べるのはGoogleの認証ができる人のみ。
既に公開しているhttps://script.google.com/macros/s/スクリプトID/exec
にはGoogleの認証無しで見れるので、こっちに飛ばしてパラメータでコールバック前か後かを判断する。
認証前のページ
--- Oath.html ---
<a target="_top" href=<?=auth_url?>Twitterで認証</a>
クリックで飛ばす仕組み。
というのも、GAS上で表示するページは自動遷移ができない らしい。
metaタグやJavaScriptは書いても無効化されてしまう。セキュリティの関係上であろうし、コレは仕方ない。
(自動で別ページへ飛んで勝手にアヤシイサイトに入会させられて○○万円振り込め。 なんてよくある手口ですからね…)
スクリプトのプロパティ
--- コード.gs ---
var twitter = TwitterWebService.getInstance(
PropertiesService.getScriptProperties().getProperty("TWITTER_CONSUMER_KEY"),
PropertiesService.getScriptProperties().getProperty("TWITTER_CONSUMER_SECRET")
);
コード内でグローバル変数的なもの、マジックナンバーのようなものを格納できるGASの機能。
setProperty
もある。
QiitaやGitHubにコードを投稿した時にAWSのキーを消し忘れて大変なことに… って事が無くなる効果もある。
これからも積極的に使っていきたくなる機能。(グローバル変数の乱立には注意)
良い設定方法の記事無かったので書きました ↓
GoogleAppsScript スクリプトのプロパティの超簡単な使い方
HTMLの作成
--- コード.gs ---
var html_template = HtmlService.createTemplateFromFile('Comp');
html_template.name=user_info[3];
return html_template.evaluate();
--- Comp.html ---
<body>
<br /><?=name?>さんの受付が完了しました。</center>
</body>
HtmlService.createTemplateFromFile(拡張子なしファイル名)
で生成したテンプレートファイルに値を突っ込むだけでHTMLから参照できる。
最後にテンプレートをevaluate()
して、出てきたオブジェクトをreturnで返してあげればページがユーザーに表示される仕組み。
プログラムでゴニョゴニョしてできた値を簡単にHTMLとして表示できる。
実装
以下のライブラリを追加。
- TwitterWebService: MFE2ytR_vQqYfZ9VodecRE0qO0XQ_ydfb
- OAuth1: 1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s
コード.gs
'use strict';
// OAuth1認証用インスタンス
var twitter = TwitterWebService.getInstance(
PropertiesService.getScriptProperties().getProperty("TWITTER_CONSUMER_KEY"),
PropertiesService.getScriptProperties().getProperty("TWITTER_CONSUMER_SECRET")
);
// コールバック先をexecに変更
// デフォルトのusercallbackだとGoogleでの認証が必要になってしまう。
OAuth1.getCallbackUrl = function(scriptId) {
return Utilities.formatString(
'https://script.google.com/macros/s/%s/exec', scriptId);
}
// getServiceを上書き、スクリプトIDを手動設定に変更
twitter.getService = function() {
return OAuth1.createService('Twitter')
.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
.setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
.setConsumerKey(twitter.consumer_key)
.setConsumerSecret(twitter.consumer_secret)
.setCallbackFunction('exec')
.setPropertyStore(PropertiesService.getUserProperties())
.setScriptId(PropertiesService.getScriptProperties().getProperty("OPENED_SCRIPT_ID"))
}
// 認証時にURLを返すように変更
twitter.authorize = function() {
var service = this.getService();
if (service.hasAccess()) {
Logger.log('Already authorized');
} else {
var authorizationUrl = service.authorize();
return authorizationUrl;
}
}
// 認証をリセット
function reset() {
twitter.reset();
}
// 認証を行う
function authorize() {
return twitter.authorize();
}
// スプレッドシートに追記
function addSpreadSheet(value){
var id = PropertiesService.getScriptProperties().getProperty("SPREADSHEET_ID");
var spreadSheet = SpreadsheetApp.openById(id);
// 既に受付済の人は追記せずに帰る
var idlst = spreadSheet.getSheetValues(2,3,spreadSheet.getSheetByName('data').getMaxRows(),1);
for(var idv in idlst){
if(idlst[idv][0]==value[2]){
return;
}
}
spreadSheet.getSheetByName('data').appendRow(value);
}
// ユーザ情報を取得
function getUserInfo() {
var service = twitter.getService();
var response = service.fetch('https://api.twitter.com/1.1/account/verify_credentials.json');
var response_list = JSON.parse(response)
return [
Date(),
response_list["id_str"],
'@'+response_list["screen_name"],
response_list["name"],
]
}
function doGet(e) {
//test_code
// Comp.htmlをテストするときに此方を使う
// var html_template = HtmlService.createTemplateFromFile('Comp');
// html_template.name="テスト";
// return html_template.evaluate();
//test_code
// 初回、コールバック共に此方の関数を使う。
// OAuthのパラメタ有無で認証前か後を判断する
if (e && e.parameter.oauth_verifier){
twitter.authCallback(e);
var user_info = getUserInfo();
addSpreadSheet(user_info);
var html_template = HtmlService.createTemplateFromFile('Comp');
html_template.name=user_info[3]; //name
return html_template.evaluate();
}else{
reset();
var html_template = HtmlService.createTemplateFromFile('Oath');
html_template.auth_url=authorize();
return html_template.evaluate();
}
}
Oath.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title>「ふぁぼった人に○○します!」の代替をGoogleAppsScriptで作った</title>
</head>
<body><center>
<a target="_top" href=<?=auth_url?>Twitterで認証</a>
</center></body>
</html>
Comp.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title>認証完了</title>
</head>
<body>
<br /><?=name?>さんの受付が完了しました。</center>
</body>
</html>
プロジェクトのプロパティ -> スクリプトのプロパティ
TWITTER_CONSUMER_SECRET : **************************************************
TWITTER_CONSUMER_KEY : *************************
SPREADSHEET_ID : ********************************************
OPENED_SCRIPT_ID : ********************************************************
-
TWITTER_CONSUMER_SECRET
とTWITTER_CONSUMER_KEY
の二つはTwitterのアプリキー -
SPREADSHEET_ID
は書き込み先スプレッドシートID -
OPENED_SCRIPT_ID
は、アプリを公開した時のID(一度Webに公開してキーをコピってから再公開)