stealth-bandwidth 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7819293192d202d15f7d9bdfc5f9bcda6f9a4316f929e6d6a96b8e08286a8530
4
+ data.tar.gz: 23828c62352610ac0c52947150f2b1e4790070ee09d4cfdeec27eef11d68fc8a
5
+ SHA512:
6
+ metadata.gz: b425eb611f44cbb026e01b3fa6a68c54f47d8f8be29303b6069dd15de4fe64f25ae4bfa71b17d09e28f011b7421467c912a76d63a32373321b8b1dadba289ed3
7
+ data.tar.gz: 6b06a35322e10a7e9303ff68b446db8c1e54ddaa8086d7cf334e09816a99c48e6caef689d8fb7472a5e6079f8972e467a241864e5d20fdb5a4dcd5cfb606428e
@@ -0,0 +1,60 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.4.1-node-browsers
11
+ environment:
12
+ STEALTH_ENV: test
13
+
14
+ # Specify service dependencies here if necessary
15
+ # CircleCI maintains a library of pre-built images
16
+ # documented at https://circleci.com/docs/2.0/circleci-images/
17
+ # - image: circleci/postgres:9.4
18
+
19
+ working_directory: ~/repo
20
+
21
+ steps:
22
+ - checkout
23
+
24
+ # Download and cache dependencies
25
+ - restore_cache:
26
+ keys:
27
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
28
+ # fallback to using the latest cache if no exact match is found
29
+ - v1-dependencies-
30
+
31
+ - run:
32
+ name: install dependencies
33
+ command: |
34
+ bundle install --jobs=4 --retry=3 --path vendor/bundle
35
+
36
+ - save_cache:
37
+ paths:
38
+ - ./vendor/bundle
39
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
40
+
41
+ # run tests!
42
+ - run:
43
+ name: run tests
44
+ command: |
45
+ mkdir /tmp/test-results
46
+ TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
47
+
48
+ bundle exec rspec --format progress \
49
+ --format RspecJunitFormatter \
50
+ --out /tmp/test-results/rspec.xml \
51
+ --format progress \
52
+ -- \
53
+ $TEST_FILES
54
+
55
+ # collect reports
56
+ - store_test_results:
57
+ path: /tmp/test-results
58
+ - store_artifacts:
59
+ path: /tmp/test-results
60
+ destination: test-results
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ # please add general patterns to your global ignore list
2
+ # see https://github.com/github/gitignore#readme
3
+ .DS_STORE
4
+ *.swp
5
+ *.rbc
6
+ *.sass-cache
7
+ /pkg
8
+ /doc/api
9
+ /coverage
10
+ .yardoc
11
+ doc/
12
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'stealth', '>= 2.0.0.beta6'
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,109 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stealth-bandwidth (1.0.0)
5
+ http (~> 4.1)
6
+ oj (~> 3.11)
7
+ stealth (>= 2.0.0.beta6)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (6.1.7)
13
+ concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ i18n (>= 1.6, < 2)
15
+ 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)
28
+ rake
29
+ http (4.4.1)
30
+ addressable (~> 2.3)
31
+ http-cookie (~> 1.0)
32
+ http-form_data (~> 2.2)
33
+ http-parser (~> 1.2.0)
34
+ http-cookie (1.0.5)
35
+ domain_name (~> 0.5)
36
+ http-form_data (2.3.0)
37
+ http-parser (1.2.3)
38
+ ffi-compiler (>= 1.0, < 2.0)
39
+ i18n (1.12.0)
40
+ 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.21)
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
53
+ rack-test (1.1.0)
54
+ 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)
64
+ diff-lcs (>= 1.2.0, < 2.0)
65
+ rspec-support (~> 3.11.0)
66
+ rspec-mocks (3.11.1)
67
+ 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)
71
+ 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)
92
+ concurrent-ruby (~> 1.0)
93
+ unf (0.1.4)
94
+ unf_ext
95
+ unf_ext (0.0.8.2)
96
+ zeitwerk (2.6.0)
97
+
98
+ PLATFORMS
99
+ ruby
100
+
101
+ DEPENDENCIES
102
+ rack-test (~> 1.1)
103
+ rspec (~> 3.6)
104
+ rspec_junit_formatter (~> 0.3)
105
+ stealth (>= 2.0.0.beta6)
106
+ stealth-bandwidth!
107
+
108
+ BUNDLED WITH
109
+ 1.17.3
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Stealth Bandwidth SMS
2
+
3
+ The [Stealth](https://github.com/whoisblackops/stealth) Bandwidth SMS driver adds the ability to build your bot using Bandwidth's SMS service.
4
+
5
+ ## Supported Reply Types
6
+
7
+ * Text
8
+ * Image
9
+ * Audio
10
+ * Video
11
+ * File
12
+ * Delay
13
+
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.
16
+
17
+ If you store your files on S3, please make sure you have set the `content-type` appropriately or Bandwidth might reject your media.
18
+
19
+ ## Service Message
20
+
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.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ require 'stealth/services/bandwidth/version'
3
+ require 'stealth/services/bandwidth/client'
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'http'
4
+
5
+ require 'stealth/services/bandwidth/message_handler'
6
+ require 'stealth/services/bandwidth/reply_handler'
7
+ require 'stealth/services/bandwidth/setup'
8
+
9
+ module Stealth
10
+ module Services
11
+ module Bandwidth
12
+ class Client < Stealth::Services::BaseClient
13
+
14
+ attr_reader :http_client, :reply, :endpoint
15
+
16
+ def initialize(reply:)
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
22
+ @endpoint = "https://messaging.bandwidth.com/api/v2/users/#{account_id}/messages"
23
+ @http_client = HTTP
24
+ .timeout(connect: 15, read: 30)
25
+ .basic_auth(user: username, pass: password)
26
+ .headers('Content-Type' => 'application/json')
27
+ end
28
+
29
+ def transmit
30
+ # Don't transmit anything for delays
31
+ return true if reply.blank?
32
+
33
+ json_reply = Oj.dump(reply, mode: :compat)
34
+ response = http_client.post(endpoint, body: json_reply)
35
+
36
+ Stealth::Logger.l(
37
+ topic: 'bandwidth',
38
+ message: "Transmitting. Response: #{response.status.code}: #{response.body}"
39
+ )
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
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').first
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
@@ -0,0 +1,128 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Stealth
5
+ module Services
6
+ module Bandwidth
7
+ class ReplyHandler < Stealth::Services::BaseReplyHandler
8
+
9
+ ALPHA_ORDINALS = ('A'..'Z').to_a.freeze
10
+
11
+ attr_reader :recipient_id, :reply
12
+
13
+ def initialize(recipient_id: nil, reply: nil)
14
+ @recipient_id = recipient_id
15
+ @reply = reply
16
+ end
17
+
18
+ def text
19
+ check_text_length
20
+
21
+ translated_reply = reply['text']
22
+
23
+ suggestions = generate_suggestions(suggestions: reply['suggestions'])
24
+ buttons = generate_buttons(buttons: reply['buttons'])
25
+
26
+ if suggestions.present?
27
+ translated_reply = [
28
+ translated_reply,
29
+ 'Reply with:'
30
+ ].join("\n\n")
31
+
32
+ suggestions.each_with_index do |suggestion, i|
33
+ translated_reply = [
34
+ translated_reply,
35
+ "\"#{ALPHA_ORDINALS[i]}\" for #{suggestion}"
36
+ ].join("\n")
37
+ end
38
+ end
39
+
40
+ if buttons.present?
41
+ buttons.each do |button|
42
+ translated_reply = [
43
+ translated_reply,
44
+ button
45
+ ].join("\n\n")
46
+ end
47
+ end
48
+
49
+ format_response({ text: translated_reply })
50
+ end
51
+
52
+ def image
53
+ check_text_length
54
+
55
+ format_response({ text: reply['text'], media: [reply['image_url']] })
56
+ end
57
+
58
+ def audio
59
+ check_text_length
60
+
61
+ format_response({ text: reply['text'], media: [reply['audio_url']] })
62
+ end
63
+
64
+ def video
65
+ check_text_length
66
+
67
+ format_response({ text: reply['text'], media: [reply['video_url']] })
68
+ end
69
+
70
+ def file
71
+ check_text_length
72
+
73
+ format_response({ text: reply['text'], media: [reply['file_url']] })
74
+ end
75
+
76
+ def delay
77
+
78
+ end
79
+
80
+ private
81
+
82
+ def check_text_length
83
+ if reply['text'].present? && reply['text'].size > 2048
84
+ raise(ArgumentError, 'Text messages must be 2048 characters or less.')
85
+ end
86
+ end
87
+
88
+ def format_response(response)
89
+ sender_info = {
90
+ from: Stealth.config.bandwidth.from_phone.to_s,
91
+ to: recipient_id,
92
+ applicationId: Stealth.config.bandwidth.application_id
93
+ }
94
+
95
+ response.merge(sender_info)
96
+ end
97
+
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
+ def generate_buttons(buttons:)
107
+ return if buttons.blank?
108
+
109
+ sms_buttons = buttons.map do |button|
110
+ case button['type']
111
+ when 'url'
112
+ "#{button['text']}: #{button['url']}"
113
+ when 'payload'
114
+ "To #{button['text'].downcase}: Text #{button['payload'].upcase}"
115
+ when 'call'
116
+ "#{button['text']}: #{button['phone_number']}"
117
+ else # Don't raise for unsupported buttons
118
+ next
119
+ end
120
+ end.compact
121
+
122
+ sms_buttons
123
+ end
124
+
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stealth/services/bandwidth/client'
4
+
5
+ module Stealth
6
+ module Services
7
+ module Bandwidth
8
+
9
+ class Setup
10
+
11
+ class << self
12
+ def trigger
13
+ Stealth::Logger.l(
14
+ topic: "bandwidth",
15
+ message: "There is no setup needed!"
16
+ )
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Stealth
4
+ module Services
5
+ module Bandwidth
6
+ module Version
7
+ def self.version
8
+ File.read(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'VERSION')).strip
9
+ end
10
+ end
11
+
12
+ VERSION = Version.version
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stealth/bandwidth'
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+
5
+ require 'stealth'
6
+ require 'stealth-bandwidth'
7
+
8
+ # Requires supporting files with custom matchers and macros, etc,
9
+ # in ./support/ and its subdirectories.
10
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
11
+
12
+ RSpec.configure do |config|
13
+
14
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ describe "Stealth::Services::Bandwidth::Version" do
6
+
7
+ let(:version_in_file) { File.read(File.join(File.dirname(__FILE__), '..', 'VERSION')).strip }
8
+
9
+ it "should return the current gem version" do
10
+ expect(Stealth::Services::Bandwidth::Version.version).to eq version_in_file
11
+ end
12
+
13
+ it "should return the current gem version via a constant" do
14
+ expect(Stealth::Services::Bandwidth::VERSION).to eq version_in_file
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
+
3
+ version = File.read(File.join(File.dirname(__FILE__), 'VERSION')).strip
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'stealth-bandwidth'
7
+ s.summary = 'Stealth Bandwidth SMS driver'
8
+ s.description = 'Bandwidth.com SMS driver for Stealth.'
9
+ s.homepage = 'https://github.com/hellostealth/stealth-bandwidth'
10
+ s.licenses = ['MIT']
11
+ s.version = version
12
+ s.authors = ['Mauricio Gomes', 'Emilie Morissette']
13
+ s.email = ['mauricio@edge14.com', 'emorissettegregoire@gmail.com']
14
+
15
+ s.add_dependency 'stealth', '>= 2.0.0.beta6'
16
+ s.add_dependency 'http', '~> 4.1'
17
+ s.add_dependency 'oj', '~> 3.11'
18
+
19
+ s.add_development_dependency 'rspec', '~> 3.6'
20
+ s.add_development_dependency 'rspec_junit_formatter', '~> 0.3'
21
+ s.add_development_dependency 'rack-test', '~> 1.1'
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
26
+ s.require_paths = ['lib']
27
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stealth-bandwidth
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mauricio Gomes
8
+ - Emilie Morissette
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2022-09-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: stealth
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 2.0.0.beta6
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 2.0.0.beta6
28
+ - !ruby/object:Gem::Dependency
29
+ name: http
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '4.1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '4.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: oj
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.11'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.11'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.6'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.6'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec_junit_formatter
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '0.3'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '0.3'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rack-test
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.1'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.1'
98
+ description: Bandwidth.com SMS driver for Stealth.
99
+ email:
100
+ - mauricio@edge14.com
101
+ - emorissettegregoire@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".circleci/config.yml"
107
+ - ".gitignore"
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - README.md
111
+ - VERSION
112
+ - lib/stealth-bandwidth.rb
113
+ - lib/stealth/bandwidth.rb
114
+ - lib/stealth/services/bandwidth/client.rb
115
+ - lib/stealth/services/bandwidth/message_handler.rb
116
+ - lib/stealth/services/bandwidth/reply_handler.rb
117
+ - lib/stealth/services/bandwidth/setup.rb
118
+ - lib/stealth/services/bandwidth/version.rb
119
+ - spec/spec_helper.rb
120
+ - spec/version_spec.rb
121
+ - stealth-bandwidth.gemspec
122
+ homepage: https://github.com/hellostealth/stealth-bandwidth
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubygems_version: 3.0.8
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Stealth Bandwidth SMS driver
145
+ test_files:
146
+ - spec/spec_helper.rb
147
+ - spec/version_spec.rb