smsinabox 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/History.txt +13 -0
- data/PostInstall.txt +10 -0
- data/README.rdoc +47 -0
- data/Rakefile +29 -0
- data/TODO.txt +14 -0
- data/bin/sms-credit +38 -0
- data/bin/sms-send +76 -0
- data/bin/sms-setup +54 -0
- data/lib/smsinabox.rb +143 -0
- data/lib/smsinabox/configuration.rb +55 -0
- data/lib/smsinabox/delivery_report.rb +49 -0
- data/lib/smsinabox/exceptions.rb +9 -0
- data/lib/smsinabox/message.rb +21 -0
- data/lib/smsinabox/reply.rb +27 -0
- data/lib/smsinabox/sent_message.rb +32 -0
- data/lib/smsinabox/sms.rb +4 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/smsinabox.gemspec +101 -0
- data/spec/delivery_report_spec.rb +40 -0
- data/spec/fixtures/sendparam_response.xml +29 -0
- data/spec/message_spec.rb +47 -0
- data/spec/reply_spec.rb +36 -0
- data/spec/sent_message_spec.rb +40 -0
- data/spec/smsinabox_spec.rb +80 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +40 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +9 -0
- metadata +137 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module Smsinabox
|
2
|
+
class DeliveryReport
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Generate a delivery report from a nokogiri response
|
7
|
+
def from_response( nokogiri_xml )
|
8
|
+
response = new
|
9
|
+
|
10
|
+
# basic send_info stuff
|
11
|
+
response.event_id = nokogiri_xml.xpath('/api_result/send_info/eventid/text()').to_s.to_i
|
12
|
+
response.credits = nokogiri_xml.xpath('/api_result/send_info/credits/text()').to_s.to_i
|
13
|
+
response.fail_count = nokogiri_xml.xpath('/api_result/send_info/msgs_failed/text()').to_s.to_i
|
14
|
+
response.success_count = nokogiri_xml.xpath('/api_result/send_info/msgs_success/text()').to_s.to_i
|
15
|
+
|
16
|
+
# failures
|
17
|
+
nokogiri_xml.xpath('/api_result/entries_failed').each do |node|
|
18
|
+
response.failures << {
|
19
|
+
:numto => node.xpath('./numto/text()').to_s,
|
20
|
+
:customerid => node.xpath('./customerid/text()').to_s,
|
21
|
+
:reason => node.xpath('./reason/text()').to_s
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# successes
|
26
|
+
nokogiri_xml.xpath('/api_result/entries_success').each do |node|
|
27
|
+
response.successes << {
|
28
|
+
:numto => node.xpath('./numto/text()').to_s,
|
29
|
+
:customerid => node.xpath('./customerid/text()').to_s
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
response
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :event_id, :credits, :fail_count, :success_count, :failures, :successes
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
@fail_count = 0
|
42
|
+
@success_count = 0
|
43
|
+
|
44
|
+
@failures = []
|
45
|
+
@successes = []
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Smsinabox
|
2
|
+
|
3
|
+
class Message
|
4
|
+
|
5
|
+
attr_accessor :recipient
|
6
|
+
attr_accessor :body
|
7
|
+
|
8
|
+
def initialize( options = {} )
|
9
|
+
@recipient = options.delete(:recipient)
|
10
|
+
@body = options.delete(:body)
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid?
|
14
|
+
!( @recipient.nil? || @body.nil? )
|
15
|
+
end
|
16
|
+
|
17
|
+
def body
|
18
|
+
@body.gsub( /\n/, '|' )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Smsinabox
|
2
|
+
class Reply
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Generate a reply from the nokogiri response fragment
|
7
|
+
def from_response( nokogiri_xml )
|
8
|
+
reply = new
|
9
|
+
|
10
|
+
reply.id = nokogiri_xml.xpath('./replyid/text()').to_s.to_i
|
11
|
+
reply.event_id = nokogiri_xml.xpath('./eventid/text()').to_s.to_i
|
12
|
+
reply.from = nokogiri_xml.xpath('./numfrom/text()').to_s
|
13
|
+
reply.message = nokogiri_xml.xpath('./receiveddata/text()').to_s
|
14
|
+
reply.sent_id = nokogiri_xml.xpath('./sentid/text()').to_s.to_i
|
15
|
+
reply.original = nokogiri_xml.xpath('./sentdata/text()').to_s
|
16
|
+
reply.sent_customer_id = nokogiri_xml.xpath('./sentcustomerid/text()').to_s
|
17
|
+
reply.received = nokogiri_xml.xpath('./received/text()').to_s
|
18
|
+
reply.sent = nokogiri_xml.xpath('./sentdatetime/text()').to_s
|
19
|
+
|
20
|
+
reply
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :id, :event_id, :from, :message, :sent_id, :original,
|
25
|
+
:sent_customer_id, :received, :sent
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Smsinabox
|
2
|
+
class SentMessage
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Generate a #SentMessage from a response xml fragment
|
7
|
+
def from_response( nokogiri_xml )
|
8
|
+
msg = new
|
9
|
+
|
10
|
+
msg.id = nokogiri_xml.xpath('./sentid/text()').to_s.to_i
|
11
|
+
msg.change_id = nokogiri_xml.xpath('./changeid/text()').to_s.to_i
|
12
|
+
msg.event_id = nokogiri_xml.xpath('./eventid/text()').to_s.to_i
|
13
|
+
msg.type = nokogiri_xml.xpath('./smstype/text()').to_s
|
14
|
+
msg.to = nokogiri_xml.xpath('./numto/text()').to_s
|
15
|
+
msg.message = nokogiri_xml.xpath('./data/text()').to_s
|
16
|
+
msg.flash = nokogiri_xml.xpath('./flash/text()').to_s == 'true'
|
17
|
+
msg.customer_id = nokogiri_xml.xpath('./customerid/text()').to_s
|
18
|
+
msg.status = nokogiri_xml.xpath('./status/text()').to_s
|
19
|
+
msg.status_date = nokogiri_xml.xpath('./statusdate/text()').to_s
|
20
|
+
|
21
|
+
msg
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :id, :change_id, :event_id, :type, :to, :message, :flash,
|
26
|
+
:customer_id, :status, :status_date
|
27
|
+
|
28
|
+
def delivered?
|
29
|
+
@status == 'DELIVRD'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/smsinabox.rb'}"
|
9
|
+
puts "Loading smsinabox gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/smsinabox.gemspec
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{smsinabox}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["kenneth.kalmer@gmail.com"]
|
12
|
+
s.date = %q{2010-06-18}
|
13
|
+
s.description = %q{Ruby API for sending text messages via http://www.smsinabox.co.za}
|
14
|
+
s.email = %q{kenneth.kalmer@gmail.com}
|
15
|
+
s.executables = ["sms-credit", "sms-send", "sms-setup"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"History.txt",
|
18
|
+
"PostInstall.txt",
|
19
|
+
"README.rdoc",
|
20
|
+
"TODO.txt"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".gitignore",
|
24
|
+
"History.txt",
|
25
|
+
"PostInstall.txt",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"TODO.txt",
|
29
|
+
"bin/sms-credit",
|
30
|
+
"bin/sms-send",
|
31
|
+
"bin/sms-setup",
|
32
|
+
"lib/smsinabox.rb",
|
33
|
+
"lib/smsinabox/configuration.rb",
|
34
|
+
"lib/smsinabox/delivery_report.rb",
|
35
|
+
"lib/smsinabox/exceptions.rb",
|
36
|
+
"lib/smsinabox/message.rb",
|
37
|
+
"lib/smsinabox/reply.rb",
|
38
|
+
"lib/smsinabox/sent_message.rb",
|
39
|
+
"lib/smsinabox/sms.rb",
|
40
|
+
"script/console",
|
41
|
+
"script/destroy",
|
42
|
+
"script/generate",
|
43
|
+
"smsinabox.gemspec",
|
44
|
+
"spec/delivery_report_spec.rb",
|
45
|
+
"spec/fixtures/sendparam_response.xml",
|
46
|
+
"spec/message_spec.rb",
|
47
|
+
"spec/reply_spec.rb",
|
48
|
+
"spec/sent_message_spec.rb",
|
49
|
+
"spec/smsinabox_spec.rb",
|
50
|
+
"spec/spec.opts",
|
51
|
+
"spec/spec_helper.rb",
|
52
|
+
"tasks/deployment.rake",
|
53
|
+
"tasks/environment.rake",
|
54
|
+
"tasks/rspec.rake",
|
55
|
+
"tasks/website.rake"
|
56
|
+
]
|
57
|
+
s.homepage = %q{http://github.com/kennethkalmer/smsinabox}
|
58
|
+
s.post_install_message = %q{
|
59
|
+
For more information on smsinabox, see http://www.opensourcery.co.za/smsinabox
|
60
|
+
|
61
|
+
Setup your account by running sms-setup now. You can then use the following
|
62
|
+
commands to interact with SMS in a Box:
|
63
|
+
|
64
|
+
sms-send: Send SMS messages
|
65
|
+
sms-credit: Quick overview of the credit available
|
66
|
+
sms-replies: Quick access to your replies
|
67
|
+
sms-setup: To change the account details
|
68
|
+
}
|
69
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
70
|
+
s.require_paths = ["lib"]
|
71
|
+
s.rubygems_version = %q{1.3.5}
|
72
|
+
s.summary = %q{Ruby API for sending text messages via http://www.smsinabox.co.za}
|
73
|
+
s.test_files = [
|
74
|
+
"spec/delivery_report_spec.rb",
|
75
|
+
"spec/message_spec.rb",
|
76
|
+
"spec/reply_spec.rb",
|
77
|
+
"spec/sent_message_spec.rb",
|
78
|
+
"spec/smsinabox_spec.rb",
|
79
|
+
"spec/spec_helper.rb"
|
80
|
+
]
|
81
|
+
|
82
|
+
if s.respond_to? :specification_version then
|
83
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
84
|
+
s.specification_version = 3
|
85
|
+
|
86
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
87
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.3"])
|
88
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
89
|
+
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
90
|
+
else
|
91
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
92
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
93
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
94
|
+
end
|
95
|
+
else
|
96
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.3"])
|
97
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
98
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Smsinabox::DeliveryReport do
|
4
|
+
before(:each) do
|
5
|
+
f = File.open( File.dirname(__FILE__) + '/fixtures/sendparam_response.xml' )
|
6
|
+
sample_response = Nokogiri::XML( f )
|
7
|
+
|
8
|
+
@report = Smsinabox::DeliveryReport.from_response( sample_response )
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have an event id" do
|
12
|
+
@report.event_id.should be(27105067)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should have credits" do
|
16
|
+
@report.credits.should be(39763)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should know how many failed" do
|
20
|
+
@report.fail_count.should be(1)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should know how many succeeded" do
|
24
|
+
@report.success_count.should be(3)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have a list of failures" do
|
28
|
+
@report.failures.should_not be_empty
|
29
|
+
|
30
|
+
f = @report.failures.first
|
31
|
+
f.should == { :numto => '', :customerid => '', :reason => 'numto invalid' }
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have a list of successes" do
|
35
|
+
@report.successes.should_not be_empty
|
36
|
+
|
37
|
+
s = @report.successes.first
|
38
|
+
s.should == { :numto => '27832297941', :customerid => 'UnqiueValue1' }
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<api_result>
|
2
|
+
<entries_failed>
|
3
|
+
<numto />
|
4
|
+
<customerid />
|
5
|
+
<reason>numto invalid</reason>
|
6
|
+
</entries_failed>
|
7
|
+
<entries_success>
|
8
|
+
<numto>27832297941</numto>
|
9
|
+
<customerid>UnqiueValue1</customerid>
|
10
|
+
</entries_success>
|
11
|
+
<entries_success>
|
12
|
+
<numto>27832297941</numto>
|
13
|
+
<customerid>UnqiueValue1</customerid>
|
14
|
+
</entries_success>
|
15
|
+
<entries_success>
|
16
|
+
<numto>27832297941</numto>
|
17
|
+
<customerid>d47e1efd-5e4f-4832-ba7f-07f35d8c10f9</customerid>
|
18
|
+
</entries_success>
|
19
|
+
<send_info>
|
20
|
+
<eventid>27105067</eventid>
|
21
|
+
<credits>39763</credits>
|
22
|
+
<msgs_success>3</msgs_success>
|
23
|
+
<msgs_failed>1</msgs_failed>
|
24
|
+
</send_info>
|
25
|
+
<call_result>
|
26
|
+
<result>True</result>
|
27
|
+
<error />
|
28
|
+
</call_result>
|
29
|
+
</api_result>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe Smsinabox::Message do
|
4
|
+
|
5
|
+
it "should accept a recipient" do
|
6
|
+
message = Smsinabox::Message.new( :recipient => '5555555555' )
|
7
|
+
message.recipient.should eql('5555555555')
|
8
|
+
|
9
|
+
message = Smsinabox::Message.new
|
10
|
+
message.recipient = '5555555555'
|
11
|
+
message.recipient.should eql('5555555555')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should accept a body" do
|
15
|
+
message = Smsinabox::Message.new( :body => 'text' )
|
16
|
+
message.body.should eql('text')
|
17
|
+
|
18
|
+
message = Smsinabox::Message.new
|
19
|
+
message.body = 'text'
|
20
|
+
message.body.should eql('text')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should only be valid if both the recipient and body is set" do
|
24
|
+
message = Smsinabox::Message.new
|
25
|
+
message.should_not be_valid
|
26
|
+
|
27
|
+
message.recipient = '5555555555'
|
28
|
+
message.should_not be_valid
|
29
|
+
|
30
|
+
message.body = 'text'
|
31
|
+
message.should be_valid
|
32
|
+
|
33
|
+
message.recipient = nil
|
34
|
+
message.should_not be_valid
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should replace newlines with pipe (|) characters" do
|
38
|
+
message = Smsinabox::Message.new
|
39
|
+
message.body = <<-EOF
|
40
|
+
This
|
41
|
+
needs
|
42
|
+
pipes
|
43
|
+
EOF
|
44
|
+
|
45
|
+
message.body.should match( /This|\s+needs|\s+pipes/ )
|
46
|
+
end
|
47
|
+
end
|
data/spec/reply_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Smsinabox::Reply do
|
4
|
+
before(:each) do
|
5
|
+
xml = <<-EOF
|
6
|
+
<api_result>
|
7
|
+
<data>
|
8
|
+
<replyid>3903103</replyid>
|
9
|
+
<eventid>33368123</eventid>
|
10
|
+
<numfrom>27123456789</numfrom>
|
11
|
+
<receiveddata>Bar</receiveddata>
|
12
|
+
<sentid>339548269</sentid>
|
13
|
+
<sentdata>Foo</sentdata>
|
14
|
+
<sentcustomerid/>
|
15
|
+
<received>10/Aug/2009 00:09:46</received>
|
16
|
+
<sentdatetime>07/Aug/2009 13:51:48</sentdatetime>
|
17
|
+
</data>
|
18
|
+
</api_result>
|
19
|
+
EOF
|
20
|
+
@xml_reply = Nokogiri::XML( xml )
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should parse from response data" do
|
24
|
+
reply = Smsinabox::Reply.from_response( @xml_reply.xpath('/api_result/data').first )
|
25
|
+
|
26
|
+
reply.id.should == 3903103
|
27
|
+
reply.event_id.should == 33368123
|
28
|
+
reply.from.should == '27123456789'
|
29
|
+
reply.message.should == 'Bar'
|
30
|
+
reply.sent_id.should == 339548269
|
31
|
+
reply.original.should == 'Foo'
|
32
|
+
reply.sent_customer_id.should == ''
|
33
|
+
reply.received.should == '10/Aug/2009 00:09:46'
|
34
|
+
reply.sent.should == '07/Aug/2009 13:51:48'
|
35
|
+
end
|
36
|
+
end
|