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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -8
  3. data/app/controllers/bobot/webhook_controller.rb +54 -30
  4. data/config/routes.rb +1 -2
  5. data/lib/bobot.rb +15 -1
  6. data/lib/bobot/commander.rb +9 -8
  7. data/lib/bobot/configuration.rb +149 -186
  8. data/lib/bobot/engine.rb +0 -4
  9. data/lib/bobot/events/common.rb +4 -4
  10. data/lib/bobot/events/delivery.rb +0 -1
  11. data/lib/bobot/events/message.rb +4 -0
  12. data/lib/bobot/events/message_echo.rb +3 -2
  13. data/lib/bobot/events/message_request.rb +9 -0
  14. data/lib/bobot/graph_facebook.rb +4 -4
  15. data/lib/bobot/profile.rb +2 -6
  16. data/lib/bobot/version.rb +3 -3
  17. data/lib/generators/bobot/templates/app/bobot/workflow.rb +9 -11
  18. data/lib/generators/bobot/templates/config/bobot.yml +41 -32
  19. data/lib/generators/bobot/templates/config/initializers/bobot.rb +25 -9
  20. data/lib/generators/bobot/templates/config/locales/bobot.en.yml +29 -28
  21. data/lib/generators/bobot/templates/config/locales/bobot.fr.yml +28 -27
  22. data/lib/generators/bobot/utils.rb +0 -9
  23. data/spec/bobot/bobot_spec.rb +18 -12
  24. data/spec/bobot/event/common_spec.rb +3 -1
  25. data/spec/bobot/event/message_spec.rb +7 -0
  26. data/spec/bobot/profile_spec.rb +3 -1
  27. data/spec/bobot/subscription_spec.rb +4 -2
  28. data/spec/bobot/user_spec.rb +4 -2
  29. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  30. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  31. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  32. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  33. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  34. data/spec/dummy/bin/setup +0 -8
  35. data/spec/dummy/bin/update +0 -3
  36. data/spec/dummy/config/application.rb +3 -2
  37. data/spec/dummy/config/cable.yml +10 -0
  38. data/spec/dummy/config/environments/development.rb +5 -3
  39. data/spec/dummy/config/environments/production.rb +5 -3
  40. data/spec/dummy/config/environments/test.rb +6 -2
  41. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -4
  42. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -5
  43. data/spec/dummy/config/routes.rb +1 -1
  44. data/spec/dummy/config/secrets.yml +2 -2
  45. data/spec/dummy/log/development.log +0 -0
  46. data/spec/dummy/log/test.log +2 -0
  47. data/spec/dummy/tmp/generator/app/bobot/workflow.rb +15 -0
  48. data/spec/dummy/tmp/generator/config/bobot.yml +48 -0
  49. data/spec/dummy/tmp/generator/config/initializers/bobot.rb +46 -0
  50. data/spec/dummy/tmp/generator/config/locales/bobot.en.yml +31 -0
  51. data/spec/dummy/tmp/generator/config/locales/bobot.fr.yml +30 -0
  52. data/spec/dummy/tmp/generator/config/routes.rb +0 -0
  53. data/spec/rails_helper.rb +8 -10
  54. metadata +43 -34
  55. data/app/mailers/bobot/application_mailer.rb +0 -6
  56. data/app/models/bobot/application_record.rb +0 -5
  57. data/lib/generators/bobot/templates/app/bobot/message.rb +0 -3
  58. data/lib/generators/bobot/templates/app/bobot/postback.rb +0 -22
  59. data/spec/dummy/app/bobot/workflow.rb +0 -17
  60. data/spec/dummy/app/models/application_record.rb +0 -3
  61. data/spec/dummy/config/bobot.yml +0 -27
  62. data/spec/dummy/config/database.yml +0 -19
  63. data/spec/dummy/config/initializers/bobot.rb +0 -30
  64. data/spec/dummy/config/locales/bobot.en.yml +0 -28
  65. data/spec/dummy/config/locales/bobot.fr.yml +0 -27
  66. data/spec/dummy/db/schema.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9abca691c0b2cccaa74e39426221e12d320ff0d4
