uncoil 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +2 -1
- data/README.md +24 -1
- data/Rakefile +5 -0
- data/lib/uncoil.rb +23 -98
- data/lib/uncoil/domain_finder.rb +33 -0
- data/lib/uncoil/expander.rb +24 -0
- data/lib/uncoil/expanders/bitly_expander.rb +5 -0
- data/lib/uncoil/expanders/default_expander.rb +17 -0
- data/lib/uncoil/expanders/isgd_expander.rb +19 -0
- data/lib/uncoil/response.rb +11 -0
- data/lib/uncoil/version.rb +1 -1
- data/spec/fixtures/uncoil_cassettes/array_of_links.yml +102 -0
- data/spec/fixtures/uncoil_cassettes/bitly_api.yml +69 -0
- data/spec/fixtures/uncoil_cassettes/isgd_api.yml +36 -0
- data/spec/fixtures/uncoil_cassettes/isgd_response.yml +36 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/uncoil/domain_finder_spec.rb +12 -0
- data/spec/uncoil/expander_spec.rb +5 -0
- data/spec/uncoil_response_spec.rb +17 -14
- data/spec/uncoil_spec.rb +53 -64
- data/uncoil.gemspec +3 -0
- metadata +95 -28
- data/.yardoc/checksums +0 -3
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -2
- data/lib/uncoil_submethods.rb +0 -38
- data/spec/helper_method_spec.rb +0 -55
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MWM0ZjY2YWI1MTM5ZmQ4M2M4NjY0ZDYwMzI2MTg1NTM2YTQyNGI0YQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDBlOTBjZDU5NTI5OGFjY2RjN2JkN2YyYzg5NmQ5Zjc0MjJmODlkNA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
M2IxY2Y5NmZiNTI0MDE2NjllNzRlMzM2ODYwZmIwMWE4Y2IxNDM5N2M5M2Vl
|
10
|
+
MGFjYmQ0Yjc0OTI0NGFiNGZjYzM5ZThkOTlhYWNlMjZiYWU5NDQ0ZWY2MTZl
|
11
|
+
ZDJiYjI3YWFkYjNhNjVhNWMyNTFiOGM5NDNmZTJlYmQwOGE4NmU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODFmOTY3NzlhMjk5NWFhZWE0YjA2ZGI0YzdkMTIxNWE4YjBhNTFjMjEzYWIx
|
14
|
+
YmQzYWQ2OTQ5N2E4ZDk1Y2VmOGE1MTFhOTdkZTE1OGQ3MjgyZTlhNWE2Zjli
|
15
|
+
M2U3ODQ4YWIyNjNkOTc0MTdkYmIxYzVmMzZiMDgzMWVhYjYzODQ=
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -6,7 +6,7 @@ The uncoil gem is a one stop shop for un-shortening urls.
|
|
6
6
|
|
7
7
|
The idea is based off of my site http://uncoil.me and I built this as part of my UWE-Ruby fall project.
|
8
8
|
|
9
|
-
|
9
|
+
### Why the heck does this exist?
|
10
10
|
This gem is all about transparency, safety and knowing where you are going on the internet.
|
11
11
|
|
12
12
|
The last straw was seeing TechCrunch articles with titles like "Don't click on this one specific goo.gl link! It's a virus!" (like [this](http://techcrunch.com/2010/12/07/twitter-virus/) one), which was flabbergasting. How is it that a tech blog and community's only response to these kind of threats is so reactionary and linear? **We can do better than that.**
|
@@ -29,6 +29,17 @@ require 'uncoil'
|
|
29
29
|
```
|
30
30
|
|
31
31
|
## Usage
|
32
|
+
|
33
|
+
### One-off Calls
|
34
|
+
If you want to just make a single call, give this a try:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
Uncoil.expand('http://bit.ly/2EEjBl') # => <Uncoil::Response:0x00000100a0d948 @long_url="http://www.cnn.com/" @short_url="http://bit.ly/2EEjBl" @error=nil>
|
38
|
+
```
|
39
|
+
|
40
|
+
### Creating an Instance
|
41
|
+
If you need to make repeated calls or would like to access the bitly api, you need to create an instance.
|
42
|
+
|
32
43
|
* If you have Bitly login credentials, use them to create a new instance:
|
33
44
|
|
34
45
|
```ruby
|
@@ -76,3 +87,15 @@ Here are a few ideas I have for the future:
|
|
76
87
|
* Dynamic method assignment based on domain.
|
77
88
|
* This goes with the modularized structure above, because it allows you to just drop more API files into the folder and not have to modify the main method
|
78
89
|
* Better error handling (I'd appreciate any comments on what to catch and what to leave)
|
90
|
+
|
91
|
+
## License
|
92
|
+
|
93
|
+
The MIT License (MIT)
|
94
|
+
|
95
|
+
Copyright (c) 2012 Joel Stimson
|
96
|
+
|
97
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
98
|
+
|
99
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
100
|
+
|
101
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
data/lib/uncoil.rb
CHANGED
@@ -1,118 +1,43 @@
|
|
1
|
+
require 'uncoil/domain_finder'
|
2
|
+
require 'uncoil/expander'
|
3
|
+
require 'uncoil/response'
|
4
|
+
|
1
5
|
require 'bitly'
|
2
|
-
require_relative 'uncoil_submethods'
|
3
6
|
|
4
|
-
# @author Joel Stimson
|
5
7
|
class Uncoil
|
6
|
-
|
7
|
-
BITLY_DOM_ARRAY = %w[bit.ly, j.mp, bitlypro.com, cs.pn, nyti.ms]
|
8
|
-
|
9
|
-
# Creates a new Uncoil object and will log into Bit.ly if you provide credentials
|
10
|
-
#
|
11
|
-
# @option options [String] :bitlyuser A key for your Bit.ly API username
|
12
|
-
# @option options [String] :bitlykey A key for your Bit.ly API key
|
13
|
-
#
|
14
|
-
# @return [Class] the new instance of the Uncoil class
|
15
|
-
#
|
16
|
-
# @example Set up a new instance
|
17
|
-
# Uncoil.new(:bitlyuser => CREDENTIALS['bitlyuser'], :bitlykey => CREDENTIALS['bitlykey']) => "#<Uncoil:0x00000102560d30 @bitly_access=true>"
|
18
|
-
#
|
19
|
-
def initialize options = {}
|
8
|
+
def initialize(options = {})
|
20
9
|
Bitly.use_api_version_3
|
21
|
-
|
22
|
-
|
23
|
-
# create bitly instance if the auth criteria are all entered by user
|
10
|
+
|
24
11
|
if options.has_key?(:bitlyuser) && options.has_key?(:bitlykey)
|
25
12
|
@bitly_instance = Bitly.new("#{options[:bitlyuser]}", "#{options[:bitlykey]}")
|
26
|
-
@bitly_access = true
|
27
13
|
end
|
28
14
|
end
|
29
15
|
|
30
|
-
|
31
|
-
|
32
|
-
# @param [String, Array] short_url The single url or array of urls you would like to expand
|
33
|
-
#
|
34
|
-
# @example Use the class method for a one-off request
|
35
|
-
# Uncoil.expand("http://tinyurl.com/736swvl") # => #<Uncoil::Response:0x00000101ed9250 @long_url="http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm", @short_url="http://tinyurl.com/736swvl", @error=nil>
|
36
|
-
#
|
37
|
-
def self.expand short_url
|
38
|
-
Uncoil.new.expand(short_url)
|
16
|
+
def self.expand(urls)
|
17
|
+
Uncoil.new.expand(urls)
|
39
18
|
end
|
40
19
|
|
41
|
-
|
42
|
-
|
43
|
-
# @param [String, Array] url_arr This can be a single url as a String or an array of Strings that the method will expand in order
|
44
|
-
#
|
45
|
-
# @return [Uncoil::Response] Returns a response object with getters for the long and short url
|
46
|
-
#
|
47
|
-
def expand url_arr
|
48
|
-
output_array = Array(url_arr).flatten.map do |short_url|
|
49
|
-
short_url = clean_url(short_url)
|
50
|
-
domain = identify_domain(short_url)
|
51
|
-
|
52
|
-
begin
|
53
|
-
long_url =
|
54
|
-
if @bitly_access && ( BITLY_DOM_ARRAY.include?(domain) || check_bitly_pro(domain) )
|
55
|
-
uncoil_bitly(short_url)
|
56
|
-
elsif domain == "is.gd"
|
57
|
-
uncoil_isgd(short_url)
|
58
|
-
else
|
59
|
-
uncoil_other(short_url)
|
60
|
-
end
|
61
|
-
rescue => exception
|
62
|
-
long_url = nil
|
63
|
-
error = exception.message
|
64
|
-
end
|
65
|
-
# return a response object for each time through the loop
|
66
|
-
Response.new(long_url, short_url, error)
|
67
|
-
end
|
68
|
-
# here's the return
|
69
|
-
output_array.length == 1 ? output_array[0] : output_array
|
20
|
+
def expand(urls)
|
21
|
+
format_output(expand_all(urls))
|
70
22
|
end
|
71
23
|
|
24
|
+
private
|
72
25
|
|
73
|
-
|
74
|
-
|
75
|
-
# @param [String] url_domain The domain to check against the bit.ly API.
|
76
|
-
#
|
77
|
-
def check_bitly_pro url_domain
|
78
|
-
@bitly_instance.bitly_pro_domain(url_domain)
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
# Extracts the domain from the link to help match it with the right sub-method to expand the url
|
83
|
-
#
|
84
|
-
# @param [String] short_url A single url to extract a domain from.
|
85
|
-
#
|
86
|
-
def identify_domain short_url
|
87
|
-
clean_url(short_url).split("/")[2].to_s
|
26
|
+
def expand_all(urls)
|
27
|
+
Array(urls).flatten.map { |short_url| response_for(short_url) }
|
88
28
|
end
|
89
|
-
|
90
29
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
30
|
+
def response_for(url)
|
31
|
+
response = Response.new({:short_url => url})
|
32
|
+
begin
|
33
|
+
response.long_url = Expander.expand(url, @bitly_instance)
|
34
|
+
rescue => exception
|
35
|
+
response.long_url, response.error = nil, exception.message
|
36
|
+
end
|
37
|
+
response
|
99
38
|
end
|
100
|
-
|
101
|
-
end
|
102
39
|
|
103
|
-
|
104
|
-
|
105
|
-
attr_reader :long_url, :short_url, :error
|
106
|
-
|
107
|
-
# Creates a new Response object with attributes for the original and short url, as well as any errors that occured. It is called at the end of 'expand' method.
|
108
|
-
#
|
109
|
-
# @param [String] long_url The expanded url that we were looking for.
|
110
|
-
# @param [String] short_url The original, short url that we used to look up the long url.
|
111
|
-
# @param [String] error The error output if anything went wrong during the request. And I mean ANYTHING from a code error to an HTTP issue. It catches it all.
|
112
|
-
#
|
113
|
-
def initialize(long_url, short_url, error)
|
114
|
-
@long_url = long_url
|
115
|
-
@short_url = short_url
|
116
|
-
@error = error
|
40
|
+
def format_output(output_array)
|
41
|
+
output_array.length == 1 ? output_array[0] : output_array
|
117
42
|
end
|
118
43
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
class DomainFinder
|
4
|
+
def domain_for(short_url)
|
5
|
+
#TODO: new object here?
|
6
|
+
match_host_to_provider(host_for(short_url))
|
7
|
+
end
|
8
|
+
|
9
|
+
def host_for(url)
|
10
|
+
URI.parse(url).host
|
11
|
+
end
|
12
|
+
|
13
|
+
def match_host_to_provider(host)
|
14
|
+
case
|
15
|
+
when bitly_domains.include?(host)
|
16
|
+
:bitly
|
17
|
+
when isgd_domains.include?(host)
|
18
|
+
:isgd
|
19
|
+
else
|
20
|
+
host
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def bitly_domains
|
27
|
+
%w[bit.ly j.mp bitlypro.com cs.pn nyti.ms]
|
28
|
+
end
|
29
|
+
|
30
|
+
def isgd_domains
|
31
|
+
'is.gd'
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative './expanders/default_expander'
|
2
|
+
require_relative './expanders/bitly_expander'
|
3
|
+
require_relative './expanders/isgd_expander'
|
4
|
+
|
5
|
+
module Expander
|
6
|
+
class << self
|
7
|
+
def expand(short_url, bitly_instance = nil)
|
8
|
+
case
|
9
|
+
when domain_for(short_url) == :bitly && bitly_instance
|
10
|
+
BitlyExpander.expand(short_url, bitly_instance)
|
11
|
+
when domain_for(short_url) == :isgd
|
12
|
+
IsgdExpander.expand(short_url)
|
13
|
+
else
|
14
|
+
DefaultExpander.expand(short_url)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def domain_for(short_url)
|
21
|
+
DomainFinder.new.domain_for(short_url)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
class DefaultExpander
|
5
|
+
class << self
|
6
|
+
def expand(short_url)
|
7
|
+
response = Typhoeus.head(short_url, :followlocation => true)
|
8
|
+
location_from_response(response)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def location_from_response(response)
|
14
|
+
response.options[:effective_url]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'typhoeus'
|
3
|
+
|
4
|
+
class IsgdExpander
|
5
|
+
ISGD_ROOT_URL = "http://is.gd/forward.php?format=json&shorturl="
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def expand(short_url)
|
9
|
+
response = Typhoeus.get("#{ISGD_ROOT_URL}#{short_url}")
|
10
|
+
isgd_location_from_response(response.response_body)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def isgd_location_from_response(body)
|
16
|
+
JSON.parse(body)["url"]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/uncoil/version.rb
CHANGED
@@ -0,0 +1,102 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.bit.ly/v3/expand?apiKey=R_7a6f6d845668a8a7bb3e0c80ee3c28d6&login=stim371&shortUrl=http://bit.ly/2EEjBl
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Server:
|
16
|
+
- nginx
|
17
|
+
Date:
|
18
|
+
- Thu, 12 Sep 2013 22:46:57 GMT
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Connection:
|
22
|
+
- keep-alive
|
23
|
+
Mime-Version:
|
24
|
+
- '1.0'
|
25
|
+
Content-Length:
|
26
|
+
- '199'
|
27
|
+
body:
|
28
|
+
encoding: US-ASCII
|
29
|
+
string: ! '{ "status_code": 200, "status_txt": "OK", "data": { "expand": [ {
|
30
|
+
"short_url": "http:\/\/bit.ly\/2EEjBl", "long_url": "http:\/\/www.cnn.com\/",
|
31
|
+
"user_hash": "2EEjBl", "global_hash": "2EEjBl" } ] } }
|
32
|
+
|
33
|
+
'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Thu, 12 Sep 2013 22:47:09 GMT
|
36
|
+
- request:
|
37
|
+
method: get
|
38
|
+
uri: http://is.gd/forward.php?format=json&shorturl=http://is.gd/gbKNRq
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ''
|
42
|
+
headers:
|
43
|
+
User-Agent:
|
44
|
+
- Typhoeus - https://github.com/typhoeus/typhoeus
|
45
|
+
response:
|
46
|
+
status:
|
47
|
+
code: 200
|
48
|
+
message: OK
|
49
|
+
headers:
|
50
|
+
Server:
|
51
|
+
- nginx
|
52
|
+
Date:
|
53
|
+
- Thu, 12 Sep 2013 22:46:57 GMT
|
54
|
+
Content-Type:
|
55
|
+
- text/javascript; charset=utf8
|
56
|
+
Transfer-Encoding:
|
57
|
+
- chunked
|
58
|
+
Connection:
|
59
|
+
- keep-alive
|
60
|
+
X-Powered-By:
|
61
|
+
- PHP/5.2.17
|
62
|
+
Access-Control-Allow-Origin:
|
63
|
+
- ! '*'
|
64
|
+
body:
|
65
|
+
encoding: US-ASCII
|
66
|
+
string: ! '{ "url": "http://www.google.com" }'
|
67
|
+
http_version:
|
68
|
+
recorded_at: Thu, 12 Sep 2013 22:47:09 GMT
|
69
|
+
- request:
|
70
|
+
method: get
|
71
|
+
uri: http://api.bit.ly/v3/expand?apiKey=R_7a6f6d845668a8a7bb3e0c80ee3c28d6&login=stim371&shortUrl=http://cs.pn/vsZpra
|
72
|
+
body:
|
73
|
+
encoding: US-ASCII
|
74
|
+
string: ''
|
75
|
+
headers: {}
|
76
|
+
response:
|
77
|
+
status:
|
78
|
+
code: 200
|
79
|
+
message: OK
|
80
|
+
headers:
|
81
|
+
Server:
|
82
|
+
- nginx
|
83
|
+
Date:
|
84
|
+
- Thu, 12 Sep 2013 22:46:57 GMT
|
85
|
+
Content-Type:
|
86
|
+
- application/json; charset=utf-8
|
87
|
+
Connection:
|
88
|
+
- keep-alive
|
89
|
+
Mime-Version:
|
90
|
+
- '1.0'
|
91
|
+
Content-Length:
|
92
|
+
- '222'
|
93
|
+
body:
|
94
|
+
encoding: US-ASCII
|
95
|
+
string: ! '{ "status_code": 200, "status_txt": "OK", "data": { "expand": [ {
|
96
|
+
"short_url": "http:\/\/cs.pn\/vsZpra", "long_url": "http:\/\/www.c-spanvideo.org\/program\/CainNew",
|
97
|
+
"user_hash": "vsZpra", "global_hash": "vPQYzq" } ] } }
|
98
|
+
|
99
|
+
'
|
100
|
+
http_version:
|
101
|
+
recorded_at: Thu, 12 Sep 2013 22:47:09 GMT
|
102
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,69 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://api.bit.ly/v3/expand?apiKey=R_7a6f6d845668a8a7bb3e0c80ee3c28d6&login=stim371&shortUrl=http://bit.ly/2EEjBl
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Server:
|
16
|
+
- nginx
|
17
|
+
Date:
|
18
|
+
- Thu, 12 Sep 2013 22:46:55 GMT
|
19
|
+
Content-Type:
|
20
|
+
- application/json; charset=utf-8
|
21
|
+
Connection:
|
22
|
+
- keep-alive
|
23
|
+
Mime-Version:
|
24
|
+
- '1.0'
|
25
|
+
Content-Length:
|
26
|
+
- '199'
|
27
|
+
body:
|
28
|
+
encoding: US-ASCII
|
29
|
+
string: ! '{ "status_code": 200, "status_txt": "OK", "data": { "expand": [ {
|
30
|
+
"short_url": "http:\/\/bit.ly\/2EEjBl", "long_url": "http:\/\/www.cnn.com\/",
|
31
|
+
"user_hash": "2EEjBl", "global_hash": "2EEjBl" } ] } }
|
32
|
+
|
33
|
+
'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Thu, 12 Sep 2013 22:47:07 GMT
|
36
|
+
- request:
|
37
|
+
method: get
|
38
|
+
uri: http://api.bit.ly/v3/expand?apiKey=R_7a6f6d845668a8a7bb3e0c80ee3c28d6&login=stim371&shortUrl=http://cs.pn/vsZpra
|
39
|
+
body:
|
40
|
+
encoding: US-ASCII
|
41
|
+
string: ''
|
42
|
+
headers: {}
|
43
|
+
response:
|
44
|
+
status:
|
45
|
+
code: 200
|
46
|
+
message: OK
|
47
|
+
headers:
|
48
|
+
Server:
|
49
|
+
- nginx
|
50
|
+
Date:
|
51
|
+
- Thu, 12 Sep 2013 22:46:55 GMT
|
52
|
+
Content-Type:
|
53
|
+
- application/json; charset=utf-8
|
54
|
+
Connection:
|
55
|
+
- keep-alive
|
56
|
+
Mime-Version:
|
57
|
+
- '1.0'
|
58
|
+
Content-Length:
|
59
|
+
- '222'
|
60
|
+
body:
|
61
|
+
encoding: US-ASCII
|
62
|
+
string: ! '{ "status_code": 200, "status_txt": "OK", "data": { "expand": [ {
|
63
|
+
"short_url": "http:\/\/cs.pn\/vsZpra", "long_url": "http:\/\/www.c-spanvideo.org\/program\/CainNew",
|
64
|
+
"user_hash": "vsZpra", "global_hash": "vPQYzq" } ] } }
|
65
|
+
|
66
|
+
'
|
67
|
+
http_version:
|
68
|
+
recorded_at: Thu, 12 Sep 2013 22:47:08 GMT
|
69
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://is.gd/forward.php?format=json&shorturl=http://is.gd/gbKNRq
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Typhoeus - https://github.com/typhoeus/typhoeus
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Server:
|
18
|
+
- nginx
|
19
|
+
Date:
|
20
|
+
- Thu, 12 Sep 2013 22:46:56 GMT
|
21
|
+
Content-Type:
|
22
|
+
- text/javascript; charset=utf8
|
23
|
+
Transfer-Encoding:
|
24
|
+
- chunked
|
25
|
+
Connection:
|
26
|
+
- keep-alive
|
27
|
+
X-Powered-By:
|
28
|
+
- PHP/5.2.17
|
29
|
+
Access-Control-Allow-Origin:
|
30
|
+
- ! '*'
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{ "url": "http://www.google.com" }'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Thu, 12 Sep 2013 22:47:08 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: http://is.gd/forward.php?format=json&shorturl=http://is.gd/gbKNRq
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Typhoeus - https://github.com/typhoeus/typhoeus
|
12
|
+
response:
|
13
|
+
status:
|
14
|
+
code: 200
|
15
|
+
message: OK
|
16
|
+
headers:
|
17
|
+
Server:
|
18
|
+
- nginx
|
19
|
+
Date:
|
20
|
+
- Thu, 12 Sep 2013 22:46:55 GMT
|
21
|
+
Content-Type:
|
22
|
+
- text/javascript; charset=utf8
|
23
|
+
Transfer-Encoding:
|
24
|
+
- chunked
|
25
|
+
Connection:
|
26
|
+
- keep-alive
|
27
|
+
X-Powered-By:
|
28
|
+
- PHP/5.2.17
|
29
|
+
Access-Control-Allow-Origin:
|
30
|
+
- ! '*'
|
31
|
+
body:
|
32
|
+
encoding: US-ASCII
|
33
|
+
string: ! '{ "url": "http://www.google.com" }'
|
34
|
+
http_version:
|
35
|
+
recorded_at: Thu, 12 Sep 2013 22:47:07 GMT
|
36
|
+
recorded_with: VCR 2.5.0
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,22 @@
|
|
1
1
|
require 'simplecov'
|
2
|
+
require 'vcr'
|
3
|
+
require 'webmock/rspec'
|
2
4
|
SimpleCov.start
|
3
5
|
|
6
|
+
require 'uncoil'
|
7
|
+
|
4
8
|
CREDENTIALS = YAML.load_file("./credentials.yml")['bitly']
|
9
|
+
|
10
|
+
VCR.configure do |c|
|
11
|
+
c.cassette_library_dir = 'spec/fixtures/uncoil_cassettes'
|
12
|
+
c.hook_into :webmock
|
13
|
+
c.allow_http_connections_when_no_cassette = true
|
14
|
+
c.configure_rspec_metadata!
|
15
|
+
c.default_cassette_options = {
|
16
|
+
:record => :new_episodes
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
RSpec.configure do |c|
|
21
|
+
c.treat_symbols_as_metadata_keys_with_true_values = true
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DomainFinder do
|
4
|
+
it 'should return the host from a url' do
|
5
|
+
subject.domain_for('http://bit.ly/abcde13').should eq :bitly
|
6
|
+
subject.domain_for('http://tinyurl.com/abcde13').should eq 'tinyurl.com'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should raise error if url empty' do
|
10
|
+
lambda{ subject.domain_for(nil) }.should raise_error
|
11
|
+
end
|
12
|
+
end
|
@@ -1,21 +1,24 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'uncoil'
|
3
2
|
|
4
|
-
describe
|
3
|
+
describe Uncoil::Response, :vcr => { :cassette_name => 'isgd_response' } do
|
5
4
|
|
6
|
-
subject { Uncoil.
|
5
|
+
subject { Uncoil.expand('http://is.gd/gbKNRq') }
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
}
|
11
|
-
|
12
|
-
it "should return a response object" do
|
13
|
-
@subject.class.should eq Uncoil::Response
|
7
|
+
it 'should return a response object' do
|
8
|
+
subject.class.should eq Uncoil::Response
|
14
9
|
end
|
15
10
|
|
16
|
-
it
|
17
|
-
|
18
|
-
|
11
|
+
it 'should respond to getter methods' do
|
12
|
+
lambda{subject.long_url}.should_not raise_error
|
13
|
+
lambda{subject.short_url}.should_not raise_error
|
14
|
+
lambda{subject.error}.should_not raise_error
|
19
15
|
end
|
20
|
-
|
21
|
-
|
16
|
+
|
17
|
+
describe 'response body' do
|
18
|
+
it 'should assign variables correctly' do
|
19
|
+
subject.long_url.should eq 'http://www.google.com'
|
20
|
+
subject.short_url.should eq 'http://is.gd/gbKNRq'
|
21
|
+
subject.error.should be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/uncoil_spec.rb
CHANGED
@@ -1,101 +1,90 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'uncoil'
|
3
2
|
|
4
3
|
describe Uncoil do
|
5
4
|
|
6
5
|
subject { Uncoil.new(:bitlyuser => CREDENTIALS['bitlyuser'], :bitlykey => CREDENTIALS['bitlykey'])}
|
7
6
|
|
8
|
-
describe
|
9
|
-
it
|
10
|
-
Uncoil.expand(
|
7
|
+
describe '#expand class method', :vcr => { :cassette_name => 'isgd_response' } do
|
8
|
+
it 'should successfully return a response object' do
|
9
|
+
Uncoil.expand('http://is.gd/gbKNRq').class.should eq Uncoil::Response
|
11
10
|
end
|
12
11
|
|
13
12
|
it "should bring back the correct link" do
|
14
|
-
response = Uncoil.expand(
|
15
|
-
response.long_url.should eq "http://www.
|
13
|
+
response = Uncoil.expand('http://is.gd/gbKNRq')
|
14
|
+
response.long_url.should eq "http://www.google.com"
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
19
|
-
describe "
|
20
|
-
|
21
|
-
context "when trying to undo a bit.ly and bit.ly pro link" do
|
22
|
-
it "should bring back the correct long link" do
|
23
|
-
{"http://bit.ly/2EEjBl" => "http://www.cnn.com/", "http://cs.pn/vsZpra" => "http://www.c-spanvideo.org/program/CainNew" }.each { |short_url, long_url|
|
24
|
-
subject.uncoil_bitly(short_url).should eq long_url
|
25
|
-
}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "when trying to undo an is.gd link" do
|
30
|
-
it "should bring back the correct long link" do
|
31
|
-
subject.uncoil_isgd("http://is.gd/gbKNRq").should eq "http://www.google.com"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
context "when trying to undo from other services" do
|
36
|
-
it "should bring back the correct long link" do
|
37
|
-
subject.uncoil_other("http://tinyurl.com/736swvl").should eq "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "the main expand method" do
|
18
|
+
describe "#expand instance method" do
|
43
19
|
|
44
20
|
it "should raise an error for non-urls" do
|
45
21
|
subject.expand("a").error.should_not be_nil
|
46
22
|
end
|
47
23
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
24
|
+
def check_response(response, expected_result)
|
25
|
+
response.long_url.should eq expected_result[:long_url]
|
26
|
+
response.short_url.should eq expected_result[:short_url]
|
27
|
+
response.error.should eq expected_result[:error]
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'for bitly api', :vcr => { :cassette_name => 'bitly_api' } do
|
55
31
|
|
56
|
-
it
|
57
|
-
expected_result = Hash[:long_url =>
|
58
|
-
response = subject.expand(
|
32
|
+
it 'should expand bitly correctly' do
|
33
|
+
expected_result = Hash[:long_url => 'http://www.cnn.com/', :short_url => 'http://bit.ly/2EEjBl', :error => nil]
|
34
|
+
response = subject.expand('http://bit.ly/2EEjBl')
|
59
35
|
check_response response, expected_result
|
60
36
|
end
|
61
37
|
|
62
|
-
it
|
63
|
-
expected_result = Hash[:long_url =>
|
64
|
-
response = subject.expand(
|
38
|
+
it 'should expand bitlypro domains correctly' do
|
39
|
+
expected_result = Hash[:long_url => 'http://www.c-spanvideo.org/program/CainNew', :short_url => 'http://cs.pn/vsZpra', :error => nil]
|
40
|
+
response = subject.expand('http://cs.pn/vsZpra')
|
65
41
|
check_response response, expected_result
|
66
42
|
end
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'for isgd api', :vcr => { :cassette_name => 'isgd_api' } do
|
46
|
+
it 'should expand isgd domains correctly' do
|
47
|
+
expected_result = Hash[:long_url => 'http://www.google.com', :short_url => 'http://is.gd/gbKNRq', :error => nil]
|
48
|
+
response = subject.expand('http://is.gd/gbKNRq')
|
71
49
|
check_response response, expected_result
|
72
50
|
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'for other requests' do
|
54
|
+
it 'should expand other shortened urls correctly' do
|
55
|
+
expected_result = Hash[:long_url => 'http://paulgraham.com/', :short_url => 'http://tinyurl.com/p8o2', :error => nil]
|
56
|
+
response = subject.expand('http://tinyurl.com/p8o2')
|
77
57
|
check_response response, expected_result
|
78
58
|
end
|
59
|
+
|
60
|
+
it 'should expand https urls correctly' do
|
61
|
+
expected_result = Hash[:long_url => 'https://www.facebook.com/photo.php?fbid=436380063146407&l=7554e08219', :short_url => 'http://fb.me/6txI6APS5', :error => nil]
|
62
|
+
response = subject.expand('http://fb.me/6txI6APS5')
|
63
|
+
check_response response, expected_result
|
64
|
+
end
|
65
|
+
end
|
79
66
|
|
80
|
-
|
67
|
+
describe 'with an array input', :vcr => { :cassette_name => 'array_of_links' } do
|
81
68
|
|
82
|
-
|
83
|
-
arr_of_links = ["http://bit.ly/2EEjBl","http://is.gd/gbKNRq","http://cs.pn/vsZpra"]
|
84
|
-
@response = subject.expand(arr_of_links)
|
85
|
-
}
|
69
|
+
arr_of_links = %w[http://bit.ly/2EEjBl http://is.gd/gbKNRq http://cs.pn/vsZpra]
|
86
70
|
|
87
|
-
|
88
|
-
@response.class.should eq Array
|
89
|
-
end
|
71
|
+
let(:resp) {subject.expand(arr_of_links) }
|
90
72
|
|
91
|
-
it
|
92
|
-
|
73
|
+
it 'should return an array' do
|
74
|
+
resp.class.should eq Array
|
93
75
|
end
|
94
76
|
|
95
|
-
it
|
96
|
-
|
97
|
-
@response.each_with_index { |response_array, index| check_response response_array, @expected_result[index] }
|
77
|
+
it 'should return an array of response objects' do
|
78
|
+
resp.each { |r| r.class.should eq Uncoil::Response }
|
98
79
|
end
|
80
|
+
|
81
|
+
it 'should successfully expand all links' do
|
82
|
+
@expected_result = [Hash[:long_url => 'http://www.cnn.com/', :short_url => 'http://bit.ly/2EEjBl', :error => nil],
|
83
|
+
Hash[:long_url => 'http://www.google.com', :short_url => 'http://is.gd/gbKNRq', :error => nil],
|
84
|
+
Hash[:long_url => 'http://www.c-spanvideo.org/program/CainNew', :short_url => 'http://cs.pn/vsZpra', :error => nil]]
|
85
|
+
resp.each_with_index { |response, index|
|
86
|
+
check_response(response, @expected_result[index])
|
87
|
+
}
|
99
88
|
end
|
100
89
|
end
|
101
90
|
end
|
data/uncoil.gemspec
CHANGED
@@ -23,6 +23,9 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_development_dependency "guard-rspec"
|
24
24
|
s.add_development_dependency "simplecov"
|
25
25
|
s.add_development_dependency "rake"
|
26
|
+
s.add_development_dependency "vcr"
|
27
|
+
s.add_development_dependency "webmock"
|
26
28
|
|
27
29
|
s.add_runtime_dependency "bitly"
|
30
|
+
s.add_runtime_dependency "typhoeus"
|
28
31
|
end
|
metadata
CHANGED
@@ -1,71 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uncoil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Joel Stimson
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-09-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
17
|
- - ! '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: guard-rspec
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - ! '>='
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
42
|
name: simplecov
|
38
|
-
requirement:
|
39
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
45
|
- - ! '>='
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
48
|
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
47
55
|
- !ruby/object:Gem::Dependency
|
48
56
|
name: rake
|
49
|
-
requirement:
|
50
|
-
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
59
|
- - ! '>='
|
53
60
|
- !ruby/object:Gem::Version
|
54
61
|
version: '0'
|
55
62
|
type: :development
|
56
63
|
prerelease: false
|
57
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: vcr
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
58
97
|
- !ruby/object:Gem::Dependency
|
59
98
|
name: bitly
|
60
|
-
requirement:
|
61
|
-
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: typhoeus
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
62
114
|
requirements:
|
63
115
|
- - ! '>='
|
64
116
|
- !ruby/object:Gem::Version
|
65
117
|
version: '0'
|
66
118
|
type: :runtime
|
67
119
|
prerelease: false
|
68
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ! '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
69
125
|
description: Uncoil is a gem to unshorten urls so you know where obscured links really
|
70
126
|
go. If you have bitly login credentials, initialize an instance of Uncoil to use
|
71
127
|
the bitly API.
|
@@ -77,50 +133,61 @@ extra_rdoc_files: []
|
|
77
133
|
files:
|
78
134
|
- .gitignore
|
79
135
|
- .travis.yml
|
80
|
-
- .yardoc/checksums
|
81
|
-
- .yardoc/objects/root.dat
|
82
|
-
- .yardoc/proxy_types
|
83
136
|
- Gemfile
|
84
137
|
- Guardfile
|
85
138
|
- Manifest
|
86
139
|
- README.md
|
87
140
|
- Rakefile
|
88
141
|
- lib/uncoil.rb
|
142
|
+
- lib/uncoil/domain_finder.rb
|
143
|
+
- lib/uncoil/expander.rb
|
144
|
+
- lib/uncoil/expanders/bitly_expander.rb
|
145
|
+
- lib/uncoil/expanders/default_expander.rb
|
146
|
+
- lib/uncoil/expanders/isgd_expander.rb
|
147
|
+
- lib/uncoil/response.rb
|
89
148
|
- lib/uncoil/version.rb
|
90
|
-
-
|
91
|
-
- spec/
|
149
|
+
- spec/fixtures/uncoil_cassettes/array_of_links.yml
|
150
|
+
- spec/fixtures/uncoil_cassettes/bitly_api.yml
|
151
|
+
- spec/fixtures/uncoil_cassettes/isgd_api.yml
|
152
|
+
- spec/fixtures/uncoil_cassettes/isgd_response.yml
|
92
153
|
- spec/spec_helper.rb
|
154
|
+
- spec/uncoil/domain_finder_spec.rb
|
155
|
+
- spec/uncoil/expander_spec.rb
|
93
156
|
- spec/uncoil_response_spec.rb
|
94
157
|
- spec/uncoil_spec.rb
|
95
158
|
- uncoil.gemspec
|
96
159
|
homepage: https://github.com/stim371/uncoil
|
97
160
|
licenses: []
|
161
|
+
metadata: {}
|
98
162
|
post_install_message:
|
99
163
|
rdoc_options: []
|
100
164
|
require_paths:
|
101
165
|
- lib
|
102
166
|
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
-
none: false
|
104
167
|
requirements:
|
105
168
|
- - ! '>='
|
106
169
|
- !ruby/object:Gem::Version
|
107
170
|
version: '0'
|
108
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
-
none: false
|
110
172
|
requirements:
|
111
173
|
- - ! '>='
|
112
174
|
- !ruby/object:Gem::Version
|
113
175
|
version: '0'
|
114
176
|
requirements: []
|
115
177
|
rubyforge_project: uncoil
|
116
|
-
rubygems_version: 1.
|
178
|
+
rubygems_version: 2.1.3
|
117
179
|
signing_key:
|
118
|
-
specification_version:
|
180
|
+
specification_version: 4
|
119
181
|
summary: Uncoil is a gem to unshorten urls so you know where obscured links really
|
120
182
|
go.
|
121
183
|
test_files:
|
122
|
-
- spec/
|
184
|
+
- spec/fixtures/uncoil_cassettes/array_of_links.yml
|
185
|
+
- spec/fixtures/uncoil_cassettes/bitly_api.yml
|
186
|
+
- spec/fixtures/uncoil_cassettes/isgd_api.yml
|
187
|
+
- spec/fixtures/uncoil_cassettes/isgd_response.yml
|
123
188
|
- spec/spec_helper.rb
|
189
|
+
- spec/uncoil/domain_finder_spec.rb
|
190
|
+
- spec/uncoil/expander_spec.rb
|
124
191
|
- spec/uncoil_response_spec.rb
|
125
192
|
- spec/uncoil_spec.rb
|
126
193
|
has_rdoc:
|
data/.yardoc/checksums
DELETED
data/.yardoc/objects/root.dat
DELETED
Binary file
|
data/.yardoc/proxy_types
DELETED
data/lib/uncoil_submethods.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'net/http'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
class Uncoil
|
6
|
-
|
7
|
-
# Expands any links that are bitly or bitlypro domains as long as you have logged into the bitly API.
|
8
|
-
#
|
9
|
-
# @param [String] short_url The short url you would like to expand.
|
10
|
-
#
|
11
|
-
def uncoil_bitly short_url
|
12
|
-
@bitly_instance.expand(short_url).long_url
|
13
|
-
end
|
14
|
-
|
15
|
-
# Expands any links that are isgd domains.
|
16
|
-
#
|
17
|
-
# @param [String] short_url The short url you would like to expand.
|
18
|
-
#
|
19
|
-
def uncoil_isgd short_url
|
20
|
-
JSON.parse(open(ISGD_ROOT_URL + "#{short_url}") { |file| file.read } )["url"]
|
21
|
-
end
|
22
|
-
|
23
|
-
# Expands any links that do not match the above domains.
|
24
|
-
#
|
25
|
-
# @param [String] short_url The short url you would like to expand.
|
26
|
-
# @param [Integer, 10] depth The number of redirects you would like this method to follow.
|
27
|
-
#
|
28
|
-
def uncoil_other short_url, depth = 10
|
29
|
-
url = URI.encode(short_url)
|
30
|
-
response = Net::HTTP.get_response(URI.parse(url))
|
31
|
-
|
32
|
-
case response
|
33
|
-
when Net::HTTPSuccess then url
|
34
|
-
when Net::HTTPRedirection then uncoil_other(response['location'], depth - 1)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
data/spec/helper_method_spec.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'uncoil'
|
3
|
-
|
4
|
-
describe Uncoil do
|
5
|
-
|
6
|
-
subject { Uncoil.new(:bitlyuser => "stim371", :bitlykey => "R_7a6f6d845668a8a7bb3e0c80ee3c28d6")}
|
7
|
-
|
8
|
-
context "when cleaning up the url" do
|
9
|
-
|
10
|
-
it "should add the prefix if none exists" do
|
11
|
-
subject.clean_url("cnn.com").should eq "http://cnn.com"
|
12
|
-
subject.clean_url("cnn.com/").should eq "http://cnn.com"
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should not add the prefix if one exists" do
|
16
|
-
subject.clean_url("http://cnn.com").should eq "http://cnn.com"
|
17
|
-
subject.clean_url("http://cnn.com/").should eq "http://cnn.com"
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should not add the prefix if a secure one exists" do
|
21
|
-
subject.clean_url("https://cnn.com").should eq "https://cnn.com"
|
22
|
-
subject.clean_url("https://cnn.com/").should eq "https://cnn.com"
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should remove the trailing slash" do
|
26
|
-
subject.clean_url("http://cnn.com/").should eq "http://cnn.com"
|
27
|
-
subject.clean_url("cnn.com/").should eq "http://cnn.com"
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should not remove characters on the end that aren't slashes" do
|
31
|
-
subject.clean_url("http://cnn.com").should eq "http://cnn.com"
|
32
|
-
subject.clean_url("cnn.com").should eq "http://cnn.com"
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when extracting the domain" do
|
38
|
-
it "should correctly extract the domain from a normal url" do
|
39
|
-
subject.identify_domain("http://bit.ly/2EEjBl").should eq "bit.ly"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
context "when checking a domain" do
|
44
|
-
|
45
|
-
it "should identify pro domains" do
|
46
|
-
subject.check_bitly_pro("cs.pn").should be_true
|
47
|
-
subject.check_bitly_pro("nyti.ms").should be_true
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should identify non-pro domains" do
|
51
|
-
subject.check_bitly_pro("bit.ly").should be_false #the bit.ly domain comes back false since its not a "pro" domain
|
52
|
-
subject.check_bitly_pro("tinyurl.com").should be_false
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|