ChatWorkMentionTaskを作った

sue445

2018/03/25 Rails Developers Meetup 2018: Day 2

https://github.com/sue445/rails-developers-meetup-2018

自己紹介 sue445

  • @sue445
  • 最近はTerraformと戦う日々
  • 去年は尿管結石が3〜4回できたり、持病が悪化して入院したり、親が死んで喪主やったりと色々と大変だったので今年は平穏に生きたい

今回話すこと

  • 趣味アプリと副産物の宣伝

ChatWorkMentionTaskとは

chatwork_unread_mentions

動作風景

  • 自分宛にきたメンションが自動的に別部屋にタスク化され、一覧表示される
  • 重要なものや後で対応必要なものだけ残して、それ以外のタスクを完了にする運用

about

所感

  • 1ヶ月くらい人柱運用してるけど日々の仕事がむっちゃ捗ってる!!!
  • ぶっちゃげChatWork本体に欲しい機能なんだが、3年前から要望は出ている がいまだに実装されていないので諦めて自分で作った

技術的なこと

仕組み

overview

頑張ったこと

ChatWorkのAPIのリフレッシュトークンの有効期限は2週間なので、リフレッシュトークンが切れる3日前にリマインド用にタスクを作るようにした

chatwork_mention_task_reminder

webhookの params[:body] にチャット本文が入っていて、それがログに出るのが嫌だったのでパスワード同様フィルタリングするようにした。

chatwork_mention_task_log

commit_ec3e2583044e2c132ef1de9ef0c656f1e74dcac1

https://github.com/sue445/chatwork_mention_task/commit/ec3e2583044e2c132ef1de9ef0c656f1e74dcac1

Deploy to Herokuボタンに対応してるので、HerokuのアカウントとChatWorkのOAuth Clientさえあればワンクリックでデプロイできる

chatwork_mention_task_heroku_deploy

  • エンジニア以外にも使ってもらいたかったので真面目にi18n対応頑張った。(日本語と英語のみ)
    • 自分が英語が苦手なので、最初に英語でシンプルに書いておいてからそれを日本語訳するのが楽だった

副産物の紹介

  • omniauth-chatwork :gem:
  • chatwork :gem:
  • chatwork_webhook_verify :gem:
  • dockerfile-heroku-cli :whale:
  • dockerhub-slack-webhook :whale:

omniauth-chatwork :gem:

https://github.com/sue445/omniauth-chatwork

実際の設定

Railsだとこんな風に書いておくだけでいい感じにChatWorkのOAuth認証が使えるようになる

# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :chatwork, ENV["CHATWORK_CLIENT_ID"], ENV["CHATWORK_CLIENT_SECRET"], scope: ["users.profile.me:read", "rooms.tasks:write", "rooms.info:read"]
end

https://github.com/sue445/chatwork_mention_task/blob/10dd0c197060fbc62016fe33b60a2089dfb74261/config/initializers/omniauth.rb

chatwork :gem:

https://github.com/asonas/chatwork-ruby

やったこと

chatwork-ruby_contributors

頑張ったこと

実際のテストコード
  • stub_chatwork_requestit_behaves_like :a_chatwork_api でramlを利用
  • APIクライアントではテストデータの生成が面倒なのでそこを公式が提供しているデータを使って自動化できて便利
describe ".create", type: :api do
  subject { ChatWork::Message.create(room_id: room_id, body: body, &block) }

  let(:room_id) { 123 }
  let(:body)    { "Hello ChatWork!" }

  before do
    stub_chatwork_request(:post, "/rooms/#{room_id}/messages", "/rooms/{room_id}/messages")
  end

  it_behaves_like :a_chatwork_api, :post, "/rooms/{room_id}/messages"
end

https://github.com/asonas/chatwork-ruby/blob/v0.8.0/spec/lib/chatwork/message_spec.rb#L24-L35

chatwork_webhook_verify :gem:

# app/controllers/webhook_controller.rb
class WebhookController < ApplicationController
  before_action :verify_chatwork_webhook_signature!
end

リクエストごとにtokenを変えて検証する必要がある場合はこんな感じ

class WebhookController < ApplicationController
  before_action :set_user
  before_action :verify_signature!

  private

    def verify_signature!
      return unless Global.app.verify_signature?

      verify_chatwork_webhook_signature!(@user.webhook_token)
    end
end

https://github.com/sue445/chatwork_mention_task/blob/10dd0c197060fbc62016fe33b60a2089dfb74261/app/controllers/webhook_controller.rb

dockerfile-heroku-cli :whale:

  • https://github.com/sue445/dockerfile-heroku-cli
  • https://hub.docker.com/r/sue445/heroku-cli/
  • CircleCIからherokuにデプロイする時に毎回 heroku/cli をダウンロードしたくなかったのでインストール済のイメージを作った
  • alpineに必要最低限のパッケージやバイナリしか入れてないので47MBしかない超軽量イメージ
    • Docker Hubを検索してると似たようなイメージを作ってる人はたくさんいるけど、自分が見た範囲では sue445/heroku-cli が最軽量

頑張ったこと

常に最新のheroku/cliをDockerイメージで使いたかったので、heroku/cliの更新を自動検知してDockerイメージを自動ビルドする仕組を作った

  1. CircleCIのスケジューラが1日1回起動
  2. heroku cliのバージョンが上がっていればCircleCIがファイルをコミットしてGitHubにpush
  3. GitHubにpushされればDocker Hubの automated builds でビルドがされる

https://github.com/sue445/dockerfile-heroku-cli/blob/36e2441df5664baeb3ed97bd02386490d38355df/.circleci/config.yml#L72-L79

dockerhub-slack-webhook :whale:

  • https://github.com/sue445/dockerhub-slack-webhook
  • Docker Hubでビルドした後にSlackに通知するためのSinatra製のwebhook
  • ビルドしたイメージがいつビルド終わるか分からないので、Slackに手軽に通知できるようにしたかった

dockerhub-slack-webhook

頑張ったこと

Deploy to Herokuボタンに対応してるので、HerokuのアカウントとSlackのwebhookさえあればワンクリックでデプロイできる

dockerhub-slack-webhook_usage

まとめ

  • ChatWorkを使ってる場合はChatWorkMentionTaskは便利なので是非使ってください
  • RubyでChatWorkをハックする技術はだいたい制覇できた感あるw