bobot 1.0.52
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/MIT-LICENSE +20 -0
- data/README.md +66 -0
- data/Rakefile +19 -0
- data/app/controllers/bobot/application_controller.rb +5 -0
- data/app/controllers/bobot/webhook_controller.rb +76 -0
- data/app/jobs/bobot/application_job.rb +4 -0
- data/app/jobs/bobot/commander_job.rb +9 -0
- data/app/jobs/bobot/deliver_job.rb +16 -0
- data/app/mailers/bobot/application_mailer.rb +6 -0
- data/app/models/bobot/application_record.rb +5 -0
- data/config/locales/bobot.en.yml +28 -0
- data/config/routes.rb +6 -0
- data/lib/bobot.rb +18 -0
- data/lib/bobot/buttons.rb +168 -0
- data/lib/bobot/commander.rb +68 -0
- data/lib/bobot/configuration.rb +206 -0
- data/lib/bobot/engine.rb +33 -0
- data/lib/bobot/error_parser.rb +102 -0
- data/lib/bobot/event.rb +40 -0
- data/lib/bobot/events/account_linking.rb +15 -0
- data/lib/bobot/events/common.rb +170 -0
- data/lib/bobot/events/delivery.rb +20 -0
- data/lib/bobot/events/message.rb +72 -0
- data/lib/bobot/events/message_echo.rb +8 -0
- data/lib/bobot/events/optin.rb +11 -0
- data/lib/bobot/events/postback.rb +20 -0
- data/lib/bobot/events/read.rb +15 -0
- data/lib/bobot/events/referral.rb +33 -0
- data/lib/bobot/exceptions.rb +73 -0
- data/lib/bobot/graph_facebook.rb +90 -0
- data/lib/bobot/profile.rb +23 -0
- data/lib/bobot/subscription.rb +19 -0
- data/lib/bobot/user.rb +13 -0
- data/lib/bobot/version.rb +14 -0
- data/lib/generators/bobot/install_generator.rb +28 -0
- data/lib/generators/bobot/templates/app/bobot/message.rb +3 -0
- data/lib/generators/bobot/templates/app/bobot/postback.rb +22 -0
- data/lib/generators/bobot/templates/app/bobot/workflow.rb +17 -0
- data/lib/generators/bobot/templates/config/bobot.yml +39 -0
- data/lib/generators/bobot/templates/config/initializers/bobot.rb +30 -0
- data/lib/generators/bobot/templates/config/locales/bobot.en.yml +30 -0
- data/lib/generators/bobot/templates/config/locales/bobot.fr.yml +29 -0
- data/lib/generators/bobot/uninstall_generator.rb +24 -0
- data/lib/generators/bobot/utils.rb +30 -0
- data/lib/tasks/bobot_tasks.rake +11 -0
- data/spec/bobot/bobot_spec.rb +24 -0
- data/spec/bobot/event/account_linking_spec.rb +59 -0
- data/spec/bobot/event/common_spec.rb +259 -0
- data/spec/bobot/event/delivery_spec.rb +62 -0
- data/spec/bobot/event/message_echo_spec.rb +276 -0
- data/spec/bobot/event/message_spec.rb +276 -0
- data/spec/bobot/event/optin_spec.rb +50 -0
- data/spec/bobot/event/postback_spec.rb +94 -0
- data/spec/bobot/event/read_spec.rb +51 -0
- data/spec/bobot/event/referral_spec.rb +66 -0
- data/spec/bobot/event_spec.rb +167 -0
- data/spec/bobot/install_generator_spec.rb +43 -0
- data/spec/bobot/profile_spec.rb +170 -0
- data/spec/bobot/subscription_spec.rb +139 -0
- data/spec/bobot/user_spec.rb +91 -0
- data/spec/controllers/bobot/application_controller_spec.rb +4 -0
- data/spec/controllers/bobot/webhook_controller_spec.rb +5 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/bobot/workflow.rb +17 -0
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- data/spec/dummy/app/jobs/application_job.rb +2 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +35 -0
- data/spec/dummy/bin/update +29 -0
- data/spec/dummy/config.ru +5 -0
- data/spec/dummy/config/application.rb +30 -0
- data/spec/dummy/config/bobot.yml +27 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +19 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +42 -0
- data/spec/dummy/config/environments/production.rb +78 -0
- data/spec/dummy/config/environments/test.rb +38 -0
- data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/bobot.rb +30 -0
- data/spec/dummy/config/initializers/cors.rb +16 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/bobot.en.yml +28 -0
- data/spec/dummy/config/locales/bobot.fr.yml +27 -0
- data/spec/dummy/config/locales/en.yml +33 -0
- data/spec/dummy/config/puma.rb +56 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +32 -0
- data/spec/dummy/config/spring.rb +6 -0
- data/spec/dummy/db/schema.rb +15 -0
- data/spec/examples.txt +111 -0
- data/spec/helpers/graph_api_helpers.rb +6 -0
- data/spec/jobs/bobot/commander_job_spec.rb +31 -0
- data/spec/lint/rubocop_spec.rb +8 -0
- data/spec/rails_helper.rb +67 -0
- data/spec/spec_helper.rb +105 -0
- data/spec/travis/database.travis.mysql.yml +19 -0
- metadata +251 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: eaf59a5fc23f77c3ac873a376a706b695d816160
|
|
4
|
+
data.tar.gz: 817d2a4690326c0e9da432c4fb0da059b62dd6ae
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5c37f10f0452a0b9a591dadd1c3d9e0bb676e16d006c93b67558b9557df623f6e8677b14ca8cb7dd9e6ae8a4adfdab775df45b01bb1501587e9a817efc3794dd
|
|
7
|
+
data.tar.gz: 196ddbca0e9fbd883553f591510477d7c1b83ebb9788d8673a21da744b059e04e7de2708f8e8199561fcf04de1d97bccb7b88ac343d220141d42271034f3e7b6
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2017 Navid EMAD
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/navidemad/bobot/master/assets/images/bobot-logo.png"/>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Bobot [Gem under development !][](https://travis-ci.org/navidemad/bobot) [](https://rubygems.org/gems/bobot)
|
|
6
|
+
`Bobot` is a Ruby wrapped framework to build easily a Facebook Messenger Bot.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
Add this line to your application's Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem 'bobot'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And then execute:
|
|
16
|
+
|
|
17
|
+
$ bundle
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
$ gem install bobot
|
|
22
|
+
|
|
23
|
+
## Requirement
|
|
24
|
+
`bobot` has only requirement to have at least `ruby 2.3.1`.
|
|
25
|
+
|
|
26
|
+
## Setup
|
|
27
|
+
|
|
28
|
+
Typing the following command in your Rails application will add the bot to your app.
|
|
29
|
+
`rails g bobot:install`
|
|
30
|
+
|
|
31
|
+
`config/bobot.yml` contains your bot keys
|
|
32
|
+
`app/bobot/workflow.rb` contains the workflow of your bot
|
|
33
|
+
|
|
34
|
+
You can run in a Rails console:
|
|
35
|
+
`Bobot.update_facebook_setup!`
|
|
36
|
+
|
|
37
|
+
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
|
+
|
|
45
|
+
Greeting Text and Persistent Menus are translated by I18n.
|
|
46
|
+
You have to define into your `config/application.rb` your available_locales as I18n defined them.
|
|
47
|
+
Then, Bobot when you will catch the content of them from `locales/bobot.{locale}.yml`
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
See example [Workflow](BOBOT_WORKFLOW.md)
|
|
51
|
+
## Wiki
|
|
52
|
+
The [Messenger Platform - Facebook for Developers](https://developers.facebook.com/docs/messenger-platform) is available and provides full documentation for the API section.
|
|
53
|
+
All informations related to webhook [Messenger Platform - Webhook](https://developers.facebook.com/docs/messenger-platform/webhook-reference).
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/navidemad/bobot.
|
|
57
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
|
|
61
|
+
|
|
62
|
+
## Code of Conduct
|
|
63
|
+
Everyone interacting in the Bobot project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/navidemad/bobot/blob/master/CODE_OF_CONDUCT.md).
|
|
64
|
+
|
|
65
|
+
## Contributing
|
|
66
|
+
Please refer to [CONTRIBUTING.md](CONTRIBUTING.md).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Bobot'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
load 'rails/tasks/statistics.rake'
|
|
18
|
+
|
|
19
|
+
require 'bundler/gem_tasks'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Bobot
|
|
2
|
+
class WebhookController < Bobot::ApplicationController
|
|
3
|
+
include ActionView::Helpers::TextHelper
|
|
4
|
+
|
|
5
|
+
skip_before_action :verify_authenticity_token, raise: false
|
|
6
|
+
|
|
7
|
+
layout :bobot_layout rescue nil
|
|
8
|
+
|
|
9
|
+
def notify
|
|
10
|
+
if check_integrity?
|
|
11
|
+
respond_with body: ActiveSupport::JSON.encode(trigger(parsed_body)), status: :ok
|
|
12
|
+
else
|
|
13
|
+
respond_with status: :forbidden
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
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
|
|
21
|
+
else
|
|
22
|
+
respond_with status: :forbidden
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def body
|
|
29
|
+
@body ||= request.body.read
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
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
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def signature(str, key = nil)
|
|
41
|
+
key ||= Bobot.app_secret
|
|
42
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), key, str)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def check_integrity?
|
|
46
|
+
request.headers['HTTP_X_HUB_SIGNATURE'].to_s =~ /\Asha1=([0-9a-z]{40})\z/
|
|
47
|
+
hub_signature = Regexp.last_match(1)
|
|
48
|
+
hub_signature && Rack::Utils.secure_compare(hub_signature, signature(body))
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def trigger(events)
|
|
52
|
+
events['entry'].inject([]) do |payloads_sent, entry|
|
|
53
|
+
entry['messaging'].each do |messaging|
|
|
54
|
+
begin
|
|
55
|
+
payloads_sent << Bobot::Commander.receive(messaging)
|
|
56
|
+
rescue => e
|
|
57
|
+
payloads_sent << e.to_s
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
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
|
+
def bobot_layout
|
|
73
|
+
'bobot/application'
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Bobot
|
|
2
|
+
class DeliverJob < ApplicationJob
|
|
3
|
+
queue_as :default
|
|
4
|
+
|
|
5
|
+
def perform(sender:, access_token:, payload_template:)
|
|
6
|
+
Bobot::Commander.deliver(
|
|
7
|
+
body: {
|
|
8
|
+
recipient: sender,
|
|
9
|
+
}.merge(payload_template),
|
|
10
|
+
query: {
|
|
11
|
+
access_token: access_token,
|
|
12
|
+
},
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
en:
|
|
2
|
+
bobot:
|
|
3
|
+
config:
|
|
4
|
+
facebook_locales:
|
|
5
|
+
- "en_US"
|
|
6
|
+
- "en_UD"
|
|
7
|
+
- "en_GB"
|
|
8
|
+
greeting_text: "Bobot is an intelligent robot."
|
|
9
|
+
persistent_menu:
|
|
10
|
+
composer_input_disabled: false
|
|
11
|
+
call_to_actions:
|
|
12
|
+
- title: "My Account"
|
|
13
|
+
type: "nested"
|
|
14
|
+
call_to_actions:
|
|
15
|
+
- title: "What is a chatbot?"
|
|
16
|
+
type: "postback"
|
|
17
|
+
payload: "WHAT_IS_A_CHATBOT"
|
|
18
|
+
- title: "History"
|
|
19
|
+
type: "postback"
|
|
20
|
+
payload: "HISTORY_PAYLOAD"
|
|
21
|
+
- title: "Contact Info"
|
|
22
|
+
type: "postback"
|
|
23
|
+
payload: "CONTACT_INFO_PAYLOAD"
|
|
24
|
+
- type: "web_url"
|
|
25
|
+
title: "Get some help"
|
|
26
|
+
url: "https://github.com/navidemad/bobot"
|
|
27
|
+
webview_height_ratio: "full"
|
|
28
|
+
what_is_a_chatbot: "A chatbot is a computer program which conducts a conversation via auditory or textual methods."
|
data/config/routes.rb
ADDED
data/lib/bobot.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'net/https'
|
|
2
|
+
require 'uri'
|
|
3
|
+
|
|
4
|
+
require 'bobot/engine'
|
|
5
|
+
require 'bobot/exceptions'
|
|
6
|
+
require 'bobot/error_parser'
|
|
7
|
+
require 'bobot/graph_facebook'
|
|
8
|
+
require 'bobot/configuration'
|
|
9
|
+
require 'bobot/subscription'
|
|
10
|
+
require 'bobot/profile'
|
|
11
|
+
require 'bobot/user'
|
|
12
|
+
require 'bobot/buttons'
|
|
13
|
+
require 'bobot/commander'
|
|
14
|
+
require 'bobot/event'
|
|
15
|
+
|
|
16
|
+
module Bobot
|
|
17
|
+
extend Configuration
|
|
18
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
module Bobot
|
|
2
|
+
module Buttons
|
|
3
|
+
def self.encode_payload(payload:)
|
|
4
|
+
unless payload.is_a?(String)
|
|
5
|
+
begin
|
|
6
|
+
payload = ActiveSupport::JSON.encode(payload)
|
|
7
|
+
rescue ::ActiveSupport::JSON.parse_error
|
|
8
|
+
raise Bobot::FieldFormat.new('payload is not string and not a valid to be JSONified.')
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
payload
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.postback(title:, payload:)
|
|
15
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
16
|
+
raise Bobot::FieldFormat.new('title length is limited to 20.') if title.size > 20
|
|
17
|
+
raise Bobot::FieldFormat.new('payload is required.') unless payload.present?
|
|
18
|
+
payload = Bobot::Buttons.encode_payload(payload: payload)
|
|
19
|
+
raise Bobot::FieldFormat.new('payload length is limited to 1000.') if payload.bytesize > 1000
|
|
20
|
+
{
|
|
21
|
+
type: 'postback',
|
|
22
|
+
title: title,
|
|
23
|
+
payload: payload,
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.generic_element(title:, subtitle: nil, image_url: nil, default_action_url: nil, buttons: nil)
|
|
28
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
29
|
+
raise Bobot::FieldFormat.new('title length is limited to 80.') if title.size > 80
|
|
30
|
+
raise Bobot::FieldFormat.new('subtitle length is limited to 80.') if subtitle.present? && subtitle.size > 80
|
|
31
|
+
raise Bobot::FieldFormat.new('buttons are limited to 3.') if buttons.present? && buttons.size > 3
|
|
32
|
+
{
|
|
33
|
+
title: title,
|
|
34
|
+
}.tap do |properties|
|
|
35
|
+
properties[:image_url] = image_url if image_url.present?
|
|
36
|
+
properties[:subtitle] = subtitle if subtitle.present?
|
|
37
|
+
properties[:default_action_url] = default_action_url if default_action_url.present?
|
|
38
|
+
properties[:buttons] = buttons if buttons.present?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
class <<self
|
|
42
|
+
alias_method :carousel_element, :generic_element
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.quick_reply_location(image_url: nil)
|
|
46
|
+
{
|
|
47
|
+
content_type: 'location',
|
|
48
|
+
}.tap do |properties|
|
|
49
|
+
properties[:image_url] = image_url if image_url.present?
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.quick_reply_text(title:, payload:, image_url: nil)
|
|
54
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
55
|
+
raise Bobot::FieldFormat.new('title length is limited to 20.') if title.size > 20
|
|
56
|
+
raise Bobot::FieldFormat.new('payload is required.') unless payload.present?
|
|
57
|
+
payload = Bobot::Buttons.encode_payload(payload: payload)
|
|
58
|
+
raise Bobot::FieldFormat.new('payload length is limited to 1000.') if payload.bytesize > 1000
|
|
59
|
+
{
|
|
60
|
+
content_type: 'text',
|
|
61
|
+
title: title,
|
|
62
|
+
payload: payload,
|
|
63
|
+
}.tap do |properties|
|
|
64
|
+
properties[:image_url] = image_url if image_url.present?
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.share_basic
|
|
69
|
+
{
|
|
70
|
+
type: 'element_share',
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.share_custom(title:, subtitle:, image_url:, web_url:, button_title:, image_aspect_ratio:)
|
|
75
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
76
|
+
raise Bobot::FieldFormat.new('title length is limited to 80.') if title.size > 80
|
|
77
|
+
raise Bobot::FieldFormat.new('subtitle is required.') unless subtitle.present?
|
|
78
|
+
raise Bobot::FieldFormat.new('subtitle length is limited to 80.') if subtitle.size > 80
|
|
79
|
+
raise Bobot::FieldFormat.new('button_title is required.') unless button_title.present?
|
|
80
|
+
raise Bobot::FieldFormat.new('button_title length is limited to 20.') if button_title.size > 20
|
|
81
|
+
{
|
|
82
|
+
type: 'element_share',
|
|
83
|
+
share_contents: {
|
|
84
|
+
attachment: {
|
|
85
|
+
type: 'template',
|
|
86
|
+
payload: {
|
|
87
|
+
template_type: 'generic',
|
|
88
|
+
image_aspect_ratio: image_aspect_ratio,
|
|
89
|
+
elements: [
|
|
90
|
+
{
|
|
91
|
+
title: title,
|
|
92
|
+
subtitle: subtitle,
|
|
93
|
+
image_url: image_url,
|
|
94
|
+
default_action: {
|
|
95
|
+
type: 'web_url',
|
|
96
|
+
url: web_url,
|
|
97
|
+
},
|
|
98
|
+
buttons: [
|
|
99
|
+
{
|
|
100
|
+
type: 'web_url',
|
|
101
|
+
url: web_url,
|
|
102
|
+
title: button_title,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.default_action_url(url:, options: {})
|
|
114
|
+
raise Bobot::FieldFormat.new('url is required.') unless url.present?
|
|
115
|
+
if options.key?(:messenger_extensions) && options[:messenger_extensions] && !url.include?('https')
|
|
116
|
+
raise Bobot::FieldFormat.new('must use url HTTPS protocol if messenger_extensions is true.')
|
|
117
|
+
end
|
|
118
|
+
if options.key?(:webview_height_ratio) && !%w[compact tall full].include?(options[:webview_height_ratio])
|
|
119
|
+
raise Bobot::FieldFormat.new('invalid webview_height_ratio, only "compact, tall, full" are permitted.')
|
|
120
|
+
end
|
|
121
|
+
{
|
|
122
|
+
type: 'web_url',
|
|
123
|
+
url: url,
|
|
124
|
+
}.tap do |properties|
|
|
125
|
+
properties[:webview_height_ratio] = options[:webview_height_ratio] if options.key?(:webview_height_ratio)
|
|
126
|
+
properties[:messenger_extensions] = options[:messenger_extensions] if options.key?(:messenger_extensions)
|
|
127
|
+
properties[:fallback_url] = options[:fallback_url] if options.key?(:fallback_url)
|
|
128
|
+
properties[:webview_share_button] = options[:webview_share_button] if options.key?(:webview_share_button)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.url(title:, url:, options: {})
|
|
133
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
134
|
+
raise Bobot::FieldFormat.new('title length is limited to 20.') if title.size > 20
|
|
135
|
+
raise Bobot::FieldFormat.new('url is required.') unless url.present?
|
|
136
|
+
if options.key?(:messenger_extensions) && options[:messenger_extensions] && !url.include?('https')
|
|
137
|
+
raise Bobot::FieldFormat.new('must use url HTTPS protocol if messenger_extensions is true.')
|
|
138
|
+
end
|
|
139
|
+
if options.key?(:webview_height_ratio) && !%w[compact tall full].include?(options[:webview_height_ratio])
|
|
140
|
+
raise Bobot::FieldFormat.new('invalid webview_height_ratio, only "compact, tall, full" are permitted.')
|
|
141
|
+
end
|
|
142
|
+
{
|
|
143
|
+
type: 'web_url',
|
|
144
|
+
url: url,
|
|
145
|
+
title: title,
|
|
146
|
+
}.tap do |properties|
|
|
147
|
+
properties[:webview_height_ratio] = options[:webview_height_ratio] if options.key?(:webview_height_ratio)
|
|
148
|
+
properties[:messenger_extensions] = options[:messenger_extensions] if options.key?(:messenger_extensions)
|
|
149
|
+
properties[:fallback_url] = options[:fallback_url] if options.key?(:fallback_url)
|
|
150
|
+
properties[:webview_share_button] = options[:webview_share_button] if options.key?(:webview_share_button)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
REGEX_PHONE_NUMBER = /\A(?:\+)(?:\d{1,3}\s*-?)?\(?(?:\d{3})?\)?[- ]?\d{3}[- ]?\d{4}\z/
|
|
155
|
+
def self.call(title:, payload:)
|
|
156
|
+
raise Bobot::FieldFormat.new('title is required.') unless title.present?
|
|
157
|
+
raise Bobot::FieldFormat.new('title length is limited to 20.') if title.size > 20
|
|
158
|
+
raise Bobot::FieldFormat.new('payload is required.') unless payload.present?
|
|
159
|
+
raise Bobot::FieldFormat.new('payload has to be only a string') unless payload.is_a?(String)
|
|
160
|
+
raise Bobot::FieldFormat.new('payload has to start with a "+" and be a valid phone number') unless REGEX_PHONE_NUMBER =~ payload
|
|
161
|
+
{
|
|
162
|
+
type: 'phone_number',
|
|
163
|
+
title: title,
|
|
164
|
+
payload: payload,
|
|
165
|
+
}
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|