4
- data.tar.gz: 16f6c8684ae068e0ec36306cf4125061a4fd7fea
3
+ metadata.gz: 238ce4063aa11a3df2f3150c8a7a65e23cc0063f
4
+ data.tar.gz: ce018a45a1d777752c746c4b7f46e2049fdfa071
5
5
  SHA512:
6
- metadata.gz: 52e6bb306d99fc08db6436822c9b29396e5ecf4031b59e62f35da3bc5af71fb9a426138faccc338dcbed38b0c695345c7b9b1ad75a813976d62fb70590c54cb6
7
- data.tar.gz: bb9bf2d9500c16da7c4dc5a6233bb467b3564263028d24882a85b8104c3273f4ad315aac1bd6ab85a12a2c717ebcc4072a13bcced26d5d8d6424e003a30f2bc1
6
+ metadata.gz: 76f2106985520b82654e76d11340e24bcf3c4a25074c87a345f3d543f54384419538fbcc05ed82b33015ee539c4f5dc75736e5eb9f518ae38ef179e9978e0802
7
+ data.tar.gz: f793e2ae3e8b5bdb50bcbda3e639c16018e4db52f420bf823dd81b489ce4f208623fe78050f09337a67f53c29d3a465756f676fe3c8a62cfb53192fb26b7b54d
data/README.md CHANGED
@@ -31,16 +31,26 @@ Typing the following command in your Rails application will add the bot to your
31
31
  `config/bobot.yml` contains your bot keys
32
32
  `app/bobot/workflow.rb` contains the workflow of your bot
33
33
 
34
- You can run in a Rails console:
35
- `Bobot.update_facebook_setup!`
34
+ You can access to page settings:
35
+ ```
36
+ Bobot.config.find_page_by_id(facebook_page_id)
37
+ Bobot.config.find_page_by_slug(facebook_page_slug)
38
+ ```
39
+
40
+ After fetching the page with command above, you have access to:
41
+ `update_facebook_setup!`
36
42
 
37
43
  Or one by one in a Rails console:
38
- - `Bobot.subscribe_to_facebook_page!`
39
- - `Bobot.unsubscribe_to_facebook_page!`
40
- - `Bobot.set_greeting_text!`
41
- - `Bobot.set_whitelist_domains!`
42
- - `Bobot.set_get_started_button!`
43
- - `Bobot.set_persistent_menu!`
44
+ - `subscribe_to_facebook_page!`
45
+ - `unsubscribe_to_facebook_page!`
46
+ - `unset_greeting_text!`
47
+ - `set_greeting_text!`
48
+ - `unset_whitelist_domains!`
49
+ - `set_whitelist_domains!`
50
+ - `unset_get_started_button!`
51
+ - `set_get_started_button!`
52
+ - `unset_persistent_menu!`
53
+ - `set_persistent_menu!`
44
54
 
45
55
  Greeting Text and Persistent Menus are translated by I18n.
46
56
  You have to define into your `config/application.rb` your available_locales as I18n defined them.
@@ -1,28 +1,46 @@
1
1
  module Bobot
2
2
  class WebhookController < Bobot::ApplicationController
3
+ class BadRequestError < Error; end
4
+
3
5
  include ActionView::Helpers::TextHelper
4
6
 
5
7
  skip_before_action :verify_authenticity_token, raise: false
6
8
 
7
9
  layout :bobot_layout rescue nil
8
10
 
9
- def notify
10
- if check_integrity?
11
- respond_with body: ActiveSupport::JSON.encode(trigger(parsed_body)), status: :ok
11
+ X_HUB_SIGNATURE_MISSING_WARNING = <<-HEREDOC.freeze
12
+ The X-Hub-Signature header is not present in the request. This is
13
+ expected for the first webhook requests. If it continues after
14
+ some time, check your app's secret token.
15
+ HEREDOC
16
+
17
+ def webhook
18
+ if request.get?
19
+ verify
20
+ elsif request.post?
21
+ receive
12
22
  else
13
- respond_with status: :forbidden
23
+ head :method_not_allowed
14
24
  end
15
25
  end
16
26
 
17
27
  def verify
18
- if verify_params['hub.mode'] == 'subscribe' &&
19
- verify_params['hub.verify_token'] == Bobot.verify_token
20
- respond_with body: params['hub.challenge'], status: :ok
28
+ if params['hub.mode'.freeze] == 'subscribe' &&
29
+ params['hub.verify_token'.freeze] == Bobot.config.verify_token
30
+ render plain: params['hub.challenge'.freeze], status: :ok
21
31
  else
