Skip to content

Instantly share code, notes, and snippets.

@Tyralion
Created September 3, 2013 08:18
Show Gist options
  • Select an option

  • Save Tyralion/6421035 to your computer and use it in GitHub Desktop.

Select an option

Save Tyralion/6421035 to your computer and use it in GitHub Desktop.
Простой скрипт отправки смс через сервис http://sms24x7.ru
# encoding: utf-8
require 'net/http'
require 'timeout'
# SMS24x7.login('[email protected]', 'password')
# SMS24x7.message('you-phone', 'Привет')
module SMS24x7
HOST = 'api.sms24x7.ru'
PHONE_RE = /\A(\+7|7|8)(\d{10})\Z/
TIMEOUT = 25 # сек
class Error < ::StandardError; end
class AuthError < ::SMS24x7::Error; end
class TimeoutError < ::SMS24x7::Error; end
class TimeoutResponseError < ::SMS24x7::Error; end
class AccountBlockedError < ::SMS24x7::Error; end
class UndefinedError < ::SMS24x7::Error; end
class ApiVersionError < ::SMS24x7::Error; end
class ArgumentsError < ::SMS24x7::Error; end
class UnauthorizedPartnerError < ::SMS24x7::Error; end
class SaveError < ::SMS24x7::Error; end
class ActionRejectedError < ::SMS24x7::Error; end
class PasswordError < ::SMS24x7::Error; end
class SessionExpiredError < ::SMS24x7::Error; end
class AccountNotFoundError < ::SMS24x7::Error; end
class SenderNameError < ::SMS24x7::Error; end
class DeliveryError < ::SMS24x7::Error; end
class DomainBusyError < ::SMS24x7::Error; end
class TarifNotFoundError < ::SMS24x7::Error; end
class MessagesNotDeliveryError < ::SMS24x7::Error; end
class BaseError < ::SMS24x7::Error; end
class InterfaceError < ::SMS24x7::Error; end
class NoLoginError < ::SMS24x7::Error; end
class BalanceError < ::SMS24x7::Error; end
class SpamError < ::SMS24x7::Error; end
class EncodingError < ::SMS24x7::Error; end
class NoGateError < ::SMS24x7::Error; end
class OtherError < ::SMS24x7::Error; end
extend self
# Отключение отправки смс, с возможностью повторной попытки
# по истеению заданного таймаута
def turn_off(try_after = 0)
@active = false
if @turn_of_timeout_selected
# Если задано таймаут повторной отправки SMS то,
# запоминает текущую дату и таймаут отправки
if try_after.is_a?(Numeric) && try_after > 0
puts "Попытка повторной отправки SMS будет доступна через #{try_after*10} минут"
set_turn_on_timeout(try_after)
end
end # if
puts "Отправка SMS отключена"
self
end # turn_off
def turn_on
@active = true
clear_turn_on_timeout
puts "Отправка SMS ВКЛЮЧЕНА"
self
end # turn_on
def active?
# Если задана повторная попытка отпрвки смс и время ожидания истекло то,
# очищаем информацию об ожидании и переводим отправку смс в активную фазу.
if @try_after && @last_try && (::Time.now.to_i - @last_try > @try_after)
@active = true
clear_turn_on_timeout
end
@active === true
end # active?
def valid_phone?(phone)
!(phone.to_s.gsub(/\D/, "") =~ ::SMS24x7::PHONE_RE).nil?
end # valid_phone?
def convert_phone(phone, prefix = "7")
r = phone.to_s.gsub(/\D/, "").scan(::SMS24x7::PHONE_RE)
r.empty? ? nil : "#{prefix}#{r.last.last}"
end # convert_phone
def login(email, password, secure = true)
return self unless self.active?
@email = email
@password = password
@secure = secure
auth
self
end # login
def message(phone, text, params = {})
return unless self.active?
request = {
:method => 'push_msg',
:unicode => 1,
:phone => phone,
:text => text
}.merge(params)
begin
data = request(request)[:data] || {}
rescue ::SMS24x7::TimeoutError, ::SMS24x7::SessionExpiredError
logout
auth
retry
end
unless (n_raw_sms = data['n_raw_sms']) && (credits = data['credits'])
raise ::SMS24x7::InterfaceError, "Could not find 'n_raw_sms' or 'credits' in successful push_msg response"
end
data
end # message
def logout
return self unless self.active?
request({
:method => 'logout'
})
@cookie = nil
self
end # logout
private
def set_turn_on_timeout(time)
@turn_of_timeout_selected = true
@try_after = time*60 # Минуты
@last_try = ::Time.now.utc.to_i
self
end # set_turn_on_timeout
def clear_turn_on_timeout
@turn_of_timeout_selected = nil
@try_after = nil
@last_try = nil
self
end # clear_turn_on_timeout
def auth
return if @cookie
responce = request({
:method => 'login',
:email => @email,
:password => @password
})
sid = (responce[:data] || {})["sid"]
raise ::SMS24x7::InterfaceError, "Login request OK, but no 'sid' set" if sid.nil?
@cookie = "sid=#{::CGI::escape(sid)}"
end # auth
def request(request = {})
request[:format] = "json"
if @secure
http = ::Net::HTTP.new(::SMS24x7::HOST, 443)
http.use_ssl = true
http.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
else
http = ::Net::HTTP.new(::SMS24x7::HOST, 80)
end
header = {}
header["Cookie"] = @cookie if @cookie
error_code = -1
response = {}
res = nil
begin
::Timeout::timeout(::SMS24x7::TIMEOUT) {
res = http.post('/', ::URI.encode_www_form(request), header)
}
rescue ::Timeout::Error
self.turn_off(2)
raise ::SMS24x7::TimeoutResponseError, "Превышено время ожиданеи ответа сервера: #{::SMS24x7::TIMEOUT} (сек)"
rescue => e
self.turn_off(2)
raise ::SMS24x7::OtherError, e.message
end
unless res.nil?
if res.code.to_i != 200
raise ::SMS24x7::InterfaceError, "#{res.message} (#{res.code})"
end
json = ::JSON.parse(res.body) rescue {}
unless (response = json['response']) && (msg = response['msg']) && (error_code = msg['err_code'].to_i)
raise ::SMS24x7::InterfaceError, 'Empty some necessary data fields'
end
case error_code
when 0 then nil
when 2 then raise ::SMS24x7::AuthError, 'AuthError. Неверный логин или пароль.'
when 3 then raise ::SMS24x7::TimeoutError, 'TimeoutError. Вы были неактивный более 24 минут. В целях безопасности авторизуйтесь заново.'
when 4 then raise ::SMS24x7::AccountBlockedError, 'AccountBlockedError. Ваш аккаутн заблокирован, обратитесь к администратору.'
when 5 then raise ::SMS24x7::UndefinedError, 'UndefinedError. Неизвестный метод.'
when 6 then raise ::SMS24x7::ApiVersionError, 'ApiVersionError. Указанной версии API не существует.'
when 7 then raise ::SMS24x7::ArgumentsError, 'ArgumentsError. Заданы не все необходимые параметры.'
when 10 then raise ::SMS24x7::UnauthorizedPartnerError, 'UnauthorizedPartnerError. Данный партнер не авторизован.'
when 11 then raise ::SMS24x7::SaveError, 'SaveError. При сохранении произошла ошибка.'
when 15 then raise ::SMS24x7::ActionRejectedError, 'ActionRejectedError. Действие запрещено.'
when 16 then raise ::SMS24x7::PasswordError, 'PasswordError. Пароль указан неверно.'
when 18 then raise ::SMS24x7::SessionExpiredError, 'SessionExpiredError. Сессия устарела.'
when 19 then raise ::SMS24x7::Error, 'Error. Произошла ошибка.'
when 22 then raise ::SMS24x7::AccountNotFoundError, 'AccountNotFoundError. Учетной записи не существует.'
when 29 then raise ::SMS24x7::NoGateError, 'NoGateError. Сотовый оператор не подключен.'
when 35 then raise ::SMS24x7::EncodingError, 'EncodingError. Кодировка текста сообщения не соотвествует заявленной.'
when 36 then raise ::SMS24x7::BalanceError, 'BalanceError. Недостаточно средств, пополните баланс.'
when 37, 38, 59 then raise ::SMS24x7::SpamError, 'Spam'
when 39 then raise ::SMS24x7::SenderNameError, 'SenderNameError. Недопустимое имя отправителя.'
when 40 then raise ::SMS24x7::DeliveryError, 'DeliveryError. Невозможно доставить.'
when 42 then raise ::SMS24x7::NoLoginError, 'NoLoginError. Авторизуйтесь, чтобы продолжить.'
when 43 then raise ::SMS24x7::DomainBusyError, 'DomainBusyError. Домен занят.'
when 45 then raise ::SMS24x7::BaseError, 'BaseError. Не найдены базоввые настройки кабинета.'
when 44, 47 then raise ::SMS24x7::TarifNotFoundError, 'TarifNotFoundError. Не найден преднастроенный тариф, доступный при регистрации.'
when 58 then raise ::SMS24x7::MessagesNotDeliveryError, 'MessagesNotDeliveryError. Ни одного сообщения отправлено не было.'
else raise ::SMS24x7::OtherError, "Communication to API failed. Error code: #{error_code}"
end
end # if
{ :error_code => error_code, :data => response['data'] }
end # request
end # SMS24x7
# SMS24x7.turn_on
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment