φ(.. ) 備忘録
   
  

2021年9月23日木曜日

既存UbuntuサーバをWindows10のWSL2に置換する!(其の五)

其の五:hubotの文字化けを直す

前回、hubotが無事インストールできたので、文字化けを対策する。

hubotで扱う文字コードはUTF-8が前提となっており、会社で使っているISO-2022-JPのチャットサーバーだと、文字化けを起こしてしまう。

以前perlのnkfモジュールを用いて対策を行ったことがあったが、coffeeスクリプトで対策できることが分かったので、そちらで対策する。

まずは、hubotをインストールしたディレクトリに移動して、必要なモジュール(jschardet、iconv)を追加インストールする。

$ cd ~/hubot
$ npm install jschardet
$ npm install iconv
次に、irc.coffeeに修正を加える。
$ cd ~/hubot/node_modules/hubot-irc/src
$ cp irc.coffee irc.coffee.org
$ vi irc.coffee
修正内容(diffイメージ)は以下で、最初にrequireで追加したモジュールをロード。
日本語のチャンネル名が指定された場合に備えて、チャンネル名をUTF8からISO-2022-JPに変更する処理を追加。
sendメソッドとnoticeメソッドに文字コードをUTF-8からISO-2022-JPに変更する処理を追加。messageやchannelを受け取るbotListener(message,notice等)に受け取った文字をUTF-8に変更する処理を追加。
ちなみに、iconv生成時のパラメータで指定している『TRANSLIT//IGNORE』はコード変換失敗時にエラーを無視するためのおまじないみたい。
 # Irc library
 Irc = require 'irc'

+# for ISO-2022-JP
+Jschardet = require 'jschardet'
+Iconv = (require 'iconv').Iconv
+
 class IrcBot extends Adapter
   send: (envelope, strings...) ->
     # Use @notice if SEND_NOTICE_MODE is set
@@ -15,6 +19,8 @@
       return console.log "ERROR: Not sure who to send to. envelope=", envelope

     for str in strings
+      iconv = new Iconv('UTF-8','ISO-2022-JP//TRANSLIT//IGNORE')
+      str = iconv.convert(str).toString()
       @bot.say target, str

   topic: (envelope, strings...) ->
@@ -52,6 +58,8 @@
       if not str?
         continue

+      iconv = new Iconv('UTF-8','ISO-2022-JP//TRANSLIT//IGNORE')
+      str = iconv.convert(str).toString()
       @bot.notice target, str

   reply: (envelope, strings...) ->
@@ -131,11 +139,15 @@

     do @checkCanStart

+    iconv = new Iconv('UTF-8','ISO-2022-JP//TRANSLIT//IGNORE')
+    roomsValue = iconv.convert(process.env.HUBOT_IRC_ROOMS).toString()
+
     options =
       nick:     process.env.HUBOT_IRC_NICK or @robot.name
       realName: process.env.HUBOT_IRC_REALNAME
       port:     process.env.HUBOT_IRC_PORT
-      rooms:    process.env.HUBOT_IRC_ROOMS.split(",")
+#      rooms:    process.env.HUBOT_IRC_ROOMS.split(",")
+      rooms:    roomsValue.split(",")
       ignoreUsers: process.env.HUBOT_IRC_IGNORE_USERS?.split(",") or []
       server:   process.env.HUBOT_IRC_SERVER
       password: process.env.HUBOT_IRC_PASSWORD
@@ -189,15 +201,27 @@

     if options.connectCommand?
       bot.addListener 'registered', (message) ->
+        detectResult = Jschardet.detect(message)
+        iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+        message = iconv.convert(message).toString()
+
         # The 'registered' event is fired when you are connected to the server
         strings = options.connectCommand.split " "
         self.command strings.shift(), strings...

     bot.addListener 'names', (channel, nicks) ->
+      detectResult = Jschardet.detect(channel)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      channel = iconv.convert(channel).toString()
+
       for nick of nicks
         self.createUser channel, nick

     bot.addListener 'notice', (from, to, message) ->
+      detectResult = Jschardet.detect(message)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      message = iconv.convert(message).toString()
+
       if from in options.ignoreUsers
         console.log('Ignoring user: %s', from)
         # we'll ignore this message if it's from someone we want to ignore
@@ -209,6 +233,10 @@
       self.receive new TextMessage(user, message)

     bot.addListener 'message', (from, to, message) ->
+      detectResult = Jschardet.detect(message)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      message = iconv.convert(message).toString()
+
       if options.nick.toLowerCase() == to.toLowerCase()
         # this is a private message, let the 'pm' listener handle it
         return
