stealth-bandwidth 1.1.0 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 565292b84eb7d1e445ce2b19e005fff01054433a5baf2ea68f0541c33880952c
4
- data.tar.gz: c4b39e0c8f2f97661f36ef81e04bd01e7df0e07be1a75960509d92aa84ef21f9
3
+ metadata.gz: ecda2c1c3faacb7b24ee05639dfa4ca4b1cbeffdd5ad9dccece4f900b2ecb7c5
4
+ data.tar.gz: 166e8491675511d267be7e66b5d6907acf45c29ab930d0475bdb26e72f35ce20
5
5
  SHA512:
6
- metadata.gz: 5598611b534f85ebc5dafbb6c3e12c70c8a72b8cba0bafb9419c0d6af4798142adb0ca945127147dd64f562686a60d9b6d5ec7f2cb6ef3dcea862b6ac86fdca7
7
- data.tar.gz: 18f80889909dc586159f4f1746936041abe71257d1f409847e7c24513c66ffe6ad96f43f12f4dc0ed5046338f12e96115319c50c0ce025aea7a9076da51c15ab
6
+ metadata.gz: d906c1d9eb891a7167ec2263ee5a746727ac5d9e01be50b86601cbf4a68547870b9d669dcec7a56b1735fe0fc2b209e4ffc3fdbad813a7dfa785b33a259ebe61
7
+ data.tar.gz: f00cffbcdaabcc950ebf6253b6228c21b8e2df568052a1f37aa9858c8986d2e9dcabedb6fdb09df1c52736c42db4aaf21843d52f2c0b6c2ea253efc031a530af
@@ -9,5 +9,5 @@ jobs:
9
9
  - uses: actions/checkout@v3
10
10
  - uses: ruby/setup-ruby@v1
11
11
  with:
12
- ruby-version: 2.7
12
+ ruby-version: 3.0
13
13
  bundler-cache: true
@@ -15,7 +15,7 @@ jobs:
15
15
  - uses: actions/checkout@v3
16
16
  - uses: ruby/setup-ruby@v1
17
17
  with:
18
- ruby-version: 2.7
18
+ ruby-version: 3.0
19
19
  bundler-cache: true
20
20
  - name: Publish gem
21
21
  env:
data/Gemfile CHANGED
@@ -1,5 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'stealth', '>= 2.0.0.beta6'
3
+ gem 'stealth', git: 'https://github.com/hellostealth/stealth.git', branch: '3.0-mountable'
4
4
 
5
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,99 +1,252 @@
1
+ GIT
2
+ remote: https://github.com/hellostealth/stealth.git
3
+ revision: 1dcdc7d3fe8bf5851d10840ff9d8546f26248f95
4
+ branch: 3.0-mountable
5
+ specs:
6
+ stealth (3.0.0.alpha1)
7
+ rails (>= 7.1.3.4)
8
+ redis (~> 5.0)
9
+ sidekiq (~> 7.0)
10
+ spectre_ai (~> 1.2.0)
11
+
1
12
  PATH
2
13
  remote: .
3
14
  specs:
4
- stealth-bandwidth (1.1.0)
15
+ stealth-bandwidth (2.0.0)
5
16
  http (~> 4.1)
6
17
  oj (~> 3.11)
7
- stealth (>= 2.0.0.beta6)
18
+ stealth (>= 3.0.0.alpha1)
8
19
 
9
20
  GEM
10
21
  remote: https://rubygems.org/
11
22
  specs:
12
- activesupport (6.1.7)
13
- concurrent-ruby (~> 1.0, >= 1.0.2)
23
+ actioncable (7.2.2.1)
24
+ actionpack (= 7.2.2.1)
25
+ activesupport (= 7.2.2.1)
26
+ nio4r (~> 2.0)
27
+ websocket-driver (>= 0.6.1)
28
+ zeitwerk (~> 2.6)
29
+ actionmailbox (7.2.2.1)
30
+ actionpack (= 7.2.2.1)
31
+ activejob (= 7.2.2.1)
32
+ activerecord (= 7.2.2.1)
33
+ activestorage (= 7.2.2.1)
34
+ activesupport (= 7.2.2.1)
35
+ mail (>= 2.8.0)
36
+ actionmailer (7.2.2.1)
37
+ actionpack (= 7.2.2.1)
38
+ actionview (= 7.2.2.1)
39
+ activejob (= 7.2.2.1)
40
+ activesupport (= 7.2.2.1)
41
+ mail (>= 2.8.0)
42
+ rails-dom-testing (~> 2.2)
43
+ actionpack (7.2.2.1)
44
+ actionview (= 7.2.2.1)
45
+ activesupport (= 7.2.2.1)
46
+ nokogiri (>= 1.8.5)
47
+ racc
48
+ rack (>= 2.2.4, < 3.2)
49
+ rack-session (>= 1.0.1)
50
+ rack-test (>= 0.6.3)
51
+ rails-dom-testing (~> 2.2)
52
+ rails-html-sanitizer (~> 1.6)
53
+ useragent (~> 0.16)
54
+ actiontext (7.2.2.1)
55
+ actionpack (= 7.2.2.1)
56
+ activerecord (= 7.2.2.1)
57
+ activestorage (= 7.2.2.1)
58
+ activesupport (= 7.2.2.1)
59
+ globalid (>= 0.6.0)
60
+ nokogiri (>= 1.8.5)
61
+ actionview (7.2.2.1)
62
+ activesupport (= 7.2.2.1)
63
+ builder (~> 3.1)
64
+ erubi (~> 1.11)
65
+ rails-dom-testing (~> 2.2)
66
+ rails-html-sanitizer (~> 1.6)
67
+ activejob (7.2.2.1)
68
+ activesupport (= 7.2.2.1)
69
+ globalid (>= 0.3.6)
70
+ activemodel (7.2.2.1)
71
+ activesupport (= 7.2.2.1)
72
+ activerecord (7.2.2.1)
73
+ activemodel (= 7.2.2.1)
74
+ activesupport (= 7.2.2.1)
75
+ timeout (>= 0.4.0)
76
+ activestorage (7.2.2.1)
77
+ actionpack (= 7.2.2.1)
78
+ activejob (= 7.2.2.1)
79
+ activerecord (= 7.2.2.1)
80
+ activesupport (= 7.2.2.1)
81
+ marcel (~> 1.0)
82
+ activesupport (7.2.2.1)
83
+ base64
84
+ benchmark (>= 0.3)
85
+ bigdecimal
86
+ concurrent-ruby (~> 1.0, >= 1.3.1)
87
+ connection_pool (>= 2.2.5)
88
+ drb
14
89
  i18n (>= 1.6, < 2)
90
+ logger (>= 1.4.2)
15
91
  minitest (>= 5.1)
16
- tzinfo (~> 2.0)
17
- zeitwerk (~> 2.3)
18
- addressable (2.8.1)
19
- public_suffix (>= 2.0.2, < 6.0)
20
- concurrent-ruby (1.1.10)
21
- connection_pool (2.3.0)
22
- diff-lcs (1.5.0)
23
- domain_name (0.5.20190701)
24
- unf (>= 0.0.5, < 1.0.0)
25
- ffi (1.15.5)
26
- ffi-compiler (1.0.1)
27
- ffi (>= 1.0.0)
92
+ securerandom (>= 0.3)
93
+ tzinfo (~> 2.0, >= 2.0.5)
94
+ addressable (2.8.7)
95
+ public_suffix (>= 2.0.2, < 7.0)
96
+ base64 (0.2.0)
97
+ benchmark (0.4.0)
98
+ bigdecimal (3.1.9)
99
+ builder (3.3.0)
100
+ concurrent-ruby (1.3.5)
101
+ connection_pool (2.5.0)
102
+ crass (1.0.6)
103
+ date (3.4.1)
104
+ diff-lcs (1.5.1)
105
+ domain_name (0.6.20240107)
106
+ drb (2.2.1)
107
+ erubi (1.13.1)
108
+ ffi (1.17.1)
109
+ ffi-compiler (1.3.2)
110
+ ffi (>= 1.15.5)
28
111
  rake
112
+ globalid (1.2.1)
113
+ activesupport (>= 6.1)
29
114
  http (4.4.1)
30
115
  addressable (~> 2.3)
31
116
  http-cookie (~> 1.0)
32
117
  http-form_data (~> 2.2)
33
118
  http-parser (~> 1.2.0)
34
- http-cookie (1.0.5)
119
+ http-cookie (1.0.8)
35
120
  domain_name (~> 0.5)
36
121
  http-form_data (2.3.0)
37
122
  http-parser (1.2.3)
38
123
  ffi-compiler (>= 1.0, < 2.0)
39
- i18n (1.12.0)
124
+ i18n (1.14.7)
40
125
  concurrent-ruby (~> 1.0)
41
- minitest (5.16.3)
42
- multi_json (1.15.0)
43
- mustermann (2.0.2)
44
- ruby2_keywords (~> 0.0.1)
45
- nio4r (2.5.8)
46
- oj (3.13.23)
47
- public_suffix (5.0.0)
48
- puma (5.6.5)
49
- nio4r (~> 2.0)
50
- rack (2.2.4)
51
- rack-protection (2.2.2)
52
- rack
126
+ io-console (0.8.0)
127
+ irb (1.15.1)
128
+ pp (>= 0.6.0)
129
+ rdoc (>= 4.0.0)
130
+ reline (>= 0.4.2)
131
+ logger (1.6.5)
132
+ loofah (2.24.0)
133
+ crass (~> 1.0.2)
134
+ nokogiri (>= 1.12.0)
135
+ mail (2.8.1)
136
+ mini_mime (>= 0.1.1)
137
+ net-imap
138
+ net-pop
139
+ net-smtp
140
+ marcel (1.0.4)
141
+ mini_mime (1.1.5)
142
+ mini_portile2 (2.8.8)
143
+ minitest (5.25.4)
144
+ net-imap (0.5.5)
145
+ date
146
+ net-protocol
147
+ net-pop (0.1.2)
148
+ net-protocol
149
+ net-protocol (0.2.2)
150
+ timeout
151
+ net-smtp (0.5.1)
152
+ net-protocol
153
+ nio4r (2.7.4)
154
+ nokogiri (1.18.2)
155
+ mini_portile2 (~> 2.8.2)
156
+ racc (~> 1.4)
157
+ oj (3.16.9)
158
+ bigdecimal (>= 3.0)
159
+ ostruct (>= 0.2)
160
+ ostruct (0.6.1)
161
+ pp (0.6.2)
162
+ prettyprint
163
+ prettyprint (0.2.0)
164
+ psych (5.2.3)
165
+ date
166
+ stringio
167
+ public_suffix (6.0.1)
168
+ racc (1.8.1)
169
+ rack (2.2.10)
170
+ rack-session (1.0.2)
171
+ rack (< 3)
53
172
  rack-test (1.1.0)
54
173
  rack (>= 1.0, < 3)
55
- rake (13.0.6)
56
- redis (4.8.0)
57
- rspec (3.11.0)
58
- rspec-core (~> 3.11.0)
59
- rspec-expectations (~> 3.11.0)
60
- rspec-mocks (~> 3.11.0)
61
- rspec-core (3.11.0)
62
- rspec-support (~> 3.11.0)
63
- rspec-expectations (3.11.0)
174
+ rackup (1.0.1)
175
+ rack (< 3)
176
+ webrick
177
+ rails (7.2.2.1)
178
+ actioncable (= 7.2.2.1)
179
+ actionmailbox (= 7.2.2.1)
180
+ actionmailer (= 7.2.2.1)
181
+ actionpack (= 7.2.2.1)
182
+ actiontext (= 7.2.2.1)
183
+ actionview (= 7.2.2.1)
184
+ activejob (= 7.2.2.1)
185
+ activemodel (= 7.2.2.1)
186
+ activerecord (= 7.2.2.1)
187
+ activestorage (= 7.2.2.1)
188
+ activesupport (= 7.2.2.1)
189
+ bundler (>= 1.15.0)
190
+ railties (= 7.2.2.1)
191
+ rails-dom-testing (2.2.0)
192
+ activesupport (>= 5.0.0)
193
+ minitest
194
+ nokogiri (>= 1.6)
195
+ rails-html-sanitizer (1.6.2)
196
+ loofah (~> 2.21)
197
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
198
+ railties (7.2.2.1)
199
+ actionpack (= 7.2.2.1)
200
+ activesupport (= 7.2.2.1)
201
+ irb (~> 1.13)
202
+ rackup (>= 1.0.0)
203
+ rake (>= 12.2)
204
+ thor (~> 1.0, >= 1.2.2)
205
+ zeitwerk (~> 2.6)
206
+ rake (13.2.1)
207
+ rdoc (6.12.0)
208
+ psych (>= 4.0.0)
209
+ redis (5.3.0)
210
+ redis-client (>= 0.22.0)
211
+ redis-client (0.23.2)
212
+ connection_pool
213
+ reline (0.6.0)
214
+ io-console (~> 0.5)
215
+ rspec (3.13.0)
216
+ rspec-core (~> 3.13.0)
217
+ rspec-expectations (~> 3.13.0)
218
+ rspec-mocks (~> 3.13.0)
219
+ rspec-core (3.13.3)
220
+ rspec-support (~> 3.13.0)
221
+ rspec-expectations (3.13.3)
64
222
  diff-lcs (>= 1.2.0, < 2.0)
