Skip to main content

9 posts tagged with "javascript"

View All Tags

· 2 min read

It's a small challenge and fun to setup a chatbot on a small device with restrained resource.

Here's the instruction to setup a chatbot on Respberry pi with 4GB SD Card.

Download respbian lite

We need respbian lite because normal Respbian took more than 4GB space. If you have 8GB or larger SD Card, normal Respbian works fine for you.

You can download them from https://www.raspberrypi.org/downloads/raspbian/

Flash image to sdcard

I did it in Mac with diskutil. You can check the install guide from https://www.raspberrypi.org/documentation/installation/installing-images/README.md for other platforms.

$ diskutil list
/dev/disk0 (internal, physical):
...
/dev/disk1 (internal, virtual):
...
/dev/disk2 (internal, virtual):
... 2: Linux 3.8 GB disk2s2

$ diskutil unmountDisk disk2
$ sudo dd bs=1m if=2016-03-18-raspbian-jessie-lite.img of=/dev/rdisk2

Login to respbian

Respbian lite does not provide desktop environment, so we'll do everything with command line.

Insert SDCard, bootup and login into respbian with

name: pi
password: raspberry

Refer from http://elinux.org/RPi_Distributions#Raspbian

Install node and redis

Refer from https://nodejs.org/en/download/package-manager/

