Facebook Messenger 机器人:postback.reply webhook 与数据库查询不匹配
Facebook Messenger bot: postback.reply webhook mismatch with db query
我有一个正在使用 this rails gem 的 Messenger 聊天机器人。它发送一个选择加入以允许人们订阅。当他们点击订阅按钮时,webhook 会发送一个回发负载 "SUB_YES_PAYLOAD",它允许我们保存订阅者并回复用户定义的确认消息(该消息从使用我们的 bot 的页面更改为另一个页面)。
但是,有时回传回复会发送另一个页面的确认消息...我挠了挠头好几个小时,但找不到问题所在?
这里是 webhook 代码:
Bot.on :postback do |postback|
# We get the page record with the page ID sent by Facebook
@core_bot = CoreBot.find_by_page_id(postback.recipient['id'])
if postback.payload == 'SUB_YES_PAYLOAD'
# We check the subscriber is not already subscribed in our db
if BotUser.find_by_sender_id(postback.sender['id']).present? == false
# save to the db
url = "https://graph.facebook.com/v2.6/" + postback.sender['id'] + "?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=" + @core_bot.page_access_token
resp = Net::HTTP.get_response(URI.parse(url))
@user_data = JSON.parse(resp.body)
@first_name = @user_data['first_name']
@last_name = @user_data['last_name']
@profile_pic = @user_data['profile_pic']
@locale = @user_data['locale']
@timezone = @user_data['timezone']
@gender = @user_data['gender']
@bot_user = BotUser.new(core_bot_id: @core_bot.id, sender_id: postback.sender['id'], first_name: @first_name, last_name: @last_name, profile_pic: @profile_pic, locale: @locale, timezone: @timezone, gender: @gender)
@bot_user.save
if @bot_user.save
# if the user defined a confirmation message in his settings
if @core_bot.yes_subscribe_message.present? == true
postback.reply({
text: @core_bot.yes_subscribe_message # That's what's wrong here sometimes
})
else
postback.reply({
text: "Welcome!"
})
end
end
end
end
end
这是发送错误确认的一张图片:
当我调用@core_bot.yes_subscribe_message 时,@core_bot 似乎不正确,但订阅者被保存到正确的@core_bot ID,所以没有理由在...
之后发生变化
我的应用程序在一个 Heroku 标准 web dyno 和一个 Heroku Postgres Hobby 经典数据库上。
编辑,这里是CoreBot模型:
# id :integer not null, primary key
# user_id :integer
# page_name :string
# page_id :integer
# page_access_token :string
# greeting_message :string
# yes_subscribe_button :string
# no_subscribe_button :string
# yes_subscribe_message :string
# no_subscribe_message :string
# created_at :datetime not null
# updated_at :datetime not null
# active :boolean default(TRUE)
# picture :string default("https://scontent.xx.fbcdn.net/v/t1.0-1/p480x480/20729408_135562287047146_4447605348389117589_n.png?oh=ba7b4a319a002db384168f50e1ccfec5&oe=5AAE506E")
#
class CoreBot < ApplicationRecord
validates_uniqueness_of :page_id
validates :page_id, :presence => true
has_secure_token
belongs_to :user
has_many :letters, dependent: :destroy
has_many :bot_users, dependent: :destroy
has_many :weekly_analytics, dependent: :destroy
has_many :segments, dependent: :destroy
has_many :sequences, dependent: :destroy
has_many :invitations, dependent: :destroy
has_one :checkbox_iframe, dependent: :destroy
has_one :button_iframe, dependent: :destroy
end
谢谢。
我认为发生这种情况是因为您使用了实例变量 @core_bot
并且您的机器人可能只有一个实例,每次用户进入时都会执行该块。因此,如果没有并行发生任何事情,一切都很好,因为 shared
@core_bot
实例已设置并始终保持不变。但是如果你有很多用户,一个新的@core_bot实例被添加,而块仍然是运行。
所以解决方案是删除所有 @
符号,使变量在块的执行范围内是局部的。
Bot.on :postback do |postback|
# We get the page record with the page ID sent by Facebook
core_bot = CoreBot.find_by_page_id(postback.recipient['id'])
if postback.payload == 'SUB_YES_PAYLOAD'
# We check the subscriber is not already subscribed in our db
if BotUser.find_by_sender_id(postback.sender['id']).present? == false
# save to the db
url = "https://graph.facebook.com/v2.6/" + postback.sender['id'] + "?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=" + core_bot.page_access_token
resp = Net::HTTP.get_response(URI.parse(url))
user_data = JSON.parse(resp.body)
first_name = user_data['first_name']
last_name = user_data['last_name']
profile_pic = user_data['profile_pic']
locale = user_data['locale']
timezone = user_data['timezone']
gender = user_data['gender']
bot_user = BotUser.new(core_bot_id: core_bot.id, sender_id: postback.sender['id'], first_name: first_name, last_name: last_name, profile_pic: profile_pic, locale: locale, timezone: timezone, gender: gender)
if bot_user.save
# if the user defined a confirmation message in his settings
if core_bot.yes_subscribe_message.present? == true
postback.reply({
text: core_bot.yes_subscribe_message
})
else
postback.reply({
text: "Welcome!"
})
end
end
end
end
end
我有一个正在使用 this rails gem 的 Messenger 聊天机器人。它发送一个选择加入以允许人们订阅。当他们点击订阅按钮时,webhook 会发送一个回发负载 "SUB_YES_PAYLOAD",它允许我们保存订阅者并回复用户定义的确认消息(该消息从使用我们的 bot 的页面更改为另一个页面)。
但是,有时回传回复会发送另一个页面的确认消息...我挠了挠头好几个小时,但找不到问题所在?
这里是 webhook 代码:
Bot.on :postback do |postback|
# We get the page record with the page ID sent by Facebook
@core_bot = CoreBot.find_by_page_id(postback.recipient['id'])
if postback.payload == 'SUB_YES_PAYLOAD'
# We check the subscriber is not already subscribed in our db
if BotUser.find_by_sender_id(postback.sender['id']).present? == false
# save to the db
url = "https://graph.facebook.com/v2.6/" + postback.sender['id'] + "?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=" + @core_bot.page_access_token
resp = Net::HTTP.get_response(URI.parse(url))
@user_data = JSON.parse(resp.body)
@first_name = @user_data['first_name']
@last_name = @user_data['last_name']
@profile_pic = @user_data['profile_pic']
@locale = @user_data['locale']
@timezone = @user_data['timezone']
@gender = @user_data['gender']
@bot_user = BotUser.new(core_bot_id: @core_bot.id, sender_id: postback.sender['id'], first_name: @first_name, last_name: @last_name, profile_pic: @profile_pic, locale: @locale, timezone: @timezone, gender: @gender)
@bot_user.save
if @bot_user.save
# if the user defined a confirmation message in his settings
if @core_bot.yes_subscribe_message.present? == true
postback.reply({
text: @core_bot.yes_subscribe_message # That's what's wrong here sometimes
})
else
postback.reply({
text: "Welcome!"
})
end
end
end
end
end
这是发送错误确认的一张图片:
当我调用@core_bot.yes_subscribe_message 时,@core_bot 似乎不正确,但订阅者被保存到正确的@core_bot ID,所以没有理由在...
之后发生变化我的应用程序在一个 Heroku 标准 web dyno 和一个 Heroku Postgres Hobby 经典数据库上。
编辑,这里是CoreBot模型:
# id :integer not null, primary key
# user_id :integer
# page_name :string
# page_id :integer
# page_access_token :string
# greeting_message :string
# yes_subscribe_button :string
# no_subscribe_button :string
# yes_subscribe_message :string
# no_subscribe_message :string
# created_at :datetime not null
# updated_at :datetime not null
# active :boolean default(TRUE)
# picture :string default("https://scontent.xx.fbcdn.net/v/t1.0-1/p480x480/20729408_135562287047146_4447605348389117589_n.png?oh=ba7b4a319a002db384168f50e1ccfec5&oe=5AAE506E")
#
class CoreBot < ApplicationRecord
validates_uniqueness_of :page_id
validates :page_id, :presence => true
has_secure_token
belongs_to :user
has_many :letters, dependent: :destroy
has_many :bot_users, dependent: :destroy
has_many :weekly_analytics, dependent: :destroy
has_many :segments, dependent: :destroy
has_many :sequences, dependent: :destroy
has_many :invitations, dependent: :destroy
has_one :checkbox_iframe, dependent: :destroy
has_one :button_iframe, dependent: :destroy
end
谢谢。
我认为发生这种情况是因为您使用了实例变量 @core_bot
并且您的机器人可能只有一个实例,每次用户进入时都会执行该块。因此,如果没有并行发生任何事情,一切都很好,因为 shared
@core_bot
实例已设置并始终保持不变。但是如果你有很多用户,一个新的@core_bot实例被添加,而块仍然是运行。
所以解决方案是删除所有 @
符号,使变量在块的执行范围内是局部的。
Bot.on :postback do |postback|
# We get the page record with the page ID sent by Facebook
core_bot = CoreBot.find_by_page_id(postback.recipient['id'])
if postback.payload == 'SUB_YES_PAYLOAD'
# We check the subscriber is not already subscribed in our db
if BotUser.find_by_sender_id(postback.sender['id']).present? == false
# save to the db
url = "https://graph.facebook.com/v2.6/" + postback.sender['id'] + "?fields=first_name,last_name,profile_pic,locale,timezone,gender&access_token=" + core_bot.page_access_token
resp = Net::HTTP.get_response(URI.parse(url))
user_data = JSON.parse(resp.body)
first_name = user_data['first_name']
last_name = user_data['last_name']
profile_pic = user_data['profile_pic']
locale = user_data['locale']
timezone = user_data['timezone']
gender = user_data['gender']
bot_user = BotUser.new(core_bot_id: core_bot.id, sender_id: postback.sender['id'], first_name: first_name, last_name: last_name, profile_pic: profile_pic, locale: locale, timezone: timezone, gender: gender)
if bot_user.save
# if the user defined a confirmation message in his settings
if core_bot.yes_subscribe_message.present? == true
postback.reply({
text: core_bot.yes_subscribe_message
})
else
postback.reply({
text: "Welcome!"
})
end
end
end
end
end