22
- respond_with status: :forbidden
32
+ render plain: "Error wrong verify token".freeze, status: :forbidden
23
33
  end
24
34
  end
25
35
 
36
+ def receive
37
+ check_integrity
38
+ return_json = trigger(parsed_body)
39
+ render plain: ActiveSupport::JSON.encode(return_json), status: :ok
40
+ rescue BadRequestError => error
41
+ render plain: error.message, status: :bad_request
42
+ end
43
+
26
44
  private
27
45
 
28
46
  def body
@@ -30,27 +48,42 @@ module Bobot
30
48
  end
31
49
 
32
50
  def parsed_body
33
- @parsed_body ||= begin
34
- ActiveSupport::JSON.decode(body)
35
- rescue ::ActiveSupport::JSON.parse_error
36
- 'payload is not string and not a valid to be JSONified.'
37
- end
51
+ @parsed_body ||= ActiveSupport::JSON.decode(body)
52
+ rescue ::ActiveSupport::JSON.parse_error
53
+ raise BadRequestError.new("Error parsing request body format")
54
+ end
55
+
56
+ def valid_signature?
57
+ Rack::Utils.secure_compare(signature, signature_for(body))
58
+ end
59
+
60
+ def generate_hmac(content)
61
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'.freeze), Bobot.config.app_secret, content)
38
62
  end
39
63
 
40
- def signature(str, key = nil)
41
- key ||= Bobot.app_secret
42
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), key, str)
64
+ def signature_for(string)
65
+ format('sha1=%s'.freeze, generate_hmac(string))
43
66
  end
44
67
 
45
- def check_integrity?
46
- request.headers['HTTP_X_HUB_SIGNATURE'].to_s =~ /\Asha1=([0-9a-z]{40})\z/
68
+ def signature
69
+ request.headers['HTTP_X_HUB_SIGNATURE'.freeze].to_s
70
+ end
71
+
72
+ def check_integrity
73
+ signature =~ /\Asha1=([0-9a-z]{40})\z/
47
74
  hub_signature = Regexp.last_match(1)
48
- hub_signature && Rack::Utils.secure_compare(hub_signature, signature(body))
75
+ unless hub_signature
76
+ Rails.logger.error(X_HUB_SIGNATURE_MISSING_WARNING)
77
+ raise BadRequestError.new("Error getting integrity signature".freeze)
78
+ end
79
+ unless valid_signature?
80
+ raise BadRequestError.new("Error checking message integrity".freeze)
81
+ end
49
82
  end
50
83
 
51
84
  def trigger(events)
52
- events['entry'].inject([]) do |payloads_sent, entry|
53
- entry['messaging'].each do |messaging|
85
+ events['entry'.freeze].to_a.inject([]) do |payloads_sent, entry|
86
+ entry['messaging'.freeze].to_a.each do |messaging|
54
87
  begin
55
88
  payloads_sent << Bobot::Commander.receive(messaging)
56
89
  rescue => e
@@ -60,15 +93,6 @@ module Bobot
60
93
  end
61
94
  end
62
95
 
63
- def respond_with(body: '', status:)
64
- self.response_body = body
65
- self.status = status
66
- end
67
-
68
- def verify_params
69
- params.permit('hub.mode', 'hub.challenge', 'hub.verify_token')
70
- end
71
-
72
96
  def bobot_layout
73
97
  'bobot/application'
74
98
  end
@@ -1,6 +1,5 @@
1
1
  Bobot::Engine.routes.draw do
2
2
  controller 'webhook' do
3
- match 'facebook', action: :notify, via: :post, as: :facebook_notify
4
- match 'facebook', action: :verify, via: :get, as: :facebook_verify
3
+ match 'facebook', action: :webhook, via: [:get, :post]
5
4
  end
6
5
  end
@@ -14,5 +14,19 @@ require 'bobot/commander'
14
14
  require 'bobot/event'
15
15
 
16
16
  module Bobot
17
- extend Configuration
17
+ def self.configure
18
+ yield config
19
+ end
20
+
21
+ def self.config
22
+ @config ||= Configuration.new
23
+ end
24
+
25
+ def self.config=(config)
26
+ @config = config
27
+ end
28
+
29
+ configure do |config|
30
+ config.pages = []
31
+ end
18
32
  end
