Created
September 3, 2013 08:18
-
-
Save Tyralion/6421035 to your computer and use it in GitHub Desktop.
Простой скрипт отправки смс через сервис http://sms24x7.ru
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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