megalabs_sms 0.1.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: 514e53d5f271af0a42284dd94de370448da8ff6dcafebf05dd140d3f2810f6ee
4
+ data.tar.gz: 68a2127266570145e574a6df04a2210c29394b51521e6ffdf53566363d98fbc4
5
+ SHA512:
6
+ metadata.gz: 01136beb138bf4639efe0116996d8c20ad3a80d9d6f3bf915df1e2c0f632819f473e40f89f6df8c37996153aba6e3b1efe26ab6c53bd6e7705a189083864a8ae
7
+ data.tar.gz: 4093d7da0fe27621c8adaf161f0c357b01427becf11e2d73e003a880c59e0b01edfdb305acef2a78d303e017a110adaf82d6abe3dc44d95c562b09dbe341b9ab
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # MegalabsSms
2
+
3
+ Простой и удобный гем для отправки SMS через A2P API от Megalabs (Мегафон). Создан для разработчиков, которые хотят быстро и эффективно интегрировать отправку SMS в свои Ruby-приложения.
4
+
5
+ ## Установка
6
+
7
+ Добавьте эту строку в `Gemfile` вашего приложения:
8
+
9
+ ```ruby
10
+ gem 'megalabs_sms'
11
+ ```
12
+
13
+ И затем выполните:
14
+
15
+ ```bash
16
+ $ bundle install
17
+ ```
18
+
19
+ Или установите гем напрямую:
20
+
21
+ ```bash
22
+ $ gem install megalabs_sms
23
+ ```
24
+
25
+ ## Использование
26
+
27
+ ### Базовый пример
28
+
29
+ ```ruby
30
+ require 'megalabs_sms'
31
+
32
+ # Создаем клиент
33
+ client = MegalabsSms::Client.new(
34
+ 'ваш_логин',
35
+ 'ваш_пароль'
36
+ )
37
+
38
+ # Отправляем SMS
39
+ client.send_sms(
40
+ 'SenderName', # имя отправителя
41
+ '+79001234567', # номер получателя
42
+ 'Привет! Это тестовое сообщение.' # текст сообщения
43
+ )
44
+ ```
45
+
46
+ ### Дополнительные возможности
47
+
48
+ #### Задержка между запросами
49
+
50
+ Если вам нужно добавить задержку между запросами (например, чтобы не превысить лимиты API):
51
+
52
+ ```ruby
53
+ client = MegalabsSms::Client.new(
54
+ 'ваш_логин',
55
+ 'ваш_пароль',
56
+ sleep_time: 1.0 # задержка в 1 секунду между запросами
57
+ )
58
+ ```
59
+
60
+ #### Тестовый режим
61
+
62
+ Для тестирования можно использовать режим эмуляции:
63
+
64
+ ```ruby
65
+ # Эмуляция успешной отправки
66
+ client = MegalabsSms::Client.new(
67
+ 'ваш_логин',
68
+ 'ваш_пароль',
69
+ success_stub: true
70
+ )
71
+
72
+ # Эмуляция ошибки отправки
73
+ client = MegalabsSms::Client.new(
74
+ 'ваш_логин',
75
+ 'ваш_пароль',
76
+ error_stub: true
77
+ )
78
+ ```
79
+
80
+ ## Обработка ошибок
81
+
82
+ Гем автоматически обрабатывает различные ошибки и возвращает понятные сообщения:
83
+
84
+ - При отсутствии учетных данных
85
+ - При проблемах с сетью
86
+ - При ошибках API
87
+ - При проблемах с форматом данных
88
+
89
+ ## Разработка
90
+
91
+ После клонирования репозитория, установите зависимости:
92
+
93
+ ```bash
94
+ $ bundle install
95
+ ```
96
+
97
+ Запуск тестов:
98
+
99
+ ```bash
100
+ $ bundle exec rspec
101
+ ```
102
+
103
+ ## Лицензия
104
+
105
+ Гем доступен как open source под лицензией MIT.
106
+
107
+ ## Поддержка
108
+
109
+ Если у вас возникли вопросы или проблемы, пожалуйста, создайте issue в репозитории проекта.
110
+
111
+ ## Автор
112
+
113
+ - Vitalii Dementev - [@DementevVV](https://github.com/DementevVV)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MegalabsSms
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+ require_relative 'megalabs_sms/version'
6
+
7
+ #
8
+ # Главный модуль для взаимодействия с API Megalabs, включая отправку SMS.
9
+ #
10
+ module MegalabsSms
11
+ # Класс для взаимодействия с API Megalabs для отправки SMS
12
+ class Client
13
+ #
14
+ # Конструктор, инициализирующий параметры клиента:
15
+ #
16
+ # @param api_user [String] логин для Basic Auth
17
+ # @param api_password [String] пароль для Basic Auth
18
+ # @param sleep_time [Float] время задержки в секундах (по умолчанию 0)
19
+ # @param success_stub [Boolean] эмулировать успешную отправку?
20
+ # @param error_stub [Boolean] эмулировать ошибку отправки?
21
+ #
22
+ # @raise [ArgumentError] если api_user или api_password отсутствуют или пусты
23
+ #
24
+ def initialize(api_user,
25
+ api_password,
26
+ sleep_time: 0,
27
+ success_stub: false,
28
+ error_stub: false)
29
+ raise ArgumentError, 'api_user is required' if api_user.nil? || api_user.strip.empty?
30
+ raise ArgumentError, 'api_password is required' if api_password.nil? || api_password.strip.empty?
31
+
32
+ @api_user = api_user
33
+ @api_password = api_password
34
+ @sleep_time = sleep_time
35
+ @success_stub = success_stub
36
+ @error_stub = error_stub
37
+ end
38
+
39
+ #
40
+ # Метод для форматирования сообщений логирования
41
+ #
42
+ # @param message [String] исходное сообщение для логирования
43
+ #
44
+ # @return [String] отформатированное сообщение с префиксом модуля
45
+ #
46
+ def log_message(message)
47
+ "[MegalabsSms] #{message}"
48
+ end
49
+
50
+ #
51
+ # Метод для отправки SMS через сервис Megalabs.
52
+ #
53
+ # @param from [String] имя/номер отправителя
54
+ # @param to [String] номер телефона получателя
55
+ # @param message [String] текст сообщения
56
+ #
57
+ # @return [String] статус отправки или текст ошибки
58
+ #
59
+ def send_sms(from, to, message)
60
+ return handle_stub_response if stub_enabled?
61
+
62
+ request = build_request(from, to, message)
63
+ send_request(request)
64
+ end
65
+
66
+ private
67
+
68
+ #
69
+ # Проверяет, включен ли режим эмуляции ответов
70
+ #
71
+ # @return [Boolean] true если включена эмуляция успеха или ошибки, false в противном случае
72
+ #
73
+ def stub_enabled?
74
+ @error_stub || @success_stub
75
+ end
76
+
77
+ #
78
+ # Обрабатывает эмуляцию ответов
79
+ #
80
+ # @return [String] сообщение об успехе или ошибке эмуляции
81
+ #
82
+ def handle_stub_response
83
+ return log_message('Stubbed error: SMS not sent') if @error_stub
84
+
85
+ log_message('Stubbed success: SMS would be sent') if @success_stub
86
+ end
87
+
88
+ #
89
+ # Создает HTTP-запрос для отправки SMS
90
+ #
91
+ # @param from [String] имя отправителя
92
+ # @param to [String] номер телефона получателя
93
+ # @param message [String] текст сообщения
94
+ #
95
+ # @return [Net::HTTP::Post] объект HTTP-запроса
96
+ #
97
+ def build_request(from, to, message)
98
+ uri = URI('https://a2p-api.megalabs.ru/sms/v1/sms')
99
+ request = Net::HTTP::Post.new(uri)
100
+ request.basic_auth(@api_user, @api_password)
101
+ request.content_type = 'application/json'
102
+ request.body = build_request_body(from, to, message)
103
+ request
104
+ end
105
+
106
+ #
107
+ # Создает HTTP-запрос для отправки SMS
108
+ #
109
+ # @param from [String] имя/номер отправителя
110
+ # @param to [String] <description>
111
+ # @param message [String] <description>
112
+ #
113
+ # @return [Net::HTTP::Post] объект HTTP-запроса
114
+ #
115
+ def build_request_body(from, to, message)
116
+ {
117
+ from: from,
118
+ to: to.gsub(/\D/, '').to_i,
119
+ message: message
120
+ }.to_json
121
+ end
122
+
123
+ #
124
+ # Отправляет HTTP-запрос
125
+ #
126
+ # @param request [Net::HTTP::Post] объект HTTP-запроса
127
+ #
128
+ # @return [String] тело ответа или сообщение об ошибке
129
+ #
130
+ def send_request(request)
131
+ uri = URI('https://a2p-api.megalabs.ru/sms/v1/sms')
132
+ response_body = perform_http_request(uri, request)
133
+ sleep(@sleep_time) if @sleep_time.positive?
134
+ response_body
135
+ end
136
+
137
+ #
138
+ # Выполняет HTTP-запрос
139
+ #
140
+ # @param uri [URI] URI-адрес для запроса
141
+ # @param request [Net::HTTP::Post] объект HTTP-запроса
142
+ #
143
+ # @return [String] тело ответа или сообщение об ошибке
144
+ #
145
+ def perform_http_request(uri, request)
146
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
147
+ http.request(request)
148
+ end
149
+
150
+ if response.is_a?(Net::HTTPSuccess)
151
+ process_http_response(response.body)
152
+ else
153
+ log_message("Failed to send: #{response}")
154
+ end
155
+ rescue StandardError => e
156
+ log_message("Exception occurred: #{e.message}")
157
+ end
158
+
159
+ #
160
+ # Обрабатывает тело ответа HTTP и возвращает корректное сообщение.
161
+ # Если статус ответа не соответствует ожидаемому, возвращает сообщение об ошибке.
162
+ #
163
+ # @param raw_body [String] оригинальный ответ от HTTP-запроса
164
+ #
165
+ # @return [String] либо оригинальное тело (если все хорошо), либо сообщение об ошибке
166
+ #
167
+ def process_http_response(raw_body)
168
+ body = raw_body.dup.force_encoding('UTF-8')
169
+ parsed = JSON.parse(body)
170
+ result = parsed.dig('result', 'status')
171
+ return body if result&.fetch('code', nil)&.zero? && result&.fetch('description', '')&.downcase == 'ok'
172
+
173
+ log_message("Failed to send: #{body}")
174
+ rescue JSON::ParserError => e
175
+ log_message("Failed to parse JSON: #{e.message}")
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ # rubocop:disable Metrics/BlockLength
6
+
7
+ RSpec.describe MegalabsSms::Client do
8
+ let(:api_user) { 'test_user' }
9
+ let(:api_password) { 'test_password' }
10
+ let(:sleep_time) { 0 }
11
+ let(:from) { 'TestSender' }
12
+ let(:to) { '+70001234567' }
13
+ let(:message) { 'Hello from RSpec!' }
14
+
15
+ subject(:client) do
16
+ described_class.new(
17
+ api_user,
18
+ api_password,
19
+ sleep_time: sleep_time,
20
+ success_stub: success_stub,
21
+ error_stub: error_stub
22
+ )
23
+ end
24
+
25
+ context 'with stub responses' do
26
+ context 'when success_stub is true' do
27
+ let(:success_stub) { true }
28
+ let(:error_stub) { false }
29
+
30
+ it 'returns a success message (stub)' do
31
+ result = client.send_sms(from, to, message)
32
+ expect(result).to eq('[MegalabsSms] Stubbed success: SMS would be sent')
33
+ end
34
+ end
35
+
36
+ context 'when error_stub is true' do
37
+ let(:success_stub) { false }
38
+ let(:error_stub) { true }
39
+
40
+ it 'returns an error message (stub)' do
41
+ result = client.send_sms(from, to, message)
42
+ expect(result).to eq('[MegalabsSms] Stubbed error: SMS not sent')
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'with real HTTP request' do
48
+ let(:success_stub) { false }
49
+ let(:error_stub) { false }
50
+ let(:valid_response) do
51
+ '{"result":{"msg_id":"id","status":{"code":0,"description":"ok"}}}'
52
+ end
53
+
54
+ it 'makes an HTTP request' do
55
+ stub_request(:post, 'https://a2p-api.megalabs.ru/sms/v1/sms')
56
+ .to_return(status: 200, body: valid_response, headers: { 'Content-Type': 'application/json' })
57
+
58
+ result = client.send_sms(from, to, message)
59
+ expect(result).to eq(valid_response)
60
+ expect(WebMock).to have_requested(:post, 'https://a2p-api.megalabs.ru/sms/v1/sms')
61
+ .with(body: {
62
+ from: from,
63
+ # rubocop:disable Style/NumericLiterals
64
+ to: 70001234567,
65
+ # rubocop:enable Style/NumericLiterals
66
+ message: message
67
+ }.to_json)
68
+ end
69
+ end
70
+ end
71
+
72
+ # rubocop:enable Metrics/BlockLength
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rspec'
4
+ require 'webmock/rspec'
5
+
6
+ require_relative '../lib/megalabs_sms'
7
+
8
+ RSpec.configure do |config|
9
+ config.formatter = :documentation
10
+ config.color = true
11
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: megalabs_sms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vitalii Dementev
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-03-13 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: net-http
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.6.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.6.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: ostruct
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.6.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.6.0
40
+ - !ruby/object:Gem::Dependency
41
+ name: rspec
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: webmock
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: yard
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ description: This gem provides a simple interface to send SMS using the Megalabs A2P
83
+ API.
84
+ email:
85
+ - v@dementev.dev
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - README.md
91
+ - lib/megalabs_sms.rb
92
+ - lib/megalabs_sms/version.rb
93
+ - spec/megalabs_sms/client_spec.rb
94
+ - spec/spec_helper.rb
95
+ homepage: https://github.com/DementevVV/megalabs_sms.git
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 2.7.0
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubygems_version: 3.6.5
114
+ specification_version: 4
115
+ summary: Ruby gem for sending SMS via the Megalabs API
116
+ test_files: []