message_quickly 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/message_quickly/application_helper.rb +4 -0
  3. data/lib/generators/message_quickly/callbacks/templates/account_linking_callback.rb +14 -0
  4. data/lib/generators/message_quickly/callbacks/templates/message_read_callback.rb +14 -0
  5. data/lib/message_quickly.rb +1 -0
  6. data/lib/message_quickly/api/account_link.rb +41 -0
  7. data/lib/message_quickly/api/client.rb +9 -0
  8. data/lib/message_quickly/api/thread_settings.rb +74 -19
  9. data/lib/message_quickly/api/user_profile.rb +1 -1
  10. data/lib/message_quickly/callback_parser.rb +9 -1
  11. data/lib/message_quickly/messaging/account_link_button.rb +23 -0
  12. data/lib/message_quickly/messaging/account_link_event.rb +41 -0
  13. data/lib/message_quickly/messaging/account_unlink_button.rb +22 -0
  14. data/lib/message_quickly/messaging/audio_attachment.rb +41 -0
  15. data/lib/message_quickly/messaging/button_template_attachment.rb +2 -0
  16. data/lib/message_quickly/messaging/element.rb +2 -0
  17. data/lib/message_quickly/messaging/image_attachment.rb +1 -1
  18. data/lib/message_quickly/messaging/location_attachment.rb +30 -0
  19. data/lib/message_quickly/messaging/message.rb +16 -3
  20. data/lib/message_quickly/messaging/message_event.rb +28 -5
  21. data/lib/message_quickly/messaging/quick_reply.rb +34 -0
  22. data/lib/message_quickly/messaging/read_event.rb +49 -0
  23. data/lib/message_quickly/messaging/user.rb +1 -1
  24. data/lib/message_quickly/messaging/video_attachment.rb +41 -0
  25. data/lib/message_quickly/version.rb +2 -2
  26. data/spec/callback_parser_spec.rb +22 -0
  27. data/spec/controllers/webhooks_controller_spec.rb +35 -1
  28. data/spec/dummy/app/webhooks/account_linking_callback.rb +14 -0
  29. data/spec/dummy/app/webhooks/message_read_callback.rb +14 -0
  30. data/spec/dummy/log/test.log +7166 -0
  31. data/spec/fixtures/SampleVideo_1280x720_1mb.mp4 +0 -0
  32. data/spec/fixtures/account_link.json +24 -0
  33. data/spec/fixtures/jailhouse-rock-demo.mp3 +0 -0
  34. data/spec/fixtures/message_read.json +24 -0
  35. data/spec/fixtures/message_request_with_attachment.json +13 -1
  36. data/spec/message_quickly/api/account_link_spec.rb +49 -0
  37. data/spec/message_quickly/api/messages_spec.rb +70 -0
  38. data/spec/message_quickly/api/thread_settings_spec.rb +83 -7
  39. metadata +27 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 50e84b3ef8343c78048a81ffe8e06a18ec160538
4
- data.tar.gz: ba28b127efdcf9569202fe26ac375ddbacd6d54d
3
+ metadata.gz: f40defb57698c809f71d70ed577debd4a5f085d7
4
+ data.tar.gz: 45b8b80b3b61984b678a3bc58ae00705f1defc98
5
5
  SHA512:
6
- metadata.gz: 525a00f7e6803fd9d74513c5a49be838c9c6d8e31d5e8b822e8ee2a6c23af5aa9198f6908853fc7d5671256a0098df0dd52aeedf15d0a45f6381011f9550101c
7
- data.tar.gz: 16692e9535cbfdc4ec1712f848f518c6e57b136f04c36caf91d8c7348c0f63eebb6e78404d925be13764126868c7d26647c9ff9c1c899a117a7ac38445568e30
6
+ metadata.gz: d51150793b85d9293a90df174ecdcaf59a631e3e2ddc73fb1a0ae67394b1a3347f268a53bfdb04b17a28f3ef4e3dff1969343236892edf786367b1bfe3519f19
7
+ data.tar.gz: 9e326b869a79eb7ea26f7f2a8e35142b4d4430309114792f09519399afaae295bb48c2699124ecb942f1417dc1b9417293cc4069cb4f0f786874ec25bf8d0039
@@ -21,5 +21,9 @@ module MessageQuickly
21
21
  content_tag(:div, '', params)
