kogno 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/kogno +92 -0
- data/lib/boot.rb +9 -0
- data/lib/core/bin_helpers/messenger_ctl.rb +48 -0
- data/lib/core/bin_helpers/scaffolding.rb +203 -0
- data/lib/core/bin_helpers/scheduled_messages_ctl.rb +95 -0
- data/lib/core/bin_helpers/sequences_ctl.rb +95 -0
- data/lib/core/bin_helpers/server_ctl.rb +127 -0
- data/lib/core/bin_helpers/telegram_ctl.rb +48 -0
- data/lib/core/bin_helpers/webhook_ctl.rb +96 -0
- data/lib/core/db.rb +8 -0
- data/lib/core/extensions/array.rb +28 -0
- data/lib/core/extensions/hash.rb +12 -0
- data/lib/core/extensions/logger.rb +70 -0
- data/lib/core/extensions/string.rb +6 -0
- data/lib/core/extensions/wit.rb +60 -0
- data/lib/core/global_methods.rb +67 -0
- data/lib/core/helpers/string.rb +105 -0
- data/lib/core/lib/base_config.rb +17 -0
- data/lib/core/lib/block_params.rb +4 -0
- data/lib/core/lib/context.rb +1573 -0
- data/lib/core/lib/error_handler.rb +36 -0
- data/lib/core/lib/message.rb +182 -0
- data/lib/core/lib/messenger/api.rb +281 -0
- data/lib/core/lib/messenger/facebook_graph.rb +32 -0
- data/lib/core/lib/messenger/message.rb +202 -0
- data/lib/core/lib/messenger/notification.rb +351 -0
- data/lib/core/lib/messenger/post_comment.rb +104 -0
- data/lib/core/lib/messenger/recurring_notification.rb +81 -0
- data/lib/core/lib/nlp.rb +191 -0
- data/lib/core/lib/notification.rb +371 -0
- data/lib/core/lib/spelling.rb +13 -0
- data/lib/core/lib/telegram/api.rb +197 -0
- data/lib/core/lib/telegram/chat_activity.rb +111 -0
- data/lib/core/lib/telegram/inline_query.rb +112 -0
- data/lib/core/lib/telegram/message.rb +327 -0
- data/lib/core/lib/telegram/notification.rb +507 -0
- data/lib/core/lib/whatsapp/api.rb +153 -0
- data/lib/core/lib/whatsapp/message.rb +132 -0
- data/lib/core/lib/whatsapp/notification.rb +206 -0
- data/lib/core/lib/whatsapp/status_message.rb +58 -0
- data/lib/core/loaders/config_files.rb +15 -0
- data/lib/core/models/chat_log.rb +4 -0
- data/lib/core/models/long_payload.rb +25 -0
- data/lib/core/models/matched_message.rb +5 -0
- data/lib/core/models/messenger_recurring_notification.rb +16 -0
- data/lib/core/models/scheduled_message.rb +40 -0
- data/lib/core/models/sequence.rb +29 -0
- data/lib/core/models/telegram_chat_group.rb +26 -0
- data/lib/core/models/user.rb +285 -0
- data/lib/core/web/webhook.rb +198 -0
- data/lib/kogno.rb +130 -0
- data/scaffolding/new_project/Gemfile +3 -0
- data/scaffolding/new_project/application.rb +5 -0
- data/scaffolding/new_project/bot/contexts/main_context.rb +10 -0
- data/scaffolding/new_project/bot/conversation.rb +14 -0
- data/scaffolding/new_project/bot/models/user.rb +3 -0
- data/scaffolding/new_project/config/application.rb +28 -0
- data/scaffolding/new_project/config/database.yml +8 -0
- data/scaffolding/new_project/config/locales/en.yml +4 -0
- data/scaffolding/new_project/config/locales/es.yml +3 -0
- data/scaffolding/new_project/config/nlp.rb +23 -0
- data/scaffolding/new_project/config/platforms/messenger.rb +74 -0
- data/scaffolding/new_project/config/platforms/telegram.rb +45 -0
- data/scaffolding/new_project/config/platforms/whatsapp.rb +13 -0
- data/scaffolding/new_project/web/routes.rb +10 -0
- metadata +220 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
module Kogno
|
2
|
+
module Messenger
|
3
|
+
class Message < Kogno::Message
|
4
|
+
|
5
|
+
def initialize(data)
|
6
|
+
@data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def platform
|
10
|
+
:messenger
|
11
|
+
end
|
12
|
+
|
13
|
+
def sender_id
|
14
|
+
return @data[:sender][:id]
|
15
|
+
end
|
16
|
+
|
17
|
+
def page_id
|
18
|
+
return @data[:recipient][:id]
|
19
|
+
end
|
20
|
+
|
21
|
+
def raw_payload
|
22
|
+
payload = @data[:postback][:payload] rescue nil
|
23
|
+
payload = (@data[:message][:quick_reply][:payload] rescue nil) if payload.nil?
|
24
|
+
payload = @overwritten_payload if payload.nil?
|
25
|
+
return(payload)
|
26
|
+
end
|
27
|
+
|
28
|
+
def stickers
|
29
|
+
@data[:message][:attachments].map{|a| a[:payload][:sticker_id]}.compact rescue []
|
30
|
+
end
|
31
|
+
|
32
|
+
def attachments
|
33
|
+
attachments = nil
|
34
|
+
attachments = @data[:message][:attachments] rescue nil
|
35
|
+
attachments
|
36
|
+
end
|
37
|
+
|
38
|
+
def referral(field=nil) # Field could be :context or :params)
|
39
|
+
referral = (@data[:postback][:referral] rescue nil)
|
40
|
+
referral = @data[:referral] if referral.nil?
|
41
|
+
|
42
|
+
if referral.nil? || referral == ""
|
43
|
+
return nil
|
44
|
+
# elsif referral[:ref].nil? || referral[:ref] == ""
|
45
|
+
# return nil
|
46
|
+
elsif field.nil?
|
47
|
+
return referral
|
48
|
+
elsif field == :source
|
49
|
+
return referral[:source]
|
50
|
+
elsif field == :type
|
51
|
+
return referral[:type]
|
52
|
+
elsif field == :ref
|
53
|
+
return(referral[:ref] == "" ? nil : referral[:ref])
|
54
|
+
else
|
55
|
+
ref = (referral[:ref].split(Regexp.union(["/","-"]),2) rescue [])
|
56
|
+
if field == :context
|
57
|
+
return (ref[0] rescue nil)
|
58
|
+
elsif field == :params
|
59
|
+
return digest_referral_params(ref[1])
|
60
|
+
else
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def digest_referral_params(params)
|
68
|
+
dparams = {}
|
69
|
+
return dparams if params.nil?
|
70
|
+
dparams = (JSON.parse(params,{:symbolize_names => true}) rescue {})
|
71
|
+
if dparams.empty?
|
72
|
+
params.to_s.split(";").each do |param|
|
73
|
+
item = param.split(":")
|
74
|
+
if item.length > 1
|
75
|
+
dparams[item[0].to_sym] = item[1]
|
76
|
+
else
|
77
|
+
break
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
dparams = params if dparams.empty?
|
82
|
+
return dparams
|
83
|
+
end
|
84
|
+
|
85
|
+
def raw_message
|
86
|
+
m = @data[:message]
|
87
|
+
return nil if m.nil?
|
88
|
+
if !m[:text].nil?
|
89
|
+
return({
|
90
|
+
:type => :text,
|
91
|
+
:value => m[:text]
|
92
|
+
})
|
93
|
+
elsif !m[:attachments].nil?
|
94
|
+
m[:attachments].each do |attachment|
|
95
|
+
case attachment[:type]
|
96
|
+
when "location"
|
97
|
+
return({
|
98
|
+
:type => :location,
|
99
|
+
:value => {
|
100
|
+
:lat => attachment[:payload][:coordinates][:lat],
|
101
|
+
:lon => attachment[:payload][:coordinates][:long]
|
102
|
+
}
|
103
|
+
})
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def text
|
110
|
+
if (self.raw_message[:type] == :text rescue false)
|
111
|
+
return self.raw_message[:value].to_s
|
112
|
+
else
|
113
|
+
return ""
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def get_context(user,msg,notification)
|
118
|
+
|
119
|
+
if !(context_from_postback = Context.get_from_payload(msg.payload)).nil?
|
120
|
+
context_route = context_from_postback
|
121
|
+
elsif !(context_in_link = Context.get(self.referral(:ref))).nil?
|
122
|
+
context_route = context_in_link[:context]
|
123
|
+
@data[:deep_link_param] = context_in_link[:param]
|
124
|
+
elsif !(context_from_typed_postback = Context.get_from_typed_postback(msg,user)).nil?
|
125
|
+
context_route = context_from_typed_postback
|
126
|
+
else
|
127
|
+
context_route = user.context
|
128
|
+
end
|
129
|
+
|
130
|
+
context_class = Context.router(context_route, msg.type)[:class]
|
131
|
+
if context_class.nil?
|
132
|
+
user.exit_context
|
133
|
+
context_class = Context.router(Kogno::Application.config.routes.default)[:class]
|
134
|
+
end
|
135
|
+
context = context_class.new(user,msg,notification,context_route)
|
136
|
+
context
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
def handle_event(debug=false)
|
141
|
+
|
142
|
+
begin
|
143
|
+
|
144
|
+
user = User.find_or_create_by_psid(self.sender_id, :messenger, self.page_id)
|
145
|
+
user.get_session_vars
|
146
|
+
self.set_nlp(user.locale)
|
147
|
+
I18n.locale = user.locale unless user.locale.nil?
|
148
|
+
|
149
|
+
unless user.vars[:nlp_context_ref].nil?
|
150
|
+
self.nlp.set_context_reference(user.vars[:nlp_context_ref])
|
151
|
+
user.vars.delete(:nlp_context_ref) # context references will only be used once
|
152
|
+
end
|
153
|
+
|
154
|
+
notification = Notification.new(user,self)
|
155
|
+
|
156
|
+
self.log_message_info(user)
|
157
|
+
|
158
|
+
context = get_context(user,self,notification)
|
159
|
+
|
160
|
+
return({msg: self, user: user, notification: notification, context: context}) if debug
|
161
|
+
|
162
|
+
unless empty_thread_from_ad?
|
163
|
+
|
164
|
+
called_action = context.run
|
165
|
+
if Kogno::Application.config.store_log_in_database
|
166
|
+
message_log_id = user.log_message(self).id
|
167
|
+
else
|
168
|
+
message_chat_log_id = 0
|
169
|
+
end
|
170
|
+
|
171
|
+
notification.send
|
172
|
+
|
173
|
+
response_log_id = 0
|
174
|
+
if Kogno::Application.config.store_log_in_database
|
175
|
+
response_log = user.log_response(notification)
|
176
|
+
response_log_id = response_log.id unless response_log.nil?
|
177
|
+
end
|
178
|
+
|
179
|
+
# user.set_last_usage
|
180
|
+
user.save_session_vars
|
181
|
+
context.handle_message_from_memory
|
182
|
+
|
183
|
+
else
|
184
|
+
context.run_class_callbacks_only
|
185
|
+
user.save_session_vars
|
186
|
+
user.log_message(self) if Kogno::Application.config.store_log_in_database
|
187
|
+
end
|
188
|
+
logger.write "- Current user context: #{user.context}", :blue unless user.context.nil?
|
189
|
+
|
190
|
+
rescue StandardError => e
|
191
|
+
error_token = Digest::MD5.hexdigest("#{Time.now}#{rand(1000)}") # This helps to identify the error that arrives to Slack in order to search it in logs/http.log
|
192
|
+
logger.write e.message, :red
|
193
|
+
logger.write "Error Token: #{error_token}", :red
|
194
|
+
logger.write "Backtrace:\n\t#{e.backtrace.join("\n\t")}", :red
|
195
|
+
ErrorHandler.notify_by_slack(Kogno::Application.config.app_name,e, error_token) if Kogno::Application.config.error_notifier.slack[:enable] rescue false
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,351 @@
|
|
1
|
+
module Kogno
|
2
|
+
module Messenger
|
3
|
+
class Notification < Kogno::Notification
|
4
|
+
|
5
|
+
def set_context(context)
|
6
|
+
@context = context
|
7
|
+
end
|
8
|
+
|
9
|
+
def send(messaging_type="RESPONSE",recipient_id=nil,page_id=nil,delete=true)
|
10
|
+
recipient_id = @recipient.psid if recipient_id.nil?
|
11
|
+
page_id = @recipient.page_id if page_id.nil?
|
12
|
+
messages = @before_messages+@messages+@after_messages
|
13
|
+
@message_log = messages
|
14
|
+
messages.each do |message|
|
15
|
+
if message[:type].to_sym == :action
|
16
|
+
@response_log << Api::send_action(recipient_id,message[:value][:action],messaging_type,page_id)
|
17
|
+
sleep(message[:value][:duration]) if message[:value][:action].to_sym == :typing_on
|
18
|
+
else
|
19
|
+
message = self.replace_place_holders(message[:value])
|
20
|
+
@response_log << Api::send_message(recipient_id,message,messaging_type,page_id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
self.delete_messages() if delete
|
24
|
+
end
|
25
|
+
|
26
|
+
def send_using_token()
|
27
|
+
notification_token = @recipient.messenger_recurring_notification.token rescue nil
|
28
|
+
if notification_token.nil?
|
29
|
+
logger.write "Error. The user doesn't have a messenger recurring notification token", :red
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
page_id = @recipient.page_id if page_id.nil?
|
33
|
+
messages = @before_messages+@messages+@after_messages
|
34
|
+
@message_log = messages
|
35
|
+
messages.each do |message|
|
36
|
+
if message[:type].to_sym == :action
|
37
|
+
# @response_log << Api::send_action(recipient_id,message[:value][:action],messaging_type,page_id)
|
38
|
+
sleep(message[:value][:duration]) if message[:value][:action].to_sym == :typing_on
|
39
|
+
else
|
40
|
+
message = self.replace_place_holders(message[:value])
|
41
|
+
@response_log << Api::send_message_with_rn_token(notification_token,message,page_id)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
self.delete_messages()
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# def schedule(send_at, tag=nil)
|
49
|
+
# unless @recipient.nil?
|
50
|
+
# @recipient.scheduled_messages.create({
|
51
|
+
# messages: @messages.to_json,
|
52
|
+
# tag: tag,
|
53
|
+
# send_at: send_at
|
54
|
+
# })
|
55
|
+
# self.delete_messages()
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
|
59
|
+
def send_private_reply(recipient_id=nil,page_id=nil,delete=true)
|
60
|
+
response = []
|
61
|
+
recipient_id = @recipient.psid if recipient_id.nil?
|
62
|
+
@message_log = @messages
|
63
|
+
@messages.each do |message|
|
64
|
+
message = self.replace_place_holders(message[:value])
|
65
|
+
@response_log << Api::send_private_reply(recipient_id,message,page_id)
|
66
|
+
end
|
67
|
+
self.delete_messages() if delete
|
68
|
+
end
|
69
|
+
|
70
|
+
def response_log
|
71
|
+
@response_log
|
72
|
+
end
|
73
|
+
|
74
|
+
def message_log
|
75
|
+
@message_log
|
76
|
+
end
|
77
|
+
|
78
|
+
def destroy_message_log
|
79
|
+
@message_log = []
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_psid_from_response_log
|
83
|
+
return(@response_log.first[:recipient_id] rescue nil)
|
84
|
+
end
|
85
|
+
|
86
|
+
def send_multiple(users,messaging_type)
|
87
|
+
logger.write "Sending..", :green
|
88
|
+
logger.write_json @messages, :bright
|
89
|
+
logger.write "To:", :green
|
90
|
+
users.each do |user|
|
91
|
+
logger.write "PSID: #{user[:psid]}", :bright
|
92
|
+
send(messaging_type,user[:psid],user[:page_id],false)
|
93
|
+
end
|
94
|
+
self.delete_messages()
|
95
|
+
end
|
96
|
+
|
97
|
+
def import_messages(messages,position="")
|
98
|
+
messages = messages.class == Array ? messages : JSON.parse(messages,{:symbolize_names => true})
|
99
|
+
case position.to_sym
|
100
|
+
when :before
|
101
|
+
@before_messages = messages
|
102
|
+
when :after
|
103
|
+
@after_messages = messages
|
104
|
+
else
|
105
|
+
@messages = messages
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def export_messages
|
110
|
+
|
111
|
+
messages = @messages.to_json
|
112
|
+
self.delete_messages()
|
113
|
+
return messages
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
def delete_messages()
|
118
|
+
@before_messages = []
|
119
|
+
@messages = []
|
120
|
+
@after_messages = []
|
121
|
+
end
|
122
|
+
|
123
|
+
def text(text, extra_params={})
|
124
|
+
text = t(text) if text.class == Symbol
|
125
|
+
text = Notification::rand_text(text)
|
126
|
+
self.push_message(Api::text_message(text))
|
127
|
+
end
|
128
|
+
|
129
|
+
def loading_typing_on(recipient_id)
|
130
|
+
Api::send_action(recipient_id,:typing_on)
|
131
|
+
end
|
132
|
+
|
133
|
+
def loading_typing_off(recipient_id)
|
134
|
+
Api::send_action(recipient_id,:typing_off)
|
135
|
+
end
|
136
|
+
|
137
|
+
def typing_on(duration)
|
138
|
+
self.push_message({:action => :typing_on, :duration => duration}, :action)
|
139
|
+
end
|
140
|
+
|
141
|
+
def typing_off
|
142
|
+
self.push_message({:action => :typing_off}, :action)
|
143
|
+
end
|
144
|
+
|
145
|
+
def quick_reply(text,replies,extra_settings={})
|
146
|
+
settings = {typed_postbacks: Kogno::Application.config.typed_postbacks}.merge(extra_settings) # defaults
|
147
|
+
replies = [replies] if replies.class == Hash
|
148
|
+
replies = replies.map{|h| {content_type: :text}.merge(h)}
|
149
|
+
text = t(text) if text.class == Symbol
|
150
|
+
text = Notification::rand_text(text)
|
151
|
+
replies = replies.map{|r| {title: r[:title], payload: r[:payload], content_type: r[:content_type] || :text}} # :text as default
|
152
|
+
set_typed_postbacks(replies.map{|reply|
|
153
|
+
[reply[:title].to_payload, reply[:payload]] unless reply[:title].nil?
|
154
|
+
}.compact.to_h) if settings[:typed_postbacks]
|
155
|
+
self.push_message(Api::quick_replies(text, replies))
|
156
|
+
end
|
157
|
+
|
158
|
+
def button(text,buttons,extra_settings={})
|
159
|
+
settings = {typed_postbacks: Kogno::Application.config.typed_postbacks}.merge(extra_settings) # defaults
|
160
|
+
buttons = buttons.map{|h| {type: :postback}.merge(h)}
|
161
|
+
text = t(text) if text.class == Symbol
|
162
|
+
text = Notification::rand_text(text)
|
163
|
+
set_typed_postbacks(buttons.map{|button|
|
164
|
+
[button[:title].to_payload, button[:payload]] if button[:type] == :postback
|
165
|
+
}.compact.to_h) if settings[:typed_postbacks]
|
166
|
+
self.push_message(Api::button_template(text,buttons))
|
167
|
+
end
|
168
|
+
|
169
|
+
def messenger_generic_template(elements,image_aspect_ratio=:horizontal, quick_replies=[])
|
170
|
+
if quick_replies.empty?
|
171
|
+
message = Api::generic_template(elements,image_aspect_ratio)
|
172
|
+
else
|
173
|
+
quick_replies = [quick_replies] if quick_replies.class == Hash
|
174
|
+
quick_replies = quick_replies.map{|h| {content_type: :text}.merge(h)}
|
175
|
+
message = Api::generic_template_with_replies(elements,image_aspect_ratio, quick_replies)
|
176
|
+
end
|
177
|
+
self.push_message(message)
|
178
|
+
end
|
179
|
+
|
180
|
+
def url(params)
|
181
|
+
params[:messenger_extensions] = false if params[:messenger_extensions].nil?
|
182
|
+
params[:image_aspect_ratio] = :horizontal if params[:image_aspect_ratio].nil?
|
183
|
+
|
184
|
+
ge_params = {
|
185
|
+
title: params[:title],
|
186
|
+
image_url: params[:image],
|
187
|
+
default_action: {
|
188
|
+
type: :web_url,
|
189
|
+
url: params[:url],
|
190
|
+
messenger_extensions: params[:messenger_extensions]
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
ge_params[:buttons] = [
|
195
|
+
{
|
196
|
+
type: :web_url,
|
197
|
+
url: params[:url],
|
198
|
+
title: params[:button],
|
199
|
+
messenger_extensions: params[:messenger_extensions]
|
200
|
+
}
|
201
|
+
] unless params[:button].nil?
|
202
|
+
|
203
|
+
self.messenger_generic_template(ge_params,params[:image_aspect_ratio])
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
def carousel(elements, quick_replies=[], image_aspect_ratio=:horizontal)
|
208
|
+
elements = elements[0..9]
|
209
|
+
elements.map do |element| # sharing element: se va a enviar el mismo elemento con los modificadores agregados en :share_contents
|
210
|
+
unless element[:buttons].nil?
|
211
|
+
element[:buttons].map do |button|
|
212
|
+
if button[:type] == :element_share
|
213
|
+
share_element = Marshal.load(Marshal.dump(element))
|
214
|
+
share_element[:buttons].delete_if{|button| button[:type] == :element_share }
|
215
|
+
button[:share_contents] = Api::generic_template(share_element.merge(button[:share_contents]))
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
if quick_replies.empty?
|
222
|
+
message = Api::generic_template(elements,image_aspect_ratio)
|
223
|
+
else
|
224
|
+
message = Api::generic_template_with_replies(elements,image_aspect_ratio, quick_replies)
|
225
|
+
end
|
226
|
+
self.push_message(message)
|
227
|
+
end
|
228
|
+
|
229
|
+
def recurring_notification_request(request)
|
230
|
+
|
231
|
+
attachment = {
|
232
|
+
type: :template,
|
233
|
+
payload: {
|
234
|
+
template_type: :notification_messages,
|
235
|
+
title: request[:title],
|
236
|
+
notification_messages_frequency: request[:frequency].to_s.upcase,
|
237
|
+
notification_messages_reoptin: request[:reoptin] ? "ENABLED" : "DISABLED",
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
attachment[:payload][:image_url] = request[:image_url] unless request[:image_url].nil?
|
242
|
+
attachment[:payload][:payload] = request[:payload] unless request[:payload].nil?
|
243
|
+
attachment[:payload][:notification_messages_timezone] = request[:timezone] unless request[:timezone].nil?
|
244
|
+
|
245
|
+
self.push_message(Api.attachment_message(attachment))
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
def image(params)
|
250
|
+
params[:image_aspect_ratio] = :horizontal if params[:image_aspect_ratio].nil?
|
251
|
+
|
252
|
+
message = {
|
253
|
+
title: params[:caption],
|
254
|
+
image_url: params[:url]
|
255
|
+
}
|
256
|
+
|
257
|
+
quick_replies = []
|
258
|
+
quick_replies = params[:buttons] unless params[:buttons].nil?
|
259
|
+
|
260
|
+
self.messenger_generic_template(message,params[:image_aspect_ratio], quick_replies)
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
def video(params)
|
265
|
+
|
266
|
+
message = {
|
267
|
+
type: :template,
|
268
|
+
payload: {
|
269
|
+
template_type: :media,
|
270
|
+
elements: [
|
271
|
+
{
|
272
|
+
media_type: :video,
|
273
|
+
url: params[:url]
|
274
|
+
}
|
275
|
+
]
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
unless params[:buttons].nil?
|
280
|
+
buttons = params[:buttons].class == Hash ? [params[:buttons]] : params[:buttons]
|
281
|
+
buttons.map{|button| {type: :postback}.merge(button)}
|
282
|
+
message[:payload][:elements][0][:buttons] = buttons
|
283
|
+
end
|
284
|
+
|
285
|
+
Api::attachment_message(message)
|
286
|
+
end
|
287
|
+
|
288
|
+
def set_vars(vars)
|
289
|
+
@vars = @vars.merge(vars)
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.rand_text(text)
|
293
|
+
if text.class == Array
|
294
|
+
return(text[rand(text.count)])
|
295
|
+
else
|
296
|
+
return(text)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
def replace_place_holders(message)
|
302
|
+
message_in_json = message.to_json
|
303
|
+
@vars.each do |place_holder,replacement_value|
|
304
|
+
message_in_json = message_in_json.gsub(":::#{place_holder}:::",replacement_value.to_s)
|
305
|
+
end
|
306
|
+
JSON.parse(message_in_json)
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
def push_message(message,type=:message) # :message o :action
|
311
|
+
new_message = {:type => type, :value => message}
|
312
|
+
logger.debug_json new_message, :blue
|
313
|
+
@messages << new_message
|
314
|
+
end
|
315
|
+
|
316
|
+
|
317
|
+
def set_typed_postbacks(typed_postbacks)
|
318
|
+
@recipient.vars[:typed_postbacks] = {} if @recipient.vars[:typed_postbacks].nil?
|
319
|
+
@recipient.vars[:typed_postbacks] = @recipient.vars[:typed_postbacks].merge(typed_postbacks)
|
320
|
+
end
|
321
|
+
|
322
|
+
# Advanced responses.
|
323
|
+
|
324
|
+
# def opt_out(text, button_label)
|
325
|
+
# self.quick_reply(
|
326
|
+
# text,
|
327
|
+
# [
|
328
|
+
# {
|
329
|
+
# :content_type => :text,
|
330
|
+
# :title => button_label,
|
331
|
+
# :payload => PAYLOADS[:opt_out]
|
332
|
+
# }
|
333
|
+
# ]
|
334
|
+
# )
|
335
|
+
# end
|
336
|
+
|
337
|
+
def location_request(text) # Deprecated by Facebook
|
338
|
+
self.quick_reply(
|
339
|
+
text,
|
340
|
+
[
|
341
|
+
{
|
342
|
+
:content_type => :location
|
343
|
+
}
|
344
|
+
],
|
345
|
+
{typed_postbacks: false}
|
346
|
+
)
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Kogno
|
2
|
+
module Messenger
|
3
|
+
class PostComment
|
4
|
+
|
5
|
+
attr_accessor :event
|
6
|
+
|
7
|
+
@overwritten_payload = nil
|
8
|
+
|
9
|
+
def initialize(data, page_id)
|
10
|
+
@data = data
|
11
|
+
@page_id = page_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
:post_comment
|
16
|
+
end
|
17
|
+
|
18
|
+
def payload_action
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def sender_id
|
23
|
+
return(@data[:value][:from][:id] rescue nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
def sender_name
|
27
|
+
return(@data[:value][:from][:name] rescue nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
def post_id
|
31
|
+
return(@data[:value][:post_id] rescue nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def page_id
|
35
|
+
@page_id
|
36
|
+
end
|
37
|
+
|
38
|
+
def item_type
|
39
|
+
return(@data[:value][:item].to_sym rescue nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
def text
|
43
|
+
return(@data[:value][:message] rescue "")
|
44
|
+
end
|
45
|
+
|
46
|
+
def comment_id
|
47
|
+
return(@data[:value][:comment_id] rescue nil)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_context(user,notification)
|
51
|
+
# Here you can use different contexts by self.post_id
|
52
|
+
context_class = Context::router(Kogno::Application.config.routes.post_comment)[:class]
|
53
|
+
context_route = nil
|
54
|
+
context = context_class.new(user,self,notification,context_route)
|
55
|
+
return(context)
|
56
|
+
end
|
57
|
+
|
58
|
+
def empty?
|
59
|
+
self.text.to_s.empty?
|
60
|
+
end
|
61
|
+
|
62
|
+
def handle_event(debug=false)
|
63
|
+
|
64
|
+
begin
|
65
|
+
|
66
|
+
user = User.new(last_usage_at: Time.now, vars:{})
|
67
|
+
self.set_nlp(user.locale)
|
68
|
+
|
69
|
+
notification = Notification.new(user,self)
|
70
|
+
|
71
|
+
logger.write "--------------------MESSAGE: #{self.text}--------------------------", :green
|
72
|
+
|
73
|
+
context = get_context(user,notification)
|
74
|
+
|
75
|
+
return({post_comment: self, user: user, notification: notification, context: context}) if debug
|
76
|
+
|
77
|
+
context.run_for_text_only
|
78
|
+
|
79
|
+
notification.send_private_reply(self.comment_id)
|
80
|
+
|
81
|
+
recipient_psid = notification.get_psid_from_response_log
|
82
|
+
|
83
|
+
user = User.find_or_create_by_psid(recipient_psid, :messenger, self.page_id, self.sender_id, false)
|
84
|
+
|
85
|
+
if Kogno::Application.config.store_log_in_database
|
86
|
+
user.log_message(self, :post_comment_received)
|
87
|
+
user.log_response(notification)
|
88
|
+
end
|
89
|
+
|
90
|
+
logger.write "**********************#{user.context}***********************", :green
|
91
|
+
|
92
|
+
rescue StandardError => e
|
93
|
+
error_token = Digest::MD5.hexdigest("#{Time.now}#{rand(1000)}") # This helps to identify the error that arrives to Slack in order to search it in logs/http.log
|
94
|
+
logger.write e.message, :red
|
95
|
+
logger.write "Error Token: #{error_token}", :red
|
96
|
+
logger.write "Backtrace:\n\t#{e.backtrace.join("\n\t")}", :red
|
97
|
+
ErrorHandler.notify_by_slack(Kogno::Application.config.app_name,e, error_token) if Kogno::Application.config.error_notifier.slack[:enable] rescue false
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|