powncer 0.1.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/Rakefile +80 -0
- data/lib/powncer.rb +20 -0
- data/lib/powncer/authentication.rb +84 -0
- data/lib/powncer/base.rb +103 -0
- data/lib/powncer/connection.rb +33 -0
- data/lib/powncer/event.rb +40 -0
- data/lib/powncer/ext.rb +58 -0
- data/lib/powncer/link.rb +28 -0
- data/lib/powncer/media.rb +26 -0
- data/lib/powncer/note.rb +101 -0
- data/lib/powncer/user.rb +64 -0
- data/lib/powncer/version.rb +16 -0
- data/test/examples/authenticated_examples.rb +953 -0
- data/test/examples/basic_examples.rb +462 -0
- data/test/test_helper.rb +34 -0
- data/test/unit/1_1_TESTS +21 -0
- data/test/unit/authentication_test.rb +28 -0
- data/test/unit/base_test.rb +13 -0
- data/test/unit/connection_test.rb +12 -0
- data/test/unit/event_test.rb +44 -0
- data/test/unit/link_test.rb +48 -0
- data/test/unit/media_test.rb +22 -0
- data/test/unit/note_test.rb +131 -0
- data/test/unit/user_test.rb +45 -0
- metadata +85 -0
data/Rakefile
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require File.join(File.dirname(__FILE__), 'lib', 'powncer', 'version')
|
7
|
+
|
8
|
+
def library_root
|
9
|
+
File.dirname(__FILE__)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Run tests'
|
13
|
+
task :default => :test
|
14
|
+
|
15
|
+
Rake::TestTask.new('test') do |t|
|
16
|
+
t.libs << 'test'
|
17
|
+
t.pattern = 'test/*/*_test.rb'
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Check code to test ratio'
|
21
|
+
task :stats do
|
22
|
+
library_files = FileList["#{library_root}/lib/**/*.rb"]
|
23
|
+
test_files = FileList["#{library_root}/test/**/*_test.rb"]
|
24
|
+
count_code_lines = Proc.new do |lines|
|
25
|
+
lines.inject(0) do |code_lines, line|
|
26
|
+
next code_lines if [/^\s*$/, /^\s*#/].any? {|non_code_line| non_code_line === line}
|
27
|
+
code_lines + 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
count_code_lines_for_files = Proc.new do |files|
|
32
|
+
files.inject(0) {|code_lines, file| code_lines + count_code_lines[IO.read(file)]}
|
33
|
+
end
|
34
|
+
|
35
|
+
library_code_lines = count_code_lines_for_files[library_files]
|
36
|
+
test_code_lines = count_code_lines_for_files[test_files]
|
37
|
+
ratio = Proc.new { sprintf('%.2f', test_code_lines.to_f / library_code_lines)}
|
38
|
+
|
39
|
+
puts "Code LOC: #{library_code_lines} Test LOC: #{test_code_lines} Code to Test Ratio: 1:#{ratio.call}"
|
40
|
+
end
|
41
|
+
|
42
|
+
namespace :dist do
|
43
|
+
spec = Gem::Specification.new do |s|
|
44
|
+
s.name = "powncer"
|
45
|
+
s.version = Gem::Version.new(Powncer::Version::VERSION)
|
46
|
+
s.author = "Jae Hess"
|
47
|
+
s.email = "jae.hess@gmail.com"
|
48
|
+
s.homepage = "http://powncer.rubyforge.org"
|
49
|
+
s.platform = Gem::Platform::RUBY
|
50
|
+
s.summary = "Powncer is a Ruby library to the Pownce REST API"
|
51
|
+
s.files = FileList['Rakefile', 'lib/**/*.rb']
|
52
|
+
s.require_path = "lib"
|
53
|
+
s.test_files = Dir['test/**/*']
|
54
|
+
s.has_rdoc = true
|
55
|
+
s.rubyforge_project = 'powncer'
|
56
|
+
s.add_dependency 'json'
|
57
|
+
end
|
58
|
+
|
59
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
60
|
+
pkg.need_tar = true
|
61
|
+
end
|
62
|
+
|
63
|
+
package_name = lambda {|specification| File.join('pkg', "#{specification.name}-#{specification.version}")}
|
64
|
+
|
65
|
+
desc 'Push a release to rubyforge'
|
66
|
+
task :release => ['dist:clobber_package', :package] do
|
67
|
+
require 'rubyforge'
|
68
|
+
package = package_name[spec]
|
69
|
+
|
70
|
+
rubyforge = RubyForge.new
|
71
|
+
rubyforge.login
|
72
|
+
|
73
|
+
if release_id = rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version, "#{package}.tgz")
|
74
|
+
rubyforge.add_file(spec.rubyforge_project, spec.name, release_id, "#{package}.gem")
|
75
|
+
else
|
76
|
+
puts 'Release failed!'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/powncer.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'cgi'
|
3
|
+
require 'net/http'
|
4
|
+
require 'base64'
|
5
|
+
require 'open-uri'
|
6
|
+
|
7
|
+
require 'powncer/ext'
|
8
|
+
require 'powncer/base'
|
9
|
+
require 'powncer/connection'
|
10
|
+
require 'powncer/authentication'
|
11
|
+
require 'powncer/user'
|
12
|
+
require 'powncer/note'
|
13
|
+
require 'powncer/link'
|
14
|
+
require 'powncer/event'
|
15
|
+
require 'powncer/media'
|
16
|
+
require 'powncer/version'
|
17
|
+
|
18
|
+
require_library_or_gem 'json'
|
19
|
+
|
20
|
+
begin; load "~/.powncer"; rescue LoadError; end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Powncer
|
2
|
+
|
3
|
+
module Authentication
|
4
|
+
|
5
|
+
class Basic < Connection
|
6
|
+
|
7
|
+
attr_accessor :options
|
8
|
+
|
9
|
+
def initialize(options={})
|
10
|
+
super(true)
|
11
|
+
options[:username] ||= Basic.load_username
|
12
|
+
options[:password] ||= Basic.load_password
|
13
|
+
options[:application_key] ||= Basic.load_application_key
|
14
|
+
options[:secret_key] ||= Basic.load_secret_key
|
15
|
+
@options = options
|
16
|
+
Powncer.connections << self
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(uri)
|
20
|
+
super(uri, true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(uri, params={})
|
24
|
+
# TODO: Refactor
|
25
|
+
endpoint = "#{@url}#{uri}"
|
26
|
+
url = URI.parse(endpoint)
|
27
|
+
req = Net::HTTP::Post.new(url.path)
|
28
|
+
req.basic_auth(options[:username], options[:password])
|
29
|
+
# create hash to add Link, Event params to request
|
30
|
+
form_params = {}
|
31
|
+
form_params.merge!({'note_body' => params[:body]}) if params[:body]
|
32
|
+
form_params.merge!({'url' => params[:url]}) if params[:url]
|
33
|
+
form_params.merge!({'event_name' => params[:name]}) if params[:name]
|
34
|
+
form_params.merge!({'event_location' => params[:location]}) if params[:location]
|
35
|
+
form_params.merge!({'event_date' => params[:date]}) if params[:date]
|
36
|
+
form_params.merge!({'media_file' => params[:data]}) if params[:data]
|
37
|
+
req.set_content_type('multipart/form-data')
|
38
|
+
req.set_form_data({'app_key' => options[:application_key], 'note_to' => "#{params[:to]}"}.merge(form_params))
|
39
|
+
response = Net::HTTP.new(url.host, url.port).start { |http| http.request(req) }
|
40
|
+
response.body
|
41
|
+
end
|
42
|
+
|
43
|
+
class << self
|
44
|
+
|
45
|
+
[:username, :password, :application_key, :secret_key].each do |type|
|
46
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
47
|
+
def load_#{type}
|
48
|
+
env_key(:#{type})
|
49
|
+
end
|
50
|
+
EVAL
|
51
|
+
end
|
52
|
+
|
53
|
+
def connect!(options={})
|
54
|
+
self.new(options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def open(uri, options, *args, &block)
|
58
|
+
query_params = URI.parse(uri).query
|
59
|
+
headers = {}
|
60
|
+
headers["Authorization"] = Header.new(options[:username], options[:password])
|
61
|
+
uri << "#{query_params.nil? ? "?" : "&"}"
|
62
|
+
uri << "app_key=#{options[:application_key]}"
|
63
|
+
Kernel::open(uri, headers, *args, &block)
|
64
|
+
end
|
65
|
+
|
66
|
+
def env_key(key_name)
|
67
|
+
ENV["POWNCER_#{key_name.to_s.upcase}"]
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class Header < String
|
73
|
+
|
74
|
+
def initialize(username, password)
|
75
|
+
self << "Basic #{Base64.encode64("#{username}:#{password}")}"
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/powncer/base.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
module Powncer
|
2
|
+
|
3
|
+
class PowncerError < StandardError; end
|
4
|
+
class PownceConnectionError < PowncerError; end
|
5
|
+
class ConnectionUnavailable < PownceConnectionError; end
|
6
|
+
class BadResponse < PownceConnectionError; end
|
7
|
+
class WebServiceError < PownceConnectionError; end
|
8
|
+
class InvalidFriend < PowncerError; end
|
9
|
+
class RequirementMissing < PowncerError; end
|
10
|
+
class InvalidFormat < RequirementMissing; end
|
11
|
+
|
12
|
+
class Base
|
13
|
+
|
14
|
+
FORMAT = 'json'
|
15
|
+
|
16
|
+
def id
|
17
|
+
@attributes["id"] || nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def request(url)
|
21
|
+
self.class.request(url)
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(url, *params)
|
25
|
+
self.class.post(url, params)
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
def request(url)
|
31
|
+
response = Powncer.connect!.get(url)
|
32
|
+
parse(response)
|
33
|
+
end
|
34
|
+
|
35
|
+
def post(url, *params)
|
36
|
+
options = extract_options(params.flatten)
|
37
|
+
response = Powncer.connect!.post(url, options)
|
38
|
+
parse(response)
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse(response)
|
42
|
+
json = JSON.parse(response)
|
43
|
+
if json.has_key? 'error'
|
44
|
+
raise WebServiceError, json["error"]["message"]
|
45
|
+
end
|
46
|
+
return json
|
47
|
+
end
|
48
|
+
|
49
|
+
def instantiate(attributes)
|
50
|
+
object = allocate
|
51
|
+
object.instance_variable_set("@attributes", attributes)
|
52
|
+
object
|
53
|
+
end
|
54
|
+
|
55
|
+
def extract_options(args)
|
56
|
+
args.last.is_a?(Hash) ? args.pop : {}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def extract_attributes(args)
|
63
|
+
args.last.is_a?(Hash) ? args.pop : {}
|
64
|
+
end
|
65
|
+
|
66
|
+
alias :orig_method_missing :method_missing
|
67
|
+
|
68
|
+
def method_missing(method_id, *args)
|
69
|
+
attribute_name = method_id.to_s
|
70
|
+
if @attributes.stringify_keys!.has_key?(attribute_name)
|
71
|
+
return @attributes.fetch(method_id.to_s)
|
72
|
+
else
|
73
|
+
orig_method_missing(method_id, args)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
class << self
|
80
|
+
|
81
|
+
def connections
|
82
|
+
@connections ||= []
|
83
|
+
end
|
84
|
+
|
85
|
+
def add_connection(connection)
|
86
|
+
connections << connection
|
87
|
+
end
|
88
|
+
|
89
|
+
def make_default_connection
|
90
|
+
add_connection(Connection.new).first
|
91
|
+
end
|
92
|
+
|
93
|
+
def connect!
|
94
|
+
connections.last || make_default_connection
|
95
|
+
end
|
96
|
+
|
97
|
+
def disconnect!
|
98
|
+
@connections.clear unless connections.empty?
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Powncer
|
2
|
+
|
3
|
+
class Connection
|
4
|
+
|
5
|
+
attr_accessor :url, :authenticated
|
6
|
+
|
7
|
+
def initialize(is_auth=false)
|
8
|
+
@url = "#{Powncer::Version::API_URL}/#{Powncer::Version::API_VERSION}"
|
9
|
+
@authenticated = is_auth
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(uri, use_auth=false)
|
13
|
+
endpoint = "#{@url}#{uri}"
|
14
|
+
begin
|
15
|
+
if use_auth
|
16
|
+
response = Authentication::Basic.open(endpoint, Powncer.connect!.options)
|
17
|
+
else
|
18
|
+
response = open(endpoint)
|
19
|
+
end
|
20
|
+
case response.status
|
21
|
+
when ["200", "OK"]
|
22
|
+
response.read
|
23
|
+
else
|
24
|
+
raise BadResponse
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
raise ConnectionUnavailable
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end #/Connection
|
32
|
+
|
33
|
+
end #/Powncer
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Powncer
|
2
|
+
|
3
|
+
class Event < Note
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
raise RequirementMissing, "Event requires a name" unless options[:name]
|
7
|
+
raise RequirementMissing, "Event requires a location" unless options[:location]
|
8
|
+
raise RequirementMissing, "Event requires a date" unless options[:date]
|
9
|
+
raise InvalidFormat, "Event date should be formatted YYYY-MM-DD hh:mm" unless options[:date].is_valid_date?
|
10
|
+
super
|
11
|
+
@attributes["name"] = options[:name]
|
12
|
+
@attributes["location"] = options[:location]
|
13
|
+
@attributes["date"] = options[:date]
|
14
|
+
end
|
15
|
+
|
16
|
+
[:name, :location, :date].each do |attribute|
|
17
|
+
class_eval(<<-EVAL, __FILE__, __LINE__)
|
18
|
+
def #{attribute}
|
19
|
+
@attributes["#{attribute}"] || @attributes["event"]["#{attribute}"]
|
20
|
+
end
|
21
|
+
EVAL
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
|
26
|
+
def create(attributes)
|
27
|
+
attributes.symbolize_keys!
|
28
|
+
event = self.new(attributes)
|
29
|
+
unless event.to.is_a?(Symbol)
|
30
|
+
target_key = self.superclass.ensure_send_to(:friend, event.to)
|
31
|
+
end
|
32
|
+
url = "/send/event.#{self.superclass::FORMAT}"
|
33
|
+
Event.instantiate post(url, {:to => target_key || event.to, :name => event.name, :location => event.location, :date => event.date})
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/powncer/ext.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# :stopdoc:
|
2
|
+
class Hash
|
3
|
+
def to_query
|
4
|
+
query_string = self.empty? ? "" : "?"
|
5
|
+
query_array = []
|
6
|
+
self.map.each{|ary| query_array << "#{ary.first}=#{ary.last}"}
|
7
|
+
query_string << query_array.join("&")
|
8
|
+
end
|
9
|
+
def stringify_keys
|
10
|
+
inject({}) do |options, (key, value)|
|
11
|
+
options[key.to_s] = value
|
12
|
+
options
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def stringify_keys!
|
16
|
+
self.replace(self.stringify_keys)
|
17
|
+
end
|
18
|
+
def symbolize_keys
|
19
|
+
inject({}) do |options, (key, value)|
|
20
|
+
options[key.to_sym || key] = value
|
21
|
+
options
|
22
|
+
end
|
23
|
+
end
|
24
|
+
def symbolize_keys!
|
25
|
+
self.replace(self.symbolize_keys)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class String
|
30
|
+
def is_valid_url?
|
31
|
+
return true if self =~ /http\:\/\//
|
32
|
+
end
|
33
|
+
def is_valid_date?
|
34
|
+
return !/\d{4}\-\d{2}\-\d{2}\s\d{2}\:\d{2}/.match(self).nil?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Kernel
|
39
|
+
def require_library_or_gem(library)
|
40
|
+
require library
|
41
|
+
rescue LoadError => library_not_installed
|
42
|
+
begin
|
43
|
+
require 'rubygems'
|
44
|
+
require library
|
45
|
+
rescue LoadError
|
46
|
+
raise library_not_installed
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module Net
|
52
|
+
module HTTPHeader
|
53
|
+
def set_form_data(params, sep = '&')
|
54
|
+
self.body = params.map {|k,v| "#{urlencode(k.to_s)}=#{urlencode(v.to_s)}" }.join(sep)
|
55
|
+
self.content_type ||= 'application/x-www-form-urlencoded'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/powncer/link.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Powncer
|
2
|
+
|
3
|
+
class Link < Note
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
options[:url] ||= ""
|
7
|
+
raise RequirementMissing unless options[:url].is_valid_url?
|
8
|
+
super
|
9
|
+
@attributes["url"] = options[:url]
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def create(attributes)
|
15
|
+
attributes.symbolize_keys!
|
16
|
+
link = self.new(attributes)
|
17
|
+
unless link.to.is_a?(Symbol)
|
18
|
+
target_key = self.superclass.ensure_send_to(:friend, link.to)
|
19
|
+
end
|
20
|
+
url = "/send/link.#{self.superclass::FORMAT}"
|
21
|
+
Link.instantiate post(url, {:body => link.body, :to => target_key || link.to, :url => link.url})
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|