2016年12月20日 星期二

使用Claudia.js製作查詢台銀匯率API & 自動回覆匯率BOT(Skype 版本)

前一篇文章分享了如何製作簡單的Facebook BOT,但是應該不會有人希望自己的BOT只會找理由吧。而且Lambda的最大應用其實是Web API,而Claudia其實也是可以幫忙建立API的,一樣是很輕鬆愉快喔~
這篇文章會介紹如何用Claudia寫一隻自動抓取台銀最新的現金賣出匯率,並轉成JSON格式的API,再建立一個機器人並讓機器人自動回覆匯率。

建立API

初始化npm專案

  1. 建立一個資料夾並命名為currencyrate
  2. 打開Mac Terminal/Windows command line tool並移動到這個資料夾(cd currencyrate)
  3. 初始化npm專案:輸入
    npm init  
    

安裝套件

如果之前選擇不將Claudia安裝到Global,要在這個步驟打入
npm install claudia -D
來安裝Claudia到這個專案。

另外還必須要安裝幾個npm套件:
  • claudia-api-builder:Claudia自動部署API的套件
  • minimal-request-promise:很簡單就可以取得網頁上資料的套件
  • csv-parse:因為台銀提供csv檔格式的API,這個套件可以解析csv檔
在Terminal或是Cmd輸入
npm install claudia-api-builder minimal-request-promise csv-parse -S 
即可安裝這兩個套件。

API的Code

打開你的sublime或是其他的記事本工具,輸入以下的code:
'use strict'
const parse = require('csv-parse/lib/sync');
const rp = require('minimal-request-promise')
const ApiBuilder = require("claudia-api-builder");

var api = new ApiBuilder();
var rootUri = 'http://rate.bot.com.tw/';
var currencyMethod = 'xrt/flcsv/0/day';
var sellcashcol=12;
var currencyCode=0;

api.get("/currency/{code}", function (message) {
 var code = message.pathParams.code;
 var errorMessage,sellcash;
 var returnData={errorMessage:errorMessage,sellcash:sellcash};
 return rp.get(rootUri+currencyMethod)
            .then(response => {
               var body='#'+response.body;
               var records = parse(body, {comment: '#'});
               var arrayFound = records.filter(function(item) {
     return item[currencyCode].toLowerCase()==code.toLowerCase();
    });
    if (arrayFound.length>0)
    {
     returnData.sellcash=arrayFound[0][12];
    }else{
     returnData.errorMessage='Cannot find any currency from code '+code
    }
    return returnData;
              })

});

module.exports = api;
然後儲存成index.js。 這段Code會到台銀網站提供的API取得匯率,透過csv-parser解析之後取得目標匯率並回傳。

透過Claudia部署

透過Claudia部署,一樣只要一個指令 claudia create --name currency --region us-west-2 --api-module index
部署完可以透過URL https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/currency/USD測試是否有成功,也可以進入AWS Console,選擇"API Gateway"服務後找到currency API,在resource中按下"Test“按鈕測試。

建立BOT

參考上篇文章建立機器人,然後在機器人的folder中安裝minimal-request-promise套件,並將BOT的Code修改如下:
'use strict'
const botBuilder = require('claudia-bot-builder');
const excuse = require('huh');
const rp = require('minimal-request-promise')
module.exports = botBuilder(
function(message) {
 if (message.text.lastIndexOf('Currency/', 0) === 0)
      {
          var msgArr=message.text.split('/');
          return rp.get('https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/currency/'+msgArr[1])
            .then(response => {
                var rate = JSON.parse(response.body);
                if(rate.sellcash!=null || typeof(rate.sellcash)!='undefined'){
                  return('Currency '+msgArr[1]+' exchange rate today is '+rate.sellcash) 
                }
                else
                {
                  return('Error occured, reason is'+rate.errorMessage);
                }
              })
      }
      else
      {
        return 'Thanks for sending '+ message.text +'.Your message is very important to us, but '+excuse.get();
      }
});
*注意https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/currency/ 這邊是剛剛建立好的API的URL,要記得改不要全部照抄,不然BOT找不到API不會理人的~
存檔之後,透過Claudia create或Claudia update將BOT部署到AWS。

