【GAS】特定のTwitterのアカウントのツイート更新を取得してDiscordに通知する

GASで作った経緯: IFTTTがクソだったから。

2021.4.16: GitHub上に、拡張性を持たせるための説明を書いたREADMEファイルを更新しました。
2023.1.11: リツイートを除外する方法について、GitHubのWiki記事を追加しました。(RTを除外する方法 · KanoeGitHub/HashtagTweetToDiscord Wiki

事前準備

  • Twitterのデベロッパアカウントの取得及びAPIキーの発行
  • Googleアカウントの取得
  • Twitterdevelopers側でのGASのコールバック設定
  • DiscordのWebhookキーの取得

コード内容

コード全文はgithub(https://github.com/KanoeGitHub/HashtagTweetToDiscord)より参照できます。

Twitter認証関連はTwitterWebServiceというライブラリを使用したものになっています。
こちらの記事を参考…というかほぼそのままです。(https://qiita.com/akkey2475/items/ad190a507b4a7b7dc17c

//Twitter認証関連です。ライブラリとしてTwitterWebServiceを仕様しています。
//基本的に最初のauthorize関数のみの実行後ログに表示されるURLから認証してください。
//TwitterDev側でコールバックURL設定をしておかないとうまくいきません。

//''内にそれぞれトークンを入れてください。
var twitter = TwitterWebService.getInstance(
'API Token',
'API secret Token'
);

// 認証を行う(必須)
function authorize() {
twitter.authorize();
}

// 認証をリセット
function reset() {
twitter.reset();
}

// 認証後のコールバック(必須)
function authCallback(request) {
return twitter.authCallback(request);
}

次にDiscordに送る関数です。

//Discordに送るための関数
function sendToDiscord(user, cont) {

//取得したWebhookURLを""の中に入れてください。
const WEBHOOK_URL = "Webhook URL of Discord"; 

//Discordに送信する内容。適宜Discordのwebhookドキュメントから調べてカスタムしてください。
const payload = {
username: user,
content: cont,
};

UrlFetchApp.fetch(WEBHOOK_URL, {
method: "post",
contentType: "application/json",
payload: JSON.stringify(payload),
});
}

時刻の初期設定を行う関数です。
これは一番最初に実行しておくだけで構いません。

//時刻の初期設定です。初回に実行してください。
function scriptPropatiesReset(){
//スクリプトプロパティを取得
const scriptProperties = PropertiesService.getScriptProperties();
//日時の初期値をセット
scriptProperties.setProperty('date', 'Fri Apr 02 10:00:00 +0000 2021');
}

最後にハッシュタグツイートを取得してからDiscordに送るまでを書いたスクリプトです。
取得するタイムラインのserchURLは例として私のタイムラインを記載しています。適宜カスタムしてください。
例えばハッシュタグにあたる%23を消すと普通に”shijimi”での文字検索になります。

//ここをトリガー設定して回してください。

function getMyHashTweets() {
const bearer_token = '任意のBearer_Token' //''内にBEARER_TOKENを入れてください。
var service  = twitter.getService();
var bearer_auth_header = {
'Authorization': 'Bearer ' + bearer_token
};

//URLのq=以下に検索指定設定を記載する。
//"from%3AKanoeTweet" は "from@KanoeTweet"
//"%20" は "スペース"
//"%23shijimi" は "#shijimi"
var json = service.fetch('https://api.twitter.com/1.1/search/tweets.json?q=from%3AKanoeTweet%20%23shijimi&count=5' + { 'headers': bearer_auth_header });

var array = JSON.parse(json);
array.statuses.reverse();

//スクリプトプロパティを取得
const scriptProperties = PropertiesService.getScriptProperties();

array.statuses.forEach(function(status) {    
Logger.log(status.user.screen_name +":"+ status.created_at);
var a = new Date(status.created_at);
var b = new Date(scriptProperties.getProperty('date'));

//日時の比較
if(a>b){ 
//Tweetの本文のみを表示させる場合
//sendToDiscord(status.user.name, status.text); 

//Tweetのリンクを表示させる場合
sendToDiscord(status.user.name, "https://twitter.com/" + status.user.screen_name + "/status/" + status.id_str); 

scriptProperties.setProperty('date', status.created_at); //最終日時更新
}
});

return array;
}

後書き

TwitterとDiscordの連携といえばIFTTTを使う方法がメジャーかなと思います。
IFTTTにある Twitter to Webhook 的なものを使えばできるらしい

かくいう私も本当はIFTTTでサクッと作りたかった。
しかし、IFTTTからWebhook使おうとすると、頻繁に「There was an error during check process」とか「too many requests to this host」などのエラーが出てきます。
調べると、IFTTTはリクエストは1時間毎とかいう情報もありました。
実際動かす際には別にそれでも構わないのですが、動作チェック時にもそれが適用されるみたいで、チェックすらまともにさせてくれませんでした。

なので、IFTTTは諦めてGASを使うことにしました。

しかもこっちだと最速で1分ごとに更新とかできちゃうしGAS(Google App Script)の方が使い勝手良いのではないでしょうか。
(無料枠だと1日に起動できる回数に制限はあるけど…)

まぁ問題はTwitterの開発者アカウントを取得するのが少し手間だということだけで笑

何かプログラム中にどうしても意味不明な場所があればコメントなりTwitterのDMなりしてください。

参考にした記事一覧

  1. GASで永続化する方法まとめ(設定や処理結果を保存・読み込みしたい時)
    https://qiita.com/tomboyboy/items/6a15ab1a4838bd6b7f9d
  2. GASの新エディタでスクリプトのプロパティを確認・設定する方法
    https://qiita.com/iron-smri/items/76c9837e398922d79a69
  3. 意外と知られていないJavaScriptのnew Date()の使用方法
    https://iwb.jp/javascript-new-date-gettime/
  4. Google Apps Script (GAS) でTwitterへ投稿するだけの機能を実装してみる
    https://qiita.com/akkey2475/items/ad190a507b4a7b7dc17c
  5. Google Apps ScriptからDiscordにチャットを投稿する
    https://zenn.dev/tamfoi/articles/18c4a815cc3449
  6. GASを使って、Twitter検索した結果をSlackへ定期投稿してみた
    https://qiita.com/nobu09/items/c940fc6e0d67ef1cbc85
  7. Standard search API
    https://developer.twitter.com/en/docs/twitter-api/v1/tweets/search/api-reference/get-search-tweets
  8. Discord Developer Portal — Documentation
    https://discord.com/developers/docs/resources/webhook