@@ -11,6 +11,7 @@ module Bobot
11
11
  account_linking
12
12
  referral
13
13
  message_echo
14
+ message_request
14
15
  ].freeze
15
16
 
16
17
  include Bobot::GraphFacebook
@@ -32,28 +33,28 @@ module Bobot
32
33
  def receive(payload)
33
34
  event = Bobot::Event.parse(payload)
34
35
  hooks.fetch(Bobot::Event::EVENTS.invert[event.class].to_sym)
35
- puts "[ActiveJob] << Bobot::HookJob with event #{event.class}" if Bobot.debug_log
36
- #event.mark_as_seen
36
+ puts "[ActiveJob] << Bobot::HookJob with event #{event.class}" if Bobot.config.debug_log
37
+ # event.mark_as_seen
37
38
  job = Bobot::CommanderJob
38
- if Bobot.async
39
+ if Bobot.config.async
39
40
  job.perform_later(payload: payload)
40
41
  else
41
42
  job.perform_now(payload: payload)
42
43
  end
43
44
  rescue KeyError
44
- $stderr.puts "Ignoring #{event.class} (no hook registered)"
45
+ warn "Ignoring #{event.class} (no hook registered)"
45
46
  end
46
47
 
47
48
  def trigger(payload)
48
49
  event = Bobot::Event.parse(payload)
49
50
  hook = hooks.fetch(Bobot::Event::EVENTS.invert[event.class].to_sym)
50
- puts "[ActiveJob] >> Bobot::HookJob related to event #{name.class}" if Bobot.debug_log
51
- #event.show_typing(state: true)
51
+ puts "[ActiveJob] >> Bobot::HookJob related to event #{name.class}" if Bobot.config.debug_log
52
+ # event.show_typing(state: true)
52
53
  hook.call(event)
53
- #event.show_typing(state: false)
54
+ # event.show_typing(state: false)
54
55
  [event, event.payloads_sent[1..-2]]
55
56
  rescue KeyError
56
- $stderr.puts "Ignoring #{event.class} (no hook registered)"
57
+ warn "Ignoring #{event.class} (no hook registered)"
57
58
  end
58
59
 
59
60
  def hooks
@@ -1,60 +1,7 @@
1
1
  module Bobot
2
- # Defines constants and methods related to configuration
3
- module Configuration
4
- # An array of valid keys in the options hash when configuring
5
- VALID_CONFIGURATION_KEYS = %i[
6
- page_id
7
- app_id
8
- app_secret
9
- page_access_token
10
- verify_token
11
- domains
12
- debug_log
13
- async
14
- ].freeze
15
-
16
- # By default, don't set a facebook page id
17
- DEFAULT_PAGE_ID = nil
18
-
19
- # By default, don't set a facebook developper app id
20
- DEFAULT_APP_ID = nil
21
-
22
- # By default, don't set a facebook developper app secret
23
- DEFAULT_APP_SECRET = nil
24
-
25
- # By default, don't set a facebook developper page access token
26
- DEFAULT_PAGE_ACCESS_TOKEN = nil
27
-
28
- # By default, don't set a facebook webhook_verify_token
29
- DEFAULT_VERIFY_TOKEN = nil
30
-
31
- # By default, don't set a facebook whitelisting domains
32
- DEFAULT_DOMAINS = nil
33
-
34
- # By default, debug log is to false
35
- DEFAULT_DEBUG_LOG = false
36
-
37
- # By default, async is to false
38
- DEFAULT_ASYNC = false
39
-
40
- # @private
41
- attr_accessor(*VALID_CONFIGURATION_KEYS)
42
-
43
- # Our host application root path
44
- # We set this when the engine is initialized
45
- mattr_accessor :app_root
46
-
47
- # When this module is extended, set all configuration options to their default values
48
- def self.extended(base)
49
- base.reset!
50
- end
51
-
52
- # Convenience method to allow configuration options to be set in a block
53
- def configure
54
- yield self
55
- end
2
+ class Configuration
3
+ attr_accessor :app_id, :app_secret, :verify_token, :debug_log, :async, :pages
56
4
 