22
22
  end
23
23
 
24
+ # def close_window(image_url = '', display_text = '')
25
+ # redirect_to "https://www.messenger.com/closeWindow/?image_url=#{image_url}&display_text=#{display_text}."
26
+ # end
27
+
24
28
  end
25
29
  end
@@ -0,0 +1,14 @@
1
+ class AccountLinkingCallback < MessageQuickly::Callback
2
+
3
+ def self.webhook_name
4
+ :account_linking
5
+ end
6
+
7
+ def initialize(event, json)
8
+ super
9
+ end
10
+
11
+ def run
12
+ end
13
+
14
+ end
@@ -0,0 +1,14 @@
1
+ class MessageReadCallback < MessageQuickly::Callback
2
+
3
+ def self.webhook_name
4
+ :message_reads
5
+ end
6
+
7
+ def initialize(event, json)
8
+ super
9
+ end
10
+
11
+ def run
12
+ end
13
+
14
+ end
@@ -11,6 +11,7 @@ require "message_quickly/api/not_permitted_exception"
11
11
  require "message_quickly/api/send_message_exception"
12
12
  require "message_quickly/api/thread_settings"
13
13
  require "message_quickly/api/user_profile"
14
+ require "message_quickly/api/account_link"
14
15
 
15
16
  require "message_quickly/engine"
16
17
 
@@ -0,0 +1,41 @@
1
+ module MessageQuickly
2
+ module Api
3
+ class AccountLink < Base
4
+
5
+ def self.page_scoped_id(account_linking_token)
6
+ # curl -X GET "https://graph.facebook.com/v2.6/me?access_token=PAGE_ACCESS_TOKEN \
7
+ # &fields=recipient \
8
+ # &account_linking_token=ACCOUNT_LINKING_TOKEN"
9
+
10
+ # {
11
+ # "id": "PAGE_ID",
12
+ # "recipient": "PSID"
13
+ # }
14
+ AccountLink.new.page_scoped_id(account_linking_token)
15
+ end
16
+
17
+ def page_scoped_id(account_linking_token)
18
+ json = @client.get("me", { fields: 'recipient', account_linking_token: account_linking_token })
19
+ json['recipient']
20
+ end
21
+
22
+ def self.unlink_account(page_scoped_id)
23
+ # curl -X POST -H "Content-Type: application/json" -d '{
24
+ # "psid":"PSID"
25
+ # }' "https://graph.facebook.com/v2.6/me/unlink_accounts?access_token=PAGE_ACCESS_TOKEN"
26
+
27
+ # {
28
+ # "result": "unlink account success"
29
+ # }
30
+ AccountLink.new.unlink_account(page_scoped_id)
31
+ end
32
+
33
+ def unlink_account(page_scoped_id)
34
+ json = @client.post("me/unlink_accounts", { psid: page_scoped_id })
35
+ json['result'] == "unlink account success"
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
@@ -31,6 +31,15 @@ module MessageQuickly
31
31
  parse_json(response)
32
32
  end
33
33
 
34
+ def delete(request_string, params = {})
35
+ params[:access_token] = page_access_token
36
+ response = connection.delete(request_string) do |request|
37
+ request.headers['Content-Type'] = 'application/json'
38
+ request.body = JSON.generate(params)
39
+ end
40
+ parse_json(response)
41
+ end
42
+
34
43
  private
35
44
 
36
45
  def parse_json(response)
@@ -2,40 +2,95 @@ module MessageQuickly
2
2
  module Api
3
3
  class ThreadSettings < Base
4
4
 
