QiitaいいねランキングをSlackに投稿

Qiitaのアカウントがあると、定期的にいいねランキングがメールで来ますよね。
あれをSlackに投稿出来たらいいなと思って、チャレンジしてみました。

どうやって投稿する? #

最初にいいねランキングを取得するところですが、QiitaのAPIを使えばできるのかなと思い見てみたところ、単純にQiitaのAPIだけでは難しそうでした。いろいろ工夫すればできるのかなとか考えていたなか、自作でAPIを作られている方の記事を見つけました。

Qiitaいいね数ランキングAPIの作成

QiitaAPIをスクレイピングしてランキングデータを構築しているそうです。
仕組みに関しても記事に記述がありますが、今の自分にはちょっと難しく感じました…。すごい。

こちらの方のAPIを利用させていただくとして、投稿までの手順は
1.APIでQiitaいいねランキングデータを取得する

2.取得したデータを使って、Slackに投稿する文言を組み立てる

3.Webhookを利用して、Slackに投稿する

という流れにしました。

なお、今回はGASを使用します。

準備 #

Webhook #

まずは、Slackに投稿するためのWebhookの設定をしていきます。
下記のApp管理から設定画面へ。
SlackでApp管理に行くまで

Webhookが追加されていない場合
ヘッダの検索からwebhookで検索して、Incoming Webhookを選択。

すでにWebhookが追加されている場合
ヘッダの管理からカスタムインテグレーションを選択して、Incoming Webhookを選択。

設定の追加を選択して、投稿するチャンネルを決めて、Incoming Webhookインテグレーションの追加を選択。
ここでは、投稿時のアイコンや名称などが設定できます。WebhookURLはGAS側で使用するので控えておきましょう。

GAS #

Googleドライブ上でGASプロジェクトを作成して、手順通りにスクリプトを書いていきます。

※2020/2/16 追記
v8ランタイムが使えるようになったので、それに伴いリファクタリングを行いました。

ランタイムの変更は、GASエディタを開いたときに表示される案内(Enable new Apps Script runtime powered by Chrome V8 for this project.)から変更するか、実行→Chrome V8を搭載した新しいApps Scriptランタイムを有効にする からできます。

主な変更点

  • varで定義していた変数を、その後値を変更するかどうかでletかconstに変更
  • ログの出力方法の変更(stackにファイル名や行数などが含まれるので、stackのみにしました)
  • HTTPリクエスト時に使用するリクエストURLは、スクリプトプロパティで設定して使用するよう変更
    (ファイル→プロジェクトのプロパティ→スクリプトのプロパティ から設定できますが、オーナー権限のアカウントでないと編集できません)
  • ダブルクォートをシングルクォートに変更
  • getYear()は非推奨のため、getFullYear()に変更
function noticeQiitaRanking() {
  let msg;
  try {
    let response = getQiitaRanking();
    if (response == '') {
      msg = '※最新のQiitaいいねランキングが登録されていません。\n違う取得日を指定してください。';
    } else {
      // Slack投稿内容の組み立て
      msg = '*■週間いいねランキング■* \n\n';
      // JSONをオブジェクトに変換
      response = JSON.parse(response);
      const dataList = response['data'];
      let count = 1;
      dataList.forEach(data => {
        // <url|文字列> の形式で文字列でのリンクを作成
        msg += count + '位:<' + data['url'] + '|' + data['title'] + '> \n';
        count++;
      })
    }
  } catch (e) {
    Logger.log('Qiitaいいねランキング取得エラー:' + '\nstack:\n' + e.stack);
  }

  try {
    //Slack側 Incoming WebHookのURL
    const WEBHOOK_URL = PropertiesService.getScriptProperties().getProperty('WEBHOOK_URL');
    //Incoming WebHookに渡すパラメータ
    const jsonData =
        {
          'text': msg
        };
    //パラメータをJSONに変換
    const payload = JSON.stringify(jsonData);
    //送信オプション
    const options =
        {
          'method': 'post',
          'contentType': 'application/json',
          'payload': payload
        };
    //指定URL、オプションでリクエスト
    UrlFetchApp.fetch(WEBHOOK_URL, options);
  } catch (e) {
    Logger.log('Slack送信エラー:' + e.message + '\nstack:\n' + e.stack);
  }
}

function getQiitaRanking() {
  const type = 'weekly';
  const date = new Date();
  // リクエスト時に今日を指定するとなぜかデータが取得できないので、前日を指定する
  const yesterday = new Date(date.getFullYear(), date.getMonth(), date.getDate() - 1);
  const formatYesterday = Utilities.formatDate(yesterday, 'JST', 'yyyy-MM-dd');
  const QIITA_SCRAIPING_URL = PropertiesService.getScriptProperties().getProperty('QIITA_SCRAIPING_URL') + type + '/' + formatYesterday;
  return UrlFetchApp.fetch(QIITA_SCRAIPING_URL);
}

QiitaいいねランキングAPIを使用する際に、実行日当日の日付を指定すると、なぜかデータが取得できなかったため前日を指定するようにしています。

投稿 #

上記GASスクリプトを実行することで、以下のような投稿になります。
ちゃんと、タイトルが記事リンクとして作成されています。
Slackにランキング投稿結果

GASは定期実行するようにトリガーの設定ができるので、週に一回投稿するなどもできますよー。


実は最初はGASではなく、Serverless Framework + Python + Lambdaで作成しました。
(Dockerで実行環境も作りました)
ただ、こちらの場合、事前に準備が多いのでGASの方が手軽に作成できていいですね。
需要があれば、会社でも使ってもらおうかと思いますー。

参考リンクまとめ #