4
1

More than 3 years have passed since last update.

【JavaScript】Qiita APIをGASで叩いてくるbotをSlackに導入してみた

Last updated at Posted at 2020-09-12

APIの学習がきっかけではあったのだけど、
せっかくだからSlackのbot導入についても合わせ技で一緒に学んでしまおうという目的で。
いつものように備忘録。今回は新米の自分には非常に学びが多かった気がします。

というわけで、今回の実装でやりたい事は
・Qiitaの記事一覧をくれるAPIを叩きにいきます
・Slackからコマンドでbotを呼び出し、欲しい記事のジャンルを選択
・記事一覧からランダムで1つのURLを返してくれる感じのを想定します

前提

・Qiitaアカウントを持っている(一応)
・Googleアカウントも持っている(なければ作って)
・導入したいSlackワークスペースの管理者権限がある

ざっくり手順

  1. Slackbotを作成
  2. Qiitaでアクセストークンを取得
  3. GASでslashコマンド受け取り用のwebアプリケーション1を作成
  4. GASで選択肢ボタン受け取り用のwebアプリケーション2を作成
  5. slackとアプリケーションを連携

こんな感じになりますが、各工程も躓いたところをピックアップし、他あっさり行きます。
詳しく知りたい方は参考にした記事を貼っておくので、そちらもご覧あれ。

1. まずはSlackbotを作成

導入したいワークスペースにログインした状態でslackapiにアクセスし、
Create New App からbotを作成します。

Permissions

以下の権限を設定します。
chat:write
chat:write.public

App Display Name

App Home から App Display Nameを設定します(適当で良いです)

Display Information

Basic Informationの下の方で設定出来ます。botの見た目はここで(重要)
スクリーンショット 2020-09-12 22.53.21.png

Verification Token

App Credentialsに書いてあります。
webアプリケーション作成の工程で使用するので控えておきましょう。

2. Qiitaでアクセストークンを取得

Qiitaにログインした状態で、
設定のアプリケーションから、個人用アクセストークンを発行します。
一度発行したトークンは確認出来なくなるので、これも控えておきましょ。

3. GASでslashコマンド受け取り用のwebアプリケーション1を作成

Googleドライブから新規でGASを開いたら、
まずはスラッシュコマンドの受けを作ります。

コード1.gs
function doPost(e) {
  const SLACK_TOKEN = 'トークン入れてね'; // Verification Tokenで取得したトークン

  // 指定したチャンネルからの命令しか受け付けない
  if (SLACK_TOKEN != e.parameter.token) {
    throw new Error(e.parameter.token);
  }

// 返答データ
  var data = {
    "text": "「いっちょAPIを叩いて、欲しい情報を持ってきますぜ」", //通常メッセージ
    "response_type":"ephemeral", 

    //アタッチメント部分
    "attachments": [{
      "title": "Qiitan君に指示して下さい",// アタッチメントタイトル
      "text": "Please select a task.",//アタッチメント内テキスト
      "fallback": "hogehoge",//ボタン表示に対応してないクライアント向けメッセージ. 
      "callback_id": "callback_button",//これ書かないと動かないよ
      "color": "#7fff00", //アタッチメントの棒の色を指定
      "attachment_type": "default",

      // ボタン部分
      // ちなみにボタンは最大5つまでしか設定出来ないよ
      "actions": [
        {
          "name": "books",
          "text": "技術書関連の記事を検索",
          "type": "button",
          "value": "books"
        },
        {
          "name": "Ruby",
          "text": "Ruby on Rails関連の記事を検索",
          "type": "button",
          "value": "Ruby"
        },
        {
          "name": "php",
          "text": "php laravel関連の記事を検索",
          "type": "button",
          "value": "php"
        },
        {
          "name": "infrastructure",
          "text": "インフラ関連の記事を検索",
          "type": "button",
          "value": "infrastructure"
        },
        ]
      }]
  };
  return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON);
}

ポイント

Verification Token を設定しましょ。
callback_id は忘れずに。
スクリーンショット 2020-09-12 23.26.47.png

<!DOCTYPE html><html><head><link rel="shortcut icon" href="//ssl.gstatic.com/docs/script/images/favicon.ico"><title>Error</title><style type="text/css">body {background-color: #fff; margin: 0; padding: 0;}.errorMessage {font-family: Arial,sans-serif; font-size: 12pt; font-weight: bold; line-height: 150%; padding-top: 25px;} (略

こんなの出たらちゃんとGASからslackに返ってきていないって事なのですが、デバッグが難しいですよね。自分の場合ですが、slackブラウザ版の検証モードを使いました。その時はcallback_idないよってエラーが出てたので、直ぐ解決出来ました。

公式ドキュメントのAttaching interactive message buttonsの部分にもcallback_idないとダメよと書いてありました。反省します。

※この時点ではまだ連携が完成してないからそもそもデバッグ出来ないけどね

Cuurent web app URL

webアプリケーション1のコードはこれで完成なので、デプロイします。
デプロイしたら、slackのSlash CommandsRequest URLにデプロイしたCuurent web app URLを貼り付けます。

ついでにコマンドも好きな物を設定しましょう。ここで設定したコマンドでwebアプリケーション1をリクエストする構図です。

4. GASで選択肢ボタン受け取り用のwebアプリケーション2を作成

次に選ばれた選択肢を元にQiita APIを叩いて、記事のURLを返す部分を作ります。

コード2.gs
function doPost(e) {
  // ペイロード部分の取り出し
  var payload = JSON.parse(e["parameter"]["payload"]);
  var name = payload["actions"][0]["name"];
  var value = payload["actions"][0]["value"];

  const QIITA_TOKEN  = 'トークンを入れてね';

  //APIヘッダ
  var headers = {'Authorization' : 'Bearer ' + QIITA_TOKEN};
  var params = {'headers' : headers};

  switch (name) {
    case 'books':
      var api_endpoint = 'https://qiita.com/api/v2/items?page=*&per_page=*&query=技術書';
       break;
    case 'Ruby':
      var api_endpoint = 'https://qiita.com/api/v2/items?page=*&per_page=*&query=Ruby';
      break;
    case 'php':
      var api_endpoint = 'https://qiita.com/api/v2/items?page=*&per_page=*&query=php';
      break; 
    case 'infrastructure':
      var api_endpoint = 'https://qiita.com/api/v2/items?page=*&per_page=*&query=インフラ';
      break;
  }

  // APIを叩いてパースする
  var response = UrlFetchApp.fetch(api_endpoint, params);
  var json = JSON.parse(response.getContentText());

  //ランダムにするよー
  var a = Math.floor( Math.random() * 好きな数 );

  // 返答する文章を整形
  var url = json[a]['url'];
  var title = "タイトル:" + json[a]['title'];
  var text = title + "\n" + url;

  var quest_attachment = {
    "text": text,//アタッチメント内テキスト
    "fallback": "hogahoga",
    "callback_id": "callback_button",
    "color": "#7ABB33", 
    "attachment_type": "default",
  }

  var rep =  {
    "text": "「お待たせしました!」",
    "attachments": [
      quest_attachment
    ]
  };
  return ContentService.createTextOutput(JSON.stringify(rep)).setMimeType(ContentService.MimeType.JSON);
};

叩くAPIはGET /api/v2/itemsです。
対象としたいページ数、要素数等は別途設定して下さい。
検索オプションはQiita Supportを見て、query=以下にぶち込んでもらえればと思います。
URLエンコーダーも貼っておきます。

書けたらこちらもデプロイしましょう。

ポイント(というか失敗談)

最初はIncoming Webhooksで、slackへpostする方法で進めていたのですが、
その場合、何かreturnしないと怒られてしまうのと、空データを返した場合、選択肢を表示しているbotコメントがそのまま残り続けてしまう(上書きされない)ので、素直にreturnする事としました。

5. slackとアプリケーションを連携

slackapiに戻って、Add features and functionalityからInteractive Componentsに進み、Interactivityをオンにして、デプロイしたwebアプリケーション2のURLをRequest URLに貼り付けます。

ラストはInstall App to Workspaceからワークスペースへのbot導入を許可すれば完成です。チャンネルの指定も必要になると思います。

これでスラッシュコマンドを打つと
スクリーンショット 2020-09-13 0.59.52.png
botを呼び出せます。
スクリーンショット 2020-09-12 23.44.14.png
ジャンルを選択します。
スクリーンショット 2020-09-13 1.03.07.png
上手く表示出来ました。検索が手抜きとか少し冗長なところもありますが、調べながらでなんやかんや記事の作成含め1日がかりで御座いました。勉強になりました。

参考にした記事

[GAS]Slackのbotを作る方法を、お節介なほど丁寧に説明
GASでQiita APIを使ってView・いいね・ストック数の一覧を取得する
Slack API attachmentsチートシート
Slack Interactive Messageリファレンス

あとは全部公式ドキュメントで解決しました。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1