Skype BOT設定

在這裡介紹怎麼設定Skype的BOT。Skype BOT已經整合到Microsoft的BOT Framework,目前還在Preview階段,根據Microsoft BOT Framework的Q&A將會在2017年推出正式版,這裏的設定教學都是針對Preview版本。
  1. 首先,用你的microsoft/Azure帳號登入Microsoft BOT Framework,並按下"Register a BOT"
  2. 在Bot profile區段,給你的BOT一個名字,並且在bot handle給予這個BOT一個識別值(identity)。bot handle區段一旦設定了,就不能再改了。

  3. 在Configuration區段中設定:
    1. Messaging endpoint:Claudia deploy回應結果中,deploy->skype區段中的內容,通常是https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/skype
    2. 按下"Create Microsoft App ID and password"按鈕
    3. 給予這個應用程式一個名稱(可以和bot的名字不同),然後按一下"產生應用程式密碼"
    4. 系統產生一組密碼,一定要複製起來,待會透過Claudia設定的時候要用。密碼只有這個時候可以看得到,沒有複製到就只好再產生一次了。

  4. Microsoft BOT framework的設定告一段落,回到我們的command/terminal console,打入
    Claudia update --configure-skype-bot
  5. Claudia會要求你輸入Skype App ID和Skype Private key,其中Skype App ID就是應用程式識別碼,Skype Private key則是按下“產生應用程式密碼以繼續”按鈕時,系統自動產生的那組密碼,也就是剛剛特別要你存起來的那組密碼
  6. 至此,Skype BOT已經全部設定完成。回到Microsoft BOT Framework,找到"Test connection to your bot"區段,按下Test按鈕,如果看到下方出現OK "ok",就表示兩方的configuration沒有問題。

Test in skype

在Microsoft BOT Framework中,我們可以看到系統已經很貼心地將我們的Skype Channels建立好了。

有注意到除了Skype Channel,還有一個Web Chat嗎?如果我們是自己寫API沒有透過claudia-bot-builder,這個BOT可以同時支援Skype和Web Chat。但很可惜的是claudia-bot-builder並沒有支援Web Chat,所以雖然BOT Framework有幫我們建立Web Chat的Channel,也已經啟用,在頁面最底下的Chat區段測試,BOT是不會理我們的....
請在Skype Channel旁邊有一個"Add to skype"按鈕,按下去之後會開啟另一個視窗:
按下"Add to Contacts"之後會將Skype開起來,並把BOT加入Skype聯絡人中。這時候就可以和BOT對話了。

BOT收到Currency/[幣別代碼]的指令的時候,會自動呼叫我們寫好的查詢台銀匯率API並回應。如果收到其他的訊息則是一樣隨便找個理由搪塞你。

About Microsoft BOT Framework

設定好BOT Framework之後其實我蠻好奇的,因為可以看到Channels能夠設定的並不只有Skype和Web Chat而已,還有很多種Channel可以設定,包括Facebook Messenger/slack等。
這邊可以看到Microsoft一貫的包山包海風格,其實Microsoft BOT Framework就是一個BOT Connector,可以通吃各家的BOT。.NET的Developer也可以透過Visual Studio的BOT Framework template寫好BOT後發佈到雲端或網站上,設定好應用程式的ID和密碼來串接,只要有在BOT Framework設定,一隻API可以通吃所有的BOT。當然Claudia也是可以通吃,只不過因為要跟skype串, 而在跟skype串接的時候,看到Microsoft BOT又這麼大堆頭, 可是我只是想跟你家skype連線而已,有種「Microsoft真是一以貫之的熱(ㄐㄧ)心(ㄆㄛˊ)啊~」的感覺。

想透過Visual Studio的BOT Template及Microsoft BOT Framework來開發BOT的話,可以參考董大偉老師的文章:關於bot framework (3) - 建立一個最基本的bot (v3新版)

2016年12月15日 星期四

使用Claudia.js製作Facebook機器人

以前我們常常會需要一些Web Service幫我們處理一些簡單的GET/POST,這些Web Service可能很簡單並不複雜,甚至不需要UI,不過它總是需要一個host來立足,於是你可能就必須要找一台主機,如果是Windows的話還要有IIS(然後忍受IIS偶爾的衝康跟無止盡的windows update) 

