bobot 1.0.53 → 2.1.0
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 +4 -4
- data/README.md +18 -8
- data/app/controllers/bobot/webhook_controller.rb +54 -30
- data/config/routes.rb +1 -2
- data/lib/bobot.rb +15 -1
- data/lib/bobot/commander.rb +9 -8
- data/lib/bobot/configuration.rb +149 -186
- data/lib/bobot/engine.rb +0 -4
- data/lib/bobot/events/common.rb +4 -4
- data/lib/bobot/events/delivery.rb +0 -1
- data/lib/bobot/events/message.rb +4 -0
- data/lib/bobot/events/message_echo.rb +3 -2
- data/lib/bobot/events/message_request.rb +9 -0
- data/lib/bobot/graph_facebook.rb +4 -4
- data/lib/bobot/profile.rb +2 -6
- data/lib/bobot/version.rb +3 -3
- data/lib/generators/bobot/templates/app/bobot/workflow.rb +9 -11
- data/lib/generators/bobot/templates/config/bobot.yml +41 -32
- data/lib/generators/bobot/templates/config/initializers/bobot.rb +25 -9
- data/lib/generators/bobot/templates/config/locales/bobot.en.yml +29 -28
- data/lib/generators/bobot/templates/config/locales/bobot.fr.yml +28 -27
- data/lib/generators/bobot/utils.rb +0 -9
- data/spec/bobot/bobot_spec.rb +18 -12
- data/spec/bobot/event/common_spec.rb +3 -1
- data/spec/bobot/event/message_spec.rb +7 -0
- data/spec/bobot/profile_spec.rb +3 -1
- data/spec/bobot/subscription_spec.rb +4 -2
- data/spec/bobot/user_spec.rb +4 -2
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy/bin/setup +0 -8
- data/spec/dummy/bin/update +0 -3
- data/spec/dummy/config/application.rb +3 -2
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/environments/development.rb +5 -3
- data/spec/dummy/config/environments/production.rb +5 -3
- data/spec/dummy/config/environments/test.rb +6 -2
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -4
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -5
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/config/secrets.yml +2 -2
- data/spec/dummy/log/development.log +0 -0
- data/spec/dummy/log/test.log +2 -0
- data/spec/dummy/tmp/generator/app/bobot/workflow.rb +15 -0
- data/spec/dummy/tmp/generator/config/bobot.yml +48 -0
- data/spec/dummy/tmp/generator/config/initializers/bobot.rb +46 -0
- data/spec/dummy/tmp/generator/config/locales/bobot.en.yml +31 -0
- data/spec/dummy/tmp/generator/config/locales/bobot.fr.yml +30 -0
- data/spec/dummy/tmp/generator/config/routes.rb +0 -0
- data/spec/rails_helper.rb +8 -10
- metadata +43 -34
- data/app/mailers/bobot/application_mailer.rb +0 -6
- data/app/models/bobot/application_record.rb +0 -5
- data/lib/generators/bobot/templates/app/bobot/message.rb +0 -3
- data/lib/generators/bobot/templates/app/bobot/postback.rb +0 -22
- data/spec/dummy/app/bobot/workflow.rb +0 -17
- data/spec/dummy/app/models/application_record.rb +0 -3
- data/spec/dummy/config/bobot.yml +0 -27
- data/spec/dummy/config/database.yml +0 -19
- data/spec/dummy/config/initializers/bobot.rb +0 -30
- data/spec/dummy/config/locales/bobot.en.yml +0 -28
- data/spec/dummy/config/locales/bobot.fr.yml +0 -27
- data/spec/dummy/db/schema.rb +0 -15
data/lib/bobot/engine.rb
CHANGED
@@ -8,10 +8,6 @@ module Bobot
|
|
8
8
|
|
9
9
|
config.action_dispatch.rescue_responses['Bobot::ActionNotAllowed'] = :forbidden
|
10
10
|
|
11
|
-
initializer 'bobot.load_app_root' do |app|
|
12
|
-
Bobot.app_root = app.root
|
13
|
-
end
|
14
|
-
|
15
11
|
initializer 'Bobot setup middlewares' do |app|
|
16
12
|
app.config.middleware.use ActionDispatch::Flash
|
17
13
|
end
|
data/lib/bobot/events/common.rb
CHANGED
@@ -26,11 +26,11 @@ module Bobot
|
|
26
26
|
|
27
27
|
def delay(wait: 0, wait_until: nil)
|
28
28
|
raise Bobot::FieldFormat.new('wait has to be positive integer.') unless wait.present?
|
29
|
-
if Bobot.async
|
29
|
+
if Bobot.config.async
|
30
30
|
@delay_options[:wait] = wait if wait >= 0
|
31
31
|
@delay_options[:wait_until] = wait_until if wait_until.present?
|
32
32
|
else
|
33
|
-
warn "delay is ignored since you configured Bobot.async to 'false'"
|
33
|
+
warn "delay is ignored since you configured Bobot.config.async to 'false'"
|
34
34
|
end
|
35
35
|
self
|
36
36
|
end
|
@@ -43,7 +43,7 @@ module Bobot
|
|
43
43
|
raise Bobot::FieldFormat.new('payload_template is required.') unless payload_template.present?
|
44
44
|
@payloads_sent << payload_template
|
45
45
|
job = Bobot::DeliverJob
|
46
|
-
if Bobot.async
|
46
|
+
if Bobot.config.async
|
47
47
|
job = job.set(wait: @delay_options[:wait]) if @delay_options[:wait] > 0
|
48
48
|
job = job.set(wait: @delay_options[:wait_until]) if @delay_options[:wait_until].present?
|
49
49
|
job.perform_later(sender: sender, access_token: access_token, payload_template: payload_template)
|
@@ -163,7 +163,7 @@ module Bobot
|
|
163
163
|
alias_method :reply_with_carousel, :reply_with_generic
|
164
164
|
|
165
165
|
def access_token
|
166
|
-
Bobot.page_access_token
|
166
|
+
Bobot.config.find_page_by_id(recipient["id"]).try(:page_access_token)
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
data/lib/bobot/events/message.rb
CHANGED
data/lib/bobot/graph_facebook.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Bobot
|
2
2
|
module GraphFacebook
|
3
3
|
GRAPH_FB_URL = 'https://graph.facebook.com'.freeze
|
4
|
-
GRAPH_FB_VERSION = 'v2.
|
4
|
+
GRAPH_FB_VERSION = 'v2.11'.freeze
|
5
5
|
|
6
6
|
module ClassMethods
|
7
7
|
def graph_get(path, query: {})
|
@@ -19,7 +19,7 @@ module Bobot
|
|
19
19
|
end
|
20
20
|
res = https.request(req)
|
21
21
|
json = ActiveSupport::JSON.decode(res.send(:body) || '{}')
|
22
|
-
if Bobot.debug_log
|
22
|
+
if Bobot.config.debug_log
|
23
23
|
puts "[GET] >> #{uri.request_uri}"
|
24
24
|
puts "[GET] << #{json}"
|
25
25
|
end
|
@@ -44,7 +44,7 @@ module Bobot
|
|
44
44
|
end
|
45
45
|
res = https.request(req)
|
46
46
|
json = ActiveSupport::JSON.decode(res.send(:body) || '{}')
|
47
|
-
if Bobot.debug_log
|
47
|
+
if Bobot.config.debug_log
|
48
48
|
puts "[POST] >> #{uri.request_uri}"
|
49
49
|
puts "[POST] << #{json}"
|
50
50
|
end
|
@@ -69,7 +69,7 @@ module Bobot
|
|
69
69
|
end
|
70
70
|
res = https.request(req)
|
71
71
|
json = ActiveSupport::JSON.decode(res.send(:body) || '{}')
|
72
|
-
if Bobot.debug_log
|
72
|
+
if Bobot.config.debug_log
|
73
73
|
puts "[DELETE] >> #{uri.request_uri}"
|
74
74
|
puts "[DELETE] << #{json}"
|
75
75
|
end
|
data/lib/bobot/profile.rb
CHANGED
@@ -2,18 +2,14 @@ module Bobot
|
|
2
2
|
module Profile
|
3
3
|
include Bobot::GraphFacebook
|
4
4
|
|
5
|
-
def set(body:, query:
|
6
|
-
query ||= { access_token: Bobot.page_access_token }
|
7
|
-
query[:access_token] = Bobot.page_access_token unless query.key?("access_token")
|
5
|
+
def set(body:, query:)
|
8
6
|
graph_post '/me/messenger_profile', body: body, query: {
|
9
7
|
access_token: query.fetch(:access_token),
|
10
8
|
}
|
11
9
|
end
|
12
10
|
module_function :set
|
13
11
|
|
14
|
-
def unset(body:, query:
|
15
|
-
query ||= { access_token: Bobot.page_access_token }
|
16
|
-
query[:access_token] = Bobot.page_access_token unless query.key?("access_token")
|
12
|
+
def unset(body:, query:)
|
17
13
|
graph_delete '/me/messenger_profile', body: body, query: {
|
18
14
|
access_token: query.fetch(:access_token),
|
19
15
|
}
|
data/lib/bobot/version.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
+
# message received or quick replies
|
1
2
|
Bobot::Commander.on :message do |message|
|
2
|
-
klass = message.quick_reply.present? ? Bobot::Postback : Bobot::Message
|
3
|
-
klass.perform(message)
|
4
3
|
end
|
5
4
|
|
5
|
+
# get started and click on any buttons
|
6
6
|
Bobot::Commander.on :postback do |postback|
|
7
|
-
klass = Bobot::Postback
|
8
|
-
klass.perform(postback)
|
9
7
|
end
|
10
8
|
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
|
17
|
-
|
9
|
+
# referral by m.me/XXX?ref=
|
10
|
+
Bobot::Commander.on :referral do |referral|
|
11
|
+
end
|
12
|
+
|
13
|
+
# referral by param ref into send to messenger plugin
|
14
|
+
Bobot::Commander.on :optin do |optin|
|
15
|
+
end
|
@@ -1,39 +1,48 @@
|
|
1
1
|
development:
|
2
|
-
app_id:
|
3
|
-
app_secret:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
app_id: "123"
|
3
|
+
app_secret: "456"
|
4
|
+
verify_token: "your token"
|
5
|
+
domains: "whitelisted-domain.com,second-whitelisted-domain.com"
|
6
|
+
debug_log: true
|
7
|
+
async: false
|
8
|
+
pages:
|
9
|
+
- slug: "facebook_1"
|
10
|
+
language: "fr"
|
11
|
+
page_id: "789"
|
12
|
+
page_access_token: "abc"
|
10
13
|
|
11
14
|
test:
|
12
|
-
app_id:
|
13
|
-
app_secret:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
app_id: "123"
|
16
|
+
app_secret: "456"
|
17
|
+
verify_token: "your token"
|
18
|
+
domains: "whitelisted-domain.com,second-whitelisted-domain.com"
|
19
|
+
debug_log: true
|
20
|
+
async: false
|
21
|
+
pages:
|
22
|
+
- slug: "facebook_1"
|
23
|
+
page_id: "789"
|
24
|
+
page_access_token: "abc"
|
20
25
|
|
21
26
|
staging:
|
22
|
-
app_id:
|
23
|
-
app_secret:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
app_id: <%= ENV["STAGING_BOBOT_APP_ID"] %>
|
28
|
+
app_secret: <%= ENV["STAGING_BOBOT_APP_SECRET"] %>
|
29
|
+
verify_token: <%= ENV["STAGING_BOBOT_VERIFY_TOKEN"] %>
|
30
|
+
domains: <%= ENV["STAGING_BOBOT_DOMAINS"] %>
|
31
|
+
debug_log: <%= ENV["STAGING_BOBOT_DEBUG_LOG"] %>
|
32
|
+
async: <%= ENV["STAGING_BOBOT_ASYNC"] %>
|
33
|
+
pages:
|
34
|
+
- slug: <%= ENV["STAGING_BOBOT_PAGE_SLUG"] %>
|
35
|
+
page_id: <%= ENV["STAGING_BOBOT_PAGE_ID"] %>
|
36
|
+
page_access_token: <%= ENV["STAGING_BOBOT_PAGE_ACCESS_TOKEN"] %>
|
30
37
|
|
31
38
|
production:
|
32
|
-
app_id:
|
33
|
-
app_secret:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
app_id: <%= ENV["PRODUCTION_BOBOT_APP_ID"] %>
|
40
|
+
app_secret: <%= ENV["PRODUCTION_BOBOT_APP_SECRET"] %>
|
41
|
+
verify_token: <%= ENV["PRODUCTION_BOBOT_VERIFY_TOKEN"] %>
|
42
|
+
domains: <%= ENV["PRODUCTION_BOBOT_DOMAINS"] %>
|
43
|
+
debug_log: <%= ENV["PRODUCTION_BOBOT_DEBUG_LOG"] %>
|
44
|
+
async: <%= ENV["PRODUCTION_BOBOT_ASYNC"] %>
|
45
|
+
pages:
|
46
|
+
- slug: <%= ENV["PRODUCTION_BOBOT_PAGE_SLUG"] %>
|
47
|
+
page_id: <%= ENV["PRODUCTION_BOBOT_PAGE_ID"] %>
|
48
|
+
page_access_token: <%= ENV["PRODUCTION_BOBOT_PAGE_ACCESS_TOKEN"] %>
|
@@ -1,16 +1,25 @@
|
|
1
1
|
bobot_config_path = Rails.root.join("config", "bobot.yml")
|
2
|
-
bobot_config = YAML.safe_load(ERB.new(File.read(bobot_config_path)).result)[Rails.env]
|
2
|
+
bobot_config = YAML.safe_load(ERB.new(File.read(bobot_config_path)).result, [], [], true)[Rails.env]
|
3
3
|
|
4
4
|
if bobot_config.present?
|
5
|
+
unless bobot_config.key?("pages")
|
6
|
+
raise "Bobot: #{bobot_config_path} required an array key :pages (cf. https://github.com/navidemad/bobot)"
|
7
|
+
end
|
5
8
|
Bobot.configure do |config|
|
6
|
-
config.app_id
|
7
|
-
config.app_secret
|
8
|
-
config.
|
9
|
-
config.
|
10
|
-
config.
|
11
|
-
config.
|
12
|
-
|
13
|
-
|
9
|
+
config.app_id = bobot_config["app_id"],
|
10
|
+
config.app_secret = bobot_config["app_secret"],
|
11
|
+
config.verify_token = bobot_config["verify_token"],
|
12
|
+
config.domains = bobot_config["domains"],
|
13
|
+
config.debug_log = bobot_config["debug_log"],
|
14
|
+
config.async = bobot_config["async"],
|
15
|
+
bobot_config["pages"].each do |page|
|
16
|
+
config.pages << Bobot::Configuration::Page.new(
|
17
|
+
name: page["name"],
|
18
|
+
language: page["language"],
|
19
|
+
page_access_token: page["page_access_token"],
|
20
|
+
page_id: page["page_id"],
|
21
|
+
)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
else
|
16
25
|
warn "#{bobot_config_path} not configured yet in #{Rails.env} environment."
|
@@ -28,3 +37,10 @@ unless Rails.env.production?
|
|
28
37
|
|
29
38
|
bot_files.each { |file| require_dependency file }
|
30
39
|
end
|
40
|
+
|
41
|
+
if defined?(Rails::Server)
|
42
|
+
Rails.application.config.after_initialize do
|
43
|
+
Rails.application.config.paths.add File.join("app", "bobot"), glob: File.join("**", "*.rb")
|
44
|
+
Rails.application.config.autoload_paths += Dir[Rails.root.join("app", "bobot", "*")]
|
45
|
+
end
|
46
|
+
end
|
@@ -1,30 +1,31 @@
|
|
1
1
|
en:
|
2
2
|
bobot:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
3
|
+
facebook_1:
|
4
|
+
config:
|
5
|
+
facebook_locales:
|
6
|
+
- "en_US"
|
7
|
+
- "en_UD"
|
8
|
+
- "en_GB"
|
9
|
+
greeting_text: "Bobot is an intelligent robot."
|
10
|
+
get_started:
|
11
|
+
payload: 'get_started'
|
12
|
+
persistent_menu:
|
13
|
+
composer_input_disabled: false
|
14
|
+
call_to_actions:
|
15
|
+
- title: "My Account"
|
16
|
+
type: "nested"
|
17
|
+
call_to_actions:
|
18
|
+
- title: "What is a chatbot?"
|
19
|
+
type: "postback"
|
20
|
+
payload: "WHAT_IS_A_CHATBOT"
|
21
|
+
- title: "History"
|
22
|
+
type: "postback"
|
23
|
+
payload: "HISTORY_PAYLOAD"
|
24
|
+
- title: "Contact Info"
|
25
|
+
type: "postback"
|
26
|
+
payload: "CONTACT_INFO_PAYLOAD"
|
27
|
+
- type: "web_url"
|
28
|
+
title: "Get some help"
|
29
|
+
url: "https://github.com/navidemad/bobot"
|
30
|
+
webview_height_ratio: "full"
|
31
|
+
what_is_a_chatbot: "A chatbot is a computer program which conducts a conversation via auditory or textual methods."
|
@@ -1,29 +1,30 @@
|
|
1
1
|
fr:
|
2
2
|
bobot:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
3
|
+
facebook_1:
|
4
|
+
config:
|
5
|
+
facebook_locales:
|
6
|
+
- "fr_FR"
|
7
|
+
- "fr_CA"
|
8
|
+
greeting_text: 'Bobot est un robot intelligent.'
|
9
|
+
get_started:
|
10
|
+
payload: 'get_started'
|
11
|
+
persistent_menu:
|
12
|
+
composer_input_disabled: false
|
13
|
+
call_to_actions:
|
14
|
+
- title: "Mon compte"
|
15
|
+
type: "nested"
|
16
|
+
call_to_actions:
|
17
|
+
- title: "C'est quoi un chatbot ?"
|
18
|
+
type: "postback"
|
19
|
+
payload: "WHAT_IS_A_CHATBOT"
|
20
|
+
- title: "Historique"
|
21
|
+
type: "postback"
|
22
|
+
payload: "HISTORY_PAYLOAD"
|
23
|
+
- title: "Contact Info"
|
24
|
+
type: "postback"
|
25
|
+
payload: "CONTACT_INFO_PAYLOAD"
|
26
|
+
- type: "web_url"
|
27
|
+
title: "Obtenir de l'aide"
|
28
|
+
url: "https://github.com/navidemad/bobot"
|
29
|
+
webview_height_ratio: "full"
|
30
|
+
what_is_a_chatbot: "Un chatbot est un programme qui tente de converser avec une personne durant quelques minutes ou plus en lui donnant l'impression de converser elle-même avec une personne."
|
@@ -15,15 +15,6 @@ module Bobot
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
module ClassMethods
|
18
|
-
def next_migration_number(dirname)
|
19
|
-
if ActiveRecord::Base.timestamped_migrations
|
20
|
-
migration_number = Time.current.strftime("%Y%m%d%H%M%S").to_i
|
21
|
-
migration_number += 1
|
22
|
-
migration_number.to_s
|
23
|
-
else
|
24
|
-
format("%.3d", current_migration_number(dirname) + 1)
|
25
|
-
end
|
26
|
-
end
|
27
18
|
end
|
28
19
|
end
|
29
20
|
end
|
data/spec/bobot/bobot_spec.rb
CHANGED
@@ -4,21 +4,27 @@ RSpec.describe Bobot do
|
|
4
4
|
describe '#configure' do
|
5
5
|
it 'sets correct configuration' do
|
6
6
|
Bobot.configure do |config|
|
7
|
-
config.app_id = '
|
8
|
-
config.app_secret = '
|
9
|
-
config.
|
10
|
-
config.verify_token = '4'
|
11
|
-
config.page_id = '5'
|
7
|
+
config.app_id = 'app_id'
|
8
|
+
config.app_secret = 'app_secret'
|
9
|
+
config.verify_token = 'verify_token'
|
12
10
|
config.debug_log = true
|
13
11
|
config.async = true
|
12
|
+
config.pages << Bobot::Configuration::Page.new(
|
13
|
+
slug: 'slug',
|
14
|
+
language: 'language',
|
15
|
+
page_access_token: 'page_access_token',
|
16
|
+
page_id: 'page_id',
|
17
|
+
)
|
14
18
|
end
|
15
|
-
expect(Bobot.app_id).to eql('
|
16
|
-
expect(Bobot.app_secret).to eql('
|
17
|
-
expect(Bobot.
|
18
|
-
expect(Bobot.
|
19
|
-
expect(Bobot.
|
20
|
-
expect(Bobot.
|
21
|
-
expect(Bobot.
|
19
|
+
expect(Bobot.config.app_id).to eql('app_id')
|
20
|
+
expect(Bobot.config.app_secret).to eql('app_secret')
|
21
|
+
expect(Bobot.config.verify_token).to eql('verify_token')
|
22
|
+
expect(Bobot.config.debug_log).to eql(true)
|
23
|
+
expect(Bobot.config.async).to eql(true)
|
24
|
+
expect(Bobot.config.pages[0].slug).to eql('slug')
|
25
|
+
expect(Bobot.config.pages[0].language).to eql('language')
|
26
|
+
expect(Bobot.config.pages[0].page_access_token).to eql('page_access_token')
|
27
|
+
expect(Bobot.config.pages[0].page_id).to eql('page_id')
|
22
28
|
end
|
23
29
|
end
|
24
30
|
end
|