57
- # Custom self assignments
58
5
  def domains=(rhs)
59
6
  return unless rhs.present?
60
7
  if rhs.respond_to?(:to_str)
@@ -66,166 +13,182 @@ module Bobot
66
13
  end
67
14
  end
68
15
 
69
- # Create a hash of options and their values
70
- def configurations
71
- VALID_CONFIGURATION_KEYS.inject({}) do |option, key|
72
- option.merge!(key => send(key))
73
- end
16
+ def find_page_by_id(page_id)
17
+ pages.find { |page| page.page_id == page_id }
74
18
  end
75
19
 
76
- # Reset all configuration options to defaults
77
- def reset!
78
- self.page_id = DEFAULT_PAGE_ID
79
- self.app_id = DEFAULT_APP_ID
80
- self.app_secret = DEFAULT_APP_SECRET
81
- self.page_access_token = DEFAULT_PAGE_ACCESS_TOKEN
82
- self.verify_token = DEFAULT_VERIFY_TOKEN
83
- self.domains = DEFAULT_DOMAINS
84
- self.debug_log = DEFAULT_DEBUG_LOG
85
- self.async = DEFAULT_ASYNC
20
+ def find_page_by_slug(slug)
21
+ pages.find { |page| page.slug == slug }
86
22
  end
87
23
 
88
- def update_facebook_setup!
89
- subscribe_to_facebook_page!
90
- set_greeting_text!
91
- set_whitelist_domains!
92
- set_get_started_button!
93
- set_persistent_menu!
94
- end
24
+ class Page
25
+ attr_accessor :slug, :language, :page_id, :page_access_token
95
26
 
96
- ## == Subcribe your bot to your page ==
97
- def subscribe_to_facebook_page!
98
- raise Bobot::InvalidParameter.new(:page_id) unless Bobot.page_id.present?
99
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
100
- Bobot::Subscription.set(
101
- query: {
102
- page_id: Bobot.page_id,
103
- access_token: Bobot.page_access_token,
104
- },
105
- )
106
- end
27
+ def initialize(options = {})
28
+ self.slug = options[:slug]
29
+ self.language = options[:language]
30
+ self.page_id = options[:page_id]
31
+ self.page_access_token = options[:page_access_token]
32
+ end
107
33
 
108
- ## == Unsubcribe your bot from your page ==
109
- def unsubscribe_to_facebook_page!
110
- raise Bobot::InvalidParameter.new(:page_id) unless Bobot.page_id.present?
111
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
112
- Bobot::Subscription.unset(
113
- query: {
114
- page_id: Bobot.page_id,
115
- access_token: Bobot.page_access_token,
116
- },
117
- )
118
- end
34
+ def update_facebook_setup!
35
+ subscribe_to_facebook_page!
36
+ set_greeting_text!
37
+ set_whitelist_domains!
38
+ set_get_started_button!
39
+ set_persistent_menu!
40
+ end
41
+
42
+ ## == Subcribe your bot to your page ==
43
+ def subscribe_to_facebook_page!
44
+ raise Bobot::InvalidParameter.new(:page_id) unless page_id.present?
45
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
46
+ Bobot::Subscription.set(
47
+ query: {
48
+ page_id: page_id,
49
+ access_token: page_access_token,
50
+ },
51
+ )
52
+ end
119
53
 
120
- ## == Set bot description (only displayed on first time). ==
121
- def set_greeting_text!
122
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
123
- greeting_texts = []
124
- # Default text
125
- greeting_text = I18n.t('bobot.config.greeting_text', locale: I18n.default_locale, default: nil)
126
- if greeting_text.present?
127
- greeting_texts << {
128
- locale: 'default',
129
- text: greeting_text,
130
- }
54
+ ## == Unsubcribe your bot from your page ==
55
+ def unsubscribe_to_facebook_page!
56
+ raise Bobot::InvalidParameter.new(:page_id) unless page_id.present?
57
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
58
+ Bobot::Subscription.unset(
59
+ query: {
60
+ page_id: page_id,
61
+ access_token: page_access_token,
62
+ },
63
+ )
131
64
  end
