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,276 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::Message 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' => false,
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' => false,
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' => false,
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' => false,
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' => false,
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::Message.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 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 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 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' 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' 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 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::Message.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::Message.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::Message.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::Message.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::Message.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 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
@@ -0,0 +1,50 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::Optin 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
+ 'optin' => {
14
+ 'ref' => 'PASS_THROUGH_PARAM'
15
+ }
16
+ }
17
+ end
18
+
19
+ subject { Bobot::Event::Optin.new(payload) }
20
+
21
+ describe '.messaging' do
22
+ it 'returns the original payload' do
23
+ expect(subject.messaging).to eq(payload)
24
+ end
25
+ end
26
+
27
+ describe '.sender' do
28
+ it 'returns the sender' do
29
+ expect(subject.sender).to eq(payload['sender'])
30
+ end
31
+ end
32
+
33
+ describe '.recipient' do
34
+ it 'returns the recipient' do
35
+ expect(subject.recipient).to eq(payload['recipient'])
36
+ end
37
+ end
38
+
39
+ describe '.sent_at' do
40
+ it 'returns when the postback was sent' do
41
+ expect(subject.sent_at).to eq(Time.zone.at(payload['timestamp'] / 1000))
42
+ end
43
+ end
44
+
45
+ describe '.ref' do
46
+ it 'returns the data-ref defined with the entry point' do
47
+ expect(subject.ref).to eq(payload['optin']['ref'])
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,94 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::Postback 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
+ 'postback' => {
14
+ 'payload' => 'USER_DEFINED_PAYLOAD',
15
+ 'referral' => {
16
+ 'ref' => 'my-ref-value',
17
+ 'source' => 'SHORTLINK',
18
+ 'type' => 'OPEN_THREAD'
19
+ }
20
+ }
21
+ }
22
+ end
23
+
24
+ subject { Bobot::Event::Postback.new(payload) }
25
+
26
+ describe '.messaging' do
27
+ it 'returns the original payload' do
28
+ expect(subject.messaging).to eq(payload)
29
+ end
30
+ end
31
+
32
+ describe '.sender' do
33
+ it 'returns the sender' do
34
+ expect(subject.sender).to eq(payload['sender'])
35
+ end
36
+ end
37
+
38
+ describe '.recipient' do
39
+ it 'returns the recipient' do
40
+ expect(subject.recipient).to eq(payload['recipient'])
41
+ end
42
+ end
43
+
44
+ describe '.sent_at' do
45
+ it 'returns when the postback was sent' do
46
+ expect(subject.sent_at).to eq(Time.zone.at(payload['timestamp'] / 1000))
47
+ end
48
+ end
49
+
50
+ describe '.payload' do
51
+ it 'returns the payload of the postback' do
52
+ expect(subject.payload).to eq(payload['postback']['payload'])
53
+ end
54
+ end
55
+
56
+ describe '.referral' do
57
+ it 'returns the ref value' do
58
+ expect(subject.referral.ref).to eq(payload['postback']['referral']['ref'])
59
+ end
60
+
61
+ it 'returns the source value' do
62
+ expect(subject.referral.source).to eq(
63
+ payload['postback']['referral']['source']
64
+ )
65
+ end
66
+
67
+ it 'returns the type value' do
68
+ expect(subject.referral.type).to eq(
69
+ payload['postback']['referral']['type']
70
+ )
71
+ end
72
+
73
+ context 'when referral is not set' do
74
+ let :payload do
75
+ {
76
+ 'sender' => {
77
+ 'id' => '3'
78
+ },
79
+ 'recipient' => {
80
+ 'id' => '3'
81
+ },
82
+ 'timestamp' => 145_776_419_762_7,
83
+ 'postback' => {
84
+ 'payload' => 'USER_DEFINED_PAYLOAD'
85
+ }
86
+ }
87
+ end
88
+
89
+ it 'returns nil' do
90
+ expect(subject.referral).to be_nil
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,51 @@
1
+ require 'rails_helper'
2
+
3
+ RSpec.describe Bobot::Event::Read 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
+ 'read' => {
14
+ 'watermark' => 145_866_885_625_3,
15
+ 'seq' => 38
16
+ }
17
+ }
18
+ end
19
+
20
+ subject { Bobot::Event::Read.new(payload) }
21
+
22
+ describe '.messaging' do
23
+ it 'returns the original payload' do
24
+ expect(subject.messaging).to eq(payload)
25
+ end
26
+ end
27
+
28
+ describe '.sender' do
29
+ it 'returns the sender' do
30
+ expect(subject.sender).to eq(payload['sender'])
31
+ end
32
+ end
33
+
34
+ describe '.recipient' do
35
+ it 'returns the recipient' do
36
+ expect(subject.recipient).to eq(payload['recipient'])
37
+ end
38
+ end
39
+
40
+ describe '.at' do
41
+ it 'returns when the message was read' do
42
+ expect(subject.at).to eq(Time.zone.at(payload['read']['watermark'] / 1000))
43
+ end
44
+ end
45
+
46
+ describe '.seq' do
47
+ it 'returns the read sequence number' do
48
+ expect(subject.seq).to eq(payload['read']['seq'])
49
+ end
50
+ end
51
+ end