sently-sms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Moonshado, 2012 Jerome Lacoste
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,24 @@
1
+ = sently-sms
2
+
3
+ Sent.ly SMS Gem
4
+
5
+ Heavily inspired by the Moonshado SMS Gem (http://rubygems.org/gems/moonshado-sms) in order to keep a relatively compatible API.
6
+
7
+ == Usage
8
+
9
+ Put this in Development and Test environment so no real SMS are sent out:
10
+ Sently::Sms.config = {
11
+ :test_env => true,
12
+ :username => nil,
13
+ :password => nil
14
+ }
15
+
16
+ Production environment config:
17
+ Sently::Sms.config = {
18
+ :username => ENV['SENTLY_USER'],
19
+ :password => ENV['SENTLY_PASS']
20
+ }
21
+
22
+ == Copyright
23
+
24
+ Copyright (c) 2010 Moonshado, 2012 Jerome Lacoste, Inc. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'jeweler'
4
+
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "sently-sms"
7
+ gem.summary = "Sent.ly SMS gem"
8
+ gem.description ="Allow to send SMSes using the sent.ly service"
9
+ #gem.rubyforce_project ="N/A"
10
+ gem.email = "jerome.lacoste@gmail.com"
11
+ gem.homepage = "http://github.com/lacostej/sently-sms"
12
+ gem.authors = ["Jerome Lacoste"]
13
+ gem.add_development_dependency "shoulda", ">= 0"
14
+ gem.add_development_dependency "mocha", ">= 0"
15
+ gem.add_runtime_dependency "rest-client", ">= 1.6.0"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+
20
+ require 'rake/testtask'
21
+ Rake::TestTask.new(:test) do |test|
22
+ test.libs << 'lib' << 'test'
23
+ test.pattern = 'test/**/*_test.rb'
24
+ test.verbose = true
25
+ end
26
+
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |test|
30
+ test.libs << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+ task :test => :check_dependencies
41
+
42
+ task :default => :test
43
+
44
+ require 'rdoc/task'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "sently-sms #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :build:
3
+ :patch: 0
4
+ :major: 0
5
+ :minor: 1
data/bin/sently ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # a small program to send SMS from the command line using sently
4
+ #
5
+
6
+ if ARGV.length != 2
7
+ puts "USAGE: sently.rb \"1(555)1233\" \"the message\""
8
+ exit
9
+ end
10
+
11
+ require 'rubygems'
12
+ require 'sently-sms'
13
+ require 'parseconfig'
14
+
15
+ email_config = ParseConfig.new(ENV['HOME']+'/.sently').params
16
+ username = email_config['username']
17
+ password = email_config['password']
18
+
19
+ Sently::Sms.configure do |config|
20
+ config.username = username
21
+ config.password = password
22
+ end
23
+
24
+ p Sently::Sms.new(ARGV[0], ARGV[1]).deliver_sms
data/lib/sently-sms.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'rest_client'
3
+ require 'sently/configuration'
4
+ require 'sently/sms'
5
+ require 'sently/sender'
6
+
7
+ module Sently
8
+
9
+ end
@@ -0,0 +1,66 @@
1
+ module Sently
2
+ class Configuration
3
+
4
+ OPTIONS = [:username, :password,
5
+ :http_open_timeout, :http_read_timeout,
6
+ :protocol, :host, :port, :secure,
7
+ :production_environment].freeze
8
+
9
+ attr_accessor :username
10
+ attr_accessor :password
11
+ attr_accessor :sms_uri
12
+ attr_accessor :secure
13
+ attr_accessor :http_open_timeout
14
+ attr_accessor :http_read_timeout
15
+ attr_accessor :host
16
+ attr_accessor :port
17
+ attr_accessor :production_environment
18
+
19
+ alias_method :secure?, :secure
20
+
21
+ def initialize
22
+ @secure = false
23
+ @host = 'sent.ly'
24
+ @http_open_timeout = 10
25
+ @http_read_timeout = 10
26
+ @production_environment = true
27
+ @sms_uri = '/command/sendsms'
28
+ @port = default_port
29
+ end
30
+
31
+ def [](option)
32
+ send(option)
33
+ end
34
+
35
+ def to_hash
36
+ OPTIONS.inject({}) do |hash, option|
37
+ hash.merge(option.to_sym => send(option))
38
+ end
39
+ end
40
+
41
+ def merge(hash)
42
+ to_hash.merge(hash)
43
+ end
44
+
45
+ def port
46
+ @port || default_port
47
+ end
48
+
49
+ def protocol
50
+ if secure?
51
+ 'https'
52
+ else
53
+ 'http'
54
+ end
55
+ end
56
+
57
+ private
58
+ def default_port
59
+ if secure?
60
+ 443
61
+ else
62
+ 80
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,48 @@
1
+ module Sently
2
+ class Sender
3
+ attr_reader :host, :port, :secure, :http_open_timeout, :http_read_timeout, :protocol, :username, :password
4
+
5
+ def initialize(options = {})
6
+ [:protocol, :host, :port, :secure, :http_open_timeout, :http_read_timeout, :username, :password].each do |option|
7
+ instance_variable_set("@#{option}", options[option])
8
+ end
9
+ end
10
+
11
+ #def post(data, uri)
12
+ # http = RestClient::Resource.new(
13
+ # url(uri),
14
+ # :username => username,
15
+ # :timeout => http_read_timeout,
16
+ # :open_timeout => http_open_timeout
17
+ # )
18
+
19
+ # response = http.post(data)
20
+ #end
21
+
22
+ def get(uri, additional_headers = {})
23
+ http = RestClient::Resource.new(
24
+ url(uri),
25
+ :timeout => http_read_timeout,
26
+ :open_timeout => http_open_timeout
27
+ )
28
+ headers = { :username => username, :password => password }
29
+
30
+ p = { :params => headers.merge(additional_headers) }
31
+
32
+ response = http.get p
33
+ end
34
+
35
+ private
36
+ def url(uri = "")
37
+ URI.parse("#{protocol}://#{host}:#{port}").merge(uri).to_s
38
+ end
39
+
40
+ def configuration
41
+ Sently::Sms.configuration
42
+ end
43
+
44
+ def production_environment?
45
+ configuration.production_environment
46
+ end
47
+ end
48
+ end
data/lib/sently/sms.rb ADDED
@@ -0,0 +1,98 @@
1
+ module Sently
2
+ class Sms
3
+ attr_accessor :number, :message, :hid
4
+
5
+ class << self
6
+ attr_accessor :configuration
7
+ attr_accessor :sender
8
+
9
+ def configure
10
+ self.configuration ||= Configuration.new
11
+ yield(configuration)
12
+ self.sender = Sender.new(configuration)
13
+ end
14
+
15
+ #def find(id)
16
+ # response = sender.get(configuration.sms_uri + "/#{id}")
17
+
18
+ # JSON.parse(response.to_s)
19
+ #end
20
+ end
21
+
22
+ def initialize(number = "", message = "", hid = "")
23
+ @number = number
24
+ @message = message
25
+ @hid = hid
26
+ end
27
+
28
+ def deliver_sms
29
+ #raise SentlySMSException.new("Invalid message") unless is_message_valid?(@message)
30
+
31
+ params = { :text => @message.to_s, :to => format_number(@number), :hid => @hid }
32
+
33
+ if production_environment?
34
+ begin
35
+ response = sender.get(configuration.sms_uri, params)
36
+ rescue Exception => e
37
+ response = RestClient::Response.create("Error:#{e.message}", "", {})
38
+ end
39
+ else
40
+ response = RestClient::Response.create('Id:12345', "", {})
41
+ end
42
+
43
+ parse(response.to_s)
44
+ rescue SentlySMSException => exception
45
+ raise exception
46
+ end
47
+
48
+ def format_number(number)
49
+ formatted = number.scan(/\d+/i).join
50
+ return is_number_valid?(formatted) ? formatted : (raise SentlySMSException.new("Phone number (#{number}) is not formatted correctly"))
51
+ end
52
+
53
+ def is_number_valid?(number)
54
+ number.length >= 4 && number[/^.\d+$/]
55
+ end
56
+
57
+ #def is_message_valid?(message)
58
+ # if message_length_check?
59
+ # message_length_range.include?(message.to_s.size)
60
+ # else
61
+ # true
62
+ # end
63
+ #end
64
+
65
+ class SentlySMSException < StandardError; end
66
+
67
+ private
68
+ def sender
69
+ Sently::Sms.sender
70
+ end
71
+
72
+ def configuration
73
+ Sently::Sms.configuration
74
+ end
75
+
76
+ def production_environment?
77
+ configuration.production_environment
78
+ end
79
+
80
+ def parse(str)
81
+ r = {'id' => -1, 'error' => ''}
82
+ begin
83
+ a = str.split(':')
84
+ case a[0]
85
+ when 'Id'
86
+ r['id'] = a[1].to_i
87
+ when 'Error'
88
+ r['error'] = a[1]
89
+ else
90
+ r['error'] = "Error parsing: '#{str}'"
91
+ end
92
+ r
93
+ rescue Exception => e
94
+ {"id"=>-1, "error"=>"json parser error", "response"=>json.to_s}
95
+ end
96
+ end
97
+ end
98
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ # require 'webmock/test_unit'
6
+ begin require 'redgreen'; rescue LoadError; end
7
+ begin require 'turn'; rescue LoadError; end
8
+
9
+ require 'sently-sms'
10
+
11
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
12
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
13
+
14
+ class Test::Unit::TestCase
15
+ # include WebMock
16
+ end
data/test/sms_test.rb ADDED
@@ -0,0 +1,82 @@
1
+ require 'helper'
2
+
3
+ class Sently::SmsTest < Test::Unit::TestCase
4
+ context Sently::Sms do
5
+ setup do
6
+ Sently::Sms.configuration = nil
7
+ Sently::Sms.configure do |config|
8
+ config.username = 'test@sent.ly'
9
+ config.password = '$ecret'
10
+ config.production_environment = false
11
+ end
12
+ end
13
+
14
+ should "format number with dashs" do
15
+ sms = Sently::Sms.new("1-555-5556471", "test")
16
+ assert_equal(sms.format_number("1-555-5556471"), "15555556471")
17
+ end
18
+
19
+ should "format number with brackets" do
20
+ sms = Sently::Sms.new("1(555)5556471", "test")
21
+ assert_equal(sms.format_number("1-555-5556471"), "15555556471")
22
+ end
23
+
24
+ should "format number with brackets and dashs" do
25
+ sms = Sently::Sms.new("1(555)555-6471", "test")
26
+ assert_equal(sms.format_number("1-555-5556471"), "15555556471")
27
+ end
28
+
29
+ should "accept recipient with at least 4 characters" do
30
+ sms = Sently::Sms.new("0123", "test")
31
+ assert_equal(sms.format_number("0123"), "0123")
32
+ end
33
+
34
+ should "reject recipient with less than 4 characters" do
35
+ sms = Sently::Sms.new("123", "test")
36
+ assert_raise(Sently::Sms::SentlySMSException) do
37
+ sms.format_number("123")
38
+ end
39
+ end
40
+
41
+ should "raise on invalidate message length" do
42
+ sms = Sently::Sms.new("123", "Well, if you like burgers give 'em a try sometime. I can't usually get 'em myself because my girlfriend's a vegitarian which pretty much makes me a vegitarian. But I do love the taste of a good burger. Mm-mm-mm. You know what they call a Quarter Pounder with cheese in France?")
43
+
44
+ assert_raise(Sently::Sms::SentlySMSException) do
45
+ sms.deliver_sms
46
+ end
47
+ end
48
+
49
+ should "not production submit sms" do
50
+ sms = Sently::Sms.new("40867729", "test")
51
+ assert_equal(sms.deliver_sms, {"id"=>12345, "error" => ""})
52
+ end
53
+
54
+ should "handle bad response" do
55
+ sms = Sently::Sms.new
56
+ r = sms.send(:parse, "x")
57
+ assert_equal(r, {'id' => -1, 'error' => 'Error parsing: \'x\''})
58
+ end
59
+
60
+ #should "process find" do
61
+ # Sently::Sender.any_instance.stubs(:get).returns('{"credit":5000,"id":"123456","reports":"[]","stat":"ok"}')
62
+
63
+ # assert_equal(Sently::Sms.find('123456'), {"id"=>"123456", "credit"=>5000, "stat"=>"ok", "reports"=>"[]"})
64
+ #end
65
+ end
66
+
67
+ context Sently::Sms do
68
+ setup do
69
+ Sently::Sms.configuration = nil
70
+ Sently::Sms.configure do |config|
71
+ config.username = 'test@sent.ly'
72
+ config.password = '$ecret'
73
+ config.host = 'notrealxxx1234sently.com'
74
+ end
75
+ end
76
+
77
+ should "return DNS error" do
78
+ assert_equal(Sently::Sms.new("1(555)555-6471", "test").deliver_sms["error"], "getaddrinfo")
79
+ end
80
+ end
81
+
82
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sently-sms
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Jerome Lacoste
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-07-15 00:00:00 +02:00
18
+ default_executable: sently
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: mocha
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ version: "0"
42
+ type: :development
43
+ version_requirements: *id002
44
+ - !ruby/object:Gem::Dependency
45
+ name: rest-client
46
+ prerelease: false
47
+ requirement: &id003 !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ segments:
52
+ - 1
53
+ - 6
54
+ - 0
55
+ version: 1.6.0
56
+ type: :runtime
57
+ version_requirements: *id003
58
+ description: Allow to send SMSes using the sent.ly service
59
+ email: jerome.lacoste@gmail.com
60
+ executables:
61
+ - sently
62
+ extensions: []
63
+
64
+ extra_rdoc_files:
65
+ - LICENSE
66
+ - README.rdoc
67
+ files:
68
+ - LICENSE
69
+ - README.rdoc
70
+ - Rakefile
71
+ - VERSION.yml
72
+ - bin/sently
73
+ - lib/sently-sms.rb
74
+ - lib/sently/configuration.rb
75
+ - lib/sently/sender.rb
76
+ - lib/sently/sms.rb
77
+ - test/helper.rb
78
+ - test/sms_test.rb
79
+ has_rdoc: true
80
+ homepage: http://github.com/lacostej/sently-sms
81
+ licenses: []
82
+
83
+ post_install_message:
84
+ rdoc_options: []
85
+
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ requirements: []
103
+
104
+ rubyforge_project:
105
+ rubygems_version: 1.3.6
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Sent.ly SMS gem
109
+ test_files: []
110
+