65
- rspec-support (~> 3.11.0)
66
- rspec-mocks (3.11.1)
223
+ rspec-support (~> 3.13.0)
224
+ rspec-mocks (3.13.2)
67
225
  diff-lcs (>= 1.2.0, < 2.0)
68
- rspec-support (~> 3.11.0)
69
- rspec-support (3.11.0)
70
- rspec_junit_formatter (0.5.1)
226
+ rspec-support (~> 3.13.0)
227
+ rspec-support (3.13.2)
228
+ rspec_junit_formatter (0.6.0)
71
229
  rspec-core (>= 2, < 4, != 2.12.0)
72
- ruby2_keywords (0.0.5)
73
- sidekiq (6.5.6)
74
- connection_pool (>= 2.2.5)
75
- rack (~> 2.0)
76
- redis (>= 4.5.0, < 5)
77
- sinatra (2.2.2)
78
- mustermann (~> 2.0)
79
- rack (~> 2.2)
80
- rack-protection (= 2.2.2)
81
- tilt (~> 2.0)
82
- stealth (2.0.0.beta6)
83
- activesupport (~> 6.0)
84
- multi_json (~> 1.12)
85
- puma (>= 4.2, < 6.0)
86
- sidekiq (~> 6.0)
87
- sinatra (~> 2.0)
88
- thor (~> 1.0)
89
- thor (1.2.1)
90
- tilt (2.0.11)
91
- tzinfo (2.0.5)
230
+ securerandom (0.4.1)
231
+ sidekiq (7.3.8)
232
+ base64
233
+ connection_pool (>= 2.3.0)
234
+ logger
235
+ rack (>= 2.2.4)
236
+ redis-client (>= 0.22.2)
237
+ spectre_ai (1.2.0)
238
+ stringio (3.1.2)
239
+ thor (1.3.2)
240
+ timeout (0.4.3)
241
+ tzinfo (2.0.6)
92
242
  concurrent-ruby (~> 1.0)
93
- unf (0.1.4)
94
- unf_ext
95
- unf_ext (0.0.8.2)
96
- zeitwerk (2.6.0)
243
+ useragent (0.16.11)
244
+ webrick (1.9.1)
245
+ websocket-driver (0.7.7)
246
+ base64
247
+ websocket-extensions (>= 0.1.0)
248
+ websocket-extensions (0.1.5)
249
+ zeitwerk (2.6.18)
97
250
 
98
251
  PLATFORMS
99
252
  ruby
@@ -102,8 +255,8 @@ DEPENDENCIES
102
255
  rack-test (~> 1.1)
103
256
  rspec (~> 3.6)
104
257
  rspec_junit_formatter (~> 0.3)
105
- stealth (>= 2.0.0.beta6)
258
+ stealth!
106
259
  stealth-bandwidth!
107
260
 
108
261
  BUNDLED WITH
109
- 2.2.32
262
+ 2.6.3
data/README.md CHANGED
@@ -1,21 +1,170 @@
1
1
  # Stealth Bandwidth SMS
2
2
 
