sponsored link

【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

プログラミング

コメント一覧

  1. kanoe より:

    日時の初期設定を動かさなくても別に不具合は起きませんが一応記述しています。
    また、いろいろな変数を引数にして様々なアカウントに拡張させるのもありですね。(さっき思った。)

  2. やまやま より:

    こんにちは
    いつもこちらのコードを使わせていただき、かなり便利に使わせていただいております。作ってくださりありがとうございます!

    質問を失礼しますが、最近、Twitterのアカウントを取得する数が増えてきたため、公開リストから一括でツイート取得できないか試みているのですが、上手くいかず質問させていただきました。

    検索URL部分と取得ハッシュタグ部分の username の箇所を削除するだけではだめなんでしょうか?もし他に修正点やアイデアがあれば教えていただけると助かります。

    いきなりですみませんが、ご返答いただければ幸いです。

    • kanoe より:

      こんにちは、コメントありがとうございます。

      リストの取得ということですが、リストの取得ではまず使用するWEB-APIのリクエストURLが異なります。
      私のコード上では以下の部分で指定しています。
      【var json = service.fetch(‘https://api.twitter.com/1.1/search/tweets.json?q=from%3AKanoeTweet%20%23shijimi&count=5’ + { ‘headers’: bearer_auth_header });】

      以下のURLはツイッターの投稿を検索するURLになります。
      【https://api.twitter.com/1.1/search/tweets.json】

      対して、リストの取得は以下のURLを用いるみたいです。
      【https://api.twitter.com/1.1/lists/list.json】
      ?以降に指定できるパラメータについては公式ドキュメントに記載がありますが、特定語句だけを指定できるパラメータが見当たりませんね。
      そのため、指定語句が含まれているかどうかを判定する検索機能は、GASスクリプト側で実装することになりそうです。

      回答になっていますか?
      よろしくお願いいたします。m(_ _)m

      • やまやま より:

        Kanoe様

        なるほど、WEB-APIのリクエストURLが違うんですね。基本的なところから間違えていました。一生気づかないところでした……、助かりました。
        加えてGASスクリプト側で指定など、わかりやすくありがとうございます。そのあたりも考えながらやってみたいと思います。

        とても迅速で丁寧なご返答、誠にありがとうございました!

sponsored link
KANOE STUDIO
タイトルとURLをコピーしました