$ `curl -sL https://deb.nodesource.com/setup_5.x > script
$ chmod 755 script
$ sudo -E ./script
$ sudo apt-get install -y nodejs build-essential redis-server
$ node -v
v5.10.1

Install webbybot

Webbybot is the rewrite of hubot from coffeescript to ES6, its will be more maintainable in the future.

In respbian lite, the git is not pre-installed, so we need install git-core from apt-get as well.

$ sudo apt-get install git-core
$ git clone https://github.com/gasolin/webby-template pibot
$ cd pibot
$ npm install
$ ./bin/webby
webby> webby test
webby> **pong**

Deploy on messengers

Check Workable adapters section to install your bot onto telegram, facebook messenger, or skype https://github.com/gasolin/webby-template#workable-adapters

Let's take skype for example. First you need sign up an skype account, then put the username/password on to .env file.

vi .env
HUBOT_SKYPE_USERNAME=name
HUBOT_SKYPE_PASSWORD=password

Then install hubot-skyweb adapter and switch the core to webbybot

npm install hubot-skyweb
vi node_module/hubot-skyweb/src/skyweb.coffee

replace require 'hubot' to 'webbybot'. Then run

./bin/webby -a skyweb

You are good to go! You can add new skills on your pibot by following https://github.com/gasolin/webbybot/#add-plugins which is same as hubot, and create your own plugin to control the respberry pi https://github.com/gasolin/webbybot#write-your-own-plugin.

Have fun!

· 4 min read

Hubo

We (Fred Lin & Ray Lin) have ported Github's popular chat robot framework 'Hubot' from Coffeescript to plain Javascript with ES6 features. Currently I name it webbybot to denote ES6 version of hubot, to better test the port result and avoid the naming confusion with the original hubot.

Now webbybot is fully functional and still support all coffeescript written plugins. If you have an existing bot generated by hubot-generator, you can install webbybot via npm install webbybot command, follow with simple instruction and see your bot works smoothly with webbybot core.

(For experienced developer, the instruction guide you to replace script in generated '/bin' folder from 'hubot' to 'webby'. And change the adapter library import from 'hubot' to 'webbybot'.)

As time goes to 2016, there're less reason to use Coffeescript instead of standard ES6 Javascript. During the porting we do learned something that might helpful for your projects.

1. Use npm script directly instead of gulp or grunt

With npm we can define some scripts directly in the 'script' attribution of 'package.json' file. Webbybot use 'npm run build' command to compile ES6 to plain javascript via Babel. Do style checking via 'npm run lint' command.

2. Use babel directly instead of webpack

At the beginning we count on webpack's babel-loader to convert ES6 to plain javascript. Alas its a beginning of 'Try and Error' journey. Webpack is originally designed for front-end packaging and works very well on that purpose. But for backend program like webbybot that feature is not important for us. Webpack also bring 'require' keyword to the front-end, but its not suit for backend program that depends on dynamic import. As a framework, hubot heavily counts on NODE require to load plugins. Webpack treat all 'require' as its keyword and try hard in vain to find external modules from packed files.

We tried several ways to detour these side effects, and finally replaced the full webpack stack with one line npm build script. Now its easier to debug and no hacks needed in source code.

3. return or not return, its the question

We use the "Try Coffeescript" utility provide form Coffeescript official site, which you can paste Coffeescript the page will convert the source to Javascript instantly. The converted code is... not all pretty for human read, and all converted functions will contain a return statement even its unnecessary. It needs check by hand.

4. test cases matter

Hubot itself contains good coverage of unit tests. So we are able to test one ported script file with one ported test file when we start the porting. The unit test files contain great number of redundant return sentences when convert from coffeescript.

5. class and super

Hubot use Class syntax from Coffeescript。Thanksfully ES6 support the Class syntax, which is a bit different from Coffeescript. You can check how to use Class and super on MDN.

6. Default + rest + spread

Hubot contain several syntax like 'reply(strings...)'. The syntax 'strings...' in Coffeescript is correspondent to "...strings" in ES6(The order of '...' is reversed). '...strings' denotes an array and I feel its a bit hard to figure out when to expand it or not.

7. for..of instead of for..in

To use for..in loop in ES6, we need add 'hasOwnProperty' check to make sure inherited property are not looped. Or we can rewrite for..in loop in Coffeescript to forEach iteration. Though there are some cases that need 'break' or 'return' from a loop.

Now we use ES6 for..of loop in Webbybot to replace forEach and for..in loop. You need wrap object with Object.keys syntax to iterate with object. ex: for (let item of Object.keys(TargetObj)) {...}.

8. Object.assign instead of Extend

We can use Object.assign to extend a object without handmade extend function or lodash!

9. Do you know hubot also support write plugin with plain javascript?

Learning how chat bot works is the main reason we start porting hubot to ES6! A simple plain javascript plugin could be as easy as: (src/simple.js)

> module.exports = function(robot) {
>   robot.respond(/(hello)/i, function(res) {
>     res.send('hi');
>   });
> }You can put it in generated plugin folder and it will just work.

I've created a ticket on hubot issue list to start a discussion if hubot would like to go with ES6 in its future version.

The webbybot source is at https://github.com/gasolin/webbybot

Do you have a project ported from coffeescript to ES6? Welcome to drop by your thoughts.

· 6 min read

Hubo

(English Version available here

用兩周多的時間,路路續續把原本用 Coffeescript 撰寫的 Hubot 聊天機器人框架移植成使用到 ES6 特性的純 Javascript 版本。 現在這個移植版本已經可供使用。移植後依然可以使用 Hubot 原來以 Coffeescript 撰寫的各種擴充套件 (Plugins) 。 https://github.com/gasolin/webbybot (目前的版本完全移植 Hubot 的功能,已開 Issue 詢問 Hubot 是否有興趣 merge 回去,在此之前先放在自己的 webbybot repo 裡) 移植的動機之一是為了了解整個聊天機器人框架,為後續可能的修改打基礎。 其二則是嘗試平常不常用到的 ES6 新特性。 過去 Coffeescript 和 Typescript 等最終編譯成 Javascript 執行的語言,都走在 Javascript 之前,提供了許多語法上的新特性。但在 2015 年 Javascript 開始的新發佈規劃 (一年一版) 下,ES6 (ES2015) 已將 Coffescript 眾多特性都收編了。且現在透過 Babel 可以將 ES6 編譯成現有的 Javascript 直譯器能讀懂的語法。在這樣的趨勢下,過去開發者想為這些新特性多學一套語言的誘因就不再存在了。 移植過程中採用的作法與遇到了一些坑,在此一一列出來。 1. 不用 grunt gulp, 直接使用 npm script 在 package.json 裡可以直接在 "script" 屬性中定義一些要執行的腳本,例如 webbybot 透過 "npm run build" 來將 ES6 轉換成 Javascript 直譯器能讀懂的語法。用 “npm run lint" 來做 style check。 2. 不用 webpack, 直接使用 babel 移植之初決定使用 webpack 的 babel loader 來轉換 ES6,但這是一連串從「錯誤中學習」的開始。 webpack 支援使用 require 命令載入各種檔案,而且 webpack 在轉換的過程中會將檔案打包成一份。但後端程式其實不太需要打包,而且 Hubot 作為一個框架,執行後從外部讀取 Plugin 是非常重要的功能。 使用 webpack 時,它會將程式中出現的 require 都視為它的 require,而嘗試從打包好的檔案中找到我們需要的外部 plugin,結果是徒勞的。當我們換用 npm script 直接呼叫 babel-cli 來打包,原來使用 webpack 時出現的諸多問題也都一併解決了。 3. 該不該 return 在移植的過程中常用到的工具是 Coffeescript 官網的 "Try Coffeescript" 分頁。可以即時將 Coffeescript 結果轉換成 Javascript。 但是真的把程式碼貼上去會發現, Coffeescript 所轉出來的 Javascript 所有的函式都會回傳值。需要手工一個個確認。 4. test cases Hubot 本身有很完整的單元測試。所以每移植一支程式碼時,只要一併移植對應的單元測試,就可以捉對拿來直接測試。單元測試移植時出現最多該不該 return 的問題。 5. class and super Hubot 使用了很多 Coffeescript 的 Class 語法。Class 與 super 的用法在 MDN 上可以找到相關教學。 6. Default + Rest + Spread Hubot 程式碼裡常常會出現諸如 reply (strings...) 的語法。Coffeescript 裡的 "strings..." 可以對應到 ES6 的 "...strings"(... 放置位置剛好相反)。 "...strings" 代表的是一個陣列。在程式中有時要展開有時不用,其實頗令人苦惱。7. 使用 for..of 替換 for.. in 迴圈 碰到 for..in 迴圈有幾種解法,最不會出錯的是將 Array iteration 改寫成 forEach。但是用 forEach ˇ的話無法在執行中使用 break/return 跳出是其缺點。其二是在 for..in 迴圈裡加入 hasOwnProperty 確認不會跑到無關的 function。 在 Webbybot 的第二版中已使用 ES6 支援的 for..of 迴圈 來取代 forEach 和 for..in 迴圈。由於 for..of 迴圈只支援 iteratable ,不支援一般 Object,所以碰到要對 Object 跑迴圈時可以在 Object 外包一層 Object.keys,例如 `for (let item of Object.keys (TargetObj)) {...} 8. 使用 Object.assign 替換 Extend