@@ -231,6 +259,10 @@
       self.receive new TextMessage(user, message)

     bot.addListener 'action', (from, to, message) ->
+      detectResult = Jschardet.detect(message)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      message = iconv.convert(message).toString()
+
       console.log " * From #{from} to #{to}: #{message}"

       if from in options.ignoreUsers
@@ -247,9 +279,17 @@
       self.receive new TextMessage(user, message)

     bot.addListener 'error', (message) ->
+      detectResult = Jschardet.detect(message)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      message = iconv.convert(message).toString()
+
       console.error('ERROR: %s: %s', message.command, message.args.join(' '))

     bot.addListener 'pm', (nick, message) ->
+      detectResult = Jschardet.detect(message)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      message = iconv.convert(message).toString()
+
       console.log('Got private message from %s: %s', nick, message)

       if process.env.HUBOT_IRC_PRIVATE
@@ -267,21 +307,37 @@
       self.receive new TextMessage({reply_to: nick, name: nick}, message)

     bot.addListener 'join', (channel, who) ->
+      detectResult = Jschardet.detect(channel)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      channel = iconv.convert(channel).toString()
+
       console.log('%s has joined %s', who, channel)
       user = self.createUser channel, who
       user.room = channel
       self.receive new EnterMessage(user)

     bot.addListener 'part', (channel, who, reason) ->
+      detectResult = Jschardet.detect(channel)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      channel = iconv.convert(channel).toString()
+
       console.log('%s has left %s: %s', who, channel, reason)
       user = self.createUser '', who
       user.room = channel
       self.receive new LeaveMessage(user)

     bot.addListener 'kick', (channel, who, _by, reason) ->
+      detectResult = Jschardet.detect(channel)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      channel = iconv.convert(channel).toString()
+
       console.log('%s was kicked from %s by %s: %s', who, channel, _by, reason)

     bot.addListener 'invite', (channel, from) ->
+      detectResult = Jschardet.detect(channel)
+      iconv = new Iconv(detectResult.encoding,'UTF-8//TRANSLIT//IGNORE')
+      channel = iconv.convert(channel).toString()
+
       console.log('%s invited you to join %s', from, channel)

       if from in options.ignoreUsers

本来なら、環境変数もしくはコマンドパラメータで変換する文字コードを指定すべきだが、今回はそこまでやってない。
上記修正が正しく動作するか確認するために、hubot-scriptsのhttp-post-say.coffeeを使ったため、それの設定方法も残しておく。
まず、hubotインストールディレクトリに移動して、hubot-scripts.jsonを編集。
$ cd ~/hubot
$ vi hubot-scripts.json
hubot-scripts.jsonの内容は以下。他に追加したいスクリプトがあればカンマ(,)区切りで追加すればよい。
["http-post-say.coffee"]
hubotの待ち受けポートは、デフォルト8080になっている。変更する場合には、以下のようにhubot起動スクリプトに環境変数PORTの設定処理を追加し、起動すればよい。
$ vi runbot.sh
#!/bin/bash
# hubot http port setting
export PORT=9999
# runhubot
export HUBOT_IRC_NICK="hubot"
export HUBOT_IRC_ROOMS="#test01,#test02"
export HUBOT_IRC_SERVER="localhost"
#export HUBOT_IRC_PASSWORD="hoge"
bin/hubot -a irc
$ .runbot.sh 
http-post-say.coffeeを使って、http経由でhubotに発言させるにはcurlコマンド等で以下のようにすればよい。
$ curl -X POST http://localhost:9999/hubot/say -d message=文字化けた? -d room='#test01'
ISO-2022-JPのチャットサーバって、世の中一般では、レアなんですかね。。。うちの会社だけなのかなぁ。。。。

あと、おまけで、hubotの発言をnoticeにする方法がわかった。すごく簡単で、起動時に環境変数HUBOT_IRC_SEND_NOTICE_MODEにtrueを設定するだけだった。イメージは以下。
#!/bin/bash
# hubot http port setting
export PORT=9999
# runhubot
export HUBOT_IRC_NICK="hubot"
export HUBOT_IRC_ROOMS="#test01,#test02"
export HUBOT_IRC_SERVER="localhost"
#export HUBOT_IRC_PASSWORD="hoge"
export HUBOT_IRC_SEND_NOTICE_MODE="true"
bin/hubot -a irc

0 件のコメント :

コメントを投稿