5
- def self.create(message)
5
+ def self.greeting(text)
6
+ # curl -X POST -H "Content-Type: application/json" -d '{
7
+ # "setting_type":"greeting",
8
+ # "greeting":{
9
+ # "text":"Welcome to My Company!"
10
+ # }
11
+ # }' "https://graph.facebook.com/v2.6/<PAGE_ID>/thread_settings?access_token=<PAGE_ACCESS_TOKEN>"
12
+ ThreadSettings.new.greeting(text)
13
+ end
14
+
15
+ def self.get_started_button(payload)
6
16
  # curl -X POST -H "Content-Type: application/json" -d '{
7
17
  # "setting_type":"call_to_actions",
8
18
  # "thread_state":"new_thread",
9
19
  # "call_to_actions":[
10
20
  # {
11
- # "message":{
12
- # "text":"Welcome to My Company!"
13
- # }
21
+ # "payload":"USER_DEFINED_PAYLOAD"
14
22
  # }
15
23
  # ]
16
- # }' "https://graph.facebook.com/v2.6/<PAGE_ID>/thread_settings?access_token=<PAGE_ACCESS_TOKEN>"
17
- ThreadSettings.new.create(message)
24
+ # }' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN"
25
+ ThreadSettings.new.get_started_button(payload)
18
26
  end
19
27
 
20
- def self.delete
21
- # curl -X POST -H "Content-Type: application/json" -d '{
28
+ def self.remove_get_started_button
29
+ # curl -X DELETE -H "Content-Type: application/json" -d '{
22
30
  # "setting_type":"call_to_actions",
23
- # "thread_state":"new_thread",
24
- # "call_to_actions":[]
25
- # }' "https://graph.facebook.com/v2.6/<PAGE_ID>/thread_settings?access_token=<PAGE_ACCESS_TOKEN>"
26
- ThreadSettings.new.delete
31
+ # "thread_state":"new_thread"
32
+ # }' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN"
33
+ ThreadSettings.new.remove_get_started_button
34
+ end
35
+
36
+ def self.persistent_menu(payloads = [])
37
+ # curl -X POST -H "Content-Type: application/json" -d '{
38
+ # "setting_type" : "call_to_actions",
39
+ # "thread_state" : "existing_thread",
40
+ # "call_to_actions":[
41
+ # {
42
+ # "type":"postback",
43
+ # "title":"Help",
44
+ # "payload":"DEVELOPER_DEFINED_PAYLOAD_FOR_HELP"
45
+ # },
46
+ # {
47
+ # "type":"postback",
48
+ # "title":"Start a New Order",
49
+ # "payload":"DEVELOPER_DEFINED_PAYLOAD_FOR_START_ORDER"
50
+ # },
51
+ # {
52
+ # "type":"web_url",
53
+ # "title":"View Website",
54
+ # "url":"http://petersapparel.parseapp.com/"
55
+ # }
56
+ # ]
57
+ # }' "https://graph.facebook.com/v2.6/me/thread_settings?access_token=PAGE_ACCESS_TOKEN"
58
+ ThreadSettings.new.persistent_menu(payloads)
59
+ end
60
+
61
+ def self.remove_persistent_menu
62
+ ThreadSettings.new.remove_persistent_menu
63
+ end
64
+
65
+ def greeting(text)
66
+ json = @client.post(request_string, { setting_type: 'greeting', greeting: { text: text } })
67
+ json['result'] == "Successfully updated greeting"
27
68
  end
28
69
 
29
- def create(message)
30
- request_string = "#{ENV['FACEBOOK_MESSENGER_PAGE_ID']}/thread_settings"
31
- json = @client.post(request_string, { setting_type: 'call_to_actions', thread_state: 'new_thread', call_to_actions: [{ message: { text: message } }] })
70
+ def get_started_button(payload)
71
+ json = @client.post(request_string, { setting_type: 'call_to_actions', thread_state: 'new_thread', call_to_actions: [payload: payload] })
32
72
  json['result'] == "Successfully added new_thread's CTAs"
33
73
  end
34
74
 
