Qiita
JavaScript
GoogleAppsScript
gas
Slack

社内メンバーの Qiita 新着投稿を Slack で共有するスクリプトを GAS で作った話

はじめに

社内メンバーの Qiita 新着投稿を Slack で共有するスクリプトを Google Apps Script を使って作った話です。

所属している会社のメンバーが投稿したのを皆で応援するために作ったものです。別途 GAS で Qiita Organizations ランキング も作ってます。

中身のコードは github に上げてますので自由にご利用ください > tanabee/qiita-organization-news

おおまかな流れ

  1. 特定 Organization のアクティビティページから最新の 20 件を抽出
  2. 前回の処理で取得した投稿を除外する
  3. 投稿メッセージを生成
  4. Slack に投稿

スクリーンショット 2018-04-09 8.36.04.png
アクティビティページから最新投稿を抽出して

スクリーンショット 2018-04-09 8.34.55.png
Slack に投稿!

1. 特定 Organization のアクティビティページから最新の 20 件を抽出

https://qiita.com/organizations/[organization-name]/activities の URL から最新投稿にアクセスできる。アクティビティページの HTML をフェッチして、力技で HTML をパースし、記事の URL, タイトル, ユーザー名を抽出。

find メソッドはこちらの記事で紹介してます > GAS ビギナーが GAS を使いこなすために知るべきこと 10 選

// Qiita Organization ページから組織の最新の投稿 20 件を取得
function fetchPosts() {
  var url  = 'https://qiita.com/organizations/' + config.organization + '/activities',
      html = UrlFetchApp.fetch(url).getContentText(),
      htmlFiltered = find(html, '<div class="tableList">', '<ul class="pagination">'),
      posts = htmlFiltered
        .split('</article>')
        .filter(function (article) {
          return find(article, '<div class="ItemLink__info"><a href="/', '">') !== '';
        })
        .map(function (article) {
          var elem = find(article, '<div class="ItemLink__title"><a class="u-link-no-underline" href="', '</a>');
          var elems = elem.split('">');
          return {
            user  : find(article, '<div class="ItemLink__info"><a href="/', '">'),
            url   : elems[0],
            title : elems[1]
          };
        });

  return posts;
}

コメントいただいて Organization RSS があることを知ったので、そちらをパースするのがきれいですね。更新したらこちらの記事にも反映しておきます。

2. 前回の処理で取得した投稿を除外する

PropertiesService を使って、前回実行時に保存した最新投稿以降の投稿一覧を抽出。詳しくは GAS ビギナーが GAS を使いこなすために知るべきこと 10 選 に記載。

// 前回のスクリプト実行以降の投稿のみフィルタ
function filterNewPosts(posts) {
  var key = 'LATEST_POST_PATH';
  var properties = PropertiesService.getScriptProperties();

  var value = properties.getProperty(key);
  properties.setProperty(key, posts[0].url);
  if (!value) return posts;

  var index = posts.map(function (post) { return post.url; }).indexOf(value);
  if (index === 0) return [];

  var sliceNumber = index === -1 ? posts.length-1 : index;
  return posts.slice(0, sliceNumber);
}

3. 投稿メッセージを生成

フィルタした投稿一覧の配列を弄ってメッセージを生成する。

// Slack に投稿するメッセージ生成
function makeMessage(posts) {
  return '皆で応援しましょう :tada: \n' + posts.map(function (post) {
    return post.user + ' さんが 「' + post.title+ '」 を投稿しました!\nhttps://qiita.com' + post.url;
  }).join('\n');
}

4. Slack に投稿

UrlFetchApp.fetch メソッドで Slack の Webhook URL に POST!

// Slack に POST
function postSlack(message) {
  var body = { text: message };
  var payload = JSON.stringify(body);
  var res = UrlFetchApp.fetch(config.webHookUrl, {
    method: 'POST',
    headers: {
      "Content-Type": 'application/json'
    },
    payload: payload
  });
}

まとめ

以上、トータルのコードが 100 行程度で、サクッと作ることが出来ました。また GAS ネタができたら投稿します。

他の GAS ネタ