smster 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +32 -0
  4. data/Rakefile +34 -0
  5. data/app/controllers/smster/clickatell_controller.rb +22 -0
  6. data/app/controllers/smster/nexmo_controller.rb +17 -0
  7. data/lib/generators/smster/install/templates/create_smsters.rb +20 -0
  8. data/lib/generators/smster/install/templates/smster.rb +8 -0
  9. data/lib/generators/smster/install_generator.rb +38 -0
  10. data/lib/smster.rb +21 -0
  11. data/lib/smster/configuration.rb +11 -0
  12. data/lib/smster/sms.rb +32 -0
  13. data/lib/smster/sms/clickatell.rb +34 -0
  14. data/lib/smster/sms/nexmo.rb +45 -0
  15. data/lib/smster/version.rb +3 -0
  16. data/lib/tasks/smster_tasks.rake +4 -0
  17. data/test/controller/smster/clickatell_controller_test.rb +27 -0
  18. data/test/controller/smster/nexmo_controller_test.rb +19 -0
  19. data/test/dummy/README.rdoc +28 -0
  20. data/test/dummy/Rakefile +6 -0
  21. data/test/dummy/app/assets/javascripts/application.js +13 -0
  22. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  23. data/test/dummy/app/controllers/application_controller.rb +5 -0
  24. data/test/dummy/app/helpers/application_helper.rb +2 -0
  25. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  26. data/test/dummy/bin/bundle +3 -0
  27. data/test/dummy/bin/rails +4 -0
  28. data/test/dummy/bin/rake +4 -0
  29. data/test/dummy/bin/setup +29 -0
  30. data/test/dummy/config.ru +4 -0
  31. data/test/dummy/config/application.rb +26 -0
  32. data/test/dummy/config/boot.rb +5 -0
  33. data/test/dummy/config/database.yml +25 -0
  34. data/test/dummy/config/environment.rb +5 -0
  35. data/test/dummy/config/environments/development.rb +41 -0
  36. data/test/dummy/config/environments/production.rb +79 -0
  37. data/test/dummy/config/environments/test.rb +42 -0
  38. data/test/dummy/config/initializers/assets.rb +11 -0
  39. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  40. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  41. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  42. data/test/dummy/config/initializers/inflections.rb +16 -0
  43. data/test/dummy/config/initializers/mime_types.rb +4 -0
  44. data/test/dummy/config/initializers/session_store.rb +3 -0
  45. data/test/dummy/config/initializers/smster.rb +8 -0
  46. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  47. data/test/dummy/config/locales/en.yml +23 -0
  48. data/test/dummy/config/routes.rb +4 -0
  49. data/test/dummy/config/secrets.yml +22 -0
  50. data/test/dummy/db/development.sqlite3 +0 -0
  51. data/test/dummy/db/migrate/20150330154603_create_smsters.rb +20 -0
  52. data/test/dummy/db/schema.rb +29 -0
  53. data/test/dummy/db/test.sqlite3 +0 -0
  54. data/test/dummy/log/development.log +141 -0
  55. data/test/dummy/log/test.log +1918 -0
  56. data/test/dummy/public/404.html +67 -0
  57. data/test/dummy/public/422.html +67 -0
  58. data/test/dummy/public/500.html +66 -0
  59. data/test/dummy/public/favicon.ico +0 -0
  60. data/test/smster/sms/clickatell_test.rb +21 -0
  61. data/test/smster/sms/nexmo_test.rb +22 -0
  62. data/test/smster_test.rb +16 -0
  63. data/test/test_helper.rb +19 -0
  64. metadata +181 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 715e7236f095993ddfa89768a85a791ae4c0efd8