所以當AWS推出了Lambda,身為一個Infra暴弱的Dev,真的會要給AWS一個大大的讚!這才是真正的SASS精神啊。畢竟我們不需要為了喝牛奶而去養一頭牛你說是吧。Lamdba讓程式開發人員可以專心的在程式的邏輯上面,將每個function獨立出來計費可以讓阮囊羞澀的獨立開發者與startup不需要負擔主機的維運費用,並且有精美的dashboard可以統計各個function的狀態,真的是非~常~的美好。

BUT,這世界上總是有個BUT,Lambda要寫python/node.js方便是方便,不過在部署的時候還是得設定IAM的Role,function才能正常運行。如果是AWS的菜鳥(尤其是Infra跟我一樣爆爛的)看到IAM的設定應該會很茫然。於是現在就有很多Lambda的部署工具,比方說Python用的Kappa,以及現在我想介紹的Claudia.js。

Claudia.js其實就是用AWS的Node.js framework將Lamdba的部署自動化,IAM以及Lambda的設定都在Claudia.js當中完成。之後如果要更新code,也只要一個指令就能完成,而且不需要登入AWS Console,是不是很方便啊。

以下就來介紹怎麼透過Claudia.js自動部署microservice並在Facebook上面做一個機器人。

首先你必須要申請一個AWS帳號(不然你是要部署到哪裡去),在此就不贅述如何申請了。

設定環境

因為Claudia.js是用來Deploy Node.js的microservice,所以你的電腦也要裝Node.js(這不是廢話嗎)
Node.js預設就有npm(Node.js的package管理工具)因此以下會提到npm指令,但不需要另外安裝。

安裝Node.js

Windows版

Command:
sudo curl http://nvm-latest.herokuapp.com | bash

手動安裝:到官網安裝最新版的Node.js
安裝完後在Command line工具中執行
node -v
就可以檢查Node.js是否正確安裝。

Mac版

雖然Mac的Homebrew好用到令人流淚,但因為node.js版本更新非常快速,因此推薦使用nvm安裝。透過nvm安裝Node可以很簡單的輕鬆切換Node.js版本。

  1. 如果你有安裝XCode,可以透過XCode來安裝nvm
    $ xcode-select --install
  2. 如果沒有安裝,可以透過curl來安裝
    sudo curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.32.1/install.sh | bash
  3.  在Terminal中輸入
    nvm ls-remote
    ,找出最新的版本,我寫這篇文章時最新的版本是7.2.1
  4. 執行
    $ nvm install 7.2.1
    $ nvm alias default 7.2.1
    安裝node.js

設定IAM Policy

因為AWS的IAM Role Policy預設並沒有啟用AWS Gateway API,所以要先將User Policy建立起來,Claudia在部署的時候才不會因為沒有權限而報錯。
  1. 登入AWS Console,選擇IAM service,然後按一下"Policies"。
  2. 按下"Create Policy"按鈕
  3. 選擇“Create Your Own Policy”
  4. 在Policy名稱上面填上“API_Gateway_Resources_Full”,並在Policy Document中填入以下資料:
  5. {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "Stmt1467321765000",
                "Effect": "Allow",
                "Action": [
                    "apigateway:*"
                ],
                "Resource": [
                    "*"
                ]
            }
        ]
    }

  6. 按下"Create Policy"就完成了。


新增一個IAM使用者

  1. 到AWS主控台,從上方的下拉選單選擇IAM服務,進入IAM服務後選擇左邊的"Users" ,並按下藍色的"Add User"
  2. 輸入使用者名稱,並勾選“Programmatic access”,然後按下“Next:Permissions"
  3. 選擇”Attach existing policies directly“ 並在底下的policy勾選IAM Full permission / Lambda Full permission,然後按下"Next: Review"
  4. 確定這個使用者有IAM Full Access 和Lambda Full Access之後,按下”Create User“
  5. 按下"Download .csv"按鈕可以下載這個使用者的Credential, 強烈建議要下載下來因為當按下close之後你就再也沒有機會看到Secret access key 了,只能重新建立一個使用者
    (都已經說了This is the last time these credentials will be available to download.了~)
 