132
- # Each languages
133
- I18n.available_locales.each do |locale|
134
- greeting_text = I18n.t('bobot.config.greeting_text', locale: locale, default: nil)
135
- next unless greeting_text.present?
136
- facebook_locales = I18n.t('bobot.config.facebook_locales', locale: locale, default: nil)
137
- facebook_locales.to_a.each do |locale_long|
138
- greeting_texts << { locale: locale_long, text: greeting_text }
65
+
66
+ ## == Set bot description (only displayed on first time). ==
67
+ def set_greeting_text!
68
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
69
+ greeting_texts = []
70
+ # Default text
71
+ greeting_text = I18n.t("bobot.#{slug}.config.greeting_text", locale: I18n.default_locale, default: nil)
72
+ greeting_texts << { locale: 'default', text: greeting_text } if greeting_text.present?
73
+ # Each languages
74
+ I18n.available_locales.each do |locale|
75
+ greeting_text = I18n.t("bobot.#{slug}.config.greeting_text", locale: locale, default: nil)
76
+ next unless greeting_text.present?
77
+ facebook_locales = I18n.t("bobot.#{slug}.config.facebook_locales", locale: locale, default: nil)
78
+ facebook_locales.to_a.each do |locale_long|
79
+ greeting_texts << { locale: locale_long, text: greeting_text }
80
+ end
81
+ end
82
+ if greeting_texts.present?
83
+ Bobot::Profile.set(
84
+ body: { greeting: greeting_texts },
85
+ query: { access_token: page_access_token },
86
+ )
87
+ else
88
+ unset_greeting_text!
139
89
  end
140
90
  end
141
- if greeting_texts.present?
142
- Bobot::Profile.set(
143
- body: { greeting: greeting_texts },
144
- query: { access_token: Bobot.page_access_token },
145
- )
146
- else
91
+
92
+ def unset_greeting_text!
93
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
147
94
  Bobot::Profile.unset(
148
- body: { fields: ["greeting"] },
149
- query: { access_token: Bobot.page_access_token },
150
- )
95
+ body: { fields: %w[greeting] },
96
+ query: { access_token: page_access_token },
97
+ )
151
98
  end
152
- end
153
99
 
154
- ## == Set bot whitelist domains (only displayed on first time) ==
155
- ## == Some features like Messenger Extensions and Checkbox Plugin require ==
156
- ## == a page to specify a domain whitelist. ==
157
- def set_whitelist_domains!
158
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
159
- raise Bobot::InvalidParameter.new(:domains) unless Bobot.domains.present?
160
- if Bobot.domains.present?
161
- Bobot::Profile.set(
162
- body: { whitelisted_domains: Bobot.domains },
163
- query: { access_token: Bobot.page_access_token },
164
- )
165
- else
100
+ ## == Set bot whitelist domains (only displayed on first time) ==
101
+ ## == Some features like Messenger Extensions and Checkbox Plugin require ==
102
+ ## == a page to specify a domain whitelist. ==
103
+ def set_whitelist_domains!
104
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
105
+ raise Bobot::InvalidParameter.new(:domains) unless domains.present?
106
+ if domains.present?
107
+ Bobot::Profile.set(
108
+ body: { whitelisted_domains: domains },
109
+ query: { access_token: page_access_token },
110
+ )
111
+ else
112
+ unset_whitelist_domains!
113
+ end
114
+ end
115
+
116
+ def unset_whitelist_domains!
117
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
118
+ raise Bobot::InvalidParameter.new(:domains) unless domains.present?
166
119
  Bobot::Profile.unset(
167
120
  body: { fields: ["whitelisted_domains"] },
168
- query: { access_token: Bobot.page_access_token },
169
- )
121
+ query: { access_token: page_access_token },
122
+ )
170
123
  end
171
- end
172
124
 