35
- def delete
36
- request_string = "#{ENV['FACEBOOK_MESSENGER_PAGE_ID']}/thread_settings"
37
- json = @client.post(request_string, { setting_type: 'call_to_actions', thread_state: 'new_thread', call_to_actions: [] })
38
- json['result'] == "Successfully removed all new_thread's CTAs"
75
+ def remove_get_started_button
76
+ json = @client.delete(request_string, { setting_type: 'call_to_actions', thread_state: 'new_thread' })
77
+ json['result'] == "Successfully deleted all new_thread's CTAs"
78
+ end
79
+
80
+ def persistent_menu(payloads = [])
81
+ json = @client.post(request_string, { setting_type: 'call_to_actions', thread_state: 'existing_thread', call_to_actions: payloads })
82
+ json['result'] == "Successfully added structured menu CTAs"
83
+ end
84
+
85
+ def remove_persistent_menu(payloads = [])
86
+ json = @client.delete(request_string, { setting_type: 'call_to_actions', thread_state: 'existing_thread' })
87
+ json['result'] == "Successfully deleted structured menu CTAs"
88
+ end
89
+
90
+ private
91
+
92
+ def request_string
93
+ "#{ENV['FACEBOOK_MESSENGER_PAGE_ID']}/thread_settings"
39
94
  end
40
95
 
41
96
  end
@@ -13,7 +13,7 @@ module MessageQuickly
13
13
  end
14
14
 
15
15
  def find(id)
16
- json = @client.get(id, { fields: 'first_name,last_name,profile_pic' })
16
+ json = @client.get(id, { fields: 'first_name,last_name,profile_pic,locale,timezone,gender' })
17
17
  Messaging::User.new(json)
18
18
  end
19
19
 
@@ -3,13 +3,17 @@ require 'json'
3
3
  require "message_quickly/messaging/base"
4
4
  require "message_quickly/messaging/attachment"
5
5
  require "message_quickly/messaging/image_attachment"
6
+ require "message_quickly/messaging/video_attachment"
7
+ require "message_quickly/messaging/audio_attachment"
6
8
  require "message_quickly/messaging/template_attachment"
7
9
  require "message_quickly/messaging/element"
8
10
  require "message_quickly/messaging/button"
9
11
  require "message_quickly/messaging/web_url_button"
10
12
  require "message_quickly/messaging/postback_button"
13
+ require "message_quickly/messaging/account_link_button"
11
14
  require "message_quickly/messaging/button_template_attachment"
12
15
  require "message_quickly/messaging/generic_template_attachment"
16
+ require "message_quickly/messaging/quick_reply"
13
17
 
14
18
  require "message_quickly/messaging/receipt/address"
15
19
  require "message_quickly/messaging/receipt/adjustment"
@@ -29,6 +33,8 @@ require "message_quickly/messaging/optin_event"
29
33
  require "message_quickly/messaging/delivery_event"
30
34
  require "message_quickly/messaging/message_event"
31
35
  require "message_quickly/messaging/postback_event"
36
+ require "message_quickly/messaging/read_event"
37
+ require "message_quickly/messaging/account_link_event"
32
38
 
33
39
  module MessageQuickly
34
40
  class CallbackParser
@@ -41,7 +47,9 @@ module MessageQuickly
41
47
  optin: MessageQuickly::Messaging::OptinEvent,
42
48
  postback: MessageQuickly::Messaging::PostbackEvent,
43
49
  delivery: MessageQuickly::Messaging::DeliveryEvent,
44
- message: MessageQuickly::Messaging::MessageEvent
50
+ account_linking: MessageQuickly::Messaging::AccountLinkEvent,
51
+ message: MessageQuickly::Messaging::MessageEvent,
52
+ read: MessageQuickly::Messaging::ReadEvent
45
53
  }
46
54
 
47
55
  def parse
