聊天機器人一份,不加咖啡
===
gasolin @ coscup 2016
https://hackmd.io/p/HJ7dfgVc#/
Note: 介紹我們為什麼和怎麼把流行的 Hubot 跨平台聊天機器人框架,由 Coffeescript 改寫成純 Javascript 的 ES2015 版本,並且移植後還保持對原擴充套件相容性。包含移植 ES2015 過程中從入門到摔門的經驗。
---
## 大綱
* 介紹聊天機器人與Hubot
* 轉換Coffeescript到ES6
* 移植經驗總結
---
## 聊天機器人?
(Chat) Bot, 可以和人對話的程式
![](http://i.imgur.com/ek75KHcl.png)
---
## 聊天機器人
解決大家日常生活中的一些瑣碎問題
* 為我服務
* 替我做事
---
## 為我服務
透過多種途徑查看Coscup會議交通, 地圖, 議程, ...
* IRC
* Facebook, slack, wechat
* LINE, skype, telegram...
Note: https://github.com/github/hubot/blob/master/docs/adapters.md
---
## 替我做事
* 新開/已解決 bug 訊息通知
* 叫機器人幫忙跑指令, 創建新 build ...
* 解析貼上的 issue number 後, 貼出完整網址
* Scrum每日站立會議提醒
* ...
---
## Bot與即時通訊(IM)結合
* 隨時, 隨處可得
* 自助服務
* 控制家電設備
* 訂餐,喬會議時間
Note: LG home chat IA via LINE https://www.youtube.com/watch?v=PplAymrv0hA
---
## 理想
![bat man alfred](http://img.cinemablend.com/cb/2/8/c/7/f/a/28c7fa66118c8211fc4a316d7dfe25dccc7d889317fc156e2a1481b2fabd2a1c.jpg)
---
## 現實
![Imgur](http://i.imgur.com/y61zrv2l.png)
---
## 理想很豐滿,一用之下...
![](http://i.imgur.com/ysffZbPl.png)
---
![Imgur](http://i.imgur.com/8hrCL3sl.png)
Note: 現實很骨感 >_<
---
## 熱門的bot框架: Hubot
* by Github
* 10k+ star, 1k+ scripts
* 使用 Coffeescript 撰寫
[https://github.com/github/hubot](https://github.com/github/hubot)
---
## Hubot優點
* 支援超多通訊平台
* 擴充彈性高
* 容易分享
* 容易擴充
Note: 支援新通訊平台也很容易
---
## 容易分享
使用npm
```shell=
$ npm search hubot-scripts
...
$ npm install hubot-xxx
```
Note: hubot-xxx-adapter (facebook, twitter, slack...), hubot-xxx-plugin (search, map...), hubot-xxx-addon (conversation), hubot-xxx-brain (redis, mongoDB...)
---
## 容易擴充
3 行就可以寫一份 hubot 腳本
```coffeescript=
module.exports (robot) ->
robot.respond /(hello)/i, (res) ->
res.send 'hi';
```
---
## 用的是CoffeeScript
> CoffeeScript is a little language that compiles into JavaScript
支援 class, arrow function, rest argument, destructuring...
[http://coffeescript.org/](http://coffeescript.org/)
---
## 快移植完/看懂原始碼後 才知道...
---
## 也能用 Javascript 來寫 Hubot 腳本
```javascript=
module.exports = function(robot) {
robot.respond(/(hello)/i, function(res) {
res.send('hi');
});
}
```
---
## 但我想用 ES6 阿!
![](http://a1.hoopchina.com.cn/attachment/Day_101217/1048_4828307_edaeb7b9ba6c690.jpg)
---
## ES6 是什麼?
* 最新 Javascript 參考標準
---
## ES6 是什麼?
* 最新 Javascript 參考標準
* ECMA Script 2015(ES2015)
---
## ES6 是什麼?
* 最新 Javascript 參考標準
* ECMA Script 2015(ES2015)
* 不少新語法接近 CoffeeScript
Class, arrow function, rest argument, destructuring
Note: 用ES6移植, 比移植到plain JS更合理, 也更吸引新開發者
---
## 移植到ES6
* 比移植到plain JS更合理
* 易於維護
* 更吸引新開發者
---
## 為什麼 Hubot 還不用 ES6?
* 時代的眼淚
* 向前相容
* 開發優先級
---
## 潮的代價
* 不是所有瀏覽器/JS引擎都實作所有的ES6語法
* 沒有自動 CoffeeScript to ES6 轉換工具
---
## 在 Node.js 上
執行ES6程式需要...
---
## Babel 轉譯器(transpiler)
ES6 -> Plain Javascript
[http://babeljs.io/](http://babeljs.io/)
---
## 於是乎有了Webbybot
[https://github.com/gasolin/webbybot](https://github.com/gasolin/webbybot)
---
## Webbybot
* 用ES6改寫的Hubot
* 幾乎完全相容
* 同時支援 JS, Coffeescript, ES6腳本
* 高測試覆蓋率 (79%)
* 移植所花時間:3~4周
Note: contributed by gasolin & Ray Lin
---
## 時間花到哪兒了?
* 移植
* 學 ES6
* 學 CoffeeScript
* k資料
* 用錯 webpack
---
## 終於
可以寫ES6版腳本了
```javascript=
module.exports = (robot) => {
robot.respond(/(hello)/i, (res) => {
res.send('hi');
});
}
```
Note: 但跟 hubot 不相容喔
---
## 移植經驗
* 心路歷程
* 跑起來
* 跑得好
* Merge回Hubot
---
## 心路歷程
* 專案需求
* 評估移植價值
* source code 量不多
* 發現每個檔案都有測試
---
## 目標1: 跑起來 (Make it run)
* 搞定編譯設定
* 直接使用 npm script
* 直接使用 babel
* 移植時測試優先
* 隨時參考
* Lint不可少
---
## 搞定編譯設定
* 確認改好的檔案能編譯成 Plain JS
---
## 直接使用 npm script
不用 grunt, gulp, 或 Makefile 建構工具
在 package.json 裡直接加入 scripts 區塊:
```javascript=
"scripts": {
"prebuild": "shx rm -rf dist coverage && shx mkdir dist",
"build": "babel index.js -o dist/index.js && babel src -d dist/src",
"postbuild": "shx cp package.json dist/",
"test": "mocha --compilers js:babel-register -w",
"test:single": "istanbul cover --root ./src _mocha -- 'test/**/*.js' --compilers js:babel-register -R spec",
"lint": "eslint index.js bin/webby src/ test/",
"report-coverage": "cat ./coverage/lcov.info | codecov"
},
```
---
## 直接使用 babel-cli 轉換
* Server side 腳本已支援 require
* Server side 腳本不需用 webpack 來打包
```shell=
babel src -d dist/src
```
Note: webpack 支援使用 require 命令載入各種檔案,而且webpack 在轉換的過程中會將檔案打包成一份。但後端程式其實不太需要打包,而且 Hubot 作為一個框架,執行後從外部讀取 Plugin 是非常重要的功能。 使用 webpack 時,它會將程式中出現的 require 都視為它的 require,而嘗試從打包好的檔案中找到我們需要的外部 plugin
---
## 移植時測試優先
移植好一個測試後,再移植相應代測檔案
```
移植測試 -> 測試通過 ->
移植待測檔案 -> 測試通過 ->
移植下一個測試 ->
```
---
## 隨時參考
將檔案 CoffeeScript 轉換成 JS 參考
使用 [Coffeescript > try script](http://coffeescript.org/)
![](https://i.imgur.com/uPpkZBw.png)
---
## Lint不可少
程式碼格式檢查
ESLint
[http://eslint.org/](http://eslint.org/)
---
## 目標2: 跑得好(Make it good)
讓語法更符合ES6
* 該不該 return
* class + super
* Default + Rest + Spread
* 使用 for..of 替換 for.. in 迴圈
* 使用 Object.assign 替換 Extend
Note: javascript to ES6
---
## 學ES6時,別錯過的MozHack系列文章
[ES6 in Depth](https://hacks.mozilla.org/category/es6-in-depth/)
---
## Webbybot merge 回 Hubot?
遙遙無期阿
* [plain js hubot-mockadapter instead of hubot-mock-adapter #1160](https://github.com/github/hubot/issues/1160)
* [Port hubot from coffeescript to plain Javascipt (ES2015)](https://github.com/github/hubot/issues/1138)
hubot 核心開發不活躍, review 頗慢, 幾乎不 merge...
---
## 何不直接寫一個簡易版聊天機器人?
* 運作在客戶端(網頁版)
* 參考 hubot 架構與API
* 支援腳本
* 容易擴展
* Conference Driven Development
---
## Saihubot
師傅機器人!
cosbot [https://github.com/gasolin/cosbot](https://github.com/gasolin/cosbot)
![Imgur](http://i.imgur.com/bjpwrdHl.png)
---
## 聽完記得什麼?
---
## 跑起來 (Make it run)
* 搞定編譯設定:確認改好的檔案能編譯成 Plain JS
* 直接使用 npm script:不用 grunt, gulp, 或 Makefile 建構工具
* 直接使用 babel: Server side 腳本不用 webpack
* 移植時測試優先:移植好一個測試後,再移植相應代測檔案
* 隨時參考:使用 [Coffeescript > try script](http://coffeescript.org/),將檔案 CoffeeScript 轉換成 JS 參考
* Lint不可少
---
## 跑得好(Make it good)
* 讓語法更符合ES6
---
## Reference
* https://github.com/github/hubot
* https://github.com/gasolin/webbybot
* https://github.com/gasolin/webby
* https://github.com/gasolin/saihubot
* [ES6 in Depth](https://hacks.mozilla.org/category/es6-in-depth/)
* [將聊天機器人框架 hubot 從 Coffescript 移植到 ES6](http://blog.gasolin.idv.tw/2016/03/hubot-coffescript-es6.html)
* [How we ported Hubot from Coffeescript to ES6](http://blog.gasolin.idv.tw/2016/03/how-we-ported-hubot-from-coffeescript.html)
---
# Thanks