概要
チャットワーク(chatwork)とBacklogのマッシュアップ。チャットワークにて、特定フォーマットに従ったテキストを発信することで、チャットワークのwebhookを経由してサーバで発言内容を受信し、Backlog APIを用いて課題を作成する。課題作成後は、チャットワークAPIを用いて、元のチャットルームに作成した課題URLを通知する。
目次
前提
以下環境で動作確認済み
debian | 8.6 |
ruby | 2.2.2 |
backlog_kit | 0.16.0 |
以下の点にご注意ください
- Webhookの仕組みに関する説明は割愛
- サーバーサイドにはRubyの軽量フレームワークであるSinatraを用いているが、Sinatraに関する説明は割愛
- BacklogAPIを用いて課題の作成を行うが、BacklogAPIに関する説明は以下記事に委譲する
— [Ruby] BacklogをCUIで操作してみる - チャットワークAPIを用いて通知を行うが、チャットワークAPIに関する説明は以下記事に委譲する
— チャットワークAPIをRubyで利用する
課題作成フォーマット
本記事では、以下のようなフォーマットのテキストを、webhookで設定したルーム内で発言した際に、連動してBacklogの課題が生成されるようにする。
@@課題登録 (課題タイトル) (課題本文1行目) (課題本文2行目) (課題本文3行目)
一行目の@@のあとに、実行するコマンドを指定するイメージ。本記事では「課題登録」のみ実装。その後ろに課題のタイトルを、2行目以降に課題の本文を記述する。本課題の範囲では、タイトル/本文以外の各設定値を指定する手段は提供しない。
Webhookの登録
チャットワークのwebhookは、「アカウントイベント」と「ルームイベント」の何れかを適用できる。本記事では、ルームイベントとして、自身のマイチャットのルームIDを指定して登録する。
webhookの登録は、チャットワークにログイン後のAPI設定の画面で以下のように行える。
チャットワークのメッセージを受信する(Sinatra)
マイチャット内で発言すると、Webhook登録時に指定したWebhook URLに対して、メッセージ内容とそのメタデータがPOSTされる。今回はPOSTの受け口として、Rubyの軽量フレームワークであるSinatraを用いて実装する。Sinatraについては本記事の本筋ではないので割愛するが、雰囲気でコードの内容は把握できるようになっている。
Sinatraのコントローラにて、以下のようにPOST内容を受け取る。WebhookによるPOSTデータはJSONで届くので、parseして標準出力してみる。
post '/' do pp JSON.parse(request.body.read) end
概ねリアルタイムに、以下のような標準出力が得られる
{"webhook_setting_id"=>"127", "webhook_event_type"=>"message_created", "webhook_event_time"=>1512109688, "webhook_event"=> {"message_id"=>"988329000694410240", "room_id"=>59200706, "account_id"=>2011143, "body"=>"こんにちは!", "send_time"=>1512109688, "update_time"=>0}}
本記事ではこのデータを用いて課題の作成を行う。
フォーマットに合致しない場合拒否する
POSTされたデータから、チャットワークのルームID(通知時に使う)と、メッセージ本文を取り出す。メッセージ本文に、フォーマットの必須要件である「@@課題登録」が含まれていない場合returnする。
# メッセージ内容を確認 event = JSON.parse(request.body.read)['webhook_event'] room_id = event['room_id'].to_s msg = event['body'] return unless msg.index('@@課題登録') == 0
正確にはこのタイミングで、ヘッダーをチェックして、確かにwebhookからのPOSTであることを確認しないと、不正に課題を量産されてしまうので注意
メッセージから課題タイトルと課題本文を抜き出す
メッセージは1行目と2行目以降で分かれているので、最初に改行毎に分割する。1行目は、スペース刻みでコマンド内容と課題タイトルに分かれているので、後半の課題タイトルの部分を抜き出す。2行目以降は課題本文なので、またjoinする。
# メッセージ内容から課題の情報を抜き出す lines = msg.split("\n") header = lines[0] title = header.split[1] body = lines[1..-1].join("\n")
Backlogに課題を作成する
Backlogに課題を作成するために、BacklogAPIを用いる。本ブログではお馴染みのgemである、backlog_kitを用いるが、それを含めたBacklogAPIの使い方については以下記事に委譲する。
APIキーと、対象のBacklogスペースIDは事前に取得して環境変数に入れておく。
backlog = BacklogKit::Client.new( space_id: ENV['PRIVATE_BACKLOG_SPACE_ID'], api_key: ENV['PRIVATE_BACKLOG_API_KEY'] )
create_issueメソッドを用いて課題を作成する。課題タイトルと課題本文はwebhookより受け取ったメッセージに含まれてる内容を使用。
「優先度」と、「分類」は必須なので、とりあえずここでは優先度:中と、分類:タスク に該当する数値を入れておく。
result = backlog.create_issue(title, { :projectId => 38382, :priorityId => 1, :issueTypeId => 172585, :description => body, })
課題作成成功後のレスポンスに、生成した課題のURLが含まれているので、それを抑えておく。
issue_url = result.headers.location
登録した課題をチャットワークに通知する
最後に、前項で作成した課題のURLをチャットワークに通知する。チャットワークにメッセージを投稿するためにチャットワークAPIを用いるが、ここでは手前味噌だが以下のクラスを利用する。
chatwork-ruby/chatwork.rb at master · Sa2Knight/chatwork-ruby
上記クラスについての詳細は下記記事を参照。とりあえずsendMessageメソッドにルームIDとメッセージ本文を指定すればメッセージを送信できることがわかればよい。
チャットワークのinfoタグ、titleタグを組み合わせて、いい感じのメッセージを投げる。
# 結果をチャットワークに投稿する chatwork = Chatwork.new chatwork.sendMessage(room_id, "[info][title]課題を作成しました[/title]#{issue_url}[/info]")
ソースコード
ここまでのコントローラ部の全ソースコードは以下の通り
post '/' do # メッセージ内容を確認 event = JSON.parse(request.body.read)['webhook_event'] room_id = event['room_id'].to_s msg = event['body'] return unless msg.index('@@課題登録') == 0 # メッセージ内容から課題の情報を抜き出す lines = msg.split("\n") header = lines[0] title = header.split[1] body = lines[1..-1].join("\n") # Backlogに課題を作成する backlog = BacklogKit::Client.new( space_id: ENV['PRIVATE_BACKLOG_SPACE_ID'], api_key: ENV['PRIVATE_BACKLOG_API_KEY'] ) result = backlog.create_issue(title, { :projectId => 38382, :priorityId => 1, :issueTypeId => 172585, :description => body, }) issue_url = result.headers.location # 結果をチャットワークに投稿する chatwork = Chatwork.new chatwork.sendMessage(room_id, "[info][title]課題を作成しました[/title]#{issue_url}[/info]") end
デモ(再掲)
所感
本記事では非常にシンプルな構成にしたが、以下のように拡張していけば使いみちがあるかも?
- チャットワークのユーザとBacklogのユーザを関連付けて、チャットワークの発言者をBacklog課題の作成者にする
- 複数のチャットルームでWebhookを登録し、チャットルームとBacklogプロジェクトを関連付けて対応したプロジェクトに課題を作成する
- @@課題コメント/@@課題完了 などの課題を操作する各種コマンドを導入する