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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +66 -0
  4. data/Rakefile +19 -0
  5. data/app/controllers/bobot/application_controller.rb +5 -0
  6. data/app/controllers/bobot/webhook_controller.rb +76 -0
  7. data/app/jobs/bobot/application_job.rb +4 -0
  8. data/app/jobs/bobot/commander_job.rb +9 -0
  9. data/app/jobs/bobot/deliver_job.rb +16 -0
  10. data/app/mailers/bobot/application_mailer.rb +6 -0
  11. data/app/models/bobot/application_record.rb +5 -0
  12. data/config/locales/bobot.en.yml +28 -0
  13. data/config/routes.rb +6 -0
  14. data/lib/bobot.rb +18 -0
  15. data/lib/bobot/buttons.rb +168 -0
  16. data/lib/bobot/commander.rb +68 -0
  17. data/lib/bobot/configuration.rb +206 -0
  18. data/lib/bobot/engine.rb +33 -0
  19. data/lib/bobot/error_parser.rb +102 -0
  20. data/lib/bobot/event.rb +40 -0
  21. data/lib/bobot/events/account_linking.rb +15 -0
  22. data/lib/bobot/events/common.rb +170 -0
  23. data/lib/bobot/events/delivery.rb +20 -0
  24. data/lib/bobot/events/message.rb +72 -0
  25. data/lib/bobot/events/message_echo.rb +8 -0
  26. data/lib/bobot/events/optin.rb +11 -0
  27. data/lib/bobot/events/postback.rb +20 -0
  28. data/lib/bobot/events/read.rb +15 -0
  29. data/lib/bobot/events/referral.rb +33 -0
  30. data/lib/bobot/exceptions.rb +73 -0
  31. data/lib/bobot/graph_facebook.rb +90 -0
  32. data/lib/bobot/profile.rb +23 -0
  33. data/lib/bobot/subscription.rb +19 -0
  34. data/lib/bobot/user.rb +13 -0
  35. data/lib/bobot/version.rb +14 -0
  36. data/lib/generators/bobot/install_generator.rb +28 -0
  37. data/lib/generators/bobot/templates/app/bobot/message.rb +3 -0
  38. data/lib/generators/bobot/templates/app/bobot/postback.rb +22 -0
  39. data/lib/generators/bobot/templates/app/bobot/workflow.rb +17 -0
  40. data/lib/generators/bobot/templates/config/bobot.yml +39 -0
  41. data/lib/generators/bobot/templates/config/initializers/bobot.rb +30 -0
  42. data/lib/generators/bobot/templates/config/locales/bobot.en.yml +30 -0
  43. data/lib/generators/bobot/templates/config/locales/bobot.fr.yml +29 -0
  44. data/lib/generators/bobot/uninstall_generator.rb +24 -0
  45. data/lib/generators/bobot/utils.rb +30 -0
  46. data/lib/tasks/bobot_tasks.rake +11 -0
  47. data/spec/bobot/bobot_spec.rb +24 -0
  48. data/spec/bobot/event/account_linking_spec.rb +59 -0
  49. data/spec/bobot/event/common_spec.rb +259 -0
  50. data/spec/bobot/event/delivery_spec.rb +62 -0
  51. data/spec/bobot/event/message_echo_spec.rb +276 -0
  52. data/spec/bobot/event/message_spec.rb +276 -0
  53. data/spec/bobot/event/optin_spec.rb +50 -0
  54. data/spec/bobot/event/postback_spec.rb +94 -0
  55. data/spec/bobot/event/read_spec.rb +51 -0
  56. data/spec/bobot/event/referral_spec.rb +66 -0
  57. data/spec/bobot/event_spec.rb +167 -0
  58. data/spec/bobot/install_generator_spec.rb +43 -0
  59. data/spec/bobot/profile_spec.rb +170 -0
  60. data/spec/bobot/subscription_spec.rb +139 -0
  61. data/spec/bobot/user_spec.rb +91 -0
  62. data/spec/controllers/bobot/application_controller_spec.rb +4 -0
  63. data/spec/controllers/bobot/webhook_controller_spec.rb +5 -0
  64. data/spec/dummy/Rakefile +6 -0
  65. data/spec/dummy/app/assets/config/manifest.js +3 -0
  66. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  67. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  68. data/spec/dummy/app/bobot/workflow.rb +17 -0
  69. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  70. data/spec/dummy/app/jobs/application_job.rb +2 -0
  71. data/spec/dummy/app/models/application_record.rb +3 -0
  72. data/spec/dummy/bin/bundle +3 -0
  73. data/spec/dummy/bin/rails +4 -0
  74. data/spec/dummy/bin/rake +4 -0
  75. data/spec/dummy/bin/setup +35 -0
  76. data/spec/dummy/bin/update +29 -0
  77. data/spec/dummy/config.ru +5 -0
  78. data/spec/dummy/config/application.rb +30 -0
  79. data/spec/dummy/config/bobot.yml +27 -0
  80. data/spec/dummy/config/boot.rb +5 -0
  81. data/spec/dummy/config/database.yml +19 -0
  82. data/spec/dummy/config/environment.rb +5 -0
  83. data/spec/dummy/config/environments/development.rb +42 -0
  84. data/spec/dummy/config/environments/production.rb +78 -0
  85. data/spec/dummy/config/environments/test.rb +38 -0
  86. data/spec/dummy/config/initializers/application_controller_renderer.rb +6 -0
  87. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  88. data/spec/dummy/config/initializers/bobot.rb +30 -0
  89. data/spec/dummy/config/initializers/cors.rb +16 -0
  90. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  91. data/spec/dummy/config/initializers/inflections.rb +16 -0
  92. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  93. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  94. data/spec/dummy/config/locales/bobot.en.yml +28 -0
  95. data/spec/dummy/config/locales/bobot.fr.yml +27 -0
  96. data/spec/dummy/config/locales/en.yml +33 -0
  97. data/spec/dummy/config/puma.rb +56 -0
  98. data/spec/dummy/config/routes.rb +3 -0
  99. data/spec/dummy/config/secrets.yml +32 -0
  100. data/spec/dummy/config/spring.rb +6 -0
  101. data/spec/dummy/db/schema.rb +15 -0
  102. data/spec/examples.txt +111 -0
  103. data/spec/helpers/graph_api_helpers.rb +6 -0
  104. data/spec/jobs/bobot/commander_job_spec.rb +31 -0
  105. data/spec/lint/rubocop_spec.rb +8 -0
  106. data/spec/rails_helper.rb +67 -0
  107. data/spec/spec_helper.rb +105 -0
  108. data/spec/travis/database.travis.mysql.yml +19 -0
  109. metadata +251 -0
@@ -0,0 +1,24 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot do
4
+ describe '#configure' do
5
+ it 'sets correct configuration' do
6
+ Bobot.configure do |config|
7
+ config.app_id = '1'
8
+ config.app_secret = '2'
9
+ config.page_access_token = '3'
10
+ config.verify_token = '4'
11
+ config.page_id = '5'
12
+ config.debug_log = true
13
+ config.async = true
14
+ end
15
+ expect(Bobot.app_id).to eql('1')
16
+ expect(Bobot.app_secret).to eql('2')
17
+ expect(Bobot.page_access_token).to eql('3')
18
+ expect(Bobot.verify_token).to eql('4')
19
+ expect(Bobot.page_id).to eql('5')
20
+ expect(Bobot.debug_log).to eql(true)
21
+ expect(Bobot.async).to eql(true)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,59 @@
1
+ require 'rails_helper'
2
+ require 'helpers/graph_api_helpers'
3
+
4
+ RSpec.describe Bobot::Event::AccountLinking do
5
+ let :payload do
6
+ {
7
+ 'sender' => {
8
+ 'id' => '3'
9
+ },
10
+ 'recipient' => {
11
+ 'id' => '3'
12
+ },
13
+ 'timestamp' => 145_776_419_762_7,
14
+ 'account_linking' => {
15
+ 'status' => 'linked',
16
+ 'authorization_code' => 'PASS_THROUGH_AUTHORIZATION_CODE'
17
+ }
18
+ }
19
+ end
20
+
21
+ subject { Bobot::Event::AccountLinking.new(payload) }
22
+
23
+ describe '.messaging' do
24
+ it 'returns the original payload' do
25
+ expect(subject.messaging).to eq(payload)
26
+ end
27
+ end
28
+
29
+ describe '.sender' do
30
+ it 'returns the sender' do
31
+ expect(subject.sender).to eq(payload['sender'])
32
+ end
33
+ end
34
+
35
+ describe '.recipient' do
36
+ it 'returns the recipient' do
37
+ expect(subject.recipient).to eq(payload['recipient'])
38
+ end
39
+ end
40
+
41
+ describe '.sent_at' do
42
+ it 'returns when the postback was sent' do
43
+ expect(subject.sent_at).to eq(Time.zone.at(payload['timestamp'] / 1000))
44
+ end
45
+ end
46
+
47
+ describe '.status' do
48
+ it 'returns linking status defined with the entry point' do
49
+ expect(subject.status).to eq(payload['account_linking']['status'])
50
+ end
51
+ end
52
+
53
+ describe '.authorization_code' do
54
+ it 'returns authorization code defined with the entry point' do
55
+ expect(subject.authorization_code)
56
+ .to eq(payload['account_linking']['authorization_code'])
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,259 @@
1
+ require 'rails_helper'
2
+
3
+ module Bobot
4
+ class Dummy
5
+ include Bobot::Event::Common
6
+ end
7
+ end
8
+
9
+ RSpec.describe Bobot::Dummy do
10
+ let :payload do
11
+ {
12
+ 'sender' => {
13
+ 'id' => '3'
14
+ },
15
+ 'recipient' => {
16
+ 'id' => '3'
17
+ },
18
+ 'timestamp' => 145_776_419_762_7,
19
+ 'message' => {
20
+ 'is_echo' => false,
21
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a38',
22
+ 'seq' => 73,
23
+ 'text' => 'Hello, bot!',
24
+ 'quick_reply' => {
25
+ 'payload' => 'Hi, I am a quick reply!'
26
+ },
27
+ 'attachments' => [{
28
+ 'type' => 'image',
29
+ 'payload' => {
30
+ 'url' => 'https://www.example.com/1.jpg'
31
+ }
32
+ }]
33
+ }
34
+ }
35
+ end
36
+
37
+ let(:access_token) { 'access_token' }
38
+
39
+ before do
40
+ Bobot.page_access_token = access_token
41
+ end
42
+
43
+ subject { described_class.new(payload) }
44
+
45
+ describe '.sender' do
46
+ it 'returns the sender' do
47
+ expect(subject.sender).to eq(payload['sender'])
48
+ end
49
+ end
50
+
51
+ describe '.recipient' do
52
+ it 'returns the recipient' do
53
+ expect(subject.recipient).to eq(payload['recipient'])
54
+ end
55
+ end
56
+
57
+ describe '.sent_at' do
58
+ it 'returns when the message was sent' do
59
+ expect(subject.sent_at).to eq(Time.zone.at(payload['timestamp'] / 1000))
60
+ end
61
+ end
62
+
63
+ describe '.show_typing' do
64
+ it 'sends a typing on indicator to the sender' do
65
+ expect(subject).to receive(:deliver).with(
66
+ payload_template: { sender_action: 'typing_on' }
67
+ )
68
+ subject.show_typing(state: true)
69
+ end
70
+ it 'sends a typing on indicator to the sender' do
71
+ expect(subject).to receive(:deliver).with(
72
+ payload_template: { sender_action: 'typing_off' }
73
+ )
74
+ subject.show_typing(state: false)
75
+ end
76
+ end
77
+
78
+ describe '.mark_as_seen' do
79
+ it 'sends a typing off indicator to the sender' do
80
+ expect(subject).to receive(:deliver).with(
81
+ payload_template: { sender_action: 'mark_seen' }
82
+ )
83
+ subject.mark_as_seen
84
+ end
85
+ end
86
+
87
+ describe '.reply_with_text' do
88
+ it 'replies to the sender' do
89
+ expect(subject).to receive(:deliver).with(
90
+ payload_template: { message: { text: 'Hello, human' } }
91
+ )
92
+ subject.reply_with_text(text: 'Hello, human')
93
+ end
94
+ end
95
+
96
+ describe '.reply_with_image' do
97
+ it 'replies to the sender' do
98
+ expect(subject).to receive(:deliver).with(
99
+ payload_template: {
100
+ message: {
101
+ attachment: {
102
+ type: 'image',
103
+ payload: {
104
+ url: 'https://www.foo.bar/image.jpg',
105
+ is_reusable: true,
106
+ },
107
+ },
108
+ },
109
+ },
110
+ )
111
+ subject.reply_with_image(url: 'https://www.foo.bar/image.jpg')
112
+ end
113
+ end
114
+
115
+ describe '.reply_with_audio' do
116
+ it 'replies to the sender' do
117
+ expect(subject).to receive(:deliver).with(
118
+ payload_template: {
119
+ message: {
120
+ attachment: {
121
+ type: 'audio',
122
+ payload: {
123
+ url: 'https://www.foo.bar/audio.mp3',
124
+ },
125
+ },
126
+ },
127
+ },
128
+ )
129
+ subject.reply_with_audio(url: 'https://www.foo.bar/audio.mp3')
130
+ end
131
+ end
132
+
133
+ describe '.reply_with_video' do
134
+ it 'replies to the sender' do
135
+ expect(subject).to receive(:deliver).with(
136
+ payload_template: {
137
+ message: {
138
+ attachment: {
139
+ type: 'video',
140
+ payload: {
141
+ url: 'https://www.foo.bar/video.mp4',
142
+ },
143
+ },
144
+ },
145
+ },
146
+ )
147
+ subject.reply_with_video(url: 'https://www.foo.bar/video.mp4')
148
+ end
149
+ end
150
+
151
+ describe '.reply_with_file' do
152
+ it 'replies to the sender' do
153
+ expect(subject).to receive(:deliver).with(
154
+ payload_template: {
155
+ message: {
156
+ attachment: {
157
+ type: 'file',
158
+ payload: {
159
+ url: 'https://www.foo.bar/file.zip',
160
+ },
161
+ },
162
+ },
163
+ },
164
+ )
165
+ subject.reply_with_file(url: 'https://www.foo.bar/file.zip')
166
+ end
167
+ end
168
+
169
+ describe '.reply_with_quick_replies' do
170
+ it 'replies to the sender' do
171
+ expect(subject).to receive(:deliver).with(
172
+ payload_template: {
173
+ message: {
174
+ text: 'Pick a color:',
175
+ quick_replies: [
176
+ {
177
+ content_type: 'text',
178
+ title: 'RED',
179
+ payload: 'PICKED_RED_COLOR',
180
+ image_url: 'https://foo.bar/red.png'
181
+ },
182
+ {
183
+ content_type: 'text',
184
+ title: 'GREEN',
185
+ payload: 'PICKED_GREEN_COLOR'
186
+ }
187
+ ]
188
+ },
189
+ },
190
+ )
191
+ subject.reply_with_quick_replies(
192
+ text: 'Pick a color:',
193
+ quick_replies: [
194
+ {
195
+ content_type: 'text',
196
+ title: 'RED',
197
+ payload: 'PICKED_RED_COLOR',
198
+ image_url: 'https://foo.bar/red.png'
199
+ },
200
+ {
201
+ content_type: 'text',
202
+ title: 'GREEN',
203
+ payload: 'PICKED_GREEN_COLOR'
204
+ },
205
+ ]
206
+ )
207
+ end
208
+ it 'asks the location to the sender' do
209
+ expect(subject).to receive(:deliver).with(
210
+ payload_template: {
211
+ message: {
212
+ text: 'Where are you',
213
+ quick_replies: [
214
+ {
215
+ content_type: 'location',
216
+ image_url: 'https://foo.bar/gps.png',
217
+ }
218
+ ]
219
+ },
220
+ },
221
+ )
222
+ subject.reply_with_quick_replies(
223
+ text: 'Where are you',
224
+ quick_replies: [
225
+ Bobot::Buttons.quick_reply_location(image_url: 'https://foo.bar/gps.png')
226
+ ]
227
+ )
228
+ end
229
+ end
230
+
231
+ describe '.reply_with_buttons' do
232
+ it 'replies to the sender' do
233
+ expect(subject).to receive(:deliver).with(
234
+ payload_template: {
235
+ message: {
236
+ attachment: {
237
+ type: 'template',
238
+ payload: {
239
+ template_type: 'button',
240
+ text: 'Human, do you like me?',
241
+ buttons: [
242
+ { type: 'postback', title: 'Yes', payload: 'HARMLESS' },
243
+ { type: 'postback', title: 'No', payload: 'WHAT_IS_A_CHATBOT' }
244
+ ]
245
+ }
246
+ }
247
+ },
248
+ },
249
+ )
250
+ subject.reply_with_buttons(
251
+ text: 'Human, do you like me?',
252
+ buttons: [
253
+ { type: 'postback', title: 'Yes', payload: 'HARMLESS' },
254
+ { type: 'postback', title: 'No', payload: 'WHAT_IS_A_CHATBOT' }
255
+ ]
256
+ )
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,62 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::Delivery do
4
+ let :payload do
5
+ {
6
+ 'sender' => {
7
+ 'id' => '3'
8
+ },
9
+ 'recipient' => {
10
+ 'id' => '3'
11
+ },
12
+ 'delivery' => {
13
+ 'mids' => [
14
+ 'mid.1457764197618:41d102a3e1ae206a38',
15
+ 'mid.1458668856218:ed81099e15d3f4f233'
16
+ ],
17
+ 'watermark' => 145_866_885_625_3,
18
+ 'seq' => 37
19
+ }
20
+ }
21
+ end
22
+
23
+ subject { Bobot::Event::Delivery.new(payload) }
24
+
25
+ describe '.messaging' do
26
+ it 'returns the original payload' do
27
+ expect(subject.messaging).to eq(payload)
28
+ end
29
+ end
30
+
31
+ describe '.ids' do
32
+ it 'returns the message ids' do
33
+ expect(subject.ids).to eq(payload['delivery']['mids'])
34
+ end
35
+ end
36
+
37
+ describe '.sender' do
38
+ it 'returns the sender' do
39
+ expect(subject.sender).to eq(payload['sender'])
40
+ end
41
+ end
42
+
43
+ describe '.recipient' do
44
+ it 'returns the recipient' do
45
+ expect(subject.recipient).to eq(payload['recipient'])
46
+ end
47
+ end
48
+
49
+ describe '.seq' do
50
+ it 'returns the message sequence number' do
51
+ expect(subject.seq).to eq(payload['delivery']['seq'])
52
+ end
53
+ end
54
+
55
+ describe '.at' do
56
+ it 'returns a Time' do
57
+ expect(subject.at).to eq(
58
+ Time.zone.at(payload['delivery']['watermark'] / 1000)
59
+ )
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,276 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::MessageEcho do
4
+ let :payload do
5
+ {
6
+ 'sender' => {
7
+ 'id' => '3'
8
+ },
9
+ 'recipient' => {
10
+ 'id' => '3'
11
+ },
12
+ 'timestamp' => 145_776_419_762_7,
13
+ 'message' => {
14
+ 'is_echo' => true,
15
+ 'app_id' => 184_719_329_217_930_000,
16
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a38',
17
+ 'seq' => 73,
18
+ 'text' => 'Hello, bot!',
19
+ 'quick_reply' => {
20
+ 'payload' => 'Hi, I am a quick reply!'
21
+ },
22
+ 'attachments' => [{
23
+ 'type' => 'image',
24
+ 'payload' => {
25
+ 'url' => 'https://www.example.com/1.jpg'
26
+ }
27
+ }]
28
+ }
29
+ }
30
+ end
31
+
32
+ let :video_payload do
33
+ {
34
+ 'sender' => {
35
+ 'id' => '5'
36
+ },
37
+ 'recipient' => {
38
+ 'id' => '7'
39
+ },
40
+ 'timestamp' => 145_776_419_762_4,
41
+ 'message' => {
42
+ 'is_echo' => true,
43
+ 'app_id' => 184_719_329_217_930_001,
44
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a38',
45
+ 'attachments' => [{
46
+ 'type' => 'video',
47
+ 'payload' => {
48
+ 'url' => 'https://www.example.com/2.mp4'
49
+ }
50
+ }]
51
+ }
52
+ }
53
+ end
54
+
55
+ let :file_payload do
56
+ {
57
+ 'sender' => {
58
+ 'id' => '5'
59
+ },
60
+ 'recipient' => {
61
+ 'id' => '7'
62
+ },
63
+ 'timestamp' => 145_776_412_762_4,
64
+ 'message' => {
65
+ 'is_echo' => true,
66
+ 'app_id' => 184_719_329_217_930_001,
67
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a39',
68
+ 'attachments' => [{
69
+ 'type' => 'file',
70
+ 'payload' => {
71
+ 'url' => 'https://www.example.com/3.pdf'
72
+ }
73
+ }]
74
+ }
75
+ }
76
+ end
77
+
78
+ let :audio_payload do
79
+ {
80
+ 'sender' => {
81
+ 'id' => '8'
82
+ },
83
+ 'recipient' => {
84
+ 'id' => '9'
85
+ },
86
+ 'timestamp' => 145_776_419_732_4,
87
+ 'message' => {
88
+ 'is_echo' => true,
89
+ 'app_id' => 184_719_329_217_930_001,
90
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a48',
91
+ 'attachments' => [{
92
+ 'type' => 'audio',
93
+ 'payload' => {
94
+ 'url' => 'https://www.example.com/4.ogg'
95
+ }
96
+ }]
97
+ }
98
+ }
99
+ end
100
+
101
+ let :location_payload do
102
+ {
103
+ 'sender' => {
104
+ 'id' => '6'
105
+ },
106
+ 'recipient' => {
107
+ 'id' => '9'
108
+ },
109
+ 'timestamp' => 145_776_429_762_4,
110
+ 'message' => {
111
+ 'is_echo' => true,
112
+ 'app_id' => 184_719_329_222_930_001,
113
+ 'mid' => 'mid.1457764197618:41d102a3e1ae206a38',
114
+ 'attachments' => [{
115
+ 'type' => 'location',
116
+ 'payload' => {
117
+ 'coordinates' => {
118
+ 'lat' => '39.920_770',
119
+ 'long' => '40.920_770'
120
+ }
121
+ }
122
+ }]
123
+ }
124
+ }
125
+ end
126
+
127
+ subject { Bobot::Event::MessageEcho.new(payload) }
128
+
129
+ describe '.messaging' do
130
+ it 'returns the original payload' do
131
+ expect(subject.messaging).to eq(payload)
132
+ end
133
+ end
134
+
135
+ describe '.id' do
136
+ it 'returns the message echo id' do
137
+ expect(subject.id).to eq(payload['message']['mid'])
138
+ end
139
+ end
140
+
141
+ describe '.sender' do
142
+ it 'returns the sender' do
143
+ expect(subject.sender).to eq(payload['sender'])
144
+ end
145
+ end
146
+
147
+ describe '.recipient' do
148
+ it 'returns the recipient' do
149
+ expect(subject.recipient).to eq(payload['recipient'])
150
+ end
151
+ end
152
+
153
+ describe '.seq' do
154
+ it 'returns the message echo sequence number' do
155
+ expect(subject.seq).to eq(payload['message']['seq'])
156
+ end
157
+ end
158
+
159
+ describe '.sent_at' do
160
+ it 'returns when the message echo was sent' do
161
+ expect(subject.sent_at).to eq(Time.zone.at(payload['timestamp'] / 1000))
162
+ end
163
+ end
164
+
165
+ describe '.text' do
166
+ it 'returns the text of the message echo' do
167
+ expect(subject.text).to eq(payload['message']['text'])
168
+ end
169
+ end
170
+
171
+ describe '.echo?' do
172
+ it 'returns the echo status of the message echo' do
173
+ expect(subject.echo?).to eq(payload['message']['is_echo'])
174
+ end
175
+ end
176
+
177
+ describe '.attachments' do
178
+ it 'returns the message echo attachments' do
179
+ expect(subject.attachments).to eq(payload['message']['attachments'])
180
+ end
181
+ end
182
+
183
+ describe '.image_attachment?' do
184
+ it 'returns whether the attachment is an image' do
185
+ expect(subject.image_attachment?).to be(true)
186
+ end
187
+ end
188
+
189
+ describe '.video_attachment?' do
190
+ subject { Bobot::Event::MessageEcho.new(video_payload) }
191
+
192
+ it 'returns whether the attachment is a video' do
193
+ expect(subject.video_attachment?).to be(true)
194
+ end
195
+ end
196
+
197
+ describe '.location_attachment?' do
198
+ subject { Bobot::Event::MessageEcho.new(location_payload) }
199
+
200
+ it 'returns whether the attachment is a video' do
201
+ expect(subject.location_attachment?).to be(true)
202
+ end
203
+ end
204
+
205
+ describe '.audio_attachment?' do
206
+ subject { Bobot::Event::MessageEcho.new(audio_payload) }
207
+
208
+ it 'returns whether the attachment is an audio' do
209
+ expect(subject.audio_attachment?).to be(true)
210
+ end
211
+ end
212
+
213
+ describe '.file_attachment?' do
214
+ subject { Bobot::Event::MessageEcho.new(file_payload) }
215
+
216
+ it 'returns whether the attachment is a file' do
217
+ expect(subject.file_attachment?).to be(true)
218
+ end
219
+ end
220
+
221
+ describe '.location_coordinates' do
222
+ subject { Bobot::Event::MessageEcho.new(location_payload) }
223
+
224
+ let(:attachments) { location_payload['message']['attachments'] }
225
+
226
+ it 'returns array of lat long coordinates' do
227
+ expect(subject.location_coordinates).to eq(
228
+ [
229
+ attachments.first['payload']['coordinates']['lat'],
230
+ attachments.first['payload']['coordinates']['long']
231
+ ]
232
+ )
233
+ end
234
+ end
235
+
236
+ describe '.attachment_type' do
237
+ it 'returns the type of the attachment' do
238
+ expect(subject.attachment_type).to eq(
239
+ payload['message']['attachments'].first['type']
240
+ )
241
+ end
242
+ end
243
+
244
+ describe '.attachment_url' do
245
+ it 'returns the url of the attachment' do
246
+ expect(subject.attachment_url).to eq(
247
+ payload['message']['attachments'].first['payload']['url']
248
+ )
249
+ end
250
+ end
251
+ describe '.app_id' do
252
+ it 'returns the app_id from which the message echo was sent' do
253
+ expect(subject.app_id).to eq(payload['message']['app_id'])
254
+ end
255
+ end
256
+
257
+ describe '.quick_reply' do
258
+ context 'when a quick reply was used' do
259
+ it 'returns the payload of the quick reply' do
260
+ expect(subject.quick_reply).to eq(
261
+ payload['message']['quick_reply']['payload']
262
+ )
263
+ end
264
+ end
265
+
266
+ context 'when a quick reply was not used' do
267
+ before do
268
+ payload['message'].delete('quick_reply')
269
+ end
270
+
271
+ it 'returns nil' do
272
+ expect(subject.quick_reply).to eq(nil)
273
+ end
274
+ end
275
+ end
276
+ end