bobot 1.0.52

Sign up to get free protection for your applications and to get access to all the features.
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