supr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Blake Chambers
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,57 @@
1
+ Supr
2
+ ====
3
+
4
+ Supr is a gem wrapping [Stumble Upon][su]'s [Su.pr][supr] url shortening service. The api is relatively new
5
+ and thin on features, but this gem gives you access to the shorten and expand methods. More
6
+ support for the post method is planned. Statistic information is still covered by the api
7
+ but when that is exposed, it will be added here.
8
+
9
+ **Supr uses [semantic versioning][semvar] and the api should be considered unstable until version 1.0.0.
10
+ *Consider yourself warned*.**
11
+
12
+ Installation
13
+ ------------
14
+
15
+ gem install supr
16
+
17
+ Usage
18
+ -----
19
+
20
+ Create a Bitly client using your username and api key as follows:
21
+
22
+ supr\_client = Supr.new(username, api_key)
23
+
24
+ You can then use that client to shorten or expand urls as so:
25
+
26
+ supr\_client.shorten('http://www.google.com')
27
+ supr\_client.shorten('http://www.google.com')
28
+ supr\_client.expand('xJs4E')
29
+
30
+ Special Thanks
31
+ --------------
32
+
33
+ This gem is mostly based on the [bitly gem][bitly] written by [Phil Nash][phil]. Special
34
+ thanks to him for the code base to start with.
35
+
36
+ Note on Patches/Pull Requests
37
+ -----------------------------
38
+
39
+ * Fork the project.
40
+ * Make your feature addition or bug fix.
41
+ * Add tests for it. This is important so I don't break it in a
42
+ future version unintentionally.
43
+ * Commit, do not mess with Rakefile, version, or history.
44
+ (if you want to have your own version, that is fine but bump version in a commit
45
+ by itself I can ignore when I pull)
46
+ * Send me a pull request. Bonus points for topic branches.
47
+
48
+ Copyright
49
+ ---------
50
+
51
+ Copyright (c) 2010 Blake Chambers. See LICENSE for details.
52
+
53
+ [phil]: http://github.com/philnash
54
+ [bitly]: http://github.com/philnash/bitly
55
+ [semvar]: http://semver.org/
56
+ [su]: http://www.stumbleupon.com/ "Stumble Upon"
57
+ [supr]: http://su.pr/ "Su.pr"
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "supr"
8
+ gem.summary = %Q{Use the su.pr API to shorten or expand URLs}
9
+ gem.description = %Q{Use the su.pr API to shorten or expand URLs}
10
+ gem.email = "chambb1@gmail.com"
11
+ gem.homepage = "http://github.com/blakechambers/supr"
12
+ gem.authors = ["Blake Chambers"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_development_dependency "yard", ">= 0"
15
+
16
+ gem.add_dependency 'crack', '>= 0.1.4'
17
+ gem.add_dependency 'httparty', '>= 0.5.2'
18
+
19
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'spec/rake/spectask'
27
+ Spec::Rake::SpecTask.new(:spec) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
+ end
31
+
32
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.pattern = 'spec/**/*_spec.rb'
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :spec => :check_dependencies
39
+
40
+ task :default => :spec
41
+
42
+ begin
43
+ require 'yard'
44
+ YARD::Rake::YardocTask.new
45
+ rescue LoadError
46
+ task :yardoc do
47
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
48
+ end
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/supr.rb ADDED
@@ -0,0 +1,8 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'crack'
4
+
5
+ require 'supr/utils'
6
+ require 'supr/client'
7
+ require 'supr/url'
8
+ require 'supr/version'
@@ -0,0 +1,129 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ module Supr
6
+ API_URL = 'http://su.pr/api/'
7
+ API_VERSION = '1.0'
8
+
9
+ def self.new(login, api_key)
10
+ Supr::Client.new(login,api_key)
11
+ end
12
+
13
+ class Client
14
+
15
+ include Supr::Utils
16
+
17
+ def initialize(login,api_key)
18
+ @login = login
19
+ @api_key = api_key
20
+ end
21
+
22
+ def shorten(input, opts={})
23
+ if input.is_a? String
24
+ request = create_url("shorten", :longUrl => input, :history => (opts[:history] ? 1 : nil))
25
+ result = get_result(request)
26
+ result = {:long_url => input}.merge result[input]
27
+ Supr::Url.new(@login,@api_key,result)
28
+ elsif input.is_a? Array
29
+ request = create_url("shorten", :history => (opts[:history] ? 1 : nil))
30
+ request.query << "&" + input.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless input.nil?
31
+ result = get_result(request)
32
+ input.map do |long_url|
33
+ new_url = {:long_url => long_url}.merge result[long_url]
34
+ long_url = Supr::Url.new(@login,@api_key,new_url)
35
+ end
36
+ else
37
+ raise ArgumentError.new("Shorten requires either a url or an array of urls")
38
+ end
39
+ end
40
+
41
+ def validate
42
+ @validated ||= begin
43
+ self.shorten("http://google.com").kind_of?(::Supr::Url)
44
+ rescue
45
+ false
46
+ end
47
+ end
48
+ alias :valid? :validate
49
+
50
+ def expand(input)
51
+ if input.is_a? String
52
+ if input.include?('su.pr/') || input.include?('j.mp/')
53
+ hash = create_hash_from_url(input)
54
+ request = create_url "expand", :hash => hash
55
+ result = get_result(request)
56
+ result = { :short_url => input, :hash => hash }.merge result[hash]
57
+ else
58
+ request = create_url "expand", :hash => input
59
+ result = get_result(request)
60
+ result = { :hash => input, :short_url => "http://su.pr/#{input}" }.merge result[input]
61
+ end
62
+ Supr::Url.new(@login,@api_key,result)
63
+ elsif input.is_a? Array
64
+ request = create_url "expand", :hash => input.join(',')
65
+ result = get_result(request)
66
+ input.map do |hsh|
67
+ new_url = {:hash => hsh, :short_url => "http://su.pr/#{hsh}"}.merge result[hsh]
68
+ hsh = Supr::Url.new(@login,@api_key,new_url)
69
+ end
70
+ else
71
+ raise ArgumentError('Expand requires either a short url, a hash or an array of hashes')
72
+ end
73
+ end
74
+
75
+ # def info(input)
76
+ # if input.is_a? String
77
+ # if input.include? "su.pr/"
78
+ # hash = create_hash_from_url(input)
79
+ # request = create_url 'info', :hash => hash
80
+ # result = get_result(request)
81
+ # result = { :short_url => "http://su.pr/#{hash}", :hash => hash }.merge result[hash]
82
+ # else
83
+ # request = create_url 'info', :hash => input
84
+ # result = get_result(request)
85
+ # result = { :short_url => "http://su.pr/#{input}", :hash => input }.merge result[input]
86
+ # end
87
+ # Supr::Url.new(@login,@api_key,result)
88
+ # elsif input.is_a? Array
89
+ # request = create_url "info", :hash => input.join(',')
90
+ # result = get_result(request)
91
+ # input.map do |hsh|
92
+ # new_url = {:hash => hsh, :short_url => "http://su.pr/#{hsh}"}.merge result[hsh]
93
+ # hsh = Supr::Url.new(@login,@api_key,:info => new_url)
94
+ # end
95
+ # else
96
+ # raise ArgumentError.new('Info requires either a short url, a hash or an array of hashes')
97
+ # end
98
+ # end
99
+ #
100
+ # def stats(input)
101
+ # if input.is_a? String
102
+ # if input.include? "su.pr/"
103
+ # hash = create_hash_from_url(input)
104
+ # request = create_url 'stats', :hash => hash
105
+ # result = get_result(request)
106
+ # result = { :short_url => "http://su.pr/#{hash}", :hash => hash }.merge result
107
+ # else
108
+ # request = create_url 'stats', :hash => input
109
+ # result = get_result(request)
110
+ # result = { :short_url => "http://su.pr/#{input}", :hash => input }.merge result
111
+ # end
112
+ # Supr::Url.new(@login,@api_key,:stats => result)
113
+ # else
114
+ # raise ArgumentError.new("Stats requires either a short url or a hash")
115
+ # end
116
+ # end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ class SuprError < StandardError
123
+ attr_reader :code
124
+ alias :msg :message
125
+ def initialize(msg, code)
126
+ @code = code
127
+ super("#{msg} - '#{code}'")
128
+ end
129
+ end
data/lib/supr/url.rb ADDED
@@ -0,0 +1,96 @@
1
+ module Supr
2
+
3
+ class Url
4
+ include Supr::Utils
5
+
6
+ attr_accessor :long_url, :short_url, :hash
7
+ attr_reader :info, :stats
8
+ VARIABLES = ['long_url', 'short_url', 'hash']
9
+
10
+ def initialize(login,api_key,obj=nil)
11
+ unless obj.nil?
12
+ raise SuprError.new(obj['errorMessage'],obj['errorCode']) if obj['statusCode'] == "ERROR"
13
+ instance_variablise(obj, VARIABLES)
14
+ @info = obj[:info] if obj[:info]
15
+ @stats = obj[:stats] if obj[:stats]
16
+ end
17
+ @login = login
18
+ @api_key = api_key
19
+ raise ArgumentError.new("Please provide a login and api_key") if @login.nil? || @api_key.nil?
20
+ end
21
+
22
+ def shorten(opts = {})
23
+ return @short_url if @short_url
24
+ unless @long_url.nil?
25
+ request = create_url("shorten", :longUrl => @long_url, :history => (opts[:history] ? 1 : nil))
26
+ result = get_result(request)[@long_url.gsub(/\/$/,'')]
27
+ if result['statusCode'] == "ERROR"
28
+ raise SuprError.new(result['errorMessage'],result['errorCode'])
29
+ else
30
+ instance_variablise(result,VARIABLES)
31
+ return @short_url
32
+ end
33
+ else
34
+ raise ArgumentError.new("You need a long_url in order to shorten it")
35
+ end
36
+ end
37
+
38
+ def expand
39
+ return @long_url if @long_url
40
+ unless !(@short_url || @hash)
41
+ unless @hash
42
+ @hash = create_hash_from_url(@short_url)
43
+ end
44
+ request = create_url("expand", :hash => @hash)
45
+ result = get_result(request)[@hash]
46
+ if result['statusCode'] == "ERROR"
47
+ raise SuprError.new(result['errorMessage'],result['errorCode'])
48
+ else
49
+ instance_variablise(result,VARIABLES)
50
+ return @long_url
51
+ end
52
+ else
53
+ raise ArgumentError.new("You need a short_url or a hash in order to expand it")
54
+ end
55
+ end
56
+
57
+ # def info
58
+ # if @info.nil?
59
+ # if @hash
60
+ # request = create_url "info", :hash => @hash
61
+ # result = get_result(request)[@hash]
62
+ # instance_variablise(result, VARIABLES)
63
+ # @info = result
64
+ # elsif @short_url
65
+ # @hash = create_hash_from_url(@short_url)
66
+ # request = create_url "info", :hash => hash
67
+ # result = get_result(request)[hash]
68
+ # instance_variablise(result, VARIABLES)
69
+ # @info = result
70
+ # else
71
+ # raise ArgumentError.new("You need a hash or short_url in order to get info")
72
+ # end
73
+ # return @info
74
+ # else
75
+ # @info
76
+ # end
77
+ # end
78
+ #
79
+ # def stats
80
+ # if @stats.nil?
81
+ # if @hash
82
+ # request = create_url "stats", :hash => @hash
83
+ # elsif @short_url
84
+ # @hash = create_hash_from_url(@short_url)
85
+ # request = create_url "stats", :hash => @hash
86
+ # else
87
+ # raise ArgumentError.new("You need a hash or short_url in order to get stats")
88
+ # end
89
+ # @stats = get_result(request)
90
+ # else
91
+ # @stats
92
+ # end
93
+ # end
94
+ end
95
+
96
+ end
data/lib/supr/utils.rb ADDED
@@ -0,0 +1,60 @@
1
+ require 'cgi'
2
+
3
+ module Supr
4
+ module Utils
5
+ def underscore(camel_cased_word) # stolen from rails
6
+ camel_cased_word.to_s.gsub(/::/, '/').
7
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
8
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
9
+ tr("-", "_").
10
+ downcase
11
+ end
12
+
13
+ def create_hash_from_url(url)
14
+ url.gsub(/^.*(bit\.ly|j\.mp)\//,'')
15
+ end
16
+
17
+ def attr_define(k,v)
18
+ instance_variable_set("@#{k}", v)
19
+ meta = class << self; self; end
20
+ meta.class_eval { attr_reader k.to_sym }
21
+ end
22
+
23
+ def instance_variablise(obj,variables)
24
+ if obj.is_a? Hash
25
+ obj.each do |k,v|
26
+ if v.is_a? Hash
27
+ instance_variablise(v,variables)
28
+ else
29
+ attr_define(underscore(k),v) if variables.include?(underscore(k))
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def create_url(resource="",args={})
36
+ args = args.merge({:login => @login, :apiKey => @api_key, :version => API_VERSION})
37
+ url = URI.join(API_URL,resource)
38
+ long_urls = args.delete(:long_urls)
39
+ url.query = args.map { |k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
40
+ url.query << "&" + long_urls.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless long_urls.nil?
41
+ url
42
+ end
43
+
44
+ def get_result(request)
45
+ begin
46
+ json = Net::HTTP.get(request)
47
+ # puts json.inspect
48
+ result = Crack::JSON.parse(json)
49
+ rescue
50
+ result = {'errorMessage' => 'JSON Parse Error(Bit.ly messed up)', 'errorCode' => 69, 'statusCode' => 'ERROR'}
51
+ end
52
+ if result['statusCode'] == "OK"
53
+ result = result['results']
54
+ else
55
+ raise SuprError.new(result['errorMessage'],result['errorCode'])
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ module Supr
2
+ VERSION = '0.1.0'
3
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'supr'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
data/spec/supr_spec.rb ADDED
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Supr" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: supr
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Blake Chambers
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-04 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rspec
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 13
30
+ segments:
31
+ - 1
32
+ - 2
33
+ - 9
34
+ version: 1.2.9
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: yard
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: crack
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 19
60
+ segments:
61
+ - 0
62
+ - 1
63
+ - 4
64
+ version: 0.1.4
65
+ type: :runtime
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: httparty
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 15
76
+ segments:
77
+ - 0
78
+ - 5
79
+ - 2
80
+ version: 0.5.2
81
+ type: :runtime
82
+ version_requirements: *id004
83
+ description: Use the su.pr API to shorten or expand URLs
84
+ email: chambb1@gmail.com
85
+ executables: []
86
+
87
+ extensions: []
88
+
89
+ extra_rdoc_files:
90
+ - LICENSE
91
+ - README.markdown
92
+ files:
93
+ - .document
94
+ - .gitignore
95
+ - LICENSE
96
+ - README.markdown
97
+ - Rakefile
98
+ - VERSION
99
+ - lib/supr.rb
100
+ - lib/supr/client.rb
101
+ - lib/supr/url.rb
102
+ - lib/supr/utils.rb
103
+ - lib/supr/version.rb
104
+ - spec/spec.opts
105
+ - spec/spec_helper.rb
106
+ - spec/supr_spec.rb
107
+ has_rdoc: true
108
+ homepage: http://github.com/blakechambers/supr
109
+ licenses: []
110
+
111
+ post_install_message:
112
+ rdoc_options:
113
+ - --charset=UTF-8
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project:
137
+ rubygems_version: 1.3.7
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Use the su.pr API to shorten or expand URLs
141
+ test_files:
142
+ - spec/spec_helper.rb
143
+ - spec/supr_spec.rb