tsyama記

プログラミングとそのほか

Slackへ定期的にYouTube動画をpostするSlack AppをGASでつくった記録

はじめに

最近個人用Slackチャンネル作ったはいいが特に投稿もなくて寂しいので勝手にいい感じのYouTube動画をおすすめしてくれるようなSlack Appを作りました。半ば個人的な備忘録になります。Slackへ定期的にYouTube動画をpostするSlack AppをGASで作りたい人には参考になるかもしれません。

コードだけ見たい場合はこちら。

github.com

GASでコード管理

GASの定期実行トリガーが使いたかったので、今回はGASで開発してみます。
本筋とはあまり関係ありませんが、GASのコードをWebエディタ以外で管理できるclaspというツールがリリースされていました。

github.com

今回はwindowsにclaspを入れ、clasp pullおよびclasp pushできる環境を整えましたが、デバッグするたびにclasp pushするのがめんどいのでローカルで開発する気にはあまりなりません。ソースをGit管理するときに使うとよさそうです。

使い方はこのあたりを参考にしました。

qiita.com

GASでyoutube APIを使うまで

今回はYouTube Data API (v3)を使うのですが、GASであれば割合簡単に導入することができます。

GASのメニューからリソース > Googleの拡張サービスで有効化するライブラリを選択できるので、この中からYouTube Data APIをv3で有効にしましょう。

f:id:tsyama-desu:20181125121212p:plain

画像ではなぜかON/OFFスイッチが崩れているんですが気にしません。また、モーダル下部に書かれている通り、Google Cloud Platform APIダッシュボードでも該当のAPIを有効にしておきます。

これでYouTube Data APIをGASから簡単に扱えるようになりました。今回は関連動画の検索を行うためにこんな感じで呼び出しています。

  var results = YouTube.Search.list("id,snippet",{
    type: "video",
    relatedToVideoId: videoId,
    maxResults: 5,
  });

参考にした記事はこちら。

qiita.com

SlackのIncoming Webhooksで定期実行

Slackにpostする処理

BotからSlackにpostさせるため、新規にSlack Appを作成し、GASからIncoming Webhooksに対してリクエストを送るようにします。

Slack API: Applications | SlackからCreate New Appで新しいAppを作成しましょう。
作成したらAppの設定ページからIncoming WebhooksをActivateし、Add New Webhook to Workspaceを押してチャンネルを選択すると、該当のチャンネルにpostするWebhookが生成されます。

f:id:tsyama-desu:20181125123230p:plain

これを利用して、Slackにpostする関数を作りました。

function sendSlack(message) {
  var postData = {
    "text": message
  };
  var payload = JSON.stringify(postData);
  var options = {
    "method": "post",
    "contentType": "application/json",
    "payload": payload
  };

  UrlFetchApp.fetch(endPoint, options);
}

ちなみにWebhookのエンドポイントはコードの中に直接書きたくないので、ユーザープロパティを利用して呼び出しています。GitHubのコードをそのまま使う場合はユーザープロパティTUBE_NOTIFIER_ENDPOINTに先程生成したURLを入れておいてください。

Slackからチャンネルの投稿を取得する処理

今回のAppはおすすめ動画を選定する基準として、チャンネルで直近postされたYouTube動画のURLをもとに、その関連動画を検索してpostします。これにより、関連する動画を延々と見ていったり、関連動画が気に入らなかったら手動で別の動画のURLをpostすることでおすすめする動画の方向を修正したりできるという算段です。

ただ、これを実現するためにはSlackからチャンネルの投稿を取得するAPIを利用する必要があります。これは現在Botアカウントからは利用できないようで、Bot User tokenではなくUser tokenが必要です。
Legacy tokens | Slackからトークンを生成し、これを利用します。

先ほどと同様にユーザープロパティのTUBE_NOTIFIER_TOKENトークンを格納し、getLastVideoId関数を作成しました。

function getLastVideoId() {
  var url = "https://slack.com/api/channels.history?token=" + token + "&channel=" + channel;
  var result = JSON.parse(UrlFetchApp.fetch(url));
  for (var i = 0; i < result.messages.length; i++) {
    var item = result.messages[i];
    var match = item.text.match(/^<https:\/\/www\.youtube\.com\/watch\?v=(.*)>$/);
    if (match) {
      return match[1];
    }
  }
}

あとは[編集]メニューから定期的に発火するトリガーをセットすれば、今回の目的となる定期的にYouTube動画をpostするSlack Appの完成です。

Slash CommandsとGASのエンドポイント取得

しばらくこいつを稼働させていましたが、定期実行は意外と歯がゆい場面が多いです。短めに設定するとSlackを見ていないときにpostが溜まっていてげんなりしますし、かと言って長めに設定するといざ聞きたいときにまったくおすすめしてくれません。

考えた末、Slash Commandを設定して任意のタイミングでもおすすめしてくれるようにしよう、ということになりました。

Slash Command用エンドポイント作成

Slash Commandを設定する際は、コマンド実行時にエンドポイントを設定します。SlackからSlash Commandが呼び出されると、設定したエンドポイントにPOSTリクエストが送られるようになります。

GASの関数を外部から実行可能なAPIとして公開するためには、[公開]メニューから、[実行可能APIとして導入]および[ウェブアプリケーションとして導入]をしてやる必要があります。

エンドポイントにPOSTリクエストを送信した場合、doPost()という関数がはじめに呼ばれるので、適切な関数の名称を変更して公開しましょう。

f:id:tsyama-desu:20181125133803p:plain

あとはSlash Command設定画面でAPIを呼び出してやれば完成です。簡単ですね。

おわりに

こんなことしなくても別タブでYouTube開いておけばいい気がしてきました。