2018/1/9

第二十一天:讓 Line Bot 回覆訊息

markdown 昨天我們把聊天機器人 webhook 串好了,今天我們要讓機器人回覆訊息。 我們先來看看我們能不能正常的收到訂閱通知,我說的訂閱通知是在[第五天:認識 Line Messaging API Webhook](https://ithelp.ithome.com.tw/articles/10193441) 介紹到的各種通知。 我們可以看在 heroku 上的 `rails server` 小黑框來觀察。 # 觀察 heroku 上的伺服器運作記錄 當我們在小黑框輸入 `heroku logs -t` 時,跟我們在小黑框輸入 `rails server` 有 87% 像,當有人開啟網頁時,就會看到運作紀錄(log)。 ``` D:\只要有心,人人都可以作卡米狗\ironman>heroku logs -t ``` 先開個小黑框輸入 `heroku logs -t` 之後放著。 # 觀察 Line developer 後台的 verify 我們先回到 Line developer 後台,點一下昨天點過的 `verify`,看看 Line 到底傳了什麼給我們的伺服器。 ``` 2018-01-08T15:04:43.091880+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 21213 -e production` 2018-01-08T15:04:50.486685+00:00 app[web.1]: => Booting Puma 2018-01-08T15:04:50.486716+00:00 app[web.1]: => Rails 5.1.4 application starting in production 2018-01-08T15:04:50.486718+00:00 app[web.1]: => Run `rails server -h` for more startup options 2018-01-08T15:04:50.486719+00:00 app[web.1]: Puma starting in single mode... 2018-01-08T15:04:50.486725+00:00 app[web.1]: * Version 3.11.0 (ruby 2.3.4-p301), codename: Love Song 2018-01-08T15:04:50.486733+00:00 app[web.1]: * Min threads: 5, max threads: 5 2018-01-08T15:04:50.486735+00:00 app[web.1]: * Environment: production 2018-01-08T15:04:50.486886+00:00 app[web.1]: * Listening on tcp://0.0.0.0:21213 2018-01-08T15:04:50.487396+00:00 app[web.1]: Use Ctrl-C to stop 2018-01-08T15:04:38.156226+00:00 heroku[web.1]: Unidling 2018-01-08T15:04:38.156470+00:00 heroku[web.1]: State changed from down to starting 2018-01-08T15:04:52.254468+00:00 app[web.1]: I, [2018-01-08T15:04:52.254363 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Started POST "/kamigo/webhook" for 203.104.156.74 at 2018-01-08 15:04:52 +0000 2018-01-08T15:04:52.276728+00:00 app[web.1]: I, [2018-01-08T15:04:52.276573 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Processing by KamigoController#webhook as HTML 2018-01-08T15:04:52.277008+00:00 app[web.1]: I, [2018-01-08T15:04:52.276880 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Parameters: {"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}], "kamigo"=>{"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}]}} 2018-01-08T15:04:52.297993+00:00 app[web.1]: W, [2018-01-08T15:04:52.297845 #4] WARN -- : [34361d41-4be8-4293-971d-eca0151ea11c] Can't verify CSRF token authenticity. 2018-01-08T15:04:52.298635+00:00 app[web.1]: I, [2018-01-08T15:04:52.298565 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Completed 200 OK in 21ms 2018-01-08T15:04:52.306974+00:00 heroku[router]: at=info method=POST path="/kamigo/webhook" host=people-all-love-kamigo.herokuapp.com request_id=34361d41-4be8-4293-971d-eca0151ea11c fwd="203.104.156.74" dyno=web.1 connect=0ms service=56ms status=200 bytes=289 protocol=https ``` 我們需要看懂這些東西,我們一次讀一段,慢慢讀完。 第一行: ``` 2018-01-08T15:04:43.091880+00:00 heroku[web.1]: Starting process with command `bin/rails server -p 21213 -e production` ``` 這行就是我們平常在小黑框輸入的 rails server,heroku 上也需要輸入這行,但這是由 heroku 自動幫我們輸入。 heroku 的免費伺服器有一個缺點,如果連續 30 分鐘都沒人連到我們的網頁伺服器,他就會自動關機。當他處於關機狀態時,如果有人連到我們的伺服器,那他就會把我們的網頁伺服器叫醒。 ``` 2018-01-08T15:04:50.486685+00:00 app[web.1]: => Booting Puma 2018-01-08T15:04:50.486716+00:00 app[web.1]: => Rails 5.1.4 application starting in production 2018-01-08T15:04:50.486718+00:00 app[web.1]: => Run `rails server -h` for more startup options 2018-01-08T15:04:50.486719+00:00 app[web.1]: Puma starting in single mode... 2018-01-08T15:04:50.486725+00:00 app[web.1]: * Version 3.11.0 (ruby 2.3.4-p301), codename: Love Song 2018-01-08T15:04:50.486733+00:00 app[web.1]: * Min threads: 5, max threads: 5 2018-01-08T15:04:50.486735+00:00 app[web.1]: * Environment: production 2018-01-08T15:04:50.486886+00:00 app[web.1]: * Listening on tcp://0.0.0.0:21213 2018-01-08T15:04:50.487396+00:00 app[web.1]: Use Ctrl-C to stop ``` 這是我們平常下 `rails server` 指令時會看到的訊息。 ``` 2018-01-08T15:04:38.156226+00:00 heroku[web.1]: Unidling 2018-01-08T15:04:38.156470+00:00 heroku[web.1]: State changed from down to starting ``` heroku 的狀態從關機變成開始運作中。 ``` 2018-01-08T15:04:52.254468+00:00 app[web.1]: I, [2018-01-08T15:04:52.254363 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Started POST "/kamigo/webhook" for 203.104.156.74 at 2018-01-08 15:04:52 +0000 2018-01-08T15:04:52.276728+00:00 app[web.1]: I, [2018-01-08T15:04:52.276573 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Processing by KamigoController#webhook as HTML 2018-01-08T15:04:52.277008+00:00 app[web.1]: I, [2018-01-08T15:04:52.276880 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Parameters: {"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}], "kamigo"=>{"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}]}} 2018-01-08T15:04:52.297993+00:00 app[web.1]: W, [2018-01-08T15:04:52.297845 #4] WARN -- : [34361d41-4be8-4293-971d-eca0151ea11c] Can't verify CSRF token authenticity. 2018-01-08T15:04:52.298635+00:00 app[web.1]: I, [2018-01-08T15:04:52.298565 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] Completed 200 OK in 21ms ``` 每一行的開頭都有這個: ``` 2018-01-08T15:04:52.254468+00:00 app[web.1]: I, [2018-01-08T15:04:52.254363 #4] INFO -- : [34361d41-4be8-4293-971d-eca0151ea11c] ``` 這不是很重要,因為會妨礙閱讀,所以我們先忽略他,以下是忽略後的結果: ``` Started POST "/kamigo/webhook" for 203.104.156.74 at 2018-01-08 15:04:52 +0000 Processing by KamigoController#webhook as HTML Parameters: {"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}], "kamigo"=>{"events"=>[{"replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100001", "type"=>"text", "text"=>"Hello, world"}}, {"replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{"type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef"}, "message"=>{"id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1"}}]}} Can't verify CSRF token authenticity. Completed 200 OK in 21ms ``` 這看起來就有點眼熟了。 他打了一個 POST 到我們的 `/kamigo/webhook`,並且傳了這樣的參數: ``` { "events"=>[ { "replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{ "type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef" }, "message"=>{ "id"=>"100001", "type"=>"text", "text"=>"Hello, world" } }, { "replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{ "type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef" }, "message"=>{ "id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1" } } ], "kamigo"=>{ "events"=>[ { "replyToken"=>"00000000000000000000000000000000", "type"=>"message", "timestamp"=>1515423877419, "source"=>{ "type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef" }, "message"=>{ "id"=>"100001", "type"=>"text", "text"=>"Hello, world" } }, { "replyToken"=>"ffffffffffffffffffffffffffffffff", "type"=>"message", "timestamp"=>1515423877419, "source"=>{ "type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef" }, "message"=>{ "id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1" } } ] } } ``` ### 解讀 POST BODY 經過我精美的排版之後變得比較好閱讀了,這是一個很大的 Ruby hash(雜湊陣列),我們在[第十三天:認識 Ruby 的資料型態](https://ithelp.ithome.com.tw/articles/10195196)學過這個。我把這個 hash 存成檔案,名叫 `line_verify.rb`,這麼作有一些好處,sublime text 會幫文字加顏色,以及可以使用縮小/展開功能。 ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdkzsNhAA2cBJPDvvPOPsB4K1HgCXaN8xaH2P9sFo00qRPPMS9B2q8cfghdUAifmfPEsJzwOEm5bHU5B_WByr2IOIYhTJnMe5vE_d6hFpe3lkMEYtRvnasucbufklhYlBzNFDHm4JdgSo/s1600/1.jpg) 這個 hash 有兩個 key,分別是 events 和 kamigo,events 是一個陣列,而 kamigo 是一個 hash。 kamigo 是一個只有一個 key 的 hash,而這個 key 也叫作,events。更巧的是,這兩個 events 裡面包含的資料是相同的,所以我們只要看其中一個 events 就好。 ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0vgYz9C60_y5_uWDOuAXchjDkJmNPKL3XOVBzJnq9tqwkoalA8cZWdWrVItyAD-l6fBoz7Z-gtdcyKnhRW638QzLHTioVILU20nya6jjCBVmkErg-ui71mW3FvY-d970O_7qzRiKIr7U/s1600/2.jpg) 這個 events 陣列,包含兩個 hash。這個 hash 我們在[第五天:認識 Line Messaging API Webhook](https://ithelp.ithome.com.tw/articles/10193441) 時已經介紹過了。這裡再簡單複習一下: - replyToken:是我們要回覆訊息時必須傳回的值,他代表收件者以及你的回覆權。 - type:通知類型,這是一則訊息 - timestamp:傳送時間,我們通常會忽略他 - source:發信者 - message:訊息內容 接下來看第一個 hash 裡的 source 和 message。 ``` "source"=>{ "type"=>"user", "userId"=>"Udeadbeefdeadbeefdeadbeefdeadbeef" } ``` 這是發生在私訊對話框,對方的 id 是 Udeadbeefdeadbeefdeadbeefdeadbeef。 ``` "message"=>{ "id"=>"100001", "type"=>"text", "text"=>"Hello, world" } ``` 對方傳來的訊息是文字訊息:「Hello, world」。 再看第二個 hash。第二個 hash 裡的 source 跟第一個一樣,所以我們只需要看 message 的部分。 ``` "message"=>{ "id"=>"100002", "type"=>"sticker", "packageId"=>"1", "stickerId"=>"1" } ``` 對方傳來的訊息是貼圖訊息。 # 觀察實際傳遞的訊息 讓我們試著用 Line 傳訊息給我們的聊天機器人,看看會收到什麼: ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMlyQ7a8tL5J9LNC5HKqeEYEnxbFx5GWsV6HeyZO6C0kveLtZapIP1pRPTTvqW_-qcj2fhWFSpDgW3wItgqCrAolvQXvWk8Ye8OVUWMrn5bYMLjECXjplsSffUWoxTBPijw9fv_MyjJjA/s1600/4.jpg) 看看小黑框,什麼事也沒發生。原來是 Line developer 後台還有東西沒設定。 ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYMwu_rXKeZdke_vrCzWpmCi7-DFWSincuXup6uP7XSiiQeP4Y_ZVZOY8_81DP-4nvpzYhD_T1bUGSc92HLhpU4IBYHgF0g44UGh7or7NxdhSwuYGnIhBbzSU-TX8ok8JoZYDUWdAl44g/s1600/3.jpg) 這兩個分別是`使用 Webhook` 和`可被邀請進群`,都把他打開。 ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-PXDkSv3QyTPe3QCGxuJhe3lB2PUG-pbPYfeVHGEwBT-FBuc3Klr4wrLTBCLFW5UtcDIEiYFVvzMReclB3OnCay4nEd3n7E41kncvsvNSPqA1sKYq-8lIngKUe36E5-NThbfCJEbTNBU/s1600/5.jpg) 都開啟後的樣子: ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj19dYqISo4Kdla-qB0i1RpuBfyBxz-HwkE5niTLpK0KVNZRTYjU0qZHZG6Hd1g78GFV4BANHoHl_ZoN5srguHahxElSAH88hv0-A9MhSnyGTQ5mAo6dJW5ZcnTWc77S_mLf3_6d7zy-zs/s1600/6.jpg) 都開啟後再次傳訊息就會在小黑框看到: ``` { "events"=>[ { "type"=>"message", "replyToken"=>"1d0bc2113fd344deb8131750e8d2daa2", "source"=>{ "userId"=>"Uc68d82df46b7899e7d716f396ae8e91a", "type"=>"user" }, "timestamp"=>1515432401148, "message"=>{ "type"=>"text", "id"=>"7279127481400", "text"=>"五五六六得第一" } } ] } ``` 我把不重要的部分都刪除了,剩下來的部分看起來差不多,應該不用多作解釋,現在我們來作回覆訊息。 # 回覆訊息 ### 安裝 Line Bot API 我們要先安裝一個 Line 提供的 gem,在 Gemfile 加入以下程式: ``` # line gem 'line-bot-api' ``` 記得要在小黑框輸入 bundle 下載套件。 ### 引入 Line Bot API 修改 `app/controllers/kamigo_controller.rb` 檔,在第一行加上`require 'line/bot'`: ``` require 'line/bot' ``` 這表示我們要使用 Line 的套件。 ### 修改 webhook 這個是 webhook 寫好的樣子,我會慢慢解釋他。 ``` def webhook # Line Bot API 物件初始化 client = Line::Bot::Client.new { |config| config.channel_secret = '9160ce4f0be51cc72c3c8a14119f567a' config.channel_token = '2ncMtCFECjdTVmopb/QSD1PhqM6ECR4xEqC9uwIzELIsQb+I4wa/s3pZ4BH8hCWeqfkpVGVig/mIPDsMjVcyVbN/WNeTTw5eHEA7hFhaxPmQSY2Cud51LKPPiXY+nUi+QrXy0d7Hi2YUs65B/tVOpgdB04t89/1O/w1cDnyilFU=' } # 取得 reply token reply_token = params['events'][0]['replyToken'] # 設定回覆訊息 message = { type: 'text', text: '好哦~好哦~' } # 傳送訊息 response = client.reply_message(reply_token, message) # 回應 200 head :ok end ``` ### Line Bot API 物件初始化 ``` client = Line::Bot::Client.new { |config| config.channel_secret = '9160ce4f0be51cc72c3c8a14119f567a' config.channel_token = '2ncMtCFECjdTVmopb/QSD1PhqM6ECR4xEqC9uwIzELIsQb+I4wa/s3pZ4BH8hCWeqfkpVGVig/mIPDsMjVcyVbN/WNeTTw5eHEA7hFhaxPmQSY2Cud51LKPPiXY+nUi+QrXy0d7Hi2YUs65B/tVOpgdB04t89/1O/w1cDnyilFU=' } ``` 這段程式是我們使用 Line Bot API 內提供的物件,需要傳入兩個字串分別為 `Channel secret` 和 `Channel access token`。 你可以在 Line Developer 後台找到他們: ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMvtwmgO89PEdgHdB0V2NHW9qlg0zUcfvXdFIS1ylTW3DYO8Qiu7k5mxDNaYhElJ2kNl_A2b_chXFI3_ycGCIHa752GQRWxutaWFfJnsnJiE8F53lcYxWblotLJ9O7U-3slyNteUNhPLk/s1600/7.jpg) 只要按下 `Issue` 按鈕,值就會變。 ### 取得 reply token ``` reply_token = params['events'][0]['replyToken'] ``` 根據剛剛我們觀察的 hash 結構,我們大膽假設 `events` 陣列裡只有一筆資料,用 `[0]` 取得第一筆,然後取得他裡面的 `replyToken`。 ### 設定回覆訊息 ``` message = { type: 'text', text: '好哦~好哦~' } ``` 我們回覆的訊息是純文字訊息,內容是「好哦~好哦~」 ### 傳送訊息 ``` response = client.reply_message(reply_token, message) ``` 我們透過 Line Bot API 包裝好的函數來回覆訊息,這樣我們就不用去寫在[第十六天:做一個最簡單的爬蟲](https://ithelp.ithome.com.tw/articles/10195760)寫過的那些東西。 ### 對一下程式碼 這是完整的 `app/controllers/kamigo_controller.rb` 檔內容: ``` require 'line/bot' class KamigoController < ApplicationController protect_from_forgery with: :null_session def webhook # Line Bot API 物件初始化 client = Line::Bot::Client.new { |config| config.channel_secret = '9160ce4f0be51cc72c3c8a14119f567a' config.channel_token = '2ncMtCFECjdTVmopb/QSD1PhqM6ECR4xEqC9uwIzELIsQb+I4wa/s3pZ4BH8hCWeqfkpVGVig/mIPDsMjVcyVbN/WNeTTw5eHEA7hFhaxPmQSY2Cud51LKPPiXY+nUi+QrXy0d7Hi2YUs65B/tVOpgdB04t89/1O/w1cDnyilFU=' } # 取得 reply token reply_token = params['events'][0]['replyToken'] # 設定回覆訊息 message = { type: 'text', text: '好哦~好哦~' } # 傳送訊息 response = client.reply_message(reply_token, message) # 回應 200 head :ok end ...下略 end ``` ### 上傳程式碼 確認沒問題之後,因為我們沒辦法進行本地端的測試,所以就直接上傳程式碼: ``` git add . git commit -m "回覆訊息" git push heroku master ``` 上傳完成後進行測試。 ### 實測 ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiW5PWuoQ-kxXMRNjvTQt0Rvfzq-krPNr9UOVO5L0ny5rKfZEjALXF_VHVJ1blCn3sx2AOIGRrgKvi05O9Vh3hTYxRnqnMa01nhcxSOgwK085R2yTVY0miyy-ryT9J36mqp0lkLdSrX_DI/s1600/8.jpg) 耶~我們終於作出最簡單的回應了。 如果你沒有辦法順利抵達這裡,那麼你有幾個可以作的事情,你可以讓 `heroku logs -t` 打出你想知道的內容。比方說,你想知道你的 reply_token 有沒有抓對: ``` # 取得 reply token reply_token = params['events'][0]['replyToken'] p "======這裡是 reply_token ======" p reply_token p "============" ``` 像這樣加上幾行 `p`,接著只要對 Line Bot 傳訊息,你就能在小黑框看到這個: ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkY2KcbiPvHLBz61ktvryWb6JL00hq45xDqHi6JCAkhF4zYbE2AhdnbKQhyRk2mRhHA9t4-AuDK68TQct562NB5rRwBgbsooyTV3Ru7xlgVxDZ8XU33_u4PE6shXX1L9sr5VpMlMfdD30/s1600/9.jpg) 你可以把所有的變數都用 `p` 印出來慢慢看,看是不是你想要的值。其中最值得觀察的變數是 `response`。 如果你看不懂,可以對 logs 截圖在底下留言。 # 總結 - 你知道不同的通知只有些許差異。 - 你看懂通知傳遞的內容,以及如何用程式碼擷取出他的值 - 你學會了使用套件 - 你學會了怎麼讓 Line Bot 回覆訊息 - 你學會了在 heroku 上的除錯方法 明天之後就會越來越難了,要寫的程式會越來越多。這裡有一些 Ruby 的基礎教學,有興趣的人可以補一下: [為你自己學 Ruby on Rails - 變數、常數、流程控制、迴圈](https://railsbook.tw/chapters/05-ruby-basic-1.html) [為你自己學 Ruby on Rails - 數字、字串、陣列、範圍、雜湊、符號](https://railsbook.tw/chapters/06-ruby-basic-2.html) [為你自己學 Ruby on Rails - 方法與程式碼區塊(block)](https://railsbook.tw/chapters/07-ruby-basic-3.html) [為你自己學 Ruby on Rails - 類別(Class)與模組(Module)](https://railsbook.tw/chapters/08-ruby-basic-4.html)

沒有留言: