CHANGE エンジニア BLOG

株式会社チェンジ エンジニア ユニットによる情報発信BLOG

Hubotで社内情報を一瞬ストック!

前説

社内Wikiを使用している会社は多いかと思います!
チェンジでもAtlassian社のConfluenceというサービスを社内Wikiとして使用し、社内の情報を共有をしています!
情報共有の種類はさまざまで

  1. プロジェクト詳細のまとめ
  2. 定例のまとめ
  3. 色々なサービスのまとめ
  4. 新しく出た技術のまとめ
  5. セミナーのまとめ
  6. URL先情報のまとめ

などなどあります!

そして今回、業務効率改善を含めて
6つ目のURL先情報のまとめをWikiに一瞬ストック!というものを今回開発しました。

社内Wikiでリンク先共有の煩わしさ

社内Wikiを開く時間

社内Wikiを記載する上で一番の煩わしさは

  • 社内Wikiを開いて、タイトルと本文を記載する!

だと思います。
よくUXを考える際に、ユーザーになるべく待つ時間を与えないことが大事と言われています!しかし現状はいちいち社内Wikiを開かなくてはいけなかった。
これはナンセンスだと思います!

URL先の情報をまたWikiに記載する

これはまったくもってかっこ悪いです。URLに記載している内容を理解し、それを掻い摘んで記載する、そしてタイトルはコピペ!ってめっちゃかっこ悪いと思いませんか?これは前に投稿したこの技術を使えばめっちゃ便利になると思いませんか?
blog.chgjp.net

開発内容

開発ツール

  • daab
  • Confluence API

開発言語

  • CoffeeScript
  • Node.js

仕様

  • コマンド[jfyi](Just for your information)の後に共有したいURLを記載したら、自動的にConfluenceに投稿

開発の流れ

  1. URLのmeta情報を引っ張ってくる
    1. タイトル
    2. 説明
    3. 画像
  2. Confluenceのタイトルに日付とURLのタイトルを渡す
  3. Confluenceの本文にURLの説明と誰がシェアしたか載せる
  4. 情報をConfluenceAPIを使用してConfluenceに渡す

まずはこれぐらいを実装しようと考えました!

実装

  • URLのmeta情報を引っ張ってくる
titleExist = $("meta[property='og:title']").attr("content")
extensionExist = $("meta[property='og:image']").attr("content")
keywordsExist = $("meta[name='keywords']").attr("content")

thumbnailCheck = ->
  if extensionExist
    if (extensionExist.match(/ℑ/))
      extensionExist_re = extensionExist.replace(/ℑ/g, "&image_")
      return extensionExist_re
    return extensionExist
  else
    return

titleCheck = ->
   if titleExist
     return titleExist
     else if $("title")
       return $("title").text()
     else
       return "題名"

descriptionCheck = ->
  if $("meta[name=description]").attr("content")
     return $("meta[name=description]").attr("content")
  else
    return

thumbnail = thumbnailCheck()
title = titleCheck()
description = descriptionCheck()

これでmeta情報のサムネイル画像、タイトルと説明書きが取得出来ました。
次に

  • 投稿日の取得
formatDate = () ->
  date = new Date()
  yyyy = date.getFullYear()
  mm = ("0"+(date.getMonth()+1)).slice(-2);
  dd = ("0"+date.getDate()).slice(-2);
  return yyyy+mm+dd
  • Confluecenのどこに投稿するか指定
robot.hear /^(Hubot )?jfyi (.*)/i, (res) ->
  space = {'key' : ''} //Spaceを指定
  postedName = "#{res.envelope.user.name}"
  textValue = "#{res.match[0]}"
  pickupUrl = /(http(?:s)?:\/\/[\x21-\x3B=\x3F-\x7E]+)/ .exec(textValue)
  pickupUrl_enc = pickupUrl[0].replace(/(http(?:s)?:\/\/[\x21-\x3B=\x3F-\x7E]+)/g,"<a href='$1'>$1</a>")
  • Confluenceに投稿
postConfluence = (title, description, keywords, commentText) ->
  data = JSON.stringify({
    'type':type,
    'title':formatDate() + "_" + title,
    'ancestors':keywords,
    'space':space,
    'body':{
      'storage':{
        'value':description + "<br /><br />" + pickupUrl_enc + "
written by " + postedName
        'representation':representation
      }
    }
  })
  robot.http("http://?os_authType=basic") //URLの指定
    .auth(user_name, user_password)
    .header('Content-Type', 'application/json')
    .header('Accept', 'application/json')
    .post(data) (err, response, body) ->
      if err
        res.send "エラーが発生しました。 #{err}"
        return
      else
        body_enc1 = JSON.parse(body)
        res.send "Confluenceに登録しました"+"http://?pageId="+body_enc1.id //URLの指定
        return

ここでは最後にボットから自動でConfluenceに投稿出来たことを表示出来るようにして、かつどこのページに投稿できたか知らせるようにしました!

実行結果

f:id:Taku_Nakagawa:20170821104500p:plain
f:id:Taku_Nakagawa:20170821104527p:plain
f:id:Taku_Nakagawa:20170821111922p:plain
Confluenceに自動で登録
f:id:Taku_Nakagawa:20170821104628p:plain

社内の反応

前回の記事まではURLから情報を抜き出していて、それをボット上で吐かせるというところまででしたが、今回のこのサービスはそれにプラスしてWikiにストックというところまで一瞬でやってくれるので、当たり前ですが評判がいいです!みなさん、使ってくれている気がします!

所感

JSの得意分野であるDOM解析と各ウェブサービスのAPIと、ボットを使用することでユーザが余分な手順を踏むことなく社内の情報共有することが出来るようになり、これを応用していくことでますます作業効率が上がるのではないのかと思っております。