「HubotスクリプトをCommon Lispで書く」をやってみた
深町さんのこの記事をやってみた記録
いろいろ準備
Node.jsとRoswellのインストールは省略。
Yeomanとジェネレータ、Lakeをインストール。
npm i -g yo generator-hubot ros install lake
プロジェクトディレクトリの初期化
Rocket.Chatで使いたかったので、アダプタも指定した。
mkdir hubot-cl
cd hubot-Common Lisp
yo hubot --name="bot" --adapter="rocketchat@1"
rm hubot-scripts.json
npm un -S hubot-{heroku-keepalive,google-images,google-translate,maps,redis-brain}
npm i -S hubot-mongodb-brain
external-scripts.jsonからhubot-{heroku-keepalive,google-images,google-translate,maps,redis-brain}を消してhubot-mongodb-brainを追加。
git repo初期化
git init git add . git commit -m 'Initial commit'
pm2.sh作成
PM2で起動するのと、Rocket.Chat向けに環境変数の指定がいるのでpm2.sh作成。
#!/bin/sh export ROCKETCHAT_URL='https://hogehoge.com/' export ROCKETCHAT_ROOM='roomname' export ROCKETCHAT_USER=botaccount export ROCKETCHAT_PASSWORD=botpassphrase # use password authentication(not ldap) export ROCKETCHAT_AUTH=password ./bin/hubot -a rocketchat
動作確認
./bin/hubotでターミナル内。./pm2.shでRocket.Chat。
bot pingでPONGが帰ってくれば成功。
Common Lisp (Roswell)用に追加
Lakefile作成
$ lake-tools init
# hubotifyとdefaultのタスクを作成
$ cat Lakefile
#|-*- mode:lisp -*-|#
(in-package :cl-user)
(defpackage :lake.user
(:use :cl :lake :cl-syntax)
(:shadowing-import-from :lake
:directory))
(in-package :lake.user)
(use-syntax :interpol)
(task "default" ()
(lake :target "hubotify"))
(task "hubotify" ()
(dolist (file (uiop:directory-files #P"roswell/"))
(sh `("bin/hubotify" ,(namestring file)))))
;;; here follow your tasks...
Roswellスクリプト等設置
# hubotifyをダウンロードしてビルド
$ curl -o bin/hubotify.ros https://gist.githubusercontent.com/fukamachi/ba055a9a284b181e82bf/raw/c66d65a5a18be44463ab781e669891c6a49f92c1/hubotify.ros
$ ros build bin/hubotify.ros
# whoami.rosを書く
$ mkdir roswell
$ cat roswell/whoami.ros
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(defun main (&rest argv)
(declare (ignorable argv))
(format t "~&I'm fukabot!~%"))
(ql:quickload :parenscript :silent t)
(import '(ps:ps ps:@ ps:regex))
(defun js-main ()
(ps
((@ robot respond) (regex "/who are you\\?/i")
(lambda (msg)
(run-main
(lambda (error stdout stderr)
(when error
((@ msg send) error))
(when stdout
((@ msg send) stdout))
(when stderr
((@ msg send) stderr))))))))
# whoami.rosに実行権限をつけないとERROR Error: spawn EACCESとなる
$ chmod +x roswell/whoami.ros
# whoami.jsの生成
$ lake
Already have sbcl-bin.
Making core for Roswell...
building dump:lake
up to date. stop
Wrote '/Users/shimatani/Work/Repos/other/hubot-cl/scripts/whoami.js'
Command "bin/hubotify /Users/shimatani/Work/Repos/other/hubot-cl/roswell/whoami.ros" exited with error code 1.
hubotifyがエラーコード1らしいけど生成されてる。
動作確認
./bin/hubot bot> bot who are you? bot> I'm fukabot!
JSがroswell/whoami.rosを実行してて遅かったのでこれもビルドした。
(これだと次のlakeでビルドしたものもhubotifyの対象になるのでちょっと困る)
$ ros build roswell/whoami.ros
# scripts/whoami.jsのwhoami.rosへのパスをwhoamiに変更
$ head scripts/whoami.js
function runMain(callback) {
var argv = Array.prototype.slice.call(arguments, 1);
this.execFile = require('child_process').execFile;
__PS_MV_REG = {};
return this.execFile(__dirname + '/../' + 'roswell/whoami', argv, new(Object), function (error, stdout, stderr) {
callback(error, stdout, stderr);
__PS_MV_REG = {};
return null;
});
};
これだと実行するとエラーコードが返っているみたい。
bot> bot who are you? bot> Error: Command failed: /path/to/hubot-cl/scripts/../roswell/whoami I'm fukabot!
ros buildしたものを実行すると正常終了しない?
$ ./roswell/whoami; echo $? I'm fukabot! 1 $ ./roswell/whoami.ros; echo $? I'm fukabot! 0
ひとまずParenscriptでhubotスクリプトを書いて動かすところまでできたのでここまで。
課題
- ParenScriptをjsclに変えてみる
- lakeの対象をglobで指定する(
roswell/*.ros) - ビルドするとエラーコードが返る