LoginSignup
12
9

More than 5 years have passed since last update.

hubotを使ってRocket.ChatにIRCの内容を転送する

Posted at

やったこと

slack を社内でも使いたいけどセキュリティなどの都合で使えないので、slack クローンの Rocket.Chat を最近導入しました。

irc をメインで使っていた(使っている)ので、現状でも irc 側に発言するメンバーとかがいたりします。発言が散らばるし、その時ネットワークに繋がってたら見落とすし…ってことで、irc の内容を Rocket.Chat に転送できるようにしました。

本題に入る前に…前置き

Qiita初投稿です。これまで読む専でしたが、

  • アウトプットする事でスキルアップしたい!
  • Rocket.Chat に関するノウハウ少ないしみんなに貢献したい!

という思いから記事を書いてます。Docker や coffeescript(javascript) に関しても初心者です。

なので、『記事の構成が クソ 良くないね』、『Dockerfileはこう書くべき』、『coffeescriptはこう書くと良い』、『そもそも別の方法で簡単に実現できるんだけど』などなど 厳しい 温かいコメントをお待ちしています!

動作イメージ

こんな感じで動作します。

動作イメージ.png

全体構成イメージ

全体構成.png

ざっくりシーケンス

ざっくりフロー.png

事前準備

  • Rocket.Chat 管理者で bot ユーザーを作成しておいてください。

ソースコードの前に注意点

  • REST API は β版 なので、ある日仕様が変更になるかもしれません。
  • 例外処理とかセキュリティ的なあれとか考えられていません(初心者過ぎて)。この記事を参考にする場合は自己責任でお願いします。あるいはゴリゴリと改造してください。(そして僕に教えてくだs

今度こそソースコード

github リポジトリ

github に Dockerfile と CoffeeScript をアップしました。
README.md も後ほど更新します!

Dockerfile

以下の変数を自分の環境に合わせて設定して下さい。

環境変数名 説明
HUBOT_IRC_NICK IRC 側に表示される bot のニックネーム
HUBOT_IRC_SERVER 接続先 IRC サーバ
HUBOT_IRC_ROOMS 接続チャンネル
http_proxy, no_proxy プロキシ環境下で必要に応じて使用
Dockerfile
FROM goldeneggg/hubot-irc

MAINTAINER 17number

# set hubot irc environment
# HUBOT_IRC_SERVER and HUBOT_IRC_ROOMS must be indicated by `docker run -e ...`
ENV HUBOT_IRC_NICK relaybot
ENV HUBOT_IRC_UNFLOOD true
ENV HUBOT_IRC_SERVER=<IRC SERVER IP ADDR>
ENV HUBOT_IRC_ROOMS="#ircroom1,#ircroom2"
# ENV http_proxy=http://proxyuser:proxypw@your.proxy.com:<proxyport>/
# ENV no_proxy="localhost,127.0.0.1,172.17.0.1"


# install pkgs
WORKDIR /root/mybot
RUN set -x && \
    npm install request --save && \
    npm install iconv --save && \
    npm install

# HTTP Listener listen port 9980
ENV PORT 9980
EXPOSE 9980

ADD ircforward.coffee /root/mybot/scripts/ircforward.coffee

# run redis-server and hubot("-a irc")
EXPOSE 6379
RUN /etc/init.d/redis-server start
ENTRYPOINT ["bin/hubot", "-a", "irc"]
CMD ["--name", "ircbot"]

coffeescript

こちらも同様に自分の環境に合わせて設定して下さい。

変数名 説明
dstip Rocket.Chat が動作しているサーバ(コンテナ)
botusername Rocket.Chat に追加した bot ユーザー名
botuserpw Rocket.Chat に追加した bot ユーザーのパスワード
loginrooms ircroom と rcroom をセットで設定。
  ircroom : IRC 側の転送元チャンネル名
  rcroom : Rocket.Chat 側の転送先チャンネル名
ircforward.coffee
# Description:
#   Forwards irc messages to Rocket.Chat.
#

# Parameters
dstip = "172.17.0.1:3000"
baseurl = "http://#{dstip}/api"
botusername = "yourbotname"
botuserpw = "yourbotpw"
loginrooms = [
  {"ircroom": "#ircroom1"
  "rcroom": "rocketchatroom1"},
  {"ircroom": "#ircroom2"
  "rcroom": "rocketchatroom2"},
  "ircroom": "endofroom"
  "rcroom": "endofroom"
             ]

request = require 'request'

module.exports = (robot) ->
  robot.hear /(.*)/i, (msg) ->
    # Get Token
    request.post
      url: "#{baseurl}/login"
      form:
        user: "#{botusername}"
        password: "#{botuserpw}"
    , (err, response, body) ->
      throw err if err
      if response.statusCode is not 200
        msg.send "err(get token)"
        exit 1

      logindata = JSON.parse(body)
      token = logindata.data.authToken
      userid = logindata.data.userId

      # Get Rooms
      request
        url: "#{baseurl}/publicRooms"
        headers:
          'X-Auth-Token': token
          'X-User-Id': userid
      , (err, response, body) ->
        throw err if err
        if response.statusCode is not 200
          msg.send "err(get rooms)"
          exit 1

        userroom = msg.message.user.room
        for roominfo, roomindex in loginrooms
          if roominfo['ircroom'] is userroom
            break

        roomdata = JSON.parse(body)
        for room, index in roomdata.rooms
          if room.name is loginrooms[roomindex]["rcroom"]
            roomid = room._id
            break

        # Join Room
        request.post
          url: "#{baseurl}/rooms/#{roomid}/join"
          headers:
            'X-Auth-Token': token
            'X-User-Id': userid
        , (err, response, body) ->
          throw err if err
          if response.statusCode is not 200
            msg.send "err(join rooms)"
            exit 1

          # Convert Msg
          Iconv = require('iconv').Iconv
          jis2utf = new Iconv('ISO-2022-JP', 'UTF-8')
          utf_msg = jis2utf.convert(msg.message.text).toString()
          username = msg.message.user.name
          userroom = msg.message.user.room

          # Forward Msg
          request.post
            url: "#{baseurl}/rooms/#{roomid}/send"
            headers:
              'X-Auth-Token': token
              'X-User-Id': userid
            json:
              msg: "#{userroom}: (#{username}) #{utf_msg}"
          , (err, response, body) ->
            throw err if err
            if response.statusCode is not 200
              msg.send "err(forward msg)"
              exit 1

            # Logout
            request
              url: "#{baseurl}/logout"
              headers:
                'X-Auth-Token': token
                'X-User-Id': userid
            , (err, response, body) ->
              throw err if err
              if response.statusCode is 200
              else
                msg.send "err(logout)"

コマンド実行例

$ git clone https://github.com/17number/irc-forward-rocketchat.git
$ cd irc-forward-rocketchat
$ vi Dockerfile
$ vi ircforward.coffee
$ docker build --tag=irc-forward-hubot . 
$ docker run -t -d irc-forward-hubot

イケてない点

  • エラー処理、例外処理が考慮できてない Docker, CoffeScript, Hubot 全てにおいてにわか過ぎて…
  • 関数分割できてない 同上
  • 設定値を外部ファイルなどにできてない おかげさまで同じような設定を DockerfileCoffeeScript の両方に入れないと…
  • IRC 側のチャンネル設定を変更するのに Docker build からしないといけない

苦労した点

  • docker 使ったことない Qiita で ROM ってた(死語?)だけで触るのは初めて。
  • coffescript/javascript 知らない
  • hubot もふわっとしか分かってない
  • 素敵なデバッグ方法が分からない CoffeeScript が間違ってて、コンテナ再起動後に即死にした時とか、どうやってデバッグするのですか…?後でググッてみます。
  • Rocket.Chat に関する参考ページが少ない 日本語ページばっかり探してましたが、英語をまじめに勉強しろってことですかね。
  • 絶対他にもあるので、思い出したら追記します!!

参考にしたページ

以下のページには大変お世話になりました!理解しきれていない点も多々ありますが、今回のものを作る際に参考にさせてもらいました。掲載順には特に意図はありません。あと分類がうまくできているかも怪しい

CoffeeScript

Hubot(と CoffeeScript)

Docker

Rocket.Chat

その他

12
9
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
12
9