active_smsgate 0.0.2 → 0.0.3
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.
- data/lib/active_smsgate/gateway.rb +35 -2
- data/lib/active_smsgate/gateways/amegainform.rb +118 -93
- data/lib/active_smsgate.rb +1 -0
- metadata +17 -3
@@ -1,17 +1,39 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
module ActiveSmsgate #:nodoc:
|
3
3
|
module Gateway #:nodoc:
|
4
|
+
=begin rdoc
|
5
|
+
В каждом шлюзе нужно прописать три метода
|
6
|
+
# Выполнение отправки смс завершено
|
7
|
+
def complete; end
|
8
|
+
alias :complete? :complete
|
4
9
|
|
10
|
+
# Смс досталена
|
11
|
+
def success; end
|
12
|
+
alias :success? :success
|
13
|
+
|
14
|
+
# Смс не доставлена
|
15
|
+
def failure; end
|
16
|
+
alias :failure? :failure
|
17
|
+
=end
|
5
18
|
class << self
|
6
19
|
# Список поддерживаемых
|
7
20
|
def support_gateways
|
8
|
-
[{
|
21
|
+
Dir["#{File.dirname(__FILE__)}/gateways/**/*.rb"].map { |gw|
|
22
|
+
gateway = "active_smsgate/gateway/#{File.basename(gw, ".rb")}".classify.constantize
|
23
|
+
{ :class => File.basename(gw, ".rb"), :alias => gateway::ALIAS,
|
24
|
+
:short_desc => gateway::SHORT_DESC, :desc => gateway::DESC} }
|
25
|
+
end
|
26
|
+
|
27
|
+
# получение шлюза по его имени
|
28
|
+
def gateway(gw)
|
29
|
+
"active_smsgate/gateway/#{gw.to_s}".classify.constantize
|
9
30
|
end
|
31
|
+
|
10
32
|
end
|
11
33
|
|
12
34
|
class Gateway
|
13
35
|
include HTTParty
|
14
|
-
attr_accessor :login, :password, :use_ssl
|
36
|
+
attr_accessor :login, :password, :use_ssl, :errors
|
15
37
|
|
16
38
|
# Initialize a new gateway.
|
17
39
|
# ==== Параметры
|
@@ -33,6 +55,17 @@ module ActiveSmsgate #:nodoc:
|
|
33
55
|
# Использовать резервные сервера
|
34
56
|
def use_of_backup_server?; @use_of_backup_server end
|
35
57
|
|
58
|
+
# Получение uri смс сервиса
|
59
|
+
def uri
|
60
|
+
self.class.default_options[:base_uri].gsub!(/^https?:\/\//i, '')
|
61
|
+
"http#{'s' if use_ssl?}://#{self.class.default_options[:base_uri]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def valid?
|
65
|
+
@errors.blank?
|
66
|
+
end
|
67
|
+
|
68
|
+
|
36
69
|
end
|
37
70
|
end
|
38
71
|
end
|
@@ -1,22 +1,63 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
|
3
2
|
module ActiveSmsgate #:nodoc:
|
4
|
-
# «Амега Информ» – http://amegainform.ru/
|
5
|
-
# это сервис массовой рассылки, приема SMS и голосовых сообщений.
|
6
|
-
|
7
3
|
module Gateway #:nodoc:
|
4
|
+
|
5
|
+
=begin rdoc
|
6
|
+
«Амега Информ» – http://amegainform.ru/
|
7
|
+
это сервис массовой рассылки, приема SMS и голосовых сообщений.
|
8
|
+
|
9
|
+
# Возвращаемые данные
|
10
|
+
# <output>
|
11
|
+
# <result sms_group_id="996">
|
12
|
+
# <sms id="99991" smstype="SENDSMS" phone="+79999999991" sms_res_count="1"><![CDATA[Привет]]></sms>
|
13
|
+
# <sms id="99992" smstype="SENDVOICE" phone="+79999999992" sms_res_count="38"><![CDATA[%PAUSE=1000%%SYNTH=Vika%Привет друг%SAMPLE=#1525%%PAUSE=1000%%SYNTH=Vika%С днём рождения!]]></sms>
|
14
|
+
# </result>
|
15
|
+
# <output>
|
16
|
+
|
17
|
+
|
18
|
+
# Возвращаемые данные
|
19
|
+
# -------------------------------------------------------------------
|
20
|
+
# SMS_ID - ID сообщения
|
21
|
+
# SMS_GROUP_ID - ID рассылки сообщений
|
22
|
+
# SMSTYPE - тип сообщения
|
23
|
+
# CREATED - дата и время создания сообщения
|
24
|
+
# AUL_USERNAME - Имя пользователя создавшего сообщение
|
25
|
+
# AUL_CLIENT_ADR - IP адрес пользователя создавшего сообщение
|
26
|
+
# SMS_SENDER - Имя отправителя сообщения
|
27
|
+
# SMS_TARGET - Телефон адресата
|
28
|
+
# SMS_RES_COUNT - Кол-во единиц ресурсов на данное сообщение
|
29
|
+
# SMS_TEXT - Текст сообщения
|
30
|
+
# SMSSTC_CODE - Код статуса доставки сообщения
|
31
|
+
# -- queued - сообщение в очереди отправки
|
32
|
+
# -- wait - передано оператору на отправку
|
33
|
+
# -- accepted - сообщение принято оператором, но статус доставки неизвестен
|
34
|
+
# -- delivered -сообщение доставлено
|
35
|
+
# -- not_delivered - сообщение не доставлено
|
36
|
+
# -- failed - ошибка при работе по сообщению
|
37
|
+
# SMS_STATUS - Текстовое описание статуса доставки сообщения
|
38
|
+
# SMS_CLOSED - [0,1] 0 - сообщения находится в процессинге.
|
39
|
+
# 1 = работа по отправке сообщения завершена
|
40
|
+
# SMS_SENT - [0,1] 0 - сообщение не отослано. 1 = сообщение отослано успешно
|
41
|
+
# SMS_CALL_DURATION - Время,
|
42
|
+
# в течение которого было установлено соединение для отправки сообщения.
|
43
|
+
# SMS_DTMF_DIGITS - Что пользователь нажимал в сеансе разговора (для SENDVOICE (в разработке))
|
44
|
+
# SMS_CLOSE_TIME - Время завершения работы по сообщению.
|
45
|
+
|
46
|
+
|
47
|
+
=end
|
8
48
|
class Amegainform < Gateway
|
9
49
|
|
50
|
+
CLASS_ID = 'amegainform'
|
51
|
+
ALIAS = 'www.amegainform.ru'
|
52
|
+
SHORT_DESC = 'Шлюз sms рассылок www.amegainform.ru'
|
53
|
+
DESC = "Описание шлюза"
|
54
|
+
|
10
55
|
headers 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'
|
11
56
|
base_uri 'http://service.amega-inform.ru'
|
12
57
|
|
13
58
|
# Адреса резервных серверов: service-r1.amegainform.ru и service-r2.amegainform.ru
|
14
59
|
|
15
60
|
# Создание нового шлюза AmegaInformGateway
|
16
|
-
# Для работы со шлюзом необходимы логин и пароль
|
17
|
-
#
|
18
|
-
# ==== Параметры
|
19
|
-
#
|
20
61
|
# * <tt>:login</tt> -- REQUIRED
|
21
62
|
# * <tt>:password</tt> -- REQUIRED
|
22
63
|
def initialize(options = {})
|
@@ -29,10 +70,10 @@ module ActiveSmsgate #:nodoc:
|
|
29
70
|
# OVERDRAFT [максимальных уход в минус]
|
30
71
|
# PARENT_DEBT [задолженность]
|
31
72
|
def balance
|
32
|
-
|
73
|
+
response = self.class.post("#{uri}/sendsms",
|
33
74
|
:query => { :action => "balance"}.merge(auth_options))
|
34
|
-
if
|
35
|
-
xml = Zlib::GzipReader.new( StringIO.new(
|
75
|
+
if response.code == 200
|
76
|
+
xml = Zlib::GzipReader.new( StringIO.new( response ) ).read
|
36
77
|
doc = Nokogiri::XML(xml)
|
37
78
|
{
|
38
79
|
:balance => (doc.at("//balance//AGT_BALANCE").inner_html rescue 0),
|
@@ -40,14 +81,10 @@ module ActiveSmsgate #:nodoc:
|
|
40
81
|
:overdraft => (doc.at("//balance//OVERDRAFT").inner_html rescue 0)
|
41
82
|
}
|
42
83
|
else
|
43
|
-
|
44
|
-
# raise
|
84
|
+
raise
|
45
85
|
end
|
46
|
-
|
47
|
-
|
48
|
-
# rescue
|
49
|
-
# nil
|
50
|
-
|
86
|
+
rescue
|
87
|
+
nil
|
51
88
|
end
|
52
89
|
|
53
90
|
# Отправка сообщения
|
@@ -59,107 +96,94 @@ module ActiveSmsgate #:nodoc:
|
|
59
96
|
# * sender - имя отправителя, зарегистрированного в системе service.amegainform.ru.
|
60
97
|
# NULL - используется имя отправителя по умолчанию.
|
61
98
|
|
62
|
-
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
|
68
|
-
# xml.sms(:id => '999',:smstyoe => 'sendsms', :phone => '22', :sms_res_count => '11' ) {
|
69
|
-
# xml << "\<![CDATA[---------Привет---------]]\>"}
|
70
|
-
# end
|
71
|
-
# end
|
72
|
-
# end
|
73
|
-
|
74
|
-
|
75
|
-
# Возвращаемые данные
|
76
|
-
# <output>
|
77
|
-
# <result sms_group_id="996">
|
78
|
-
# <sms id="99991" smstype="SENDSMS" phone="+79999999991" sms_res_count="1"><![CDATA[Привет]]></sms>
|
79
|
-
# <sms id="99992" smstype="SENDVOICE" phone="+79999999992" sms_res_count="38"><![CDATA[%PAUSE=1000%%SYNTH=Vika%Привет друг%SAMPLE=#1525%%PAUSE=1000%%SYNTH=Vika%С днём рождения!]]></sms>
|
80
|
-
# </result>
|
81
|
-
# <output>
|
82
|
-
|
83
|
-
def deliver(options = { :sender => nil})
|
99
|
+
# Возвращаемые параметры
|
100
|
+
# sms_id - ид в сервисе шлюза
|
101
|
+
# sms_count - сколько смс потрачено на отправку сообщения
|
102
|
+
# phone - номер куда было отправлено сообщение
|
103
|
+
# Если @errors не пустое то возвращает nil
|
104
|
+
def deliver_sms(options = { :sender => nil})
|
84
105
|
@options = {
|
85
|
-
:action => "post_sms",
|
86
|
-
:message => options[:message],
|
106
|
+
:action => "post_sms", :message => options[:message],
|
87
107
|
:target => options[:phones],
|
88
108
|
:sender => options[:sender] }
|
89
109
|
|
90
|
-
|
91
|
-
|
92
|
-
|
110
|
+
response = self.class.post("#{uri}/sendsms", :query => @options.merge(auth_options))
|
111
|
+
xml = Zlib::GzipReader.new( StringIO.new( response ) ).read
|
112
|
+
if response.code == 200
|
93
113
|
parse(xml)
|
94
|
-
{ :
|
114
|
+
@sms.map{|x| x.merge({ :sms_group_id => x[:sms_group_id],
|
115
|
+
:sms_id => x[:id], :phone => x[:phone], :sms_count => x[:sms_res_count] })}
|
116
|
+
|
95
117
|
else
|
96
118
|
raise
|
97
119
|
end
|
98
120
|
rescue
|
121
|
+
STDERR.puts " #{$!.inspect} "
|
122
|
+
STDERR.puts " #{xml} " if xml
|
99
123
|
nil
|
100
124
|
end
|
101
125
|
|
102
126
|
|
103
|
-
|
104
127
|
# Получение данных и статусов сообщений
|
105
128
|
# sms_id - ид смс
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# -- wait - передано оператору на отправку
|
123
|
-
# -- accepted - сообщение принято оператором, но статус доставки неизвестен
|
124
|
-
# -- delivered -сообщение доставлено
|
125
|
-
# -- not_delivered - сообщение не доставлено
|
126
|
-
# -- failed - ошибка при работе по сообщению
|
127
|
-
# SMS_STATUS - Текстовое описание статуса доставки сообщения
|
128
|
-
# SMS_CLOSED - [0,1] 0 - сообщения находится в процессинге.
|
129
|
-
# 1 = работа по отправке сообщения завершена
|
130
|
-
# SMS_SENT - [0,1] 0 - сообщение не отослано. 1 = сообщение отослано успешно
|
131
|
-
# SMS_CALL_DURATION - Время,
|
132
|
-
# в течение которого было установлено соединение для отправки сообщения.
|
133
|
-
# SMS_DTMF_DIGITS - Что пользователь нажимал в сеансе разговора (для SENDVOICE (в разработке))
|
134
|
-
# SMS_CLOSE_TIME - Время завершения работы по сообщению.
|
135
|
-
|
136
|
-
def reply(sms_id)
|
137
|
-
@options = { :action => "status", :sendtype => "SENDSMS", :sms_id => sms_id }
|
138
|
-
@response = self.class.post("#{uri}/sendsms", :query => @options.merge(auth_options))
|
139
|
-
|
140
|
-
if @response.code == 200
|
141
|
-
xml = Zlib::GzipReader.new( StringIO.new( @response ) ).read
|
142
|
-
doc = Nokogiri::XML(xml)
|
129
|
+
# type - sms - запрашиваем статус по одному сообщению
|
130
|
+
# - sms_group - запрашиваем статусы по рассылке
|
131
|
+
|
132
|
+
# Возвращаем hash
|
133
|
+
# где обязательно есть
|
134
|
+
# sms_id - ид в сервисе шлюза
|
135
|
+
# sms_count - кол-во смс потраченное на отправку сообщения
|
136
|
+
# phone - телефон
|
137
|
+
|
138
|
+
def reply_sms(sms_id, sms_type = :sms)
|
139
|
+
raise unless [:sms, :sms_group].include?(sms_type)
|
140
|
+
|
141
|
+
@options = { :action => "status", :sendtype => "SENDSMS", "#{sms_type}_id" => sms_id }
|
142
|
+
response = self.class.post("#{uri}/sendsms", :query => @options.merge(auth_options))
|
143
|
+
xml = Zlib::GzipReader.new( StringIO.new( response ) ).read
|
144
|
+
if response.code == 200
|
143
145
|
parse(xml)
|
144
|
-
|
146
|
+
if sms_type == :sms
|
147
|
+
@messages.map{ |msg| msg.merge({ :sms_id => msg[:sms_id],:sms_count => msg[:sms_res_count],
|
148
|
+
:phone => msg[:sms_target] }) }.find{ |x| x[:sms_id] == sms_id.to_s }
|
149
|
+
else
|
150
|
+
@messages.map{ |msg| msg.merge({ :sms_id => msg[:sms_id],
|
151
|
+
:sms_count => msg[:sms_res_count], :phone => msg[:sms_target] }) }
|
152
|
+
end
|
145
153
|
else
|
146
154
|
raise
|
147
155
|
end
|
148
156
|
rescue
|
149
|
-
|
157
|
+
STDERR.puts " #{$!.inspect} "
|
158
|
+
STDERR.puts " #{xml} " if xml
|
159
|
+
false
|
150
160
|
end
|
151
161
|
|
162
|
+
# Выполнение отправки смс завершено
|
163
|
+
def complete_sms(sms_id)
|
164
|
+
@message ||= reply_sms(sms_id)
|
165
|
+
true if @message[:sms_closed].to_i == 1
|
166
|
+
end
|
167
|
+
alias :complete_sms? :complete_sms
|
152
168
|
|
153
|
-
|
154
|
-
|
155
|
-
|
169
|
+
# Смс досталена
|
170
|
+
def success_sms(sms_id)
|
171
|
+
@message ||= reply_sms(sms_id)
|
172
|
+
true if @message[:sms_sent].to_i == 1
|
173
|
+
end
|
174
|
+
alias :success_sms? :success_sms
|
156
175
|
|
157
|
-
#
|
158
|
-
def
|
159
|
-
|
160
|
-
|
176
|
+
# Смс не доставлена
|
177
|
+
def failure_sms(sms_id)
|
178
|
+
@message ||= reply_sms(sms_id)
|
179
|
+
true if @message[:sms_sent].to_i != 1
|
161
180
|
end
|
181
|
+
alias :failure_sms? :failure_sms
|
182
|
+
|
183
|
+
private
|
162
184
|
|
185
|
+
# Возвращает параметры для авторизации
|
186
|
+
def auth_options; { :user => @login, :pass => @password } end
|
163
187
|
|
164
188
|
# Разбираем ответ от сервиса amegainform
|
165
189
|
def parse(xml)
|
@@ -169,6 +193,7 @@ module ActiveSmsgate #:nodoc:
|
|
169
193
|
@sms = doc.at("//output//result") && doc.at("//output//result").
|
170
194
|
children.search("//sms").map {|x|
|
171
195
|
_x ={}
|
196
|
+
doc.at("//output//result").each { |v,l| _x[v.downcase.to_sym] = l }
|
172
197
|
x.each { |v,l| _x[v.downcase.to_sym] = l }
|
173
198
|
_x[:text] = x.inner_html
|
174
199
|
_x
|
data/lib/active_smsgate.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Pechnikov Maxim
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-13 00:00:00 +06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -57,6 +57,20 @@ dependencies:
|
|
57
57
|
version: 0.5.2
|
58
58
|
type: :runtime
|
59
59
|
version_requirements: *id003
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: activeresource
|
62
|
+
prerelease: false
|
63
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 2
|
69
|
+
- 3
|
70
|
+
- 5
|
71
|
+
version: 2.3.5
|
72
|
+
type: :runtime
|
73
|
+
version_requirements: *id004
|
60
74
|
description: Active Smsgate
|
61
75
|
email: parallel588@gmail.com
|
62
76
|
executables: []
|