要擴展一個物件的功能不用再用 lodash 或是自己寫 extend 函式,直接用 Object.assign 吧。

以上是移植過程中碰上的問題。感謝同事 Ray Lin 一起幫忙完成這次的移植。

現在 Webbybot (Hubot ES6 port) 整套都可以用 Javascript 寫了,歡迎試用或上 Patch 喔。

https://github.com/gasolin/webbybot

· 2 min read

firebug 是 firefox 的一個插件. 可以說是當前用來 debug javascript 程式的最佳選擇. firebug 還提供了一些好用的函式可以讓您的測試更順暢.

這段影片 展示了 firebug 提供的一些好用的函式.

廢話不多說,馬上來看看吧:

印出一般訊息 : console.log

就像許多程式語言中的 'print' 語句,firebug 提供的 console.log 語句可以直接印出變數值. 例如

console.log (變數);

或者印出包含變數的敘述

console.log ("敘述: % d"% 變數);

印出具有提示圖示的訊息 console.info/console.warn/console.error

與印出一般訊息 (console.log) 使用的方式完全相同,console.info/console.warn/console.error 只是會在訊息前加上相應圖示

console.info (a) 提示圖示 console.warn (b) 警示圖示 console.error (c) 錯誤圖示

使用除錯介面 debugger

只要在想要除錯的地方前加上一行加上 debugger 語句

debugger; .....

執行時就會彈出一個互動式的除錯介面. 除錯介面提供了單步執行等功能,並即時取得當前各相關變數的狀態. 也可以看到迴圈每次執行後改變的值

計算花費時間 console.time/console.timeEnd

對於 AJAX 程式來說有些動作會花費較多的時間,使用

console.time ("跑") ..... console.timeEnd ("跑")

將要測試的程式段包起來,執行時就會印出該段程式所花費的執行時間