smesser 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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +79 -0
- data/Rakefile +11 -0
- data/bin/smesser +76 -0
- data/lib/smesser/provider.rb +81 -0
- data/lib/smesser/version.rb +3 -0
- data/lib/smesser.rb +116 -0
- data/providers/o2_ie.rb +50 -0
- data/providers/vodafone_ie.rb +65 -0
- data/smesser.gemspec +19 -0
- data/test/test_smesser.rb +16 -0
- metadata +90 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 JJ Buckley
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# SMeSser
|
2
|
+
|
3
|
+
For using your provider's WebText programatically.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'smesser'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install smesser
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Smesser is generally supposed to be used as part of a more useful application,
|
22
|
+
for sending (free!) SMSs.
|
23
|
+
|
24
|
+
It does, however, come with a little command-line application (`smesser`). Try
|
25
|
+
`smesser -h` when it's installed.
|
26
|
+
|
27
|
+
## Configuration
|
28
|
+
|
29
|
+
You can program Smesser programatically, but it will also
|
30
|
+
have a look for some configuration files, and determine the
|
31
|
+
username/password/provider from there. These config files are loaded, in order,
|
32
|
+
if they exist:
|
33
|
+
|
34
|
+
* /etc/smesserrc
|
35
|
+
* /usr/local/etc/smesserrc
|
36
|
+
* ~/.smesserrc
|
37
|
+
|
38
|
+
*HINT*: If you're a command-line type of person (which I presume yuo are, as
|
39
|
+
you're reading this), then add a "contacts" hash to your configuration file.
|
40
|
+
These can be used as aliases instead of phone number.
|
41
|
+
|
42
|
+
Here's a sample configuration file, which you'd keep as ~/.smesserrc
|
43
|
+
|
44
|
+
```yaml
|
45
|
+
provider: o2.ie
|
46
|
+
username: "0861234567" # <-- Ensure a string, or the leading 0 could vanish!
|
47
|
+
password: secret
|
48
|
+
contacts:
|
49
|
+
mom: "+3538712345678"
|
50
|
+
dad: "+1123456788"
|
51
|
+
lisa: "08517171717"
|
52
|
+
```
|
53
|
+
|
54
|
+
## Providers
|
55
|
+
|
56
|
+
The core of Smesser is done by little [Mechanize][mechanize] agents, called
|
57
|
+
Providers, that know how to log in (as you) to a specific website, fill in a
|
58
|
+
form, and submit it.
|
59
|
+
|
60
|
+
The only requirements for a Provider is that it responds to `login` and `send`.
|
61
|
+
By subclassing Smesser::Provider, you get a couple of convenience methods to
|
62
|
+
help you create your own.
|
63
|
+
|
64
|
+
Have a look at bundled providers for info on how to write your own provider.
|
65
|
+
|
66
|
+
Currently, there's
|
67
|
+
|
68
|
+
* vodafone.ie
|
69
|
+
* o2.ie
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
1. Fork it
|
74
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
75
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
76
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
77
|
+
5. Create new Pull Request
|
78
|
+
|
79
|
+
[mechanize]: http://mechanize.rubyforge.org/
|
data/Rakefile
ADDED
data/bin/smesser
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../lib/smesser'))
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
$options = {}
|
6
|
+
|
7
|
+
OptionParser.new do |opts|
|
8
|
+
opts.banner = "Usage: smesser [options]"
|
9
|
+
|
10
|
+
opts.on('-c', '--config FILE', String, 'Use a specific config file') do |f|
|
11
|
+
if File.exists?
|
12
|
+
Smesser.config_files << f
|
13
|
+
else
|
14
|
+
puts "Can't open file #{f}"
|
15
|
+
exit 3
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('-m', '--message MESSAGE', String, 'Your message. If blank, reads from STDIN.') do |m|
|
20
|
+
$options[:message] = m
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('-P', '--provider PROVIDER', String, 'Choose a provider (list with --list)') do |p|
|
24
|
+
$options[:provider] = p
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('-u', '--username USERNAME', String, 'Specify a username to log in with') do |u|
|
28
|
+
$options[:username] = u
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on('-p', '--password PASSWORD', String, 'Specify a password to log in with') do |p|
|
32
|
+
$options[:password] = p
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-L', '--list', 'Show all known providers, and exit') do
|
36
|
+
Smesser.print_providers
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on('-v', '--verbose', 'Be more verbose') do
|
41
|
+
Smesser.log.level = Logger::INFO
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on('-d', '--debug', 'Debug the application') do
|
45
|
+
Smesser.log.level = Logger::DEBUG
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on('-n', '--dry-run', "Don't actually send the message") do
|
49
|
+
Smesser.configuration[:dryrun] = true
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
53
|
+
puts opts.to_s
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end.parse!(ARGV)
|
57
|
+
|
58
|
+
if ARGV.empty?
|
59
|
+
puts "You didn't enter any recipients!"
|
60
|
+
exit 1
|
61
|
+
end
|
62
|
+
$options[:recipients] = []
|
63
|
+
$options[:recipients] << ARGV.shift until ARGV.empty?
|
64
|
+
|
65
|
+
if $options[:message].nil?
|
66
|
+
print "Type your message below, and finish with ^D:\n> "
|
67
|
+
$options[:message] = ARGF.read.chomp
|
68
|
+
end
|
69
|
+
|
70
|
+
print "Sending... "
|
71
|
+
result = Smesser.send_message($options)
|
72
|
+
|
73
|
+
puts "#{result[:remaining]} remaining" if result[:remaining]
|
74
|
+
puts result[:message] if result[:message]
|
75
|
+
puts result[:status]
|
76
|
+
exit -1 unless result[:status] == "OK"
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
require 'smesser'
|
3
|
+
|
4
|
+
module Smesser
|
5
|
+
class Provider
|
6
|
+
class << self
|
7
|
+
attr_accessor :description
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :username, :password
|
11
|
+
|
12
|
+
def self.paths
|
13
|
+
@paths ||= [File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'providers'))]
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load_all
|
17
|
+
Smesser.log.debug("Loading all provider files in #{paths.inspect}")
|
18
|
+
paths.each do |path|
|
19
|
+
Dir["#{path}/*.rb"].each do |f|
|
20
|
+
require f
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(username, password)
|
26
|
+
@username = username
|
27
|
+
@password = password
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(address)
|
31
|
+
log.debug("Getting #{address}")
|
32
|
+
agent.get(address) unless agent.page and agent.page.uri == URI.parse(address)
|
33
|
+
log.debug("Got #{address} (#{page.code})")
|
34
|
+
page.code
|
35
|
+
end
|
36
|
+
|
37
|
+
def post_form(spec, &block)
|
38
|
+
spec = { :name => spec } if spec.is_a? String
|
39
|
+
log.debug("Looking for form with #{spec.inspect}")
|
40
|
+
form = page.form_with(spec)
|
41
|
+
raise "Form not found: #{spec.inspect} on #{page.uri} (forms: #{page.forms.map(&:name).inspect})" unless form
|
42
|
+
yield form
|
43
|
+
log.debug("Submitting form: #{form.action} #{form.request_data}")
|
44
|
+
form.submit
|
45
|
+
log.debug("Submitted #{form.action} (#{page.code})")
|
46
|
+
page.code
|
47
|
+
end
|
48
|
+
|
49
|
+
def click(spec)
|
50
|
+
spec = { :text => spec } if spec.is_a? String
|
51
|
+
log.debug("Looking for a form with #{spec.inspect}")
|
52
|
+
link = page.link_with(spec)
|
53
|
+
raise "Link not found: #{spec.inspect} on #{page.uri} (links: #{page.links.map(&:text).inspect})" unless link
|
54
|
+
log.debug("Clicking link #{link.text} => #{link.href}")
|
55
|
+
link.click
|
56
|
+
log.debug("Clicked link #{link.href} (#{page.code})")
|
57
|
+
page.code
|
58
|
+
end
|
59
|
+
|
60
|
+
def login
|
61
|
+
raise "You need to override #{this}#login"
|
62
|
+
end
|
63
|
+
|
64
|
+
def send(message, *recipients)
|
65
|
+
raise "You need to override #{this}#send"
|
66
|
+
end
|
67
|
+
|
68
|
+
def agent
|
69
|
+
@agent ||= Mechanize.new
|
70
|
+
end
|
71
|
+
|
72
|
+
def page
|
73
|
+
agent.page
|
74
|
+
end
|
75
|
+
|
76
|
+
def log
|
77
|
+
Smesser.log
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/lib/smesser.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'logger'
|
4
|
+
require "smesser/version"
|
5
|
+
|
6
|
+
module Smesser
|
7
|
+
autoload :Provider, 'smesser/provider'
|
8
|
+
|
9
|
+
def self.config_files
|
10
|
+
@configfiles ||= [
|
11
|
+
"/etc/smesserrc",
|
12
|
+
"/usr/local/etc/smesserrc",
|
13
|
+
"~/.smesserrc"
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
# The easiest way to send an SMS.
|
18
|
+
#
|
19
|
+
# Accepts the following options:
|
20
|
+
#
|
21
|
+
# provider:: The name of the provider to use (see `providers`)
|
22
|
+
# username:: The username to log in with
|
23
|
+
# password:: The password to log in with
|
24
|
+
# message:: The message
|
25
|
+
# recipients:: An array of recipients. If Smesser has `contacts` configured,
|
26
|
+
# then you can use aliases here.
|
27
|
+
# retry:: The number of times to attempt sending. Default is 1.
|
28
|
+
#
|
29
|
+
# If any are missing, Smesser's configuration will be checked for a suitable
|
30
|
+
# value.
|
31
|
+
#
|
32
|
+
# Returns a hash, with (at least)
|
33
|
+
#
|
34
|
+
# status:: 'OK' if all went well, 'Failed' otherwise
|
35
|
+
#
|
36
|
+
# ...and any additional provider specific return values. A common one might be
|
37
|
+
# `:remaining`, to indicate the number of free SMSs left with the provider.
|
38
|
+
def self.send_message(options = {})
|
39
|
+
options.dup.each { |k, v| options[k.to_sym] = options.delete(k) if k.is_a?(String) }
|
40
|
+
|
41
|
+
args = configuration.merge(options)
|
42
|
+
log.debug("Sending message: args = #{args.inspect}")
|
43
|
+
|
44
|
+
provider = providers[args[:provider]].new(args[:username], args[:password])
|
45
|
+
log.debug("Provider: #{provider.inspect}")
|
46
|
+
|
47
|
+
recipients = lookup_contacts(args[:recipients])
|
48
|
+
log.debug("Recipients: #{recipients.inspect}")
|
49
|
+
|
50
|
+
unless provider.logged_in?
|
51
|
+
log.debug("Logging in... (#{args[:username]})")
|
52
|
+
provider.login unless args[:dryrun]
|
53
|
+
end
|
54
|
+
|
55
|
+
log.info("Message: #{args[:message].inspect}")
|
56
|
+
|
57
|
+
result = {}
|
58
|
+
|
59
|
+
if args[:dryrun] or provider.send(args[:message], *recipients)
|
60
|
+
log.info "Message sent."
|
61
|
+
result[:code] = "OK"
|
62
|
+
result[:remaining] = provider.remaining if provider.respond_to?(:remaining)
|
63
|
+
elsif args[:retry] and args[:retry] > 0
|
64
|
+
log.info "Failed, trying again... (#{args[:retry]})"
|
65
|
+
args[:retry] -= 1
|
66
|
+
return send_message(args)
|
67
|
+
else
|
68
|
+
log.info "Failed!"
|
69
|
+
result[:code] = "Failed"
|
70
|
+
end
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.log
|
76
|
+
return @log if @log
|
77
|
+
@log = Logger.new(STDOUT)
|
78
|
+
@log.level = Logger::WARN
|
79
|
+
@log
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.configuration
|
83
|
+
@configuration ||= load_config!
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.providers
|
87
|
+
Provider.load_all
|
88
|
+
@providers ||= {}
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.load_config!
|
92
|
+
config = {}
|
93
|
+
config_files.each do |f|
|
94
|
+
if File.exists?(path = File.expand_path(f))
|
95
|
+
config.merge!(YAML.load(File.read(path)))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
config.dup.each { |k, v| config[k.to_sym] = v if k.is_a?(String) }
|
99
|
+
config
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.lookup_contacts(recipients)
|
103
|
+
contacts = configuration[:contacts]
|
104
|
+
return recipients unless contacts
|
105
|
+
recipients.map do |r|
|
106
|
+
log.debug "#{r} => #{contacts[r]}" if contacts[r]
|
107
|
+
contacts[r] || r
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.print_providers(io = STDOUT)
|
112
|
+
providers.each do |k, v|
|
113
|
+
io.puts "#{k}: #{v.description || 'No description'}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/providers/o2_ie.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'smesser/provider'
|
2
|
+
|
3
|
+
class O2Ie < Smesser::Provider
|
4
|
+
@@start_url = "http://www.o2online.ie/o2/"
|
5
|
+
@@send_action = "http://messaging.o2online.ie/smscenter_send.osp"
|
6
|
+
@@send_delay = 2
|
7
|
+
|
8
|
+
self.description = "www.o2.ie (400 free texts per month)"
|
9
|
+
|
10
|
+
def logged_in?
|
11
|
+
get @@start_url
|
12
|
+
!!page.link_with(:text => 'Logout of o2.ie')
|
13
|
+
end
|
14
|
+
|
15
|
+
def login
|
16
|
+
get(@@start_url)
|
17
|
+
click('Login to o2.ie')
|
18
|
+
post_form('o2login_form') do |form|
|
19
|
+
form["IDToken1"] = @username
|
20
|
+
form["IDToken2"] = @password
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def send(message, *recipients)
|
25
|
+
get_webtext_page
|
26
|
+
post_form('form_WebtextSend') do |form|
|
27
|
+
form["SMSTo"] = recipients.join(", ")
|
28
|
+
form["SMSText"] = message
|
29
|
+
form.action = @@send_action
|
30
|
+
sleep(@@send_delay)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def remaining
|
35
|
+
get_webtext_page
|
36
|
+
if span = page.at("#spn_WebtextFree")
|
37
|
+
span.inner_text
|
38
|
+
else
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_webtext_page
|
44
|
+
login unless logged_in?
|
45
|
+
get(@@start_url)
|
46
|
+
click('Send a webtext')
|
47
|
+
get(page.frames.first.href)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
Smesser.providers['o2.ie'] = O2Ie
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'smesser/provider'
|
2
|
+
|
3
|
+
class VodafoneIe < Smesser::Provider
|
4
|
+
@@start_url = "https://www.vodafone.ie/myv/index.jsp"
|
5
|
+
@@login_url = "https://www.vodafone.ie/myv/services/login/login.jsp"
|
6
|
+
@@webtext_url = "https://www.vodafone.ie/myv/messaging/webtext/index.jsp"
|
7
|
+
@@send_delay = 3 # Vodafone's servers don't like instantaneousness.
|
8
|
+
|
9
|
+
self.description = "www.vodafone.ie"
|
10
|
+
|
11
|
+
def logged_in?
|
12
|
+
log.debug("Checking if logged in")
|
13
|
+
get(@@start_url)
|
14
|
+
if page.uri == URI.parse(@@start_url)
|
15
|
+
log.debug("Logged in")
|
16
|
+
true
|
17
|
+
else
|
18
|
+
log.debug("Not logged in")
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def login
|
24
|
+
get(@@login_url)
|
25
|
+
post_form('Login') do |form|
|
26
|
+
form.username = @username
|
27
|
+
form.password = @password
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def send(message, *recipients)
|
32
|
+
get(@@webtext_url)
|
33
|
+
|
34
|
+
post_form('WebText') do |form|
|
35
|
+
form.message = message
|
36
|
+
recipients.each_with_index do |recipient, index|
|
37
|
+
form["recipients[#{index}]"] = recipient
|
38
|
+
end
|
39
|
+
sleep(@@send_delay)
|
40
|
+
end
|
41
|
+
|
42
|
+
log.debug("Looking for div#webtext-thankyou")
|
43
|
+
if !!page.at('div#webtext-thankyou')
|
44
|
+
log.debug("Found!")
|
45
|
+
true
|
46
|
+
else
|
47
|
+
log.warn("No matching element found!")
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def remaining
|
53
|
+
log.debug("Checking remaining texts...")
|
54
|
+
login unless logged_in?
|
55
|
+
get @@webtext_url unless page.uri == URI::parse(@@webtext_url)
|
56
|
+
if div = page.at("div.info-row.text-remaining strong")
|
57
|
+
log.debug("Found element")
|
58
|
+
div.inner_text
|
59
|
+
else
|
60
|
+
log.warn("No matching element found!")
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
Smesser.providers['vodafone.ie'] = VodafoneIe
|
data/smesser.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/smesser/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["JJ Buckley"]
|
6
|
+
gem.email = ["jj@bjjb.org"]
|
7
|
+
gem.description = %q{Send free text messages!}
|
8
|
+
gem.summary = %q{SMeSser helps you send SMSs using various mobile provider's websites. The gem comes with a binary, which helps you set up the details for your own provider, and with a library which you can integrate into nicer front-ends.}
|
9
|
+
gem.homepage = "http://jjbuckley.github.com/smesser"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "smesser"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Smesser::VERSION
|
17
|
+
gem.add_development_dependency 'rake'
|
18
|
+
gem.add_dependency 'mechanize', '~> 2.3'
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'smesser'
|
3
|
+
|
4
|
+
class TestSmesser < Test::Unit::TestCase
|
5
|
+
def test_provider_paths
|
6
|
+
assert Smesser::Provider.paths.include?(File.expand_path(File.join(File.dirname(__FILE__), '..', 'providers')))
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_config_files
|
10
|
+
assert Smesser.config_files.include?("/usr/local/etc/smesserrc")
|
11
|
+
assert Smesser.config_files.include?("/etc/smesserrc")
|
12
|
+
assert Smesser.config_files.include?("~/.smesserrc")
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO - loads more tests!
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: smesser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- JJ Buckley
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-10 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &76809390 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *76809390
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: mechanize
|
27
|
+
requirement: &76788750 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.3'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *76788750
|
36
|
+
description: Send free text messages!
|
37
|
+
email:
|
38
|
+
- jj@bjjb.org
|
39
|
+
executables:
|
40
|
+
- smesser
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- LICENSE
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- bin/smesser
|
50
|
+
- lib/smesser.rb
|
51
|
+
- lib/smesser/provider.rb
|
52
|
+
- lib/smesser/version.rb
|
53
|
+
- providers/o2_ie.rb
|
54
|
+
- providers/vodafone_ie.rb
|
55
|
+
- smesser.gemspec
|
56
|
+
- test/test_smesser.rb
|
57
|
+
homepage: http://jjbuckley.github.com/smesser
|
58
|
+
licenses: []
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
none: false
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
hash: 251797839
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
hash: 251797839
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.8.10
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: SMeSser helps you send SMSs using various mobile provider's websites. The
|
87
|
+
gem comes with a binary, which helps you set up the details for your own provider,
|
88
|
+
and with a library which you can integrate into nicer front-ends.
|
89
|
+
test_files:
|
90
|
+
- test/test_smesser.rb
|