んなまにのメモ帳

何でも気になることを書いていきます。基本的に技術メモ

Common Lispでslackボットを作る

slackのReal Time Messaging APIを使ってechoボットを作ってみた時のメモです。

実行環境はUbuntu 16.04です。

準備

  • libuvのインストール
  • cl-slackのインストール

Real Time Messaging API(RTM)はwebsocketを使います。
リアルタイムにメッセージを読み込むために、websocket-driverのwebsocketクライアントを使います。
websocket-driverで使われているcl-asyncはlibuvの1.0.0-rc2以上が必要のようなので、最新バージョンをインストールしました。

GitHub - fukamachi/websocket-driver: WebSocket server/client implementation for Common Lisp

sudo apt install libuv1

RTMを使うためにcl-slackをインストールします。
GitHub - m0cchi/cl-slack: Slack API from cl

cd ~/.roswell/local-projects
git clone https://github.com/m0cchi/cl-slack

書き込んだ内容をオウム返しするボットを作ってみる

チャンネルを監視し、書き込まれた内容をそのまま書き込むスクリプトを作成します。
slackにアクセスするためのトークンは作成済みとして進めます。

(ql:quickload '(:cl-slack
                :websocket-driver
                :jonathan)
              :silent t)

;; slackにアクセスするためのトークン
(defparameter *token* "xxxx-xxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxx")

;; slackクライアント
(defparameter *slack-client* (make-instance 'cl-slack.core:slack-client :token *token*))

;; websocketクライアントを作成する
(defparameter *slack-bot* (wsd:make-client (getf (jonathan:parse (cl-slack.rtm:start *slack-client* nil)) :|url|)))

;; メッセージ受信時の処理
(wsd:on :message *slack-bot*
        (lambda (message)
          (let ((data (jonathan:parse message)))
            (format t "~A~%" data)
            (when (string= (getf data :|type|) "message")
              (wsd:send *slack-bot*
                        (params 1
                                "message"
                                (getf data :|channel|)
                                (getf data :|text|)))))))

;; 送信データを作成する
(defun params (id type channel text)
  (jonathan:to-json (list :|id|      id
                          :|type|    type
                          :|channel| channel
                          :|text|    text)))

;; コネクションを開始する
(as:with-event-loop (:catch-app-errors t)
  (wsd:start-connection *slack-bot*))

こんな感じになりました。

f:id:nnnamani:20161225015601p:plain:w350