Qiita organizationページの更新をSlackで通知させる【bot作成編】


やりたいこと

Qiita organizationページの更新をSlackで通知させる」で紹介した通り、SlackのRSSアプリがイケていなかったので、Qiita organazationからSlackへ投稿したい情報をパース / 投稿するbotを作る。

仕様

bot仕様を掻い摘んで説明します。

  • RSSフィールド取得先URLは以下の通りとする
    http://qiita.com/organizations/<organization名>/activities.atom
    • 前回の投稿通り、organazationページからatomを取得します
  • 1時間毎にatomをパースし、メッセージを投稿する
    • atomの確認頻度は1時間毎とします
    • 1時間の内、複数の投稿があった場合は記事毎にメッセージを投稿するようにします
    • よって、直近1時間の投稿をお知らせする形になります

実装

Slack botでメッセージを投稿する方法はいくらでも情報があるので、atomのパースに焦点を当てて紹介していきます。

import feedparser
from datetime import datetime as dt
import datetime
import logging

def get_atom():
    msg_arr = [] // botで投稿する文章は配列に格納し、1行ずつSlackへ投稿します
    d_atom = feedparser.parse('http://qiita.com/organizations/<organization名>/activities.atom')

    if len(d_atom['entries']) == 0:
        msg_arr.append("ERROR:atom is invalid")
        logging.error('atom is invalid')
        return msg_arr

    // 1時間前と現在の時刻をdatetimeで取得します
    from_time = dt.now() - datetime.timedelta(hours=1)
    to_time = dt.now()

    // ここからatomを1行ずつ確認していきます
    i = 0
    while i < len(d_atom):
        tdatetime = dt.strptime(d_atom['entries'][i]['published'], '%Y-%m-%dT%H:%M:%SZ')
        // 投稿された時間が1時間以内でない場合、以降の行も同様になるので、ループから抜けます
        if not from_time <= tdatetime <= to_time:
            break

        // テキストに挿入する情報を取得します
        author = d_atom['entries'][i]['author']
        published = d_atom['entries'][i]['published']
        link = d_atom['entries'][i]['link']
        title = d_atom['entries'][i]['title']

        // formatを使うのをサボったのですが、formatを使用した方が良いですね…
        msg = tdatetime.strftime("%Y-%m-%d %H:%M") + "に" + author + "さんの記事が投稿されました。\r\nタイトル:<" + link + "|" + title + ">"
        msg_arr.append(msg)
        i += 1

    return msg_arr

課題点

実際に動作確認をしてみたところ、アドベンドカレンダーの公開を検知できないという課題が見つかったので、今後対処してきたいです。

アドベンドカレンダーは7:00に公開されますが、どうやらatomのpublishedは限定公開した時間になってしまうようです。(で、合っていると思う…)
改良案として、更新時間を変数に格納しておき、1時間おきに差分があった場合は更新を通知する、という方法を考えています。