4
+ data.tar.gz: dd512320a0ffc07130b56771512cab7f9d86d410
5
+ SHA512:
6
+ metadata.gz: 733d1fc0f88b29bb49fc5ae099142bb03c9cf07a03a23eaaabcbd8be8b8f807d98cb96906dfd3dea633849fb54be15e34783fc78043439d28871faf2c2a686fd
7
+ data.tar.gz: f46599540651ddb19bfdf1fe08ea7fd875b4791cbb743271f0dfe5d11020ae0a27cd8d38d5796c0b17d70d103773555e4115e131479c62b531bf23c4b65c3d49
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 doniv
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,32 @@
1
+ = Smster
2
+ SMS sending service through different providers with maximum convenience.
3
+
4
+ ===== Supported
5
+ * {Nexmo}[https://www.nexmo.com/]
6
+ * {Clickatell}[https://www.clickatell.com/]
7
+
8
+ == Setup
9
+ Add gem:
10
+ gem 'smster', git: 'git@github.com:IlyaDonskikh/smster.git'
11
+
12
+ Install:
13
+ rails g smster:install
14
+
15
+ == Sending message
16
+ Add config of your provider into config/initializers/smster.rb.
17
+
18
+ And let's start!
19
+ Sms::Nexmo.create(text: 'sms text', to: phone_number)
20
+ Sms::Clickatell.create(text: 'sms text', to: phone_number)
21
+
22
+ == Callbacks
23
+ Add to routes, setup proveder callbacks and get sms statuses:
24
+ post 'smster/$provider_name/callback'
25
+
26
+ == Feedback
27
+ Please use the {issue tracker}[https://github.com/IlyaDonskikh/smster/issues].
28
+
29
+ == Thanks
30
+ 1. Mickhail Zelenin for the idea for this gem.
31
+ 2. Egor Kiselev for help in creation of this manual.
32
+ 3. Alexey Bandar for the recommendation of the first provider.
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Smster'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,22 @@
1
+ class Smster::ClickatellController < ApplicationController
2
+ skip_before_filter :verify_authenticity_token
3
+
4
+ def callback
5
+ code = clickatell_params[:apiMessageId]
6
+ description = clickatell_params[:description]
7
+ sms = Sms::Clickatell.find_by!(code: code)
8
+
9
+ sms.status_message = description
10
+ sms.save
11
+
12
+ sms.accept! if description == 'Received by recipient'
13
+ result = { sms.id => sms.status }
14
+
15
+ render json: result.as_json, status: 200
16
+ end
17
+
18
+ private
19
+ def clickatell_params
20
+ params.require(:data)
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ class Smster::NexmoController < ApplicationController
2
+ skip_before_filter :verify_authenticity_token
3
+
4
+ def callback
5
+ code = params['messageId']
6
+ status = params['status']
7
+ sms = Sms::Nexmo.find_by!(code: code)
8
+
9
+ sms.status_message = status
10
+ sms.save
11
+
12
+ sms.accept! if status == 'delivered'
13
+ result = { sms.id => sms.status }
14
+
15
+ render json: result.as_json, status: 200
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ class CreateSmsters< ActiveRecord::Migration
2
+ def up
3
+ create_table :smsters do |t|
4
+ t.string :text
5
+ t.string :name
6
+ t.string :from
7
+ t.string :to
8
+ t.string :code
9
+ t.string :type
10
+ t.integer :status
11
+ t.string :status_message
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+
17
+ def down
18
+ drop_table :smsters
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ Smster.configure do |config|
2
+ ## Nexmo
3
+ config.nexmo_key = ""
4
+ config.nexmo_sekret = ""
5
+
6
+ ## Clickatell
7
+ config.clickatell_authorization_code = ""
8
+ end
@@ -0,0 +1,38 @@
1
+ require 'rails/generators'
2
+ module Smster
3
+ class InstallGenerator < Rails::Generators::Base
4
+ desc "Add migration"
5
+ include Rails::Generators::Migration
6
+ source_root File.expand_path('../install/templates', __FILE__)
7
+
8
+ def copy_migrations
9
+ copy_migration "create_smsters"
10
+ end
11
+
12
+ def self.next_migration_number(path)
13
+ unless @prev_migration_nr
14
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
15
+ else
16
+ @prev_migration_nr += 1
17
+ end
18
+ @prev_migration_nr.to_s
19
+ end
20
+
21
+ desc 'Add initializer'
22
+ source_root File.expand_path('../install/templates', __FILE__)
23
+
24
+ def copy_initializer
25
+ filename = 'smster'
26
+ copy_file "#{filename}.rb", "config/initializers/#{filename}.rb"
27
+ end
28
+
29
+ protected
30
+ def copy_migration(filename)
31
+ if self.class.migration_exists?("db/migrate", "#{filename}")
32
+ say_status("skipped", "Migration #{filename}.rb already exists")
33
+ else
34
+ migration_template "#{filename}.rb", "db/migrate/#{filename}.rb"
35
+ end
36
+ end
37
+ end
38
+ end
data/lib/smster.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'rest_client'
2
+ require "smster/configuration"
3
+ require 'smster/sms'
4
+ require 'smster/sms/clickatell'
5
+ require 'smster/sms/nexmo'
6
+
7
+ module Smster
8
+ class Engine < Rails::Engine; end
9
+
10
+ class << self
11
+ attr_accessor :configuration
12
+ end
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration)
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Smster
2
+ class Configuration
3
+ attr_accessor :nexmo_key, :nexmo_sekret, :clickatell_authorization_code
4
+
5
+ def initialize
6
+ @nexmo_key = ""
7
+ @nexmo_sekret = ""
8
+ @clickatell_authorization_code = ""
9
+ end
10
+ end
11
+ end
data/lib/smster/sms.rb ADDED
@@ -0,0 +1,32 @@
1
+ class Sms < ActiveRecord::Base
2
+ self.table_name = "smsters"
3
+ attr_accessor :mode
4
+
5
+ ## Codes
6
+ STATUS_CODES = { created: 0, sent: 1, delivered: 2, failed: 3 }
7
+
8
+ ## Callbacks
9
+ after_create :send_sms
10
+
11
+ ## Validations
12
+ validates :type, :to, :text, presence: true
13
+
14
+ ## Etc.
15
+ def initialize(attributes = {})
16
+ attr_with_defaults = {
17
+ status: STATUS_CODES[:created]
18
+ }.merge(attributes)
19
+ super(attr_with_defaults)
20
+ end
21
+
22
+ def mode
23
+ @mode ||= case Rails.env
24
+ when 'test' then 'test'
25
+ else 'production'
26
+ end
27
+ end
28
+
29
+ def accept!
30
+ self.update(status: STATUS_CODES[:delivered])
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ class Sms::Clickatell < Sms
2
+ def send_sms
3
+ config = Smster.configuration
4
+ authorization_code = config.clickatell_authorization_code
5
+
6
+ text = self.text.tr(" ", "+")
7
+ phone = to.gsub(/\D/, '')
8
+
9
+ api_message_id = if self.mode == 'test'
10
+ logger.debug("Mode: #{mode}. To: #{phone}, text: #{text}")
11
+ self.id
12
+ else
13
+ response = RestClient.post('https://api.clickatell.com/rest/message',
14
+ { "text" => text, "to" => [phone.to_s] }.to_json,
15
+ :content_type => :json,
16
+ :accept => :json,
17
+ 'X-Version' => 1,
18
+ 'Authorization' => "bearer #{authorization_code}")
19
+ response = JSON.parse(response)
20
+ response['data']['message'][0]['apiMessageId']
21
+ end
22
+
23
+ if api_message_id.present?
24
+ self.code = api_message_id
25
+ self.status = STATUS_CODES[:sent]
26
+ self.save
27
+ end
28
+ rescue => e
29
+ logger.debug("Error #{e}")
30
+ self.status = STATUS_CODES[:failed]
31
+ self.status_message = e.to_s
32
+ self.save
33
+ end
34
+ end
@@ -0,0 +1,45 @@
1
+ class Sms::Nexmo < Sms
2
+ def send_sms
3
+ config = Smster.configuration
4
+ api_key = config.nexmo_key
5
+ api_secret = config.nexmo_sekret
6
+
7
+ text = self.text.tr(" ", "+")
8
+ phone = to.gsub(/\D/, '')
9
+ current_status = STATUS_CODES[:sent]
10
+
11
+ api_message_id = if self.mode == 'test'
12
+ logger.debug("Mode: #{mode}. To: #{phone}, text: #{text}")
13
+ self.id
14
+ else
15
+ response = RestClient.post('https://rest.nexmo.com/sms/json',
16
+ "text" => text,
17
+ "to" => phone.to_s,
18
+ :content_type => :json,
19
+ :from => 'OnlinePay',
20
+ :api_key => api_key,
21
+ :api_secret => api_secret)
22
+
23
+ json_response = JSON.parse(response)
24
+ error_text = json_response['messages'][0]['error-text']
25
+ json_response['messages'][0]['message-id']
26
+ end
27
+
28
+ if api_message_id.present?
29
+ self.code = api_message_id
30
+ self.status = STATUS_CODES[:sent]
31
+ end
32
+
33
+ if error_text.present?
34
+ self.status = STATUS_CODES[:failed]
35
+ self.status_message = error_text
36
+ end
37
+
38
+ self.save
39
+ rescue => e
40
+ logger.debug("Error #{e}")
41
+ self.status = STATUS_CODES[:failed]
42
+ self.status_message = e.to_s
43
+ self.save
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Smster
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :smster do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class Smster::ClickatellControllerTest < ActionController::TestCase
4
+ def setup
5
+ @text = "simple text"
6
+ @number = (0...7).map { (1..9).to_a.sample }.join
7
+ @provider = Sms::Clickatell
8
+ end
9
+
10
+ test 'callback' do
11
+ delivered_code = Sms::STATUS_CODES[:delivered]
12
+ sms = @provider.create(text: @text, to: @number)
13
+
14
+ post :callback, {
15
+ "data" => {
16
+ "charge" => 1.5,
17
+ "messageStatus" => 003,
18
+ "description" => "Received by recipient",
19
+ "apiMessageId" => sms.code
20
+ }
21
+ }
22
+
23
+ response = JSON.parse(@response.body)
24
+ result = { sms.id => delivered_code }
25
+ assert_equal result.as_json, response
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class Smster::NexmoControllerTest < ActionController::TestCase
4
+ def setup
5
+ @text = "simple text"
6
+ @number = (0...7).map { (1..9).to_a.sample }.join
7
+ @provider = Sms::Nexmo
8
+ end
9
+
10
+ test 'callback' do
11
+ delivered_code = Sms::STATUS_CODES[:delivered]
12
+ sms = @provider.create(text: @text, to: @number)
13
+
14
+ post :callback, { "messageId" => sms.code, "status" => 'delivered' }
15
+ response = JSON.parse(@response.body)
16
+ result = { sms.id => delivered_code }
17
+ assert_equal result.as_json, response
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.