173
- ## == You can define the action to trigger when new humans click on ==
174
- ## == the Get Started button. Before doing it you should check to select the ==
175
- ## == messaging_postbacks field when setting up your webhook. ==
176
- def set_get_started_button!
177
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
178
- if I18n.exists?('bobot.config.get_started.payload')
179
- Bobot::Profile.set(
180
- body: { get_started: { payload: I18n.t('bobot.config.get_started.payload') } },
181
- query: { access_token: Bobot.page_access_token },
182
- )
183
- else
125
+ ## == You can define the action to trigger when new humans click on ==
126
+ ## == the Get Started button. Before doing it you should check to select the ==
127
+ ## == messaging_postbacks field when setting up your webhook. ==
128
+ def set_get_started_button!
129
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
130
+ if I18n.exists?("bobot.#{slug}.config.get_started.payload")
131
+ Bobot::Profile.set(
132
+ body: { get_started: { payload: I18n.t("bobot.#{slug}.config.get_started.payload") } },
133
+ query: { access_token: page_access_token },
134
+ )
135
+ else
136
+ unset_get_started_button!
137
+ end
138
+ end
139
+
140
+ def unset_get_started_button!
141
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
184
142
  Bobot::Profile.unset(
185
- body: { fields: ["persistent_menu", "get_started"] },
186
- query: { access_token: Bobot.page_access_token },
143
+ body: { fields: %w[persistent_menu get_started] },
144
+ query: { access_token: page_access_token },
187
145
  )
188
146
  end
189
- end
190
147
 
191
- ## == You can show a persistent menu to humans. ==
192
- ## == If you want to have a persistent menu, you have to set get_started ==
193
- ## == button before. ==
194
- def set_persistent_menu!
195
- raise Bobot::InvalidParameter.new(:access_token) unless Bobot.page_access_token.present?
196
- persistent_menus = []
197
- # Default text
198
- persistent_menu = I18n.t('bobot.config.persistent_menu', locale: I18n.default_locale, default: nil)
199
- if persistent_menu.present?
200
- persistent_menus << {
201
- locale: 'default',
202
- composer_input_disabled: persistent_menu[:composer_input_disabled],
203
- call_to_actions: persistent_menu[:call_to_actions],
204
- }
205
- end
206
- # Each languages
207
- I18n.available_locales.each do |locale|
208
- persistent_menu = I18n.t('bobot.config.persistent_menu', locale: locale, default: nil)
209
- facebook_locales = I18n.t('bobot.config.facebook_locales', locale: locale, default: nil)
210
- next unless persistent_menu.present?
211
- facebook_locales.to_a.each do |locale_long|
148
+ ## == You can show a persistent menu to humans. ==
149
+ ## == If you want to have a persistent menu, you have to set get_started ==
150
+ ## == button before. ==
151
+ def set_persistent_menu!
152
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
153
+ persistent_menus = []
154
+ # Default text
155
+ persistent_menu = I18n.t("bobot.#{slug}.config.persistent_menu", locale: I18n.default_locale, default: nil)
156
+ if persistent_menu.present?
212
157
  persistent_menus << {
213
- locale: locale_long,
158
+ locale: 'default',
214
159
  composer_input_disabled: persistent_menu[:composer_input_disabled],
215
160
  call_to_actions: persistent_menu[:call_to_actions],
216
161
  }
217
162
  end
163
+ # Each languages
164
+ I18n.available_locales.each do |locale|
165
+ persistent_menu = I18n.t("bobot.#{slug}.config.persistent_menu", locale: locale, default: nil)
166
+ facebook_locales = I18n.t("bobot.#{slug}.config.facebook_locales", locale: locale, default: nil)
167
+ next unless persistent_menu.present?
168
+ facebook_locales.to_a.each do |locale_long|
169
+ persistent_menus << {
170
+ locale: locale_long,
171
+ composer_input_disabled: persistent_menu[:composer_input_disabled],
172
+ call_to_actions: persistent_menu[:call_to_actions],
173
+ }
174
+ end
175
+ end
176
+ if persistent_menus.present?
177
+ Bobot::Profile.set(
178
+ body: { persistent_menu: persistent_menus },
179
+ query: { access_token: page_access_token },
180
+ )
181
+ else
182
+ unset_persistent_menu!
183
+ end
218
184
  end
219
- if persistent_menus.present?
220
- Bobot::Profile.set(
221
- body: { persistent_menu: persistent_menus },
222
- query: { access_token: Bobot.page_access_token },
223
- )
224
- else
185
+
186
+ def unset_persistent_menu!
187
+ raise Bobot::InvalidParameter.new(:access_token) unless page_access_token.present?
225
188
  Bobot::Profile.unset(
226
189
  body: { fields: ["persistent_menu"] },
227
- query: { access_token: Bobot.page_access_token },
228
- )
190
+ query: { access_token: page_access_token },
191
+ )
229
192
  end
230
193
  end
231
194
  end