建立登入資料

這個步驟是讓你在Deploy的時候不需要再輸入帳號密碼。
用Sublime或Notepad等純文字編輯器打開 Mac/Linux 的 ~/.aws/credentials 或 Windows 的 C:\Users\USERNAME\.aws\credentials,加入以下指令:
[default]
aws_access_key_id = YOUR_ACCESS_KEY_ID

aws_secret_access_key = YOUR_ACCESS_SECRET_KEY


YOUR_ACCESS_KEY_ID指的是剛剛建立好的帳號中,最後一步顯示的access_key_id,YOUR_ACCESS_SECRET_KEY則是被隱藏的access Secret key.
如果剛剛沒有把資料保存下來...再回去重新建立一個使用者吧

安裝Claudia.js(安裝至Global,可忽略這個步驟)

因為已經安裝好npm了,安裝Claudia就是一件非常輕鬆簡單的事情。在Mac的Terminal或是Windows的console打入以下指令:
npm install claudia -g
 
Claudia就裝好了。
[12/18]*補充說明:npm指令中-g是全域安裝(安裝到global)其實因為Claudia只是部署工具,比較建議隨著專案來安裝,如果不想安裝到Global可以在下面的安裝套件步驟中一起安裝Claudia.

開始寫機器人囉!

初始化npm專案

  1. 建立一個資料夾並命名為aLittleGreeter
  2. 打開Mac Terminal/Windows command line tool並移動到這個資料夾(cd aLittleGreeter)
  3. 初始化npm專案:輸入
    npm init
      

安裝套件

(如果選擇不將Claudia安裝到Global,可以在這個步驟打入
npm install claudia -D
來安裝Claudia到這個專案。)
在寫機器人之前,我們還需要安裝兩個npm套件
  • claudia-bot-builder:有了這個套件,Claudia才能幫你設定和其他通訊軟體(例如Facebook, skype, slack)
  •  huh:這是亂數取一個理由的npm套件,可以在系統掛掉的時候第一時間回信給PM解釋(誤)
在Terminal或是Cmd輸入
npm install claudia-bot-builder huh -S 
即可安裝這兩個套件。

 BOT的Code

(讀者表示:終於到寫Code了)
打開你的sublime或是其他的記事本工具,輸入以下的code:
const botBuilder = require('claudia-bot-builder');
const excuse = require('huh');
 
module.exports = botBuilder(
function(message) {
 return 'Thanks for sending '+ message.text +'Your message is very important to us, but '+excuse.get();
});
然後儲存成index.js。 這是一個很簡單的機器人,會把你說的話再重複一次,然後找個理由回(ㄈㄨ)答(ㄧㄢˇ)你。

透過Claudia把Code部署上AWS

Claudia會幫你把Lambda和Role該設定的全部都設定好,就交給Claudia部署就可以了。只需要一個指令 claudia create --name aLittleGreeter --region us-west-2 --api-module index
  • name 屬性:Claudia會使用name來建立IAM Role和Lamdba
  • region屬性:你要部署到哪個AWS的region,在這邊使用us-west-w2指的是美國的奧勒岡州。可以參考AWS Region列表選擇要部署到哪個region
  • api-module屬性:Lamdba程式的進入點。我們的檔名是index.js,所以將api-module設定為index,Claudia就會將index.js的內容部署到Lamdba。

如果沒有問題,就會看到Claudia一直在幫你跑AWS上面的流程了。
部署完成以後,應該會看到以下的訊息
{
  "lambda": {
    "role": "aLittleGreeter-executor",
    "name": "aLittleGreeter",
    "region": "us-west-2"
  },
  "api": {
    "id": "[api-gateway-id]",
    "module": "index",
    "url": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest",
    "deploy": {
      "facebook": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/facebook",
      "slackSlashCommand": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/slack/slash-command",
      "telegram": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/telegram",
      "skype": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/skype",
      "twilio": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/twilio",
      "kik": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/kik",
      "groupme": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/groupme",
      "viber": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/viber",
      "alexa": "https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/alexa"
    }
  }
}

然後回到AWS的IAM 管理介面,選擇Role,可以看到Claudia已經幫你建好一個Role了
 

再切到AWS的Lambda管理介面,發現Claudia也建好Lambda的函數了



這樣AWS的部署就已經完成了。有沒有很方便呀。

設定Facebook粉絲專頁機器人

OK,我們已經部署完AWS的部份了,接下來是Facebook的設定。
  1. 先建立一個粉絲專頁
  2. Facebook Developer應用程式開發頁面,如果之前沒有註冊成為Facebook Developer,應該會先看到"立即註冊"的按鈕,按下立即註冊成為Facebook Developer。
  3. 按下“新增應用程式”,類別選擇“專業應用程式”,取好名字以後選擇“建立應用程式編號"
  4. 建立好之後會到這個應用程式的主控台,在產品設定中按下Messanger區塊旁的"開始使用"
  5. 在"權杖產生"中,先選擇先前建立好的粉絲專頁,在旁邊的粉絲專頁存取權杖中會顯示一組權杖,先記錄下來。
  6. 這時我們要在Claudia設定與Facebook連動,回到電腦的Terminal或是Cmd Console,打入以下指令:
    claudia update --configure-fb-bot
    Claudia會將Code重新部署,部署完後會出現以下的回應:
    Facebook Messenger setup
    
    
    Following info is required for the setup, for more info check the documentation.
    
    
    Your webhook URL is: https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/facebook
    
    Your verify token is: [verify Token]
    
    Facebook page access token: 
    
  7. Claudia詢問的Facebook page access token就是剛剛Facebook應用程式中粉絲專頁的權杖,將剛剛複製好的權杖貼入Terminal
  8. 接著Claudia會詢問Facebook App Secret,到應用程式中選擇“主控台”,在主控台中找到"應用程式秘鑰",按下顯示後將內容貼到Terminal
  9. 到這邊AWS端的連動已經設定完成,接下來回到Facebook應用程式
  10. 到"Webhooks"區段中選擇“Setup Webhook”
  11. 填寫Webhook資訊:
    • 回呼網址:填上Claudia回應中的deploy->facebook區段中的內容,通常是https://[api-gateway-id].execute-api.us-west-2.amazonaws.com/latest/facebook
    • 驗證權杖:在剛剛打入
      claudia update --configure-fb-bot
      的時候,Claudia的回應中有一段 Your verify token is: [verify Token],填入這個verify token
    • 訂閱欄位:至少要勾選messages
  12. 儲存之後,就可以看到Webhooks區段有綠色勾勾,代表已經設定完畢
  13. 然後就可以嘗試傳送訊息給你的粉絲專頁了

茶包射手

  • 部署的時候出現npm error

    檢查一下Code有沒有寫錯,或是需要的npm套件沒有安裝。
  • 部署的時候出現AccessDeniedException

    檢查IAM的使用者是否已經有IAM和Lambda的Full permission
  • 出現package.json does not exist in the source folder

    通常是因為沒有執行npm init,可以再執行一次讓npm產生package.json
  • 部署失敗,出現Make sure you have the latest version of node.js and npm installed.

    這是因為Node.js太舊了,如果Mac有安裝Homebrew只要透過Homebrew更新就可以了
    brew upgrade node
    如果沒有Homebrew,可以透過npm清除Node.js的Cache並下載最新版:
    sudo npm cache clean -f
    sudo npm install -g n
    sudo n stable
    
    Windows的使用者也可以透過npm來更新node.js
    npm cache clean
    npm update -g
    
  • 我想更新我的Code,重新執行Claudia出現這樣的訊息:

    Role with name aLittleGreeter-executor already exists.

    這是因為重複執行Claudia create。Claudia create會自動建立AWS的IAM Role和Lamdba,而名字是identity不能重複的。所以如果要更新Code或是設定其他的組態(像是Facebook連動)請用Claudia update.如果想要更新的不是只有Code本身,像是想要換AWS的region,那麼只能將建立好的IAM Role, Lamdba等等都先手動刪除再執行Claudia create。
  • Facebook機器人不會回應我的朋友

    這是正常的,這個機器人目前只會回應你而已,當全部開發完成之後會需要提交給Facebook審查,可以參考Facebook的審查說明。人工審查需要七天左右,審查通過其他人才可以用。