agilisto-smartcall 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +88 -0
- data/PostInstall.txt +6 -0
- data/README.rdoc +50 -0
- data/Rakefile +26 -0
- data/bin/smartcall +38 -0
- data/config/website.yml.sample +2 -0
- data/lib/smartcall.rb +30 -0
- data/lib/smartcall/soap/default.rb +147 -0
- data/lib/smartcall/soap/default_driver.rb +70 -0
- data/lib/smartcall/soap/smartcall_error.rb +9 -0
- data/lib/smartcall/soap/sms_ws_client.rb +108 -0
- data/lib/smartcall/utility.rb +6 -0
- data/lib/smartcall/utility/options.rb +91 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/test/test_helper.rb +3 -0
- data/test/test_smartcall.rb +11 -0
- data/website/index.html +78 -0
- data/website/index.txt +52 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +159 -0
- data/website/template.html.erb +50 -0
- metadata +92 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
module Smartcall
|
2
|
+
module Soap
|
3
|
+
class SmsWSClient
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def no_authorisation_error
|
7
|
+
raise SmartcallError.new("SmsWSErrors: Unable to Login")
|
8
|
+
end
|
9
|
+
|
10
|
+
def invalid_token_error
|
11
|
+
raise SmartcallError.new("SmsWSErrors: Invalid Token")
|
12
|
+
end
|
13
|
+
|
14
|
+
def invalid_source_address_error
|
15
|
+
raise SmartcallError.new("SmsWSErrors: Invalid Source Address")
|
16
|
+
end
|
17
|
+
|
18
|
+
def invalid_number_error
|
19
|
+
raise SmartcallError.new("SmsWSErrors: InvalidNumber")
|
20
|
+
end
|
21
|
+
|
22
|
+
def not_implemented_error
|
23
|
+
raise SmartcallError.new("SmsWSErrors: Not Implemented")
|
24
|
+
end
|
25
|
+
|
26
|
+
def debug_mode=(value)
|
27
|
+
@@debug_mode = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
@@debug_mode = false
|
32
|
+
|
33
|
+
RESPONSE_HANDLER = { 'Success' => true , 'InvalidSourceAddress' => Proc.new { SmsWSClient.invalid_source_address_error } ,
|
34
|
+
'InvalidToken' => Proc.new { SmsWSClient.invalid_token_error } , 'Failed' => false ,
|
35
|
+
'InvalidNumber' => Proc.new { SmsWSClient.invalid_number_error } }
|
36
|
+
|
37
|
+
DEFAULT_ENDPOINT = "http://www.smartcalltech.co.za/SmsWS/Service.asmx"
|
38
|
+
|
39
|
+
def initialize(username, password, campaign_id, reference)
|
40
|
+
@retry = true
|
41
|
+
@username, @password, @campaign_id, @reference = username, password, campaign_id, reference
|
42
|
+
@obj = SmsWSSoap.new(DEFAULT_ENDPOINT)
|
43
|
+
@obj.wiredump_dev = STDERR if @@debug_mode
|
44
|
+
end
|
45
|
+
|
46
|
+
def send_sms(cell , msg)
|
47
|
+
@cell = cell
|
48
|
+
@msg = msg
|
49
|
+
@token ||= self.login
|
50
|
+
if @token
|
51
|
+
s = SendSMS.new(@token , cell , msg , @reference , @campaign_id)
|
52
|
+
response = @obj.sendSMS(s)
|
53
|
+
return process_response(RESPONSE_HANDLER[response.sendSMSResult])
|
54
|
+
else
|
55
|
+
update_token
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def send_binary_sms(cell, header, part)
|
60
|
+
@cell = cell
|
61
|
+
@token ||= self.login
|
62
|
+
if @token
|
63
|
+
s = SendBinaryString.new(@token, cell, header + part, @reference, @campaign_id)
|
64
|
+
response = @obj.sendBinaryString(s)
|
65
|
+
result = process_response(RESPONSE_HANDLER[response.sendBinaryStringResult])
|
66
|
+
return result
|
67
|
+
else
|
68
|
+
update_token
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def send_wap_link(cell, href, msg)
|
73
|
+
@cell = cell
|
74
|
+
@msg = msg
|
75
|
+
@token ||= self.login
|
76
|
+
if @token
|
77
|
+
s = SendWAPLink.new(@token , cell , href, msg , @reference , @campaign_id)
|
78
|
+
response = @obj.sendWAPLink(s)
|
79
|
+
return process_response(RESPONSE_HANDLER[response.sendWAPLinkResult])
|
80
|
+
else
|
81
|
+
update_token
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def process_response(response_handler)
|
88
|
+
response_handler.class == Proc ? response_handler.call : response_handler
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_token
|
92
|
+
@retry ? @token = self.login : ( raise no_authorisation_error )
|
93
|
+
@retry = false
|
94
|
+
end
|
95
|
+
|
96
|
+
def retry_sms
|
97
|
+
send_sms(@cell , @msg) if @retry
|
98
|
+
@retry = false
|
99
|
+
end
|
100
|
+
|
101
|
+
def login
|
102
|
+
l = Login.new(@username , @password)
|
103
|
+
response = @obj.login(l)
|
104
|
+
response.loginResult != 'false' ? @token = response.token : false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Smartcall
|
5
|
+
module Utility
|
6
|
+
class Options #:nodoc:
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def parse(args)
|
10
|
+
@options = self.default_options
|
11
|
+
parser = OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: smartcall [options] recipient message"
|
13
|
+
opts.separator ""
|
14
|
+
opts.separator "Specific options:"
|
15
|
+
|
16
|
+
opts.on('-u', '--username USERNAME',
|
17
|
+
"Specify the smartcall username (overrides ~/.smartcall setting)") do |username|
|
18
|
+
@options.username = username
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-p', '--password PASSWORD',
|
22
|
+
"Specify the smartcall password (overrides ~/.smartcall setting)") do |password|
|
23
|
+
@options.password = password
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on('-c', '--campaign CAMPAIGN_ID',
|
27
|
+
"Specify the campaign key (overrides ~/.smartcall setting)") do |key|
|
28
|
+
@options.campaign_id = key
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-r', '--reference REFERENCE',
|
32
|
+
"Specify the reference (overrides ~/.smartcall setting)") do |reference|
|
33
|
+
@options.reference = reference
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on('-d', '--debug') do
|
37
|
+
Smartcall::Soap::SmsWSClient.debug_mode = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on_tail('-h', '--help', "Show this message") do
|
41
|
+
puts opts
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on_tail('-v', '--version') do
|
46
|
+
puts "Ruby Smartcall SMS Utility #{Smartcall::VERSION}"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
parser.parse!(args)
|
52
|
+
@options.recipient = ARGV[-2]
|
53
|
+
@options.message = ARGV[-1]
|
54
|
+
|
55
|
+
if (@options.message.nil? || @options.recipient.nil?) && send_message?
|
56
|
+
puts "You must specify a recipient and message!"
|
57
|
+
puts parser
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
return @options
|
62
|
+
|
63
|
+
rescue OptionParser::MissingArgument => e
|
64
|
+
switch_given = e.message.split(':').last.strip
|
65
|
+
puts "The #{switch_given} option requires an argument."
|
66
|
+
puts parser
|
67
|
+
exit
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_options
|
71
|
+
options = OpenStruct.new
|
72
|
+
config_file = File.open(File.join(ENV['HOME'], '.smartcall'))
|
73
|
+
config = YAML.load(config_file)
|
74
|
+
options.username = config['username']
|
75
|
+
options.password = config['password']
|
76
|
+
options.campaign_id = config['campaign_id']
|
77
|
+
options.reference = config['reference']
|
78
|
+
return options
|
79
|
+
rescue Errno::ENOENT
|
80
|
+
return options
|
81
|
+
end
|
82
|
+
|
83
|
+
def send_message?
|
84
|
+
(@options.show_status.nil? &&
|
85
|
+
@options.show_balance.nil?)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
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/smartcall.rb'}"
|
9
|
+
puts "Loading smartcall 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/script/txt2html
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
load File.dirname(__FILE__) + "/../Rakefile"
|
4
|
+
require 'rubyforge'
|
5
|
+
require 'redcloth'
|
6
|
+
require 'syntax/convertors/html'
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
|
10
|
+
version = $hoe.version
|
11
|
+
|
12
|
+
def rubyforge_project_id
|
13
|
+
RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
class Fixnum
|
17
|
+
def ordinal
|
18
|
+
# teens
|
19
|
+
return 'th' if (10..19).include?(self % 100)
|
20
|
+
# others
|
21
|
+
case self % 10
|
22
|
+
when 1: return 'st'
|
23
|
+
when 2: return 'nd'
|
24
|
+
when 3: return 'rd'
|
25
|
+
else return 'th'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Time
|
31
|
+
def pretty
|
32
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def convert_syntax(syntax, source)
|
37
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
38
|
+
end
|
39
|
+
|
40
|
+
if ARGV.length >= 1
|
41
|
+
src, template = ARGV
|
42
|
+
template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
|
43
|
+
else
|
44
|
+
puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
|
45
|
+
exit!
|
46
|
+
end
|
47
|
+
|
48
|
+
template = ERB.new(File.open(template).read)
|
49
|
+
|
50
|
+
title = nil
|
51
|
+
body = nil
|
52
|
+
File.open(src) do |fsrc|
|
53
|
+
title_text = fsrc.readline
|
54
|
+
body_text_template = fsrc.read
|
55
|
+
body_text = ERB.new(body_text_template).result(binding)
|
56
|
+
syntax_items = []
|
57
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
58
|
+
ident = syntax_items.length
|
59
|
+
element, syntax, source = $1, $2, $3
|
60
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
61
|
+
"syntax-temp-#{ident}"
|
62
|
+
}
|
63
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
64
|
+
body = RedCloth.new(body_text).to_html
|
65
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
66
|
+
end
|
67
|
+
stat = File.stat(src)
|
68
|
+
created = stat.ctime
|
69
|
+
modified = stat.mtime
|
70
|
+
|
71
|
+
$stdout << template.result(binding)
|
data/test/test_helper.rb
ADDED
data/website/index.html
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>
|
8
|
+
smartcall
|
9
|
+
</title>
|
10
|
+
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
|
+
<style>
|
12
|
+
|
13
|
+
</style>
|
14
|
+
<script type="text/javascript">
|
15
|
+
window.onload = function() {
|
16
|
+
settings = {
|
17
|
+
tl: { radius: 10 },
|
18
|
+
tr: { radius: 10 },
|
19
|
+
bl: { radius: 10 },
|
20
|
+
br: { radius: 10 },
|
21
|
+
antiAlias: true,
|
22
|
+
autoPad: true,
|
23
|
+
validTags: ["div"]
|
24
|
+
}
|
25
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
26
|
+
versionBox.applyCornersToAll();
|
27
|
+
}
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="main">
|
32
|
+
|
33
|
+
<h1>smartcall</h1>
|
34
|
+
<div class="sidebar">
|
35
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/smartcall"; return false'>
|
36
|
+
<p>Get Version</p>
|
37
|
+
<a href="http://rubyforge.org/projects/smartcall" class="numbers">0.0.1</a>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
<h2>What</h2>
|
41
|
+
<p>Gem to send text messages through Smartcall Technology Solutions (South African aggregator). http://www.smartcalltech.co.za</p>
|
42
|
+
<h2>Installing</h2>
|
43
|
+
<p><pre class='syntax'><span class="ident">sudo</span> <span class="ident">gem</span> <span class="ident">install</span> <span class="ident">smartcall</span></pre></p>
|
44
|
+
<h2>The basics</h2>
|
45
|
+
<p><pre class='syntax'>
|
46
|
+
|
47
|
+
<span class="ident">require</span> <span class="punct">'</span><span class="string">smartcall</span><span class="punct">'</span>
|
48
|
+
|
49
|
+
<span class="ident">api</span> <span class="punct">=</span> <span class="constant">Smartcall</span><span class="punct">::</span><span class="constant">API</span><span class="punct">.</span><span class="ident">new</span><span class="punct">(<</span><span class="constant">USERNAME</span><span class="punct">>,</span> <span class="punct"><</span><span class="constant">PASSWORD</span><span class="punct">>,</span> <span class="punct"><</span><span class="constant">CAMPAIGN_ID</span><span class="punct">>,</span> <span class="punct"><</span><span class="constant">REFERENCE</span><span class="punct">>)</span>
|
50
|
+
<span class="ident">api</span><span class="punct">.</span><span class="ident">send_message</span><span class="punct">("</span><span class="string">0825559629</span><span class="punct">",</span> <span class="punct">"</span><span class="string">Hello World</span><span class="punct">")</span>
|
51
|
+
</pre></p>
|
52
|
+
<h2>Forum</h2>
|
53
|
+
<p><a href="http://groups.google.com/group/smartcall">http://groups.google.com/group/smartcall</a></p>
|
54
|
+
<p><span class="caps">TODO</span> – create Google Group – smartcall</p>
|
55
|
+
<h2>How to submit patches</h2>
|
56
|
+
<p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people’s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
|
57
|
+
<ul>
|
58
|
+
<li>github: <a href="http://github.com/agilisto/smartcall/tree/master">http://github.com/agilisto/smartcall/tree/master</a></li>
|
59
|
+
</ul>
|
60
|
+
<pre>git clone git://github.com/agilisto/smartcall.git</pre>
|
61
|
+
<h3>Build and test instructions</h3>
|
62
|
+
<pre>cd smartcall
|
63
|
+
rake test
|
64
|
+
rake install_gem</pre>
|
65
|
+
<h2>License</h2>
|
66
|
+
<p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
|
67
|
+
<h2>Contact</h2>
|
68
|
+
<p>Comments are welcome. Send an email to <a href="mailto:armanddp@agilisto.com">Armand du Plessis</a> email via the <a href="http://groups.google.com/group/smartcall">forum</a></p>
|
69
|
+
<p class="coda">
|
70
|
+
<a href="FIXME email">FIXME full name</a>, 1st July 2009<br>
|
71
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
72
|
+
</p>
|
73
|
+
</div>
|
74
|
+
|
75
|
+
<!-- insert site tracking codes here, like Google Urchin -->
|
76
|
+
|
77
|
+
</body>
|
78
|
+
</html>
|
data/website/index.txt
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
h1. smartcall
|
2
|
+
|
3
|
+
|
4
|
+
h2. What
|
5
|
+
|
6
|
+
Gem to send text messages through Smartcall Technology Solutions (South African aggregator). http://www.smartcalltech.co.za
|
7
|
+
|
8
|
+
h2. Installing
|
9
|
+
|
10
|
+
<pre syntax="ruby">sudo gem install smartcall</pre>
|
11
|
+
|
12
|
+
h2. The basics
|
13
|
+
|
14
|
+
<pre syntax="ruby">
|
15
|
+
|
16
|
+
require 'smartcall'
|
17
|
+
|
18
|
+
api = Smartcall::API.new(<USERNAME>, <PASSWORD>, <CAMPAIGN_ID>, <REFERENCE>)
|
19
|
+
api.send_message("0825559629", "Hello World")
|
20
|
+
</pre>
|
21
|
+
|
22
|
+
|
23
|
+
h2. Forum
|
24
|
+
|
25
|
+
"http://groups.google.com/group/smartcall":http://groups.google.com/group/smartcall
|
26
|
+
|
27
|
+
TODO - create Google Group - smartcall
|
28
|
+
|
29
|
+
h2. How to submit patches
|
30
|
+
|
31
|
+
Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
|
32
|
+
|
33
|
+
* github: "http://github.com/agilisto/smartcall/tree/master":http://github.com/agilisto/smartcall/tree/master
|
34
|
+
|
35
|
+
<pre>git clone git://github.com/agilisto/smartcall.git</pre>
|
36
|
+
|
37
|
+
|
38
|
+
h3. Build and test instructions
|
39
|
+
|
40
|
+
<pre>cd smartcall
|
41
|
+
rake test
|
42
|
+
rake install_gem</pre>
|
43
|
+
|
44
|
+
|
45
|
+
h2. License
|
46
|
+
|
47
|
+
This code is free to use under the terms of the MIT license.
|
48
|
+
|
49
|
+
h2. Contact
|
50
|
+
|
51
|
+
Comments are welcome. Send an email to "Armand du Plessis":mailto:armanddp@agilisto.com email via the "forum":http://groups.google.com/group/smartcall
|
52
|
+
|