Help us understand the problem. What is going on with this article?

Google Apps Scriptで(大体)1時間毎にTweetするBotを作る

PHP + cron で動いていた Twitter Bot を Google Apps Script (GAS) で置き換えました。
スクリプトをざっくりメモ書き程度に書いておきます。

スクリプトの全容は Gist/gasTwitterBot.gs に置いておきます。

Bot の要件

  1. Tweetを投稿する
  2. Tweetする内容はスプレッドシートからランダムに取得する
  3. 投稿時間は1時間に1度のペース
  4. Botっぽくないように いい感じ にバラけた時間に投稿する
  5. 投稿は9時から21時の間まで

最終結果

雰囲気はこんな感じです。
Tweet 候補をシートに記載しておいて、コードを実行することであとは寝ているだけで動き出します。

Screen Shot 2019-09-03 at 22.14.20.png

実際に Tweet が投稿された時間帯です。
いい感じにバラけた時間に投稿しているので、Botっぽさが低減されているかと。

起動 9:13
1回目 10:01
2回目 10:33
3回目 12:09
4回目 13:07
5回目 13:50
6回目 14:52
7回目 15:33
8回目 16:32
9回目 18:07
10回目 18:51
11回目 19:46

使い方(参考)

1か2、好きな方をお好みで。

  1. createEveryHoursScheduler() をトリガー画面から実行する
  2. 以下の init() を実行して、好きな時間に createEveryHoursScheduler() の起動を予約する
function init() {
  const time = "好きな時間";
  ScriptApp.newTrigger("createEveryHoursScheduler").timeBased().at(time).create();
}

実現方法

1. Tweetを投稿する

GASでTweetする系の記事はいくつもあるので、それを参考にしていただければ!

参考: Qiita | Google Apps Script (GAS) でTwitterへ投稿するだけの機能を実装してみる
参考: Gist | TwitterWebService.gs

var twitter = TwitterWebService.getInstance(
  'xxxxx', // 作成したアプリケーションのConsumer Key
  'xxxxx'  // 作成したアプリケーションのConsumer Secret
);

// Twitterの認証
function authorize() {
  twitter.authorize();
}

// Tweetをする投稿
function postTweet(tweet) {
  const service  = twitter.getService();
  const response = service.fetch('https://api.twitter.com/1.1/statuses/update.json', {
    method: 'post',
    payload: { status: tweet }
  });
}

// 実際に実行する関数
function execute() {
  const tweet = "HOGE"; // TODO: とりあえず固定
  postTweet(tweet);
}

2. Tweetする内容はスプレッドシートからランダムに取得する

"Tweet" シートのA列に各Tweetが並んでいるのが前提です。
そして「1. Tweetを投稿する」の execute() を少し変更します。

function selectRandomTweet() {
  // Tweetシートを取得する
  const sheetData = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tweet");

  // 1 ~ 最終行までの行をランダムに選択する
  const lastRow = sheetData.getLastRow();
  const selectedRow = Math.floor(Math.random() * lastRow) + 1; 

  // 選んだ行の内容を取得する
  const selectedTweet = sheetData.getRange(selectedRow, 1).getValue();
  return selectedTweet;
}

function execute() {
  const tweet = selectedTweet(); // tweetをランダムにする
  postTweet(tweet);
}

3. 投稿は1時間に1度のペース

トリガーを設定して、1時間に一回 execute() を実行するようにします。

参考: Google App Script | Trigger
参考: Google App Script | everyHours(n)

function createEveryHoursScheduler() {
  ScriptApp.newTrigger("execute").timeBased().everyHours(1).create();
}

4. botっぽくないようにいい感じにバラけた時間に投稿する

  1. schedulePost() を1時間に1度実行
  2. 次の schedulePost() が実行されるまでの1時間の間で、ランダムな時刻を取得
  3. 取得したランダムな時刻に execute() を実行

参考: Google App Script | at(Date)
注意: 実は at(Date)±15分の誤差 が生まれます(cf. at(Date)

function createEveryHoursScheduler() {
  // schedulePost() を1時間に1度実行するように変更
  ScriptApp.newTrigger("schedulePost").timeBased().everyHours(1).create();
}

function schedulePost() {
  const scheduledTime = getScheduledTime();
  // スケジュールした時刻に execute() を実行する
  ScriptApp.newTrigger('execute').timeBased().at(scheduledTime).create();
}

function getScheduledTime() {
  var setTime = new Date();
  const minutes = setTime.getMinutes();
  const randomMinute = Math.floor(Math.random() * 59);

  // 現在時刻 + 0~59分 の時刻を設定する
  setTime.setMinutes(minutes + randomMinute); 
  return setTime;
}

5. 投稿は9時から21時の間まで

24時間ずっと投稿し続けていると人間らしくありません。
そこで9:00~21:00の間でしか投稿しないように制限します。

function schedulePost() {
  const scheduledTime = getScheduledTime();
  // スケジューリングした時間をバリデーションにかける
  if (!validateHourRange(scheduledTime.getHours())) return;

  ScriptApp.newTrigger('execute').timeBased().at(scheduledTime).create();
}

function validateHourRange(hour) {
  if (hour >= 9 || hour <= 21) return true;  // 投稿したい時間を指定する
  return false;
}

感想

Google Apps Script、めちゃめちゃ多機能で便利だなーと思いました。

  • Google Spreadsheet でコンテンツ管理可能
  • 基本は JavaScript で書ける
  • Debugger 機能
  • 定期実行機能
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away