聊天機器人一份,不加咖啡 === 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