kevwil-hellotxt 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/History.txt +9 -0
- data/Manifest.txt +14 -0
- data/README +90 -0
- data/Rakefile +38 -0
- data/bin/hellotxt +41 -0
- data/lib/hellotxt.rb +54 -0
- data/lib/hellotxt/client.rb +109 -0
- data/lib/hellotxt/keyloader.rb +58 -0
- data/spec/client_spec.rb +133 -0
- data/spec/hellotxt_spec.rb +18 -0
- data/spec/keyloader_spec.rb +43 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/spec_responses.rb +62 -0
- metadata +77 -0
data/.gitignore
ADDED
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
.gitignore
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
README
|
5
|
+
Rakefile
|
6
|
+
bin/hellotxt
|
7
|
+
lib/hellotxt.rb
|
8
|
+
lib/hellotxt/client.rb
|
9
|
+
lib/hellotxt/keyloader.rb
|
10
|
+
spec/client_spec.rb
|
11
|
+
spec/hellotxt_spec.rb
|
12
|
+
spec/keyloader_spec.rb
|
13
|
+
spec/spec_helper.rb
|
14
|
+
spec/spec_responses.rb
|
data/README
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
HelloTxt Ruby Client/Library
|
2
|
+
|
3
|
+
== Authors
|
4
|
+
|
5
|
+
* Kevin Williams (http://kevwil.github.com/)
|
6
|
+
|
7
|
+
== CODE:
|
8
|
+
|
9
|
+
http://github.com/kevwil/hellotxt/
|
10
|
+
|
11
|
+
== DESCRIPTION:
|
12
|
+
|
13
|
+
HelloTxt (http://hellotxt.com) is a simple service that makes updating your social networks a snap, and this is it's Ruby library.
|
14
|
+
|
15
|
+
== FEATURES/PROBLEMS:
|
16
|
+
|
17
|
+
* Installing the gem creates a 'hellotxt' shell script to post from the shell.
|
18
|
+
* Keys are stored in a YAML file in your home directory (%USERPROFILE% in Windows).
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
Shell usage:
|
23
|
+
|
24
|
+
$ hellotxt "This message will post to my default services."
|
25
|
+
|
26
|
+
Everything after the 'hellotxt' command is what will be posted to the service. You could do the same thing without the quotes, and it would still work:
|
27
|
+
|
28
|
+
$ hellotxt updating from the command line is very handy for developers.
|
29
|
+
|
30
|
+
If your keys have not been stored, it will ask for them. These keys will be saved
|
31
|
+
in a YAML file in your home directory and you won't be asked for them again.
|
32
|
+
|
33
|
+
You can obtain your API key here: http://hellotxt.com/api/doc
|
34
|
+
|
35
|
+
Library usage:
|
36
|
+
|
37
|
+
# Require the library and initialize it.
|
38
|
+
require 'hellotxt'
|
39
|
+
hellotxt = ::HelloTxt::Client.new('api_key', 'user_key')
|
40
|
+
|
41
|
+
# Ensure proper API and USER keys.
|
42
|
+
hellotxt.validate['status']
|
43
|
+
# => 'OK' if success, otherwise 'FAIL'
|
44
|
+
|
45
|
+
# Posting to all services.
|
46
|
+
hellotxt.post('The Dark Knight was amazing.')
|
47
|
+
# => {'status' => 'OK'} if success, otherwise 'FAIL'
|
48
|
+
|
49
|
+
|
50
|
+
Check the source comments for more details.
|
51
|
+
|
52
|
+
== REQUIREMENTS:
|
53
|
+
|
54
|
+
Ruby!
|
55
|
+
|
56
|
+
== INSTALL:
|
57
|
+
|
58
|
+
# From Rubyforge...
|
59
|
+
$ sudo gem install hellotxt
|
60
|
+
|
61
|
+
*OR*
|
62
|
+
|
63
|
+
# From Github...
|
64
|
+
$ sudo gem sources -a http://gems.github.com (only need to do this once)
|
65
|
+
$ sudo gem install kevwil-hellotxt
|
66
|
+
|
67
|
+
== LICENSE:
|
68
|
+
|
69
|
+
(The MIT License)
|
70
|
+
|
71
|
+
Copyright (c) 2008-2009 Kevin Williams
|
72
|
+
|
73
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
74
|
+
a copy of this software and associated documentation files (the
|
75
|
+
'Software'), to deal in the Software without restriction, including
|
76
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
77
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
78
|
+
permit persons to whom the Software is furnished to do so, subject to
|
79
|
+
the following conditions:
|
80
|
+
|
81
|
+
The above copyright notice and this permission notice shall be
|
82
|
+
included in all copies or substantial portions of the Software.
|
83
|
+
|
84
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
87
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
88
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
89
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
90
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
load 'tasks/setup.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
ensure_in_path 'lib'
|
13
|
+
require 'hellotxt'
|
14
|
+
|
15
|
+
task :default => 'spec:run'
|
16
|
+
|
17
|
+
PROJ.name = 'hellotxt'
|
18
|
+
PROJ.authors = ['Kevin Williams']
|
19
|
+
PROJ.email = ['kevwil@gmail.com']
|
20
|
+
PROJ.url = 'http://kevwil.github.com/hellotxt'
|
21
|
+
PROJ.version = ENV['VERSION'] || HelloTxt::VERSION
|
22
|
+
PROJ.rubyforge.name = 'hellotxt'
|
23
|
+
PROJ.readme_file = 'README'
|
24
|
+
|
25
|
+
PROJ.gem.need_tar = false
|
26
|
+
|
27
|
+
PROJ.spec.opts << '--color'
|
28
|
+
|
29
|
+
namespace :gem do
|
30
|
+
desc 'create a gemspec file to support github gems'
|
31
|
+
task :gemspec => 'gem:prereqs' do
|
32
|
+
File.open("#{PROJ.name}.gemspec", 'w+') do |f|
|
33
|
+
f.write PROJ.gem._spec.to_ruby
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# EOF
|
data/bin/hellotxt
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
API_KEY = '1wno0aw653hyry87'
|
4
|
+
|
5
|
+
require File.expand_path(
|
6
|
+
File.join(File.dirname(__FILE__), %w[.. lib hellotxt]))
|
7
|
+
|
8
|
+
keyloader = ::HelloTxt::Keyloader.new
|
9
|
+
unless keyloader.has_keys?
|
10
|
+
keyloader.api_key = API_KEY
|
11
|
+
print 'Enter your HelloTxt User API key (http://hellotxt.com/api/doc): '
|
12
|
+
keyloader.user_key = STDIN.gets.chomp
|
13
|
+
keyloader.save
|
14
|
+
end
|
15
|
+
|
16
|
+
# post message from ARGV
|
17
|
+
|
18
|
+
hellotxt = ::HelloTxt::Client.new(keyloader.api_key, keyloader.user_key)
|
19
|
+
|
20
|
+
s = hellotxt.validate
|
21
|
+
if s['status'] == 'OK'
|
22
|
+
status = ARGV.join(' ')
|
23
|
+
|
24
|
+
# Might be a good idea to throw an exception here, instead of just bailing.
|
25
|
+
if status.nil? || status.empty?
|
26
|
+
puts 'Must provide a message to send.'
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
post_result = hellotxt.post(status)
|
31
|
+
|
32
|
+
if post_result['status'] == 'FAIL'
|
33
|
+
puts post_result['message']
|
34
|
+
else
|
35
|
+
puts 'Message sent.'
|
36
|
+
end
|
37
|
+
else
|
38
|
+
puts s['message']
|
39
|
+
end
|
40
|
+
|
41
|
+
# EOF
|
data/lib/hellotxt.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module HelloTxt
|
4
|
+
|
5
|
+
# :stopdoc:
|
6
|
+
VERSION = '1.0.1'
|
7
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
8
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
9
|
+
# :startdoc:
|
10
|
+
|
11
|
+
# Returns the version string for the library.
|
12
|
+
#
|
13
|
+
def self.version
|
14
|
+
VERSION
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the library path for the module. If any arguments are given,
|
18
|
+
# they will be joined to the end of the libray path using
|
19
|
+
# <tt>File.join</tt>.
|
20
|
+
#
|
21
|
+
def self.libpath( *args )
|
22
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the lpath for the module. If any arguments are given,
|
26
|
+
# they will be joined to the end of the path using
|
27
|
+
# <tt>File.join</tt>.
|
28
|
+
#
|
29
|
+
def self.path( *args )
|
30
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Utility method used to rquire all files ending in .rb that lie in the
|
34
|
+
# directory below this file that has the same name as the filename passed
|
35
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
36
|
+
# the _filename_ does not have to be equivalent to the directory.
|
37
|
+
#
|
38
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
39
|
+
dir ||= ::File.basename(fname, '.*')
|
40
|
+
search_me = ::File.expand_path(
|
41
|
+
::File.join(::File.dirname(fname), dir, '*', '*.rb'))
|
42
|
+
|
43
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module Hellotxt
|
47
|
+
|
48
|
+
#HelloTxt.require_all_libs_relative_to(__FILE__)
|
49
|
+
module HelloTxt
|
50
|
+
autoload :Keyloader, 'hellotxt/keyloader'
|
51
|
+
autoload :Client, 'hellotxt/client'
|
52
|
+
end
|
53
|
+
|
54
|
+
# EOF
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# HelloTxt Ruby Client
|
2
|
+
require 'net/http'
|
3
|
+
require 'rexml/document'
|
4
|
+
|
5
|
+
module HelloTxt
|
6
|
+
|
7
|
+
# MUST NOT end with a trailing slash, as this string is interpolated like this:
|
8
|
+
# "#{API_URL}/user.services"
|
9
|
+
API_URL = 'http://hellotxt.com/api/v1'
|
10
|
+
|
11
|
+
class Client
|
12
|
+
|
13
|
+
def initialize(api_key, user_key)
|
14
|
+
@api_key = api_key
|
15
|
+
@user_key = user_key
|
16
|
+
end
|
17
|
+
|
18
|
+
# Validates API key and USER key
|
19
|
+
# if successful returns:
|
20
|
+
# {'status' => 'OK'}
|
21
|
+
# if unsuccessful returns:
|
22
|
+
# {'status' => 'FAIL', 'message' => 'message what went wrong'}
|
23
|
+
def validate
|
24
|
+
response = get_response('user.validate')
|
25
|
+
if response.elements['rsp'].attributes['status'] == 'OK'
|
26
|
+
return status_ok
|
27
|
+
else
|
28
|
+
return status_fail(response)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns a list of services the user has set up through HelloTxt
|
33
|
+
# if successful returns:
|
34
|
+
# {'status' => 'OK', 'services' => [{'id' => 'serviceid', 'name' => 'servicename', 'code' => 'servicecode', 'inhome' => 'checked', 'friend' => 'checked', 'collegue' => 'checked'}, ...]}
|
35
|
+
# if unsuccessful returns:
|
36
|
+
# {'status' => 'FAIL', 'message' => 'message what went wrong'}
|
37
|
+
def user_services
|
38
|
+
response = get_response('user.services')
|
39
|
+
if response.elements['rsp'].attributes['status'] == 'OK'
|
40
|
+
services = status_ok()
|
41
|
+
services['services'] = []
|
42
|
+
response.elements.each('rsp/services/service') do |service|
|
43
|
+
services['services'].push({'id' => service.attributes['id'],
|
44
|
+
'name' => service.attributes['name'],
|
45
|
+
'code' => service.elements['code'].text,
|
46
|
+
'inhome' => service.elements['inhome'].text,
|
47
|
+
'friend' => service.elements['friend'].text,
|
48
|
+
'collegue' => service.elements['collegue'].text})
|
49
|
+
end
|
50
|
+
return services
|
51
|
+
else
|
52
|
+
return status_fail(response)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Posts a message to the user's social services
|
57
|
+
# Arguments:
|
58
|
+
# body = message body
|
59
|
+
# Optional arguments:
|
60
|
+
# title = title of the posted message, only used if the service supports it
|
61
|
+
# group = service group type; either 'inhome', 'friend', 'collegue'
|
62
|
+
# image = raw bytes of an image to post
|
63
|
+
# debug = set debug to 1 to avoid posting test data
|
64
|
+
# if successful returns:
|
65
|
+
# {'status' => 'OK'}
|
66
|
+
# if unsuccessful returns:
|
67
|
+
# {'status' => 'FAIL', 'message' => 'message what went wrong'}
|
68
|
+
def post(body, title = '', group = 'inhome', image = '', debug = 0)
|
69
|
+
response = get_response('user.post',
|
70
|
+
'body' => body, 'title' => title,
|
71
|
+
'group' => group, 'image' => image,
|
72
|
+
'debug' => debug)
|
73
|
+
if response.elements['rsp'].attributes['status'] == 'OK'
|
74
|
+
return status_ok
|
75
|
+
else
|
76
|
+
return status_fail(response)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Gets a particular hellotxt response.
|
83
|
+
# <tt>type</tt>: The service type (ex. 'user.services'). Gets appended to <tt>API_URL</tt>.
|
84
|
+
# <tt>parameters</tt>: Optional (depending on the <tt>type</tt>) parameters to be passed along
|
85
|
+
# with the request. The API key and USER key are merged with this on every call.
|
86
|
+
def get_response(type, parameters = {})
|
87
|
+
parameters.merge!('app_key' => @api_key, 'user_key' => @user_key)
|
88
|
+
REXML::Document.new(http_request("#{API_URL}/method/#{type}", parameters))
|
89
|
+
end
|
90
|
+
|
91
|
+
# This makes the actual HTTP request.
|
92
|
+
def http_request(url, parameters)
|
93
|
+
response = Net::HTTP.post_form(URI.parse(url), parameters)
|
94
|
+
return response.body
|
95
|
+
end
|
96
|
+
|
97
|
+
# Successful response.
|
98
|
+
def status_ok
|
99
|
+
return {'status' => 'OK'}
|
100
|
+
end
|
101
|
+
|
102
|
+
# Failed response.
|
103
|
+
def status_fail(response)
|
104
|
+
return {'status' => 'FAIL', 'message' => response.elements['rsp/message'].text}
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module HelloTxt
|
4
|
+
|
5
|
+
class KeyloadingError < Exception; end
|
6
|
+
|
7
|
+
# manages the YAML file containing the keys - encryption might be nice, might be overkill
|
8
|
+
class Keyloader
|
9
|
+
|
10
|
+
# Path to YAML file containing keys
|
11
|
+
attr_accessor :keyfile
|
12
|
+
|
13
|
+
# hellotxt uses this as the key for the registered application
|
14
|
+
attr_accessor :api_key
|
15
|
+
|
16
|
+
# hellotxt uses this as the key for the user
|
17
|
+
attr_accessor :user_key
|
18
|
+
|
19
|
+
KEY_PATH = (RUBY_PLATFORM =~ /mswin32/ ? ENV['USERPROFILE'] : ENV['HOME'])
|
20
|
+
KEY_FILE = '.hellotxt_keys.yml'
|
21
|
+
|
22
|
+
def initialize(keyfile = File.expand_path(File.join(KEY_PATH, KEY_FILE)))
|
23
|
+
@api_key = nil
|
24
|
+
@keyfile = keyfile
|
25
|
+
|
26
|
+
# load keys on init
|
27
|
+
load_keys!
|
28
|
+
end
|
29
|
+
|
30
|
+
# load a new set of keys
|
31
|
+
def load_keys(keyfile)
|
32
|
+
if File.exist?(keyfile) and File.readable?(keyfile)
|
33
|
+
data = YAML::load_file(keyfile)
|
34
|
+
@keyfile = keyfile if @keyfile.nil?
|
35
|
+
@api_key = data['api_key']
|
36
|
+
@user_key = data['user_key']
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# load keys using the known keyfile
|
41
|
+
def load_keys!
|
42
|
+
load_keys(@keyfile)
|
43
|
+
end
|
44
|
+
|
45
|
+
# if keys have been loaded successfully
|
46
|
+
def has_keys?
|
47
|
+
return true unless @api_key.nil? or @user_key.nil?
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
|
51
|
+
# save key data to keyfile
|
52
|
+
def save
|
53
|
+
File.open( @keyfile, 'w+' ) do |out|
|
54
|
+
YAML::dump( {'api_key' => @api_key, 'user_key' => @user_key}, out )
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
3
|
+
|
4
|
+
describe HelloTxt::Client, "with expected results" do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@client = HelloTxt::Client.new('a','b')
|
8
|
+
@params = {'app_key' => 'a', 'user_key' => 'b'}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should validate keys successfully" do
|
12
|
+
init_ok_response 'user.validate'
|
13
|
+
|
14
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
15
|
+
|
16
|
+
# mock the http call
|
17
|
+
http_resp = mock('response')
|
18
|
+
http_resp.expects(:body).returns(@response)
|
19
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
20
|
+
|
21
|
+
# call and verify
|
22
|
+
result = @client.validate
|
23
|
+
result.should_not be_empty
|
24
|
+
result['status'].should_not be_nil
|
25
|
+
result['status'].should eql('OK')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should list the user's services properly" do
|
29
|
+
init_service_response
|
30
|
+
|
31
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
32
|
+
|
33
|
+
# mock the http call
|
34
|
+
http_resp = mock('response')
|
35
|
+
http_resp.expects(:body).returns(@response)
|
36
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
37
|
+
|
38
|
+
# call and verify
|
39
|
+
result = @client.user_services
|
40
|
+
result.should_not be_empty
|
41
|
+
result['status'].should_not be_nil
|
42
|
+
result['status'].should eql('OK')
|
43
|
+
result['services'].should_not be_nil
|
44
|
+
result['services'].should_not be_empty
|
45
|
+
result['services'].length.should eql(5)
|
46
|
+
result['services'].first['name'].should eql('twitter')
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should post a message to the service" do
|
50
|
+
init_ok_response 'user.post'
|
51
|
+
|
52
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
53
|
+
@params.merge!('body' => 'foo', 'title' => '',
|
54
|
+
'group' => 'inhome', 'image' => '',
|
55
|
+
'debug' => 0)
|
56
|
+
|
57
|
+
# mock the http call
|
58
|
+
http_resp = mock('response')
|
59
|
+
http_resp.expects(:body).returns(@response)
|
60
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
61
|
+
|
62
|
+
# call and verify
|
63
|
+
result = @client.post('foo')
|
64
|
+
result.should_not be_empty
|
65
|
+
result['status'].should_not be_nil
|
66
|
+
result['status'].should eql('OK')
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe HelloTxt::Client, "with error messages" do
|
72
|
+
before(:each) do
|
73
|
+
@client = HelloTxt::Client.new('a','b')
|
74
|
+
@params = {'app_key' => 'a', 'user_key' => 'b'}
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should handle a failed validate cleanly" do
|
78
|
+
init_fail_response 'user.validate'
|
79
|
+
|
80
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
81
|
+
|
82
|
+
# mock the http call
|
83
|
+
http_resp = mock('response')
|
84
|
+
http_resp.expects(:body).returns(@response)
|
85
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
86
|
+
|
87
|
+
# call and verify
|
88
|
+
result = @client.validate
|
89
|
+
result.should_not be_empty
|
90
|
+
result['status'].should_not be_nil
|
91
|
+
result['status'].should eql('FAIL')
|
92
|
+
result['message'].should_not be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should handle a failed user's services cleanly" do
|
96
|
+
init_fail_response 'user.services'
|
97
|
+
|
98
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
99
|
+
|
100
|
+
# mock the http call
|
101
|
+
http_resp = mock('response')
|
102
|
+
http_resp.expects(:body).returns(@response)
|
103
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
104
|
+
|
105
|
+
# call and verify
|
106
|
+
result = @client.user_services
|
107
|
+
result.should_not be_empty
|
108
|
+
result['status'].should_not be_nil
|
109
|
+
result['status'].should eql('FAIL')
|
110
|
+
result['message'].should_not be_nil
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should handle a failed user post cleanly" do
|
114
|
+
init_fail_response 'user.post'
|
115
|
+
|
116
|
+
uri = URI.parse "#{HelloTxt::API_URL}/method/#{@service_type}"
|
117
|
+
|
118
|
+
# mock the http call
|
119
|
+
http_resp = mock('response')
|
120
|
+
http_resp.expects(:body).returns(@response)
|
121
|
+
@params.merge!({'group' => 'inhome', 'title' => '',
|
122
|
+
'image' => '', 'body' => 'test message', 'debug' => 0})
|
123
|
+
Net::HTTP.expects(:post_form).with(uri, @params).returns(http_resp)
|
124
|
+
|
125
|
+
# call and verify
|
126
|
+
result = @client.post('test message')
|
127
|
+
result.should_not be_empty
|
128
|
+
result['status'].should_not be_nil
|
129
|
+
result['status'].should eql('FAIL')
|
130
|
+
result['message'].should_not be_nil
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
3
|
+
|
4
|
+
describe HelloTxt, 'main module' do
|
5
|
+
it 'should return the version string' do
|
6
|
+
HelloTxt.version.should be_a_kind_of(String)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return the library path' do
|
10
|
+
HelloTxt.libpath.should eql(HelloTxt::LIBPATH)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should return the path to the library' do
|
14
|
+
HelloTxt.path.should eql(HelloTxt::PATH)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# EOF
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe HelloTxt::Keyloader do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@keydata = {'api_key' => 'foo', 'user_key' => 'bar'}
|
8
|
+
@tf = Tempfile.new('keys.yml')
|
9
|
+
YAML::dump(@keydata, @tf)
|
10
|
+
@tmp_path = @tf.path
|
11
|
+
@tf.close
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
@tf.unlink
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should use keys from yaml file if found" do
|
19
|
+
loader = HelloTxt::Keyloader.new(@tmp_path)
|
20
|
+
loader.has_keys?.should be_true
|
21
|
+
loader.keyfile.should eql(@tmp_path)
|
22
|
+
loader.api_key.should eql(@keydata['api_key'])
|
23
|
+
loader.user_key.should eql(@keydata['user_key'])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should save keys to keyfile" do
|
27
|
+
loader = HelloTxt::Keyloader.new(@tmp_path)
|
28
|
+
loader.user_key = 'baz'
|
29
|
+
loader.save
|
30
|
+
|
31
|
+
loader.has_keys?.should be_true
|
32
|
+
File.exist?(loader.keyfile).should be_true
|
33
|
+
File.readable?(loader.keyfile).should be_true
|
34
|
+
YAML::load_file(loader.keyfile)['user_key'].should eql('baz')
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should behave if keys cannot be loaded" do
|
38
|
+
loader = HelloTxt::Keyloader.new('/tmp/nofile')
|
39
|
+
loader.has_keys?.should be_false
|
40
|
+
loader.api_key.should be_nil
|
41
|
+
loader.user_key.should be_nil
|
42
|
+
end
|
43
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mocha'
|
3
|
+
|
4
|
+
require File.expand_path(
|
5
|
+
File.join(File.dirname(__FILE__), %w[.. lib hellotxt]))
|
6
|
+
require File.expand_path(
|
7
|
+
File.join(File.dirname(__FILE__), %w[spec_responses]))
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
# == Mock Framework
|
11
|
+
#
|
12
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
13
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
14
|
+
#
|
15
|
+
config.mock_with :mocha
|
16
|
+
# config.mock_with :flexmock
|
17
|
+
# config.mock_with :rr
|
18
|
+
end
|
19
|
+
|
20
|
+
# EOF
|
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
def init_ok_response(service_type)
|
3
|
+
@service_type = service_type
|
4
|
+
@response = <<EOXML
|
5
|
+
<?xml version="1.0"?>
|
6
|
+
<rsp status="OK">
|
7
|
+
<method>#{@service_type}</method>
|
8
|
+
</rsp>
|
9
|
+
EOXML
|
10
|
+
end
|
11
|
+
|
12
|
+
def init_fail_response(service_type)
|
13
|
+
@service_type = service_type
|
14
|
+
@response = <<EOXML
|
15
|
+
<?xml version="1.0"?>
|
16
|
+
<rsp status="FAIL">
|
17
|
+
<method>#{@service_type}</method>
|
18
|
+
<message>You suck</message>
|
19
|
+
</rsp>
|
20
|
+
EOXML
|
21
|
+
end
|
22
|
+
|
23
|
+
def init_service_response
|
24
|
+
@service_type = 'user.services'
|
25
|
+
@response = <<EOXML
|
26
|
+
<?xml version="1.0"?>
|
27
|
+
<rsp status="OK">
|
28
|
+
<services>
|
29
|
+
<service id="tw" name="twitter">
|
30
|
+
<code>Ee6n</code>
|
31
|
+
<inhome>checked</inhome>
|
32
|
+
<friend>unchecked</friend>
|
33
|
+
<collegue>unchecked</collegue>
|
34
|
+
</service>
|
35
|
+
<service id="fb" name="facebook">
|
36
|
+
<code>XW7G</code>
|
37
|
+
<inhome>checked</inhome>
|
38
|
+
<friend>false</friend>
|
39
|
+
<collegue>false</collegue>
|
40
|
+
</service>
|
41
|
+
<service id="jk" name="jaiku">
|
42
|
+
<code>OK38</code>
|
43
|
+
<inhome>checked</inhome>
|
44
|
+
<friend>unchecked</friend>
|
45
|
+
<collegue>unchecked</collegue>
|
46
|
+
</service>
|
47
|
+
<service id="id" name="identica">
|
48
|
+
<code>IOZq</code>
|
49
|
+
<inhome>checked</inhome>
|
50
|
+
<friend>unchecked</friend>
|
51
|
+
<collegue>unchecked</collegue>
|
52
|
+
</service>
|
53
|
+
<service id="rj" name="rejaw">
|
54
|
+
<code>s46G</code>
|
55
|
+
<inhome>checked</inhome>
|
56
|
+
<friend>unchecked</friend>
|
57
|
+
<collegue>unchecked</collegue>
|
58
|
+
</service>
|
59
|
+
</services>
|
60
|
+
</rsp>
|
61
|
+
EOXML
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kevwil-hellotxt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kevin Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-01-03 00:00:00 -08:00
|
13
|
+
default_executable: hellotxt
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bones
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.2.0
|
23
|
+
version:
|
24
|
+
description: HelloTxt (http://hellotxt.com) is a simple service that makes updating your social networks a snap, and this is it's Ruby library.
|
25
|
+
email:
|
26
|
+
- kevwil@gmail.com
|
27
|
+
executables:
|
28
|
+
- hellotxt
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- History.txt
|
33
|
+
- bin/hellotxt
|
34
|
+
files:
|
35
|
+
- .gitignore
|
36
|
+
- History.txt
|
37
|
+
- Manifest.txt
|
38
|
+
- README
|
39
|
+
- Rakefile
|
40
|
+
- bin/hellotxt
|
41
|
+
- lib/hellotxt.rb
|
42
|
+
- lib/hellotxt/client.rb
|
43
|
+
- lib/hellotxt/keyloader.rb
|
44
|
+
- spec/client_spec.rb
|
45
|
+
- spec/hellotxt_spec.rb
|
46
|
+
- spec/keyloader_spec.rb
|
47
|
+
- spec/spec_helper.rb
|
48
|
+
- spec/spec_responses.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://kevwil.github.com/hellotxt
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --main
|
54
|
+
- README
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project: hellotxt
|
72
|
+
rubygems_version: 1.2.0
|
73
|
+
signing_key:
|
74
|
+
specification_version: 2
|
75
|
+
summary: HelloTxt (http://hellotxt
|
76
|
+
test_files: []
|
77
|
+
|