@@ -0,0 +1,23 @@
1
+ module MessageQuickly
2
+ module Messaging
3
+ class AccountLinkButton < Button
4
+
5
+ attr_accessor :url
6
+
7
+ def initialize(params = {})
8
+ params['type'] ||= 'account_link'
9
+ super(params)
10
+ end
11
+
12
+ def to_hash
13
+ { type: type, url: url }
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
20
+ # "buttons": [{
21
+ # "type": "account_link",
22
+ # "url": "https://www.example.com/oauth/authorize"
23
+ # }]
@@ -0,0 +1,41 @@
1
+ require "message_quickly/messaging/event"
2
+
3
+ module MessageQuickly
4
+ module Messaging
5
+ class AccountLinkEvent < Event
6
+
7
+ attr_reader :status, :authorization_code
8
+
9
+ def initialize(params = {})
10
+
11
+ if params.include? :account_linking
12
+ @status = params[:account_linking][:status]
13
+ @authorization_code = params[:account_linking][:authorization_code]
14
+ params.delete(:account_linking)
15
+ end
16
+
17
+ super(params)
18
+
19
+ end
20
+
21
+ def webhook_name
22
+ :account_linking
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ # {
30
+ # "sender":{
31
+ # "id":"USER_ID"
32
+ # },
33
+ # "recipient":{
34
+ # "id":"PAGE_ID"
35
+ # },
36
+ # "timestamp":1234567890,
37
+ # "account_linking":{
38
+ # "status":"linked",
39
+ # "authorization_code":"PASS_THROUGH_AUTHORIZATION_CODE"
40
+ # }
41
+ # }
@@ -0,0 +1,22 @@
1
+ module MessageQuickly
2
+ module Messaging
3
+ class AccountUnlinkButton < Button
4
+
5
+ attr_accessor :url
6
+
7
+ def initialize(params = {})
8
+ params['type'] ||= 'account_unlink'
9
+ super(params)
10
+ end
11
+
12
+ def to_hash
13
+ { type: type }
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
20
+ # "buttons": [{
21
+ # "type": "account_link"
22
+ # }]
@@ -0,0 +1,41 @@
1
+ module MessageQuickly
2
+ module Messaging
3
+ class AudioAttachment < Attachment
4
+
5
+ attr_accessor :url, :file, :file_type
6
+
7
+ def initialize(params = {})
8
+ params['type'] ||= 'audio'
9
+ super(params)
10
+ end
11
+
12
+ def file?
13
+ file.present? && file_type.present?
14
+ end
15
+
16
+ def to_hash
17
+ if file?
18
+ { type: type, payload: { url: '' } } # cannot send empty hash
19
+ else
20
+ { type: type, payload: { url: url } }
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+
28
+ # "attachments":[
29
+ # {
30
+ # "type":"audio",
31
+ # "payload":{
32
+ # "url":"https://petersapparel.com/bin/clip.mp3"
33
+ # }
34
+ # }
35
+ # ]
36
+
37
+ # curl \
38
+ # -F recipient='{"id":"USER_ID"}' \
39
+ # -F message='{"attachment":{"type":"audio", "payload":{}}}' \
40
+ # -F filedata=@/tmp/clip.mp3;type=audio/mp3 \
41
+ # "https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"
@@ -16,6 +16,8 @@ module MessageQuickly
16
16
  button = WebUrlButton.new
17
17
  when :postback
18
18
  button = PostbackButton.new
19
+ when :account_link
20
+ button = AccountLinkButton.new
19
21
  end
20
22
  buttons << button.tap { |button| yield button }
21
23
  end
@@ -15,6 +15,8 @@ module MessageQuickly
15
15
  button = WebUrlButton.new
16
16
  when :postback
17
17
  button = PostbackButton.new
18
+ when :account_link
19
+ button = AccountLinkButton.new
18
20
  end
19
21
  buttons << button.tap { |button| yield button }
20
22
  end
@@ -15,7 +15,7 @@ module MessageQuickly
15
15
 
16
16
  def to_hash
17
17
  if file?
18
- { type: type, payload: { _: '' } } # cannot send empty hash
18
+ { type: type, payload: { url: '' } } # cannot send empty hash
19
19
  else
20
20
  { type: type, payload: { url: url } }
21
21
  end