3
- The [Stealth](https://github.com/whoisblackops/stealth) Bandwidth SMS driver adds the ability to build your bot using Bandwidth's SMS service.
3
+ ## Compatibility
4
4
 
5
- ## Supported Reply Types
5
+ ⚠️ **Version 2.0 is only compatible with Stealth 3.0 [(Pull Request 420)](https://github.com/hellostealth/stealth/pull/420).** ⚠️
6
6
 
7
- * Text
8
- * Image
9
- * Audio
10
- * Video
11
- * File
12
- * Delay
7
+ While Stealth V2 was a standalone Ruby application, Stealth V3 is a mounted engine within an existing Ruby on Rails application.
13
8
 
14
- Image, Audio, Video, and File reply types will leverage the MMS protocol. It is recommended by Bandwidth that
15
- the content is limited to images, however, this is the full list of supported content types: https://dev.bandwidth.com/faq/messaging/mediaType.html.
9
+ ## Installation
16
10
 
17
- If you store your files on S3, please make sure you have set the `content-type` appropriately or Bandwidth might reject your media.
11
+ In your **Rails** app, add the `stealth` and `stealth-bandwidth` gems:
18
12
 
19
- ## Service Message
13
+ ```ruby
14
+ gem 'stealth', git: 'https://github.com/hellostealth/stealth.git', branch: '3.0-mountable'
15
+ gem 'stealth-bandwidth'
16
+ ```
20
17
 
21
- This driver will set `current_message.target_id` to the array of phone numbers the SMS message was delivered to. In most cases the array will just contain a single phone number (the phone number of your bot), but in the case of a group message, it will contain the phone numbers of each recipient in addition to your bot's phone number.
18
+ ## Configurations
19
+
20
+ Create a Bandwidth Messaging App, and set up the webhook URL to point to your ngrok that forwards requests to your Rails app. You must append `/stealth/<service>`.
21
+
22
+ For example:
23
+ ```ruby
24
+ https://abc1234.ngrok.io/stealth/bandwidth
25
+ ```
26
+
27
+ ## Reply Types
28
+
29
+ ### Flow-based Replies
30
+
31
+ **Inline replies** can be created by calling the `say` method within `Stealth.flow`
32
+
33
+ ```ruby
34
+ Stealth.flow :hello do
35
+ state :say_hello do
36
+ say "Hello world!"
37
+ end
38
+ end
39
+ ```
40
+
41
+ You can use the `send_replies` method within `Stealth.flow` to define the reply in `Stealth.reply`
42
+
43
+ ```ruby
44
+ stealth/flows/hello_flow.rb
45
+
46
+ Stealth.flow :hello do
47
+ state :say_hello do
48
+ send_replies
49
+ end
50
+ end
51
+
52
+ stealth/replies/hello/say_hello.rb
53
+
54
+ Stealth.reply :hello do
55
+ state :say_hello do
56
+ say "Hello world!"
57
+ end
58
+ end
59
+ ```
60
+
61
+ ☝️ We recommend using the `send_replies` method, when replies are more complex and that you want to keep your `Stealth.flow` dry.
62
+ **Note:** To follow naming conventions, in the stealth/replies directory, you must create a subdirectory that matches the **flow name**, and inside it, a file named after the **state name**.
63
+
64
+ ### Suggestions
65
+
66
+ Though suggestions are not a reply type on their own, they enhance the visual presentation of SMS replies by adding line breaks and formatting options as separate choices.
67
+
68
+ ```ruby
69
+ Stealth.flow :animal do
70
+ state :ask_if_like_dogs do
71
+ say("Do you like dogs?", suggestions: ["Yes", "No"])
72
+ update_session_to state: :get_if_like_dogs
73
+ end
74
+
75
+ state :get_if_like_dogs do
76
+ handle_message(
77
+ yes: proc { say("Woof") },
78
+ no: proc { say("Too bad...") }
79
+ )
80
+ step_to state: :ask_favorite_animal
81
+ end
82
+
83
+ state :ask_favorite_animal do
84
+ say("What's your favorite animal?", suggestions: ["Cat", "Dog", "Sloth"])
85
+ update_session_to state: :get_favorite_animal
86
+ end
87
+
88
+ state :get_favorite_animal do
89
+ translated_msg = get_match(
90
+ ['Cat', 'Dog', 'Sloth'], raise_on_mismatch: true
91
+ )
92
+ say("I like #{translated_msg} too!")
93
+ end
94
+ end
95
+ ```
96
+
97
+ ### Delays
98
+
99
+ **Delays** introduce pauses between text replies, improving user experience.
100
+
101
+ ```ruby
102
+ Stealth.reply do
103
+ say "Hello"
104
+ say(reply_type: "delay", duration: "dynamic")
105
+ say "How are you?"
106
+ say(reply_type: "delay", duration: 2)
107
+ end
108
+ ````
109
+
110
+ The duration can be a **floating point value** (in seconds) or **dynamic**, where the system automatically determines the delay.
111
+
112
+ To enable automatic delays globally:
113
+ ```ruby
114
+ Stealth.config.auto_insert_delays
115
+ ```
116
+
117
+
118
+ # Sending Media
119
+
120
+ Bandwidth supports various MMS file types. For more details, refer to: [Bandwidth Supported MMS File Types](https://support.bandwidth.com/hc/en-us/articles/360014128994-What-MMS-file-types-are-supported)
121
+
122
+ **You must use a valid URL where the file is hosted.**
123
+
124
+ ### Images
125
+
126
+ ```ruby
127
+ Stealth.reply do
128
+ say(
129
+ "Here's an image.",
130
+ reply_type: "image",
131
+ image_url: "https://example.org/image.png"
132
+ )
133
+ end
134
+ ```
135
+
136
+ ### Videos
137
+
138
+ ```ruby
139
+ Stealth.reply do
140
+ say(
141
+ "Here's a video.",
142
+ reply_type: "video",
143
+ video_url: "https://example.org/cool_video.mp4"
144
+ )
145
+ end
146
+ ```
147
+
148
+ ### Audio
149
+
150
+ ```ruby
151
+ Stealth.reply do
152
+ say(
153
+ "Here's an audio.",
154
+ reply_type: "audio",
155
+ audio_url: "https://example.org/podcast.mp3"
156
+ )
157
+ end
158
+ ```
159
+
160
+ ### Files
161
+
162
+ ```ruby
163
+ Stealth.reply do
164
+ say(
165
+ "Here's a PDF file.",
166
+ reply_type: "file",
167
+ file_url: "https://example.org/some.pdf"
168
+ )
169
+ end
170
+ ```
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 2.0.0
@@ -2,9 +2,9 @@
2
2
 
3
3
  require 'http'
4
4
 
5
- require 'stealth/services/bandwidth/message_handler'
6
- require 'stealth/services/bandwidth/reply_handler'
7
5
  require 'stealth/services/bandwidth/setup'
6
+ require 'stealth/services/bandwidth/event_handler'
7
+ require 'stealth/services/bandwidth/reply_handler'
8
8
 
9
9
  module Stealth
10
10
  module Services
@@ -13,23 +13,22 @@ module Stealth
13
13
 
14
14
  attr_reader :http_client, :reply, :endpoint
15
15
 
16
- def initialize(reply:)
16
+ def initialize(reply:, **args)
17
17
  @reply = reply
18
- account_id = Stealth.config.bandwidth.account_id
19
- username = Stealth.config.bandwidth.api_username
20
- password = Stealth.config.bandwidth.api_password
21
- application_id = Stealth.config.bandwidth.application_id
18
+ account_id = Stealth.config.dig('bandwidth', 'account_id')
19
+ username = Stealth.config.dig('bandwidth', 'api_username')
20
+ password = Stealth.config.dig('bandwidth', 'api_password')
21
+
22
22
  @endpoint = "https://messaging.bandwidth.com/api/v2/users/#{account_id}/messages"
23
23
  @http_client = HTTP
24
24
  .timeout(connect: 15, read: 30)
25
25
  .basic_auth(user: username, pass: password)
26
- .headers('Content-Type' => 'application/json')
26
+ .headers('Content-Type' => 'application/json; charset=utf-8')
27
27
  end
28
28
 
29
29
  def transmit
30
30
  # Don't transmit anything for delays
31
31
  return true if reply.blank?
32
-
33
32
  json_reply = Oj.dump(reply, mode: :compat)
34
33
  response = http_client.post(endpoint, body: json_reply)
35
34
 
@@ -0,0 +1,72 @@
1
+ module Stealth
2
+ module Services
3
+ module Bandwidth
4
+
5
+ class EventHandler < Stealth::ServiceEvent
6
+ attr_reader :params, :headers
7
+ attr_accessor :sender_id, :target_id, :message, :timestamp, :event_type, :event, :attachments, :selected_option, :previous_message, :nlp_result
8
+
9
+ def initialize(params:, headers:)
10
+ super(service: 'bandwidth')
11
+ @params = parse(params)
12
+ @headers = headers
13
+ @attachments = []
14
+ end
15
+
16
+ def coordinate
17
+ return [202, 'Accepted'] if should_ignore_event?(params)
18
+ Stealth::Services::HandleEventJob.perform_async('bandwidth', params, headers)
19
+ [202, 'Accepted']
20
+ end
21
+
22
+
23
+ def process
24
+ self.sender_id = params.dig('message', 'from')
25
+ self.target_id = params.dig('message', 'to').first
26
+ self.message = params.dig('message', 'text')
27
+ self.timestamp = params.dig('message', 'time')
28
+ params.dig('message', 'media')&.each do |attachment_url|
29
+ self.attachments << {
30
+ url: attachment_url
31
+ }
32
+ end
33
+
34
+ mapped_event = map_event_type
35
+ self.event_type = mapped_event[:event_type]
36
+ self.event = mapped_event[:event]
37
+
38
+ self
39
+ end
40
+
41
+ private
42
+
43
+ def should_ignore_event?(params)
44
+ event = params.dig('type')
45
+
46
+ ignored_events = [
47
+ event["message-sending"].present?,
48
+ event["message-delivered"].present?
49
+ ]
50
+
51
+ ignored_events.any?
52
+ end
53
+
54
+ def parse(params)
55
+ return params["_json"] if params["_json"].present?
56
+ params
57
+ end
58
+
59
+ def map_event_type
60
+ event_type = params.dig('type')
61
+
62
+ event_mapping = {
63
+ 'message-received' => 'text_received'
64
+ }
65
+
66
+ Stealth::EventMapping.map_event(service: 'bandwidth', event_type: event_mapping[event_type])
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -10,19 +10,18 @@ module Stealth
10
10
 
11
11
  attr_reader :recipient_id, :reply, :translated_reply
12
12
 
13
- def initialize(recipient_id: nil, reply: nil)
14
- @recipient_id = recipient_id
13
+ def initialize(reply: nil, **args)
14
+ @recipient_id = args[:recipient_id]
15
15
  @reply = reply
16
16
  end
17
17
 
18
18
  def text
19
19
  check_text_length
20
+ @translated_reply = reply[:text]
20
21
 
21
- @translated_reply = reply['text']
22
-
23
- suggestions = generate_suggestions(suggestions: reply['suggestions'])
24
- buttons = generate_buttons(buttons: reply['buttons'])
22
+ suggestions = reply[:suggestions]
25
23
 
24
+ buttons = generate_buttons(buttons: reply[:buttons])
26
25
  if suggestions.present?
27
26
  @translated_reply = [
28
27
  @translated_reply,
@@ -52,25 +51,25 @@ module Stealth
52
51
  def image
53
52
  check_text_length
54
53
 
55
- format_response({ text: reply['text'], media: [reply['image_url']] })
54
+ format_response({ text: reply[:text], media: [reply[:image_url]] })
56
55
  end
57
56
 
58
57
  def audio
59
58
  check_text_length
60
59
 
61
- format_response({ text: reply['text'], media: [reply['audio_url']] })
60
+ format_response({ text: reply[:text], media: [reply[:audio_url]] })
62
61
  end
63
62
 
64
63
  def video
65
64
  check_text_length
66
65
 
67
- format_response({ text: reply['text'], media: [reply['video_url']] })
66
+ format_response({ text: reply[:text], media: [reply[:video_url]] })
68
67
  end
69
68
 
70
69
  def file
71
70
  check_text_length
72
71
 
73
- format_response({ text: reply['text'], media: [reply['file_url']] })
72
+ format_response({ text: reply[:text], media: [reply[:file_url]] })
74
73
  end
75
74
 
76
75
  def delay
@@ -80,40 +79,32 @@ module Stealth
80
79
  private
81
80
 
82
81
  def check_text_length
83
- if reply['text'].present? && reply['text'].size > 2048
82
+ if reply[:text].present? && reply[:text].size > 2048
84
83
  raise(ArgumentError, 'Text messages must be 2048 characters or less.')
85
84
  end
86
85
  end
87
86
 
88
87
  def format_response(response)
89
88
  sender_info = {
90
- from: Stealth.config.bandwidth.from_phone.to_s,
89
+ from: Stealth.config.dig('bandwidth', 'from_phone'),
91
90
  to: recipient_id,
92
- applicationId: Stealth.config.bandwidth.application_id
91
+ applicationId: Stealth.config.dig('bandwidth', 'application_id')
93
92
  }
94
93
 
95
94
  response.merge(sender_info)
96
95
  end
97
96
 
98
- def generate_suggestions(suggestions:)
99
- return if suggestions.blank?
100
-
101
- mf = suggestions.collect do |suggestion|
102
- suggestion['text']
103
- end.compact
104
- end
105
-
106
97
  def generate_buttons(buttons:)
107
98
  return if buttons.blank?
108
99
 
109
100
  sms_buttons = buttons.map do |button|
110
- case button['type']
101
+ case button[:type]
111
102
  when 'url'
112
- "#{button['text']}: #{button['url']}"
103
+ "#{button[:text]}: #{button[:url]}"
113
104
  when 'payload'
114
- "To #{button['text'].downcase}: Text #{button['payload'].upcase}"
105
+ "To #{button[:text].downcase}: Text #{button[:payload].upcase}"
115
106
  when 'call'
116
- "#{button['text']}: #{button['phone_number']}"
107
+ "#{button[:text]}: #{button[:phone_number]}"
117
108
  else # Don't raise for unsupported buttons
118
109
  next
119
110
  end
@@ -9,10 +9,10 @@ Gem::Specification.new do |s|
9
9
  s.homepage = 'https://github.com/hellostealth/stealth-bandwidth'
10
10
  s.licenses = ['MIT']
11
11
  s.version = version
12
- s.authors = ['Mauricio Gomes', 'Emilie Morissette']
13
- s.email = ['mauricio@edge14.com', 'emorissettegregoire@gmail.com']
12
+ s.authors = ['Emilie Morissette']
13
+ s.email = ['emorissettegregoire@gmail.com']
14
14
 
15
- s.add_dependency 'stealth', '>= 2.0.0.beta6'
15
+ s.add_dependency 'stealth', '>= 3.0.0.alpha1'
16
16
  s.add_dependency 'http', '~> 4.1'
17
17
  s.add_dependency 'oj', '~> 3.11'
18
18
 
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stealth-bandwidth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Mauricio Gomes
8
7
  - Emilie Morissette
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2022-11-07 00:00:00.000000000 Z
11
+ date: 2025-03-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: stealth
@@ -17,14 +16,14 @@ dependencies:
17
16
  requirements:
18
17
  - - ">="
19
18
  - !ruby/object:Gem::Version
20
- version: 2.0.0.beta6
19
+ version: 3.0.0.alpha1
21
20
  type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
24
  - - ">="
26
25
  - !ruby/object:Gem::Version
27
- version: 2.0.0.beta6
26
+ version: 3.0.0.alpha1
28
27
  - !ruby/object:Gem::Dependency
29
28
  name: http
30
29
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +96,6 @@ dependencies:
97
96
  version: '1.1'
98
97
  description: Bandwidth.com SMS driver for Stealth.
99
98
  email:
100
- - mauricio@edge14.com
101
99
  - emorissettegregoire@gmail.com
102
100
  executables: []
103
101
  extensions: []
@@ -113,7 +111,7 @@ files:
113
111
  - lib/stealth-bandwidth.rb
114
112
  - lib/stealth/bandwidth.rb
115
113
  - lib/stealth/services/bandwidth/client.rb
116
- - lib/stealth/services/bandwidth/message_handler.rb
114
+ - lib/stealth/services/bandwidth/event_handler.rb
117
115
  - lib/stealth/services/bandwidth/reply_handler.rb
118
116
  - lib/stealth/services/bandwidth/setup.rb
119
117
  - lib/stealth/services/bandwidth/version.rb
@@ -124,7 +122,7 @@ homepage: https://github.com/hellostealth/stealth-bandwidth
124
122
  licenses:
125
123
  - MIT
126
124
  metadata: {}
127
- post_install_message:
125
+ post_install_message:
128
126
  rdoc_options: []
129
127
  require_paths:
130
128
  - lib
@@ -139,8 +137,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
137
  - !ruby/object:Gem::Version
140
138
  version: '0'
141
139
  requirements: []
142
- rubygems_version: 3.1.6
143
- signing_key:
140
+ rubygems_version: 3.3.7
141
+ signing_key:
144
142
  specification_version: 4
145
143
  summary: Stealth Bandwidth SMS driver
146
- test_files: []
144
+ test_files:
145
+ - spec/spec_helper.rb
146
+ - spec/version_spec.rb
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Stealth
4
- module Services
5
- module Bandwidth
6
- class MessageHandler < Stealth::Services::BaseMessageHandler
7
- attr_reader :service_message, :params, :headers
8
-
9
- def initialize(params:, headers:)
10
- @params = params
11
- @headers = headers
12
- end
13
-
14
- def coordinate
15
- case params.dig('message', 'direction')
16
- when "in"
17
- Stealth::Services::HandleMessageJob.perform_async(
18
- 'bandwidth',
19
- params,
20
- headers
21
- )
22
- when "out"
23
- # Ignoring outbound messages
24
- end
25
-
26
- # Relay our acceptance
27
- [202, 'Accepted']
28
- end
29
-
30
- def process
31
- @service_message = ServiceMessage.new(service: 'bandwidth')
32
-
33
- service_message.sender_id = params.dig('message', 'from')
34
- service_message.target_id = params.dig('message', 'to')
35
- service_message.message = params.dig('message', 'text')
36
- service_message.timestamp = params.dig('message', 'time')
37
- params.dig('message', 'media')&.each do |attachment_url|
38
- service_message.attachments << {
39
- url: attachment_url
40
- }
41
- end
42
-
43
- service_message
44
- end
45
-
46
- end
47
-
48
- end
49
- end
50
- end