smster 0.0.1

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.
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>.