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