GAS(Google Apps Script)で毎日決まった時間(9時)にツイートするコードのサンプルです。
Twitter APIもいつか使えなくなると思うのですが、一応メモということで。
Twitter APIとかの登録関係は別のサイトを見てください。(適当)
シート
シートでは以下のような準備をしました。
- A列:投稿済かどうかをチェックするためのチェックボックス
- B列:ツイートする内容
- C列:長さ(=LEN(B列のセル)で文字数をカウントしてますが、正確ではないので目安です)

コード
CreateTweet.gs
function getTwitterService(serviceName) {
return OAuth1.createService(serviceName)
.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
.setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
.setConsumerKey("自分用に変更") // API Key
.setConsumerSecret("自分用に変更") // API Key Secret
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties());
}
function authCallback(request) {
let twitterService = getTwitterService(request.parameter.serviceName);
let isAuthorized = twitterService.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('認証が正常に終了しました。');
} else {
return HtmlService.createHtmlOutput('認証がキャンセルされました。');
}
}
function doGet(e) {
let twitterService = getTwitterService(e.parameter.screenName);
let template;
if (!twitterService.hasAccess()) {
let authorizationUrl = twitterService.authorize();
template = HtmlService.createTemplateFromFile("index");
template.authorizationUrl = authorizationUrl;
} else {
template = HtmlService.createTemplateFromFile("completed");
}
return template.evaluate();
}
// v1.1のため使用しない
// function postTweet() {
// let twitterService = getTwitterService("Twitterのユーザー名");
// let options = {
// "method": "post",
// "payload": {
// status: 'This is a tweet from GAS. This tweet is a test tweet by Twitter API.'
// }
// };
// let response = JSON.parse(twitterService.fetch('https://api.twitter.com/1.1/statuses/update.json', options));
// }
function getTweetContent() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const range = sheet.getRange('A:B');
const values = range.getValues();
for (let i = 0; i < values.length; i++) {
if (values[i][0] === true) {
// console.log('true === ' + i);
// console.log(values[i][1]);
} else {
// console.log('false === ' + i);
// console.log(values[i][1]);
if (i !== 0 && values[i][1].length !== 0) {
sheet.getRange(i + 1, 1).setValue(true);
// console.log('message === ' + values[i][1]);
return values[i][1];
}
}
}
}
function postTweet() {
const service = getTwitterService("Twitterのユーザー名");
const tweetContent = getTweetContent();
// undefined(戻り値なし)の場合は、==nullで判定して強制終了させる
if (tweetContent == null) {
console.log('強制終了');
return false;
}
const options = {
"method": "post",
"muteHttpExceptions": true,
'contentType': 'application/json',
'payload': JSON.stringify({
text: tweetContent
})
}
try {
const response = JSON.parse(service.fetch("https://api.twitter.com/2/tweets", options));
// console.log(response);
} catch (e) {
const address = 'XXX@gmail.com';
const subject = 'Twitter自動投稿アプリでエラーが発生しました。';
const body = e.fileName + ': ' + e.lineNumber + '\n' + e.name + ': ' + e.message + '\n' + e.stack;
const mailOptions = { noReply: true, name: 'GASアプリエラー検知システム' };
GmailApp.sendEmail(address, subject, body, mailOptions);
//チェックボックスのfalseをこれから実装する(まだしてないw)
} finally {
// 翌日のトリガーをセット
setTrigger();
}
}
// 次回のトリガーをセット
function setTrigger() {
const triggers = ScriptApp.getProjectTriggers();
for (const trigger of triggers) {
ScriptApp.deleteTrigger(trigger);
}
let setTime = new Date();
setTime.setDate(setTime.getDate() + 1)
setTime.setHours(Number('09'));
setTime.setMinutes(Number('00'));
ScriptApp.newTrigger('postTweet').timeBased().at(setTime).create();
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<a href="<?= authorizationUrl ?>" target="_blank">Twitterの認証を行う</a>
</body>
</html>
completed.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Twitterの認証は完了しています。
</body>
</html>
トリガー
