Photoruction工事中!

Photoructionの開発ブログです!

Zenn投稿の通知を自動化したが手動運用に戻した話【GAS×Slack】

はじめに

現在、Photoructionでは月2本を目標にZennブログを投稿しています。 この取り組みを社内にも広げるため、これまでは広報チームがブログ公開のたびにSlackチャンネルへ手作業で通知を投稿していました。

ただ、手動だと通知を忘れそうになることもあり、手間もかかるので、Bot自動通知にしたいと思ったのがはじまりです。

試行1 - SlackのRSS購読機能を利用

ZennにはRSS配信機能があり、記事の更新情報をフィードとして取得可能です。 また、SlackにもRSSフィードをチャンネルに連携する機能が用意されているとのこと。

この2つを組み合わせれば簡単にブログ更新の通知を自動化できるのではと考え、まずはこの方法を試してみました。

https://slack.com/intl/ja-jp/help/articles/218688467-Slack-%E3%81%AB-RSS-%E3%83%95%E3%82%A3%E3%83%BC%E3%83%89%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B

5分程度で設定ができ、届いたのは以下のような通知です。

手軽に実現できた点は良かったものの、実際の通知内容を見るとかなりイマイチです。

bot名もピンとこないし、絵文字もないので地味。slackのメンションもないので著者がぱっと見でわかりません。 情報収集のためだけなら簡単で用途としては向いてそうですが、この通知の目的はあくまでも社内にテックブログの取り組みを広げることなので不向きと判断しました。

試行2 - GAS × Incoming Webhooksで通知させる

調べてみましたが、SlackのRSS購読機能ではbotアイコン・本文をカスタムすることは不可能そうでした。そこで次に試したのが、GAS(Google Apps Script)Incoming Webhooksを組み合わせる方法です。

この方法であれば、以下のような柔軟なカスタマイズが可能になります。 - bot名・アイコンの変更 - メッセージフォーマットの調整 - メンションの付与 - 投稿内容の加工(タイトル・著者・サムネイルなど)

全体の流れはこちらです。 1. ZennのRSSフィードをGASで定期取得 3. 前回取得した記事との差分をチェック 4. 新着記事があればSlackにWebhookで通知

コードは以下のように書きました。

function notifyLatestZennInfo() {
  const props = PropertiesService.getScriptProperties();
  const slackWebhookURL = props.getProperty('SLACK_WEBHOOK_URL');
  const lastLink = props.getProperty('lastLink');
  const rssURL = props.getProperty('RSS_URL');
  const userMap = JSON.parse(props.getProperty('USER_MAP'));

  // RSSフィードをフェッチして取得
  const xml = UrlFetchApp.fetch(rssURL).getContentText();
  const doc = XmlService.parse(xml);
  const items = doc.getRootElement()
    .getChild('channel')
    .getChildren('item');

  // 最新記事のタイトル・URL・著者名などを取得する
  const latest = items[0];
  const title = latest.getChildText('title');
  const link = latest.getChildText('link');
  const dc = XmlService.getNamespace(
  'dc',
  'http://purl.org/dc/elements/1.1/'
);
const creator = latest.getChildText('creator', dc);
const description = latest.getChildText('description');
const formattedDescription = description
  .replace(/\n{2,}/g, '\n')   
  .replace(/https?:\/\/\S+/g, '') 
  .slice(0, 200) + '...';

// 通知済みの記事であればリターン
if (lastLink === link) return

// Slack通知用のメッセージ
const message = {
  blocks: [
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `*🎊新しいZenn記事が投稿されました!🎊*`
      }
    },
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `\n今回は、<@${userMap[creator.trim()]}> さんによる記事です!`
      }
    },
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `📌 *${title}*`
      }
    },
    {
      type: "divider"
    },
    {
      type: "section",
      text: {
        type: "mrkdwn",
        text: `${formattedDescription}`
      }
    },
    {
      type: "divider"
    },
    {
      type: "actions",
      elements: [
        {
          type: "button",
          text: {
            type: "plain_text",
            text: "記事を読む 📖"
          },
          url: link
        }
      ]
    }
  ]
};


// Slackに通知を投げる
UrlFetchApp.fetch(slackWebhookURL, {
  method: 'post',
  contentType: 'application/json',
  payload: JSON.stringify(message),
});

// 通知した記事は定数lastLinkにセット
props.setProperty('lastLink', link);
};

できれば手動時のように内容の要約も行いたかったのですが、まずは自動化を実現したかったので今回は省きました。

とりあえず、このコードを毎日11:00に実行するように設定をすることで、自動化は実現できました。

また、GASにはスクリプトプロパティというものが用意されていて、簡単なデータをキー・バリュー形式で永続的に保存することができます。

イメージとしては、サーバーサイドでよく使われる環境変数のようなものです。 今回の実装では、このスクリプトプロパティを環境変数的に扱い以下の情報を管理しています。

  • SlackのWebhook URL
  • ZennのRSSフィードURL
  • 前回通知した記事のリンク
  • 著者名とSlackユーザーIDのマッピング

https://note.com/crefil/n/n2b68b3c4aa6b

トリガーもスクリプトプロパティも、web上でポチポチ簡単に登録・設定できました。

で、実際に流れてきた通知がこちら。

そして、手動に戻る

カスタマイズの結果、質素な通知には絵文字がつき、著者メンションが飛び、bot名も分かりやすくなり、手動投稿の手間も減りました。 ...

が、リアクションが目に見えて減少しました

手動投稿時。たくさんのリアクション...

自動投稿時。リアクションはたった一つ...

botにしてしまうと、一気にただの情報感がでて意識に入ってこなくなるんでしょうか。

もしこれがbotではなく、実在するメンバーのアカウントから投稿されていたらここまでリアクションが減ることはなかったのではないのかと思います。

「誰が投稿しているか」が見えるだけで、受け取る側の感じ方や反応のしやすさは思った以上に変わるのだと今回学びました...

調べてみましたが現状Slackでは特定のユーザーに代替して投稿するような機能は用意されていませんでした。botしか選択肢はなさそうです。 残念ですが自動化は一旦見送り、手動での通知に戻すことにしました。

さいごに

今回は手動に戻すことにしましたが、自動化しつつうまく反応も得られている事例があれば気になります。 同じようなことを試している方がいれば、ぜひ教えてください!

手動に戻したらリアクション復活。めでたし!