今天我們要作的是主動傳訊息的功能。
目前我們用到的都只是回覆訊息的功能:
# 傳送訊息到 line
def reply_to_line(reply_text)
return nil if reply_text.nil?
# 取得 reply token
reply_token = params['events'][0]['replyToken']
# 設定回覆訊息
message = {
type: 'text',
text: reply_text
}
# 傳送訊息
line.reply_message(reply_token, message)
end
上面這個函數是我們之前寫好的 reply_to_line
函數,裡面的最後一行:
line.reply_message(reply_token, message)
這是在呼叫 line 提供給我們的回覆訊息函數,而 line 也有提供讓我們主動發訊息的函數:
response = line.push_message(channel_id, message)
我們需要傳遞 channel_id,告訴 Line 誰應該收到這個訊息,channel_id 就是 userId, groupId 或 roomId。所以我們需要一個資料模型去保存所有頻道的 channel_id。
文件參考在這裡:https://developers.line.me/en/docs/messaging-api/reference/#send-push-message
rails g model channel channel_id
建立一個資料表叫作 channel,裡面有個欄位叫作 channel_id。
rails db:migrate
bj4
在主程式中加入一行:
Channel.create(channel_id: channel_id)
如果你覺得是這樣寫,那你就錯了,因為這樣會導致相同的資料會一直被存進去,到時候你發公告,同一個人就會收到超多次。
Channel.find_or_create_by(channel_id: channel_id)
先看有沒有相同的資料,如果已經有資料的話就不寫入。如果沒有資料才作寫入。這邊有詳細的說明:https://rails.ruby.tw/active_record_querying.html#find-or-create-by
加入後的主程式長這樣:
def webhook
# 紀錄頻道
Channel.find_or_create_by(channel_id: channel_id)
# 學說話
reply_text = learn(channel_id, received_text)
# 關鍵字回覆
reply_text = keyword_reply(channel_id, received_text) if reply_text.nil?
# 推齊
reply_text = echo2(channel_id, received_text) if reply_text.nil?
# 記錄對話
save_to_received(channel_id, received_text)
save_to_reply(channel_id, reply_text)
# 傳送訊息到 line
response = reply_to_line(reply_text)
# 回應 200
head :ok
end
接下來要作一個後台網頁去發這個公告。我們會需要兩個 Action,一個 get new Action 用來顯示發公告的後台頁面,另一個 post create Action 用來接收發公告訊息的請求。
這次我們手動新增,不使用產生器。
修改 config/routes.rb
,新增一行:
resources :push_messages, only: [:new, :create]
這是加入一組資源,但我們只使用其中的 new 和 create。
在 app/controllers
資料夾下建立一個叫作 push_messages_controller.rb
的檔案:
class PushMessagesController < ApplicationController
before_action :authenticate_user!
# GET /push_messages/new
def new
end
# POST /push_messages
def create
end
end
我們檢查使用者必須先登入,然後開了兩個空的 Action,之後再回頭來改。
我們要在 app/views/push_messages
下新增一個檔案 new.html.erb
。
這是 new.html.erb
所需要的全部程式碼:
<%= form_with(url: '/push_messages', local: true) do |form| %>
<%= text_area_tag 'text' %>
<%= submit_tag "送出" %>
<% end %>
一個表單的開始是 <%= form_with ..... do ... %>
,結束是 <% end %>
。表單預設是用 post 方法,所以就不用特別寫出來。
<%= text_area_tag 'text' %>
是輸入文字框。
<%= submit_tag "送出" %>
則是送出按鈕。
如果要了解更多的話可以參考:Action View 表單輔助方法
我們在接收到請求之後要作發訊息的動作:
def create
text = params[:text]
Channel.all.each do |channel|
push_to_line(channel.channel_id, text)
end
redirect_to '/push_messages/new'
end
text = params[:text]
這是取得剛剛在輸入文字框填的文字
Channel.all.each do |channel|
... end
這段是指我們想要對每一個 channel 作一些事情。
push_to_line(channel.channel_id, text)
這是說我們要主動發訊息 text
給頻道 channel.channel_id
,這個函數我們待會才會寫。
# 傳送訊息到 line
def push_to_line(channel_id, text)
return nil if channel_id.nil? or text.nil?
# 設定回覆訊息
message = {
type: 'text',
text: text
}
# 傳送訊息
line.push_message(channel_id, message)
end
長得跟之前的 reply_to_line
有 87% 像,就不解釋了。
完整的 push_messages_controller.rb
應該長這樣:
require 'line/bot'
class PushMessagesController < ApplicationController
before_action :authenticate_user!
# GET /push_messages/new
def new
end
# POST /push_messages
def create
text = params[:text]
Channel.all.each do |channel|
push_to_line(channel.channel_id, text)
end
redirect_to '/push_messages/new'
end
# 傳送訊息到 line
def push_to_line(channel_id, text)
return nil if channel_id.nil? or text.nil?
# 設定回覆訊息
message = {
type: 'text',
text: text
}
# 傳送訊息
line.push_message(channel_id, message)
end
# Line Bot API 物件初始化
def line
@line ||= Line::Bot::Client.new { |config|
config.channel_secret = '9160ce4f0be51cc72c3c8a14119f567a'
config.channel_token = '2ncMtCFECjdTVmopb/QSD1PhqM6ECR4xEqC9uwIzELIsQb+I4wa/s3pZ4BH8hCWeqfkpVGVig/mIPDsMjVcyVbN/WNeTTw5eHEA7hFhaxPmQSY2Cud51LKPPiXY+nUi+QrXy0d7Hi2YUs65B/tVOpgdB04t89/1O/w1cDnyilFU='
}
end
end
自己試試看,你們需要練習自己解決卡關,要養成看 log 的習慣。
你需要把主動發訊息這件事情加入排程,請參考:Active Job 基礎 以及 Delayed Job (DJ)。
自己摸這個要有花上一週的心理準備,加油加油加油,你是最棒的,耶!
沒意外的話,明天就講怎麼查天氣。
卡米大 那個我記得Push API在免費版本是不是無法使用阿
對,免費板無法用 push message。
我在第三天:作一隻最簡單的 Line 聊天機器人有提到「Plan:Developer Trail 是試用版,Free 是免費版。當然試用版也是免費,差別在於試用版只能加 50 個好友,但是可以使用加值功能,建議選試用版。」
如果你要改試用版,可以直接註冊一個新的試用版,然後把你的 webhook url 接上去,程式碼裡的 secret 跟 token 改一下就好了。
了解 因為機器人是幾個月前創的 不知道有這個試用版xD
對了想請問一下 我想用聊天室內的指令發送公告 以下是程式碼:
# 發送公告
def send_announcement(channel_id, received_text)
return nil unless received_text[0..6] == '/發送公告 '
text = received_text[7..-1]
Channel.all.each do |channel|
push_to_line(channel.channel_id, text)
end
# 傳送訊息到 line
def push_to_line(channel_id, text)
return nil if channel_id.nil? or text.nil?
puts channel_id, text
# 設定回覆訊息
message = {
type: 'text',
text: text
}
# 傳送訊息
line.push_message(channel_id, message)
end
請問這樣打是OK的嗎 還是還要在主程式調用send_announcement呢
# 發送公告
def send_announcement(channel_id, received_text)
return nil unless received_text[0..6] == '/發送公告 '
text = received_text[7..-1]
Channel.all.each do |channel|
push_to_line(channel.channel_id, text)
end
end
主程式當然要調用send_announcement
感恩卡米大 用好了XD
我照著上面的程式,也嘗試一下在聊天室發公告
但奇怪的是,只有該聊天室會出現公告,其他群組並沒有。
而且,發送公告只RUN一次,後會在打 /發送公告 就不會在反應了
應該是我 主程式調用 的方式有問題
reply_text = send_announcement(channel_id, received_text)
我也嘗試過其他方式,但也是怪怪的...
恩,終於查到原因了
return nil unless received_text[0..6] == '/發送公告 '
text = received_text[7..-1]
字數錯了
return nil unless received_text[0..5] == '/發送公告 '
text = received_text[6..-1]
XD
想請問卡米大~
今天在作heroku資料庫遷移時一直無法遷移成功,錯誤訊息顯示都卡在倒數第二個,想請問怎麼解決呢?
完整錯誤訊息:
https://drive.google.com/open?id=1RswxzP3VdST65cnY7pu8VSeppxD4KmAE24u9EA8sktQ
看起來是你的資料庫裡面已經有 users 表格了,如果資料消失也沒關係,你可以這樣:
heroku run rake db:drop
heroku run rake db:create
heroku run rake db:migrate
應該可以解決問題
sorry 說錯指令了
heroku pg:reset
heroku run rake db:migrate
這次一定行惹
他不給面紙XDD
還是不行耶XDDD
(錯誤訊息同上XD)
可是我可以
我到這步驟也可,但是一遷移資料庫又出現一樣錯誤惹~
然後我看了一下昨天的文章,有新的人留言,發現好像也卡在類似的地方,好像都是那個檔案無法遷移卡住
然後我看了一下昨天的文章,有新的人留言,發現好像也卡在類似的地方,好像都是那個檔案無法遷移卡住
額 好奇怪
可以看一下你的 db/migrate
資料夾內的檔案列表嗎?
db/migrate 資料夾:
然後我參考上一篇的留言讀取 db/development.sqlite3截圖:
你的情況跟他的不太一樣,是因為你的 migrate 出問題的是 heroku ,他出問題的是本機,這個是觀察本機的資料庫內容,而 heroku 上的資料庫要觀察的話要裝別的東西 XD
不過你怎麼有兩個 add user 的 migration 檔?我只有一個 devise_create_users,你多一個add_devise_to_users 這兩個都打開來看一下,如果一樣的話,刪掉一個。
謝謝卡米大~~
刪掉一個後就就解決了~~
cool
不好意思,如果想要設計成一個text放channel_ID,另一個test輸入文字的話該怎麼設計呢
沒事,解決了,謝謝
原本的測試完感覺很奇怪
輸入channel_id: XXXX1 之後,再輸入channel_id: XXXX2
可是他會連XXXX1跟XXXX2一起發公告,而且沒辦法取消
不知道能不能改寫成一次只發送一個群組的方式?
我看不懂你想要作什麼XD
我想,s12873514的意思是希望能把公告發出給指定的 channel_id
我照著卡米大的程式,第一個公告只有最新一次有對話的 channel_id 收到;接著我去跟這個機器人"聊"一下,再送出一個公告,結果只有最新這兩個 channel_id 有收到公告。
要怎樣指定一個或多個或全 channel_id 發公告?
卡米大大的範例,是用Channel.all.each do |channel|把整個Channel資料庫裡的channel_id逐一發送公告。
因此不要把指令放進迴圈,就可以單獨發訊息
push_to_line('Cecdd55d54053daa42f7501a8db081fa2',text)
# 紀錄頻道
if channel_id.include? 'C'
Channel.find_or_create_by(channel_id: channel_id)
end
event_type = params['events'][0]['type']
if event_type == 'join'
event_text = "感謝邀請~~\n可使用 /說明/ 查看指令用法唷"
push_to_line(channel_id,event_text)
push_to_line('Cecdd55d54053daa42f7501a8db081fa2',"邀請 #{channel_id}")
end
if event_type == 'leave'
event_text = "再見囉~~"
push_to_line(channel_id,event_text)
push_to_line('Cecdd55d54053daa42f7501a8db081fa2',"離開 #{channel_id}")
channel_dell = Channel.find_by(channel_id: channel_id)
channel_dell.destroy
end
終於成功了....原來我的其實是免費版...所以才會一直出現 304號錯誤
因為我用LINE的後台,可以發送1千次訊息,也都可以成功發送。
但撿查很多次程式和步驟,也都找不出問題。
剛剛想說確認一下,才發現我是 免費版 (因為也是好幾個月前創的BOT帳號)
重新創 試用版的 終於成功了。
感恩卡米,讚嘆卡米
恭喜
不好意思我push_messages的後台一直找不到網頁,可是我在views和routers.rb都有新增
https://imgur.com/evryOeT
找不到原因...
只看這張圖無法幫你找原因喔
我想大大是網址打錯了 要 /push_messages/new 才進得去 /push_messages 進不去
請問卡米大大 離開群組的指令該怎麼打
https://developers.line.me/en/docs/messaging-api/reference/#leave-event
這邊看半天 實在看不懂
根據 https://github.com/line/line-bot-sdk-ruby/blob/master/lib/line/bot/client.rb
可以知道
如果是群組要寫這行:
line.leave_group(channel_id)
如果是聊天室要寫這行:
line.leave_room(channel_id)
# leave
reply_text = leave(channel_id, received_text)
# 離開
def leave(channel_id, received_text)
return nil unless received_text.include? '女神掰囉'
response = reply_to_line('掰掰囉')
line.leave_group(channel_id)
line.leave_room(channel_id)
end
感恩卡米大大 成功!
請問發公告是不要要先傳訊號才會收到~ 我第一個群組因為有傳訊息才有收到,第二個群組沒有,要先傳訊息 第二個群組才會收到
這要看你的 channel 什麼時候被記錄
請問我填完內容按送出後,沒有收到主動推播
terminal 顯示302 這樣是什麼地方出問題呢? 卡米大
新增channel_id後,問題已自行解決
請問卡米大大
發一百群 大約要30~50秒,有時後一百多群 2~3分鐘
有方法可以提升速度嗎?
或者是因為 試用版的 速限
Developer Trial 1,000/min per API endpoint 20,000/min per bot
Other plans 10,000/min per API endpoint 200,000/min per bot
有方法可以提升速度嗎? 有的,有一種東西叫做 sidekiq,它可以幫助你同時進行一些工作
無法成功發送公告
請問改版後的line bot 註冊介面如何選擇或是查看自己是免費版還是試用版
不知道是不是因為帳號的原因導致無法發送