【GAS】毎日決まった時間にツイートする

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>

トリガー

タイトルとURLをコピーしました