1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-02-14

: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リクエスト制限だったはず

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?