shorturl 0.8.8 → 1.0.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/.gitignore +1 -0
- data/{ChangeLog → ChangeLog.txt} +0 -0
- data/{MIT-LICENSE → LICENSE.txt} +0 -0
- data/{README → README.rdoc} +28 -1
- data/Rakefile +42 -0
- data/{TODO → TODO.rdoc} +0 -0
- data/examples/shorten.rb +3 -3
- data/lib/shorturl.rb +35 -142
- data/lib/shorturl/exceptions.rb +7 -0
- data/lib/shorturl/service.rb +62 -0
- data/lib/shorturl/services.rb +12 -0
- data/lib/shorturl/services/bitly.rb +28 -0
- data/lib/shorturl/services/lns.rb +18 -0
- data/lib/shorturl/services/metamark.rb +20 -0
- data/lib/shorturl/services/minilink.rb +17 -0
- data/lib/shorturl/services/moourl.rb +22 -0
- data/lib/shorturl/services/shiturl.rb +20 -0
- data/lib/shorturl/services/shorl.rb +19 -0
- data/lib/shorturl/services/shortify.rb +20 -0
- data/lib/shorturl/services/snipurl.rb +22 -0
- data/lib/shorturl/services/tinyurl.rb +20 -0
- data/lib/shorturl/services/url.rb +21 -0
- data/lib/shorturl/services/vurl.rb +17 -0
- data/lib/shorturl/version.rb +3 -0
- data/shorturl.gemspec +27 -0
- data/test/helper.rb +11 -0
- data/test/tc_service.rb +6 -10
- data/test/tc_shorturl.rb +3 -12
- data/test/ts_all.rb +0 -5
- metadata +80 -63
- data/doc/classes/InvalidService.html +0 -111
- data/doc/classes/Service.html +0 -202
- data/doc/classes/Service.src/M000003.html +0 -28
- data/doc/classes/Service.src/M000004.html +0 -26
- data/doc/classes/ShortURL.html +0 -227
- data/doc/classes/ShortURL.src/M000001.html +0 -18
- data/doc/classes/ShortURL.src/M000002.html +0 -22
- data/doc/created.rid +0 -1
- data/doc/files/ChangeLog.html +0 -190
- data/doc/files/MIT-LICENSE.html +0 -129
- data/doc/files/README.html +0 -289
- data/doc/files/TODO.html +0 -113
- data/doc/files/lib/shorturl_rb.html +0 -119
- data/doc/fr_class_index.html +0 -29
- data/doc/fr_file_index.html +0 -31
- data/doc/fr_method_index.html +0 -30
- data/doc/index.html +0 -24
- data/doc/rdoc-style.css +0 -208
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
doc/
|
data/{ChangeLog → ChangeLog.txt}
RENAMED
File without changes
|
data/{MIT-LICENSE → LICENSE.txt}
RENAMED
File without changes
|
data/{README → README.rdoc}
RENAMED
@@ -13,7 +13,6 @@ http://rubyforge.org/frs/?group_id=732 if you do not want to use the gem.
|
|
13
13
|
|
14
14
|
== Supported services
|
15
15
|
Here is the list of the services supported by ShortURL:
|
16
|
-
* http://rubyurl.com
|
17
16
|
* http://tinyurl.com
|
18
17
|
* http://shorl.com
|
19
18
|
* http://snipurl.com
|
@@ -34,6 +33,7 @@ Here is the list of the services supported by ShortURL:
|
|
34
33
|
* http://moourl.com
|
35
34
|
* http://urltea.com
|
36
35
|
* http://vurl.me
|
36
|
+
* http://bit.ly
|
37
37
|
|
38
38
|
== Usage:
|
39
39
|
call-seq:
|
@@ -63,12 +63,39 @@ The second parameter represents the service you want to use. These are:
|
|
63
63
|
* <tt>:moourl</tt>
|
64
64
|
* <tt>:urltea</tt>
|
65
65
|
* <tt>:vurl</tt>
|
66
|
+
* <tt>:bitly</tt>**
|
66
67
|
|
67
68
|
|
68
69
|
You can use <tt>ShortURL.valid_services</tt> to obtain a
|
69
70
|
list of the valid services (in case I forget to update the
|
70
71
|
documentation)
|
71
72
|
|
73
|
+
Bitly**
|
74
|
+
-------
|
75
|
+
|
76
|
+
Their API changed to require an API key.
|
77
|
+
|
78
|
+
Two painfree steps to fix this.
|
79
|
+
|
80
|
+
1) Get yours easily right now from:
|
81
|
+
|
82
|
+
http://bitly.com/a/your_api_key
|
83
|
+
|
84
|
+
|
85
|
+
2) Save it in ~/.shorturl similar to this YAML template:
|
86
|
+
|
87
|
+
--- Start of file ~/.shorturl ---
|
88
|
+
|
89
|
+
---
|
90
|
+
bitly:
|
91
|
+
username: O_adsfasdfasfasfd
|
92
|
+
key: R_afasdfasdfasdf
|
93
|
+
|
94
|
+
--- END of file ~/.shorturl ---
|
95
|
+
|
96
|
+
|
97
|
+
You're done! Have a martini. Cheers.
|
98
|
+
|
72
99
|
== Thanks
|
73
100
|
- Marcel Molina Jr., Devin Mullins for some ideas
|
74
101
|
- imperator from #ruby-lang (I don't know your real name, sorry) for
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/testtask"
|
3
|
+
require "rdoc/task"
|
4
|
+
|
5
|
+
task :default => [ :test, :doc ]
|
6
|
+
|
7
|
+
desc "Run the tests"
|
8
|
+
Rake::TestTask.new("test") { |t|
|
9
|
+
t.libs << 'test'
|
10
|
+
t.pattern = "test/**/ts_*.rb"
|
11
|
+
t.verbose = true
|
12
|
+
}
|
13
|
+
|
14
|
+
desc "Write the documentation"
|
15
|
+
RDoc::Task.new("doc") { |rdoc|
|
16
|
+
rdoc.rdoc_dir = "doc"
|
17
|
+
rdoc.title = "ShortURL Documentation"
|
18
|
+
# rdoc.options << "--line-numbers --inline-source"
|
19
|
+
rdoc.rdoc_files.include("README.rdoc")
|
20
|
+
rdoc.rdoc_files.include("TODO.rdoc")
|
21
|
+
rdoc.rdoc_files.include("LICENSE.txt")
|
22
|
+
rdoc.rdoc_files.include("ChangeLog.txt")
|
23
|
+
rdoc.rdoc_files.include("lib/*.rb")
|
24
|
+
rdoc.rdoc_files.exclude("test/*")
|
25
|
+
}
|
26
|
+
|
27
|
+
desc "Upload documentation to RubyForge"
|
28
|
+
task :upload_doc do
|
29
|
+
sh "scp -r doc/* robbyrussell@rubyforge.org:/var/www/gforge-projects/shorturl"
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
desc "Statistics for the code"
|
34
|
+
task :stats do
|
35
|
+
begin
|
36
|
+
require "code_statistics"
|
37
|
+
CodeStatistics.new(["Code", "lib"],
|
38
|
+
["Units", "test"]).to_s
|
39
|
+
rescue LoadError
|
40
|
+
puts "Couldn't load code_statistics (install rails)"
|
41
|
+
end
|
42
|
+
end
|
data/{TODO → TODO.rdoc}
RENAMED
File without changes
|
data/examples/shorten.rb
CHANGED
@@ -11,9 +11,9 @@ end
|
|
11
11
|
def main
|
12
12
|
begin
|
13
13
|
case ARGV.length
|
14
|
-
when 0
|
15
|
-
when 1
|
16
|
-
else
|
14
|
+
when 0 then usage
|
15
|
+
when 1 then puts ShortURL.shorten(ARGV[0])
|
16
|
+
else puts ShortURL.shorten(ARGV[0], ARGV[1].to_sym)
|
17
17
|
end
|
18
18
|
rescue InvalidService
|
19
19
|
puts "Invalid service"
|
data/lib/shorturl.rb
CHANGED
@@ -3,148 +3,45 @@
|
|
3
3
|
# Created by Vincent Foley on 2005-06-02
|
4
4
|
#
|
5
5
|
|
6
|
-
require "
|
7
|
-
require "cgi"
|
6
|
+
require "shorturl/services"
|
8
7
|
require "uri"
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
# field which contains the long URL, and the block of what to do
|
23
|
-
# with the HTML code you get.
|
24
|
-
def initialize(hostname) # :yield: service
|
25
|
-
@hostname = hostname
|
26
|
-
@port = 80
|
27
|
-
@code = 200
|
28
|
-
@method = :post
|
29
|
-
@action = "/"
|
30
|
-
@field = "url"
|
31
|
-
|
32
|
-
if block_given?
|
33
|
-
yield self
|
34
|
-
end
|
8
|
+
require "yaml"
|
9
|
+
|
10
|
+
module ShortURL
|
11
|
+
CREDENTIALS_PATH = File.join(Gem.user_home,'.shorturl')
|
12
|
+
|
13
|
+
def self.credentials
|
14
|
+
@credentials ||= begin
|
15
|
+
if File.file?(CREDENTIALS_PATH)
|
16
|
+
YAML.load_file(CREDENTIALS_PATH)
|
17
|
+
else
|
18
|
+
{}
|
19
|
+
end
|
20
|
+
end
|
35
21
|
end
|
36
22
|
|
37
|
-
|
38
|
-
|
39
|
-
def call(url)
|
40
|
-
Net::HTTP.start(@hostname, @port) { |http|
|
41
|
-
response = case @method
|
42
|
-
when :post: http.post(@action, "#{@field}=#{CGI.escape(url)}")
|
43
|
-
when :get: http.get("#{@action}?#{@field}=#{CGI.escape(url)}")
|
44
|
-
end
|
45
|
-
if response.code == @code.to_s
|
46
|
-
@response_block ? @response_block.call(response) : @block.call(response.read_body)
|
47
|
-
end
|
48
|
-
}
|
49
|
-
rescue Errno::ECONNRESET => e
|
50
|
-
raise ServiceNotAvailable, e.to_s, e.backtrace
|
23
|
+
def self.credentials_for(service)
|
24
|
+
credentials.fetch(service,{})
|
51
25
|
end
|
52
|
-
end
|
53
26
|
|
54
|
-
class ShortURL
|
55
27
|
# Hash table of all the supported services. The key is a symbol
|
56
28
|
# representing the service (usually the hostname minus the .com,
|
57
29
|
# .net, etc.) The value is an instance of Service with all the
|
58
30
|
# parameters set so that when +instance+.call is invoked, the
|
59
31
|
# shortened URL is returned.
|
60
|
-
|
61
|
-
:
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
:
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
:shorl => Service.new("shorl.com") { |s|
|
74
|
-
s.action = "/create.php"
|
75
|
-
s.block = lambda { |body| URI.extract(body)[2] }
|
76
|
-
},
|
77
|
-
|
78
|
-
# SnipURL offers a restful HTTP API but it cannot be used without
|
79
|
-
# registration.
|
80
|
-
:snipurl => Service.new("snipurl.com") { |s|
|
81
|
-
s.action = "/site/index"
|
82
|
-
s.field = "url"
|
83
|
-
|
84
|
-
# As with other services, this is far from elegant and might break
|
85
|
-
# any time. Might just be better to do some HTML parsing instead.
|
86
|
-
s.block = lambda { |body| URI.extract(body).grep(/http:\/\/snipurl.com/)[0] }
|
87
|
-
},
|
88
|
-
|
89
|
-
:metamark => Service.new("metamark.net") { |s|
|
90
|
-
s.action = "/add"
|
91
|
-
s.field = "long_url"
|
92
|
-
s.block = lambda { |body| URI.extract(body).grep(/xrl.us/)[0] }
|
93
|
-
},
|
94
|
-
|
95
|
-
:minilink => Service.new("minilink.org") { |s|
|
96
|
-
s.method = :get
|
97
|
-
s.block = lambda { |body| URI.extract(body)[-1] }
|
98
|
-
},
|
99
|
-
|
100
|
-
:lns => Service.new("ln-s.net") { |s|
|
101
|
-
s.method = :get
|
102
|
-
s.action = "/home/api.jsp"
|
103
|
-
s.block = lambda { |body| URI.extract(body)[0] }
|
104
|
-
},
|
105
|
-
|
106
|
-
:shiturl => Service.new("shiturl.com") { |s|
|
107
|
-
s.method = :get
|
108
|
-
s.action = "/make.php"
|
109
|
-
s.block = lambda { |body| URI.extract(body).grep(/shiturl/)[0] }
|
110
|
-
},
|
111
|
-
|
112
|
-
:shortify => Service.new("shortify.wikinote.com") { |s|
|
113
|
-
s.method = :get
|
114
|
-
s.action = "/shorten.php"
|
115
|
-
s.block = lambda { |body| URI.extract(body).grep(/shortify/)[-1] }
|
116
|
-
},
|
117
|
-
|
118
|
-
:moourl => Service.new("moourl.com") { |s|
|
119
|
-
s.code = 302
|
120
|
-
s.action = "/create/"
|
121
|
-
s.method = :get
|
122
|
-
s.field = "source"
|
123
|
-
s.response_block = lambda { |res| "http://moourl.com/" + res["location"].match(/\?moo=/).post_match }
|
124
|
-
},
|
125
|
-
|
126
|
-
:bitly => Service.new("bit.ly") { |s|
|
127
|
-
s.method = :get
|
128
|
-
s.action = "/index.php"
|
129
|
-
s.field = "url"
|
130
|
-
s.block = lambda { |body|
|
131
|
-
body.match(%r{<input id="shortened-url" value="(.*)" />}).captures[0]
|
132
|
-
}
|
133
|
-
},
|
134
|
-
|
135
|
-
:ur1 => Service.new("ur1.ca") { |s|
|
136
|
-
s.method = :post
|
137
|
-
s.action = "/"
|
138
|
-
s.field = "longurl"
|
139
|
-
s.block = lambda { |body| URI.extract(body).grep(/ur1/)[0] }
|
140
|
-
},
|
141
|
-
|
142
|
-
:vurl => Service.new("vurl.me") { |s|
|
143
|
-
s.method = :get
|
144
|
-
s.action = "/shorten"
|
145
|
-
s.field = "url"
|
146
|
-
s.block = lambda { |body| body }
|
147
|
-
}
|
32
|
+
SERVICES = {
|
33
|
+
:tinyurl => Services::TinyURL.new,
|
34
|
+
:shorl => Services::Shorl.new,
|
35
|
+
:snipurl => Services::SnipURL.new,
|
36
|
+
:metamark => Services::Metamark.new,
|
37
|
+
:minilink => Services::Minilink.new,
|
38
|
+
:lns => Services::Lns.new,
|
39
|
+
:shiturl => Services::ShitURL.new,
|
40
|
+
:shortify => Services::Shortify.new,
|
41
|
+
:moourl => Services::MooURL.new,
|
42
|
+
:bitly => Services::Bitly.new,
|
43
|
+
:ur1 => Services::Url.new,
|
44
|
+
:vurl => Services::Vurl.new,
|
148
45
|
|
149
46
|
# :skinnylink => Service.new("skinnylink.com") { |s|
|
150
47
|
# s.block = lambda { |body| URI.extract(body).grep(/skinnylink/)[0] }
|
@@ -195,11 +92,8 @@ class ShortURL
|
|
195
92
|
|
196
93
|
# Array containing symbols representing all the implemented URL
|
197
94
|
# shortening services
|
198
|
-
@@valid_services = @@services.keys
|
199
|
-
|
200
|
-
# Returns @@valid_services
|
201
95
|
def self.valid_services
|
202
|
-
|
96
|
+
SERVICES.keys
|
203
97
|
end
|
204
98
|
|
205
99
|
# Main method of ShortURL, its usage is quite simple, just give an
|
@@ -209,7 +103,6 @@ class ShortURL
|
|
209
103
|
#
|
210
104
|
# Valid +service+ values:
|
211
105
|
#
|
212
|
-
# * <tt>:rubyurl</tt>
|
213
106
|
# * <tt>:tinyurl</tt>
|
214
107
|
# * <tt>:shorl</tt>
|
215
108
|
# * <tt>:snipurl</tt>
|
@@ -229,11 +122,11 @@ class ShortURL
|
|
229
122
|
# * <tt>:orz</tt>
|
230
123
|
#
|
231
124
|
# call-seq:
|
232
|
-
# ShortURL.shorten("http://mypage.com") => Uses
|
233
|
-
# ShortURL.shorten("http://mypage.com", :
|
234
|
-
def self.shorten(url, service = :
|
235
|
-
if
|
236
|
-
|
125
|
+
# ShortURL.shorten("http://mypage.com") => Uses TinyURL
|
126
|
+
# ShortURL.shorten("http://mypage.com", :bitly)
|
127
|
+
def self.shorten(url, service = :tinyurl)
|
128
|
+
if SERVICES.has_key?(service)
|
129
|
+
SERVICES[service].call(url)
|
237
130
|
else
|
238
131
|
raise InvalidService
|
239
132
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "shorturl/exceptions"
|
2
|
+
require "net/http"
|
3
|
+
require "net/https"
|
4
|
+
require "cgi"
|
5
|
+
|
6
|
+
module ShortURL
|
7
|
+
class Service
|
8
|
+
attr_accessor :port, :code, :method, :action, :field, :block, :response_block, :ssl
|
9
|
+
|
10
|
+
# Intialize the service with a hostname (required parameter) and you
|
11
|
+
# can override the default values for the HTTP port, expected HTTP
|
12
|
+
# return code, the form method to use, the form action, the form
|
13
|
+
# field which contains the long URL, and the block of what to do
|
14
|
+
# with the HTML code you get.
|
15
|
+
def initialize(hostname) # :yield: service
|
16
|
+
@hostname = hostname
|
17
|
+
@port = 80
|
18
|
+
@code = 200
|
19
|
+
@method = :post
|
20
|
+
@action = "/"
|
21
|
+
@field = "url"
|
22
|
+
@ssl = false
|
23
|
+
|
24
|
+
if block_given?
|
25
|
+
yield self
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Now that our service is set up, call it with all the parameters to
|
30
|
+
# (hopefully) return only the shortened URL.
|
31
|
+
def call(url)
|
32
|
+
http = Net::HTTP.new(@hostname, @port)
|
33
|
+
http.use_ssl = @ssl
|
34
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
35
|
+
|
36
|
+
http.start do
|
37
|
+
response = case @method
|
38
|
+
when :post
|
39
|
+
http.post(@action, "#{@field}=#{CGI.escape(url)}")
|
40
|
+
when :get
|
41
|
+
http.get("#{@action}?#{@field}=#{CGI.escape(url)}")
|
42
|
+
end
|
43
|
+
|
44
|
+
if response.code == @code.to_s
|
45
|
+
on_response(response)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
rescue Errno::ECONNRESET => e
|
49
|
+
raise ServiceNotAvailable, e.to_s, e.backtrace
|
50
|
+
end
|
51
|
+
|
52
|
+
# Extracts the shortened URL from a response body.
|
53
|
+
def on_body(body)
|
54
|
+
body
|
55
|
+
end
|
56
|
+
|
57
|
+
# Extracts the shortened URL from the response.
|
58
|
+
def on_response(response)
|
59
|
+
on_body(response.read_body)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "shorturl/services/tinyurl"
|
2
|
+
require "shorturl/services/shorl"
|
3
|
+
require "shorturl/services/snipurl"
|
4
|
+
require "shorturl/services/metamark"
|
5
|
+
require "shorturl/services/minilink"
|
6
|
+
require "shorturl/services/lns"
|
7
|
+
require "shorturl/services/shiturl"
|
8
|
+
require "shorturl/services/shortify"
|
9
|
+
require "shorturl/services/moourl"
|
10
|
+
require "shorturl/services/bitly"
|
11
|
+
require "shorturl/services/url"
|
12
|
+
require "shorturl/services/vurl"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "shorturl/service"
|
2
|
+
|
3
|
+
module ShortURL
|
4
|
+
module Services
|
5
|
+
class Bitly < Service
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super("api-ssl.bitly.com")
|
9
|
+
|
10
|
+
@method = :get
|
11
|
+
@port = 443
|
12
|
+
@ssl = true
|
13
|
+
@action = "/v3/shorten/"
|
14
|
+
|
15
|
+
creds = ShortURL.credentials_for('bitly')
|
16
|
+
username = creds['username']
|
17
|
+
key = creds['key']
|
18
|
+
|
19
|
+
@field = "format=txt&login=#{username}&apiKey=#{key}&longUrl"
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_body(body)
|
23
|
+
body
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|