ストックしたQiita記事をSlackへランダムに通知するHubotスクリプト

:warning:建てっぱなしのHubot環境を使っているので環境が非常に古いです。

問題点

ストックを整理しようとしたら800件近くあり、手をつける気分にもなれなかった。→ストックの機能不全。

これはよくある
「目の前の問題が多すぎてどこから手を付ければいいかわからない」1
状態だと思ったので、ひとまず一日ひとつ、ストックを確認していく日課を作ろうと思った。

スクリーンショット

image.png

動作環境

  • Heroku
  • Node.js v0.12(Promiseが動かなかったのでv0.10から上げた)
  • hubot 2.11.1
    • coffee-script 1.6.3
    • hubot-slack 3.3.0

コード

qiita-stock.coffee
# Description:
# Qiitaのストックをランダムに表示する
#
# Commands:
# 

QIITA_TOKEN = 'your token' # memo herokuの環境変数でもいい
USER_ID = 'khsk'

cron   = require('cron').CronJob
random = require('hubot').Response::random

qiita = (msg, stock) ->
    tags = Object.keys(stock.tags).map((v) ->
        stock.tags[v].name
    ).join(', ')
    # memo bodyから https?://.+\.(jpeg|jpg|png|gif)などを抜き出してimage_urlまたはthumb_urlとして使う (要る?)
    {
        username:'Qiita-Stock',
        icon_emoji:':books:',
        text:'Qiita記事を紹介します',
        message:msg,
        attachments:[
            {
                color: "#55c500",
                author_icon: stock.user.profile_image_url,
                author_name: stock.user.name,
                author_link: 'https://qiita.com/' + stock.user.id,
                title: stock.title,
                title_link: stock.url,
                text: stock.body.slice(0, 117),
                footer: tags,
                ts: new Date(stock.updated_at) / 1000,
            }
        ]
    }

getAllStock = (robot) ->
    page = 1
    done = stockLoop(robot, page)
    done.then (stocks) ->
        console.log(stocks.length)
        console.log('完了')
        stock = random(stocks)
        robot.adapter.customMessage qiita({room: 'random'}, stock)

# ストック取得が0件になるまでループし、取得結果を結合していく
stockLoop = (robot ,page, stocks = []) ->
    return getStock(robot, page)
    .then (result) ->
        if (result && result.length != 0)
            stocks = stocks.concat(result)
            page += 1
            stockLoop(robot, page, stocks)
        else
            return stocks
    .catch (result) ->
        console.log(result)
        return stocks

# 100件ストックを取得する
getStock = (robot, page) ->
    new Promise (resolve, reject) ->
        robot.http('https://qiita.com/api/v2/users/' + USER_ID + '/stocks?per_page=100&page=' + page)
        .header('Authorization', 'Bearer ' + QIITA_TOKEN)
        .get() (err, res, body) ->
            resolve JSON.parse body

module.exports = (robot) ->
    new cron('0 0 10 * * 1-5'
        , () ->
            getAllStock robot
        , null
        , true
    )

    # デバッグ用
    robot.respond /qs/i, (msg) ->
        msg.send 'ストックを表示します。しばらくお待ちください。'
        getAllStock robot

久々のHubot,久々のCoffeeScript,コールバックにプロミスにループ(再帰)に。
難しいですね…。
やっぱりasync/awaitは最高!

バージョン上げや生jsで書く手間を省いた代わりにCoffScript構文学習と難コーディング、読みにくいコードになったのはあまりペイできていない。

concatがrubyと違い非破壊なことでかなり躓いた。

ブラウザで見るとストックページ数が膨大に見えるが、
実際は1ページ20件なので、一度に100件とるスクリプトではページ数が5分の一まで減る。
ブラウザでは20件で40ページ2あったので勢いトークンを使っているが、実際は8ページしか取得しないのでトークン無しでも十分動く。

参考





  1. レガシーコード改善ガイドで見た記憶 

  2. トークンなしでは一時間に60リクエスト制限だったはず 

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.