uncoil 0.0.1 → 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/README.md +0 -1
- data/lib/uncoil.rb +68 -59
- data/lib/uncoil/version.rb +1 -1
- data/spec/helper_method_spec.rb +55 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/uncoil_spec.rb +55 -84
- data/uncoil.gemspec +2 -1
- metadata +24 -9
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -36,4 +36,3 @@ Here are a few ideas I have for the future:
|
|
36
36
|
* Dynamic method assignment based on domain.
|
37
37
|
* 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
|
38
38
|
* Better error handling (I'd appreciate any comments on what to catch and what to leave)
|
39
|
-
* Offer the code as a gem
|
data/lib/uncoil.rb
CHANGED
@@ -7,75 +7,84 @@ class Uncoil
|
|
7
7
|
ISGD_ROOT_URL = "http://is.gd/forward.php?format=json&shorturl="
|
8
8
|
BITLY_DOM_ARRAY = %w[bit.ly, j.mp, bitlypro.com, cs.pn, nyti.ms]
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
def identify_domain short_url
|
21
|
-
clean_url(short_url).split("/")[2].to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
def clean_url short_url
|
25
|
-
short_url = "http://" << short_url unless short_url =~ /^https?:\/\//
|
26
|
-
short_url.chop! if short_url[-1] == "/"
|
27
|
-
short_url
|
10
|
+
def initialize options = {}
|
11
|
+
Bitly.use_api_version_3
|
12
|
+
@bitly_access = false
|
13
|
+
|
14
|
+
# create bitly instance if the auth criteria are all entered by user
|
15
|
+
if options.has_key?(:bitlyuser) && options.has_key?(:bitlykey)
|
16
|
+
@bitly_instance = Bitly.new("#{options[:bitlyuser]}", "#{options[:bitlykey]}")
|
17
|
+
@bitly_access = true
|
28
18
|
end
|
19
|
+
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
long_url = uncoil_bitly(short_url)
|
40
|
-
elsif @bitly_access && check_bitly_pro(domain)
|
41
|
-
long_url = uncoil_bitly(short_url)
|
21
|
+
def expand url_arr
|
22
|
+
output_array = Array(url_arr).flatten.map do |short_url|
|
23
|
+
short_url = clean_url(short_url)
|
24
|
+
domain = identify_domain(short_url)
|
25
|
+
|
26
|
+
begin
|
27
|
+
long_url =
|
28
|
+
if @bitly_access && ( BITLY_DOM_ARRAY.include?(domain) || check_bitly_pro(domain) )
|
29
|
+
uncoil_bitly(short_url)
|
42
30
|
elsif domain == "is.gd"
|
43
|
-
|
31
|
+
uncoil_isgd(short_url)
|
44
32
|
else
|
45
|
-
|
33
|
+
uncoil_other(short_url)
|
46
34
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
{ :short_url => short_url , :long_url => long_url, :error => error }
|
53
|
-
|
35
|
+
rescue => exception
|
36
|
+
long_url = nil
|
37
|
+
error = exception.message
|
54
38
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
39
|
+
# return a response object for each time through the loop
|
40
|
+
Response.new(long_url, short_url, error)
|
58
41
|
end
|
42
|
+
# here's the return
|
43
|
+
output_array.length == 1 ? output_array[0] : output_array
|
44
|
+
end
|
59
45
|
|
60
|
-
|
61
|
-
|
62
|
-
|
46
|
+
def check_bitly_pro url_domain
|
47
|
+
@bitly_instance.bitly_pro_domain(url_domain)
|
48
|
+
end
|
63
49
|
|
64
|
-
|
65
|
-
|
66
|
-
|
50
|
+
def uncoil_bitly short_url
|
51
|
+
@bitly_instance.expand(short_url).long_url
|
52
|
+
end
|
67
53
|
|
68
|
-
|
69
|
-
|
70
|
-
|
54
|
+
def uncoil_isgd short_url
|
55
|
+
JSON.parse(open(ISGD_ROOT_URL + "#{short_url}") { |file| file.read } )["url"]
|
56
|
+
end
|
71
57
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
58
|
+
def uncoil_other short_url, depth = 10
|
59
|
+
url = URI.encode(short_url)
|
60
|
+
response = Net::HTTP.get_response(URI.parse(url))
|
61
|
+
|
62
|
+
case response
|
63
|
+
when Net::HTTPSuccess then url
|
64
|
+
when Net::HTTPRedirection then uncoil_other(response['location'], depth - 1)
|
80
65
|
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# helper methods to clean up the code above
|
69
|
+
|
70
|
+
def identify_domain short_url
|
71
|
+
clean_url(short_url).split("/")[2].to_s
|
72
|
+
end
|
73
|
+
|
74
|
+
def clean_url short_url
|
75
|
+
short_url = "http://" << short_url unless short_url =~ /^https?:\/\//
|
76
|
+
short_url.chop! if short_url[-1] == "/"
|
77
|
+
short_url
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class Uncoil::Response
|
83
|
+
attr_reader :long_url, :short_url, :error
|
84
|
+
|
85
|
+
def initialize(long_url, short_url, error)
|
86
|
+
@long_url = long_url
|
87
|
+
@short_url = short_url
|
88
|
+
@error = error
|
89
|
+
end
|
81
90
|
end
|
data/lib/uncoil/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
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
|
data/spec/spec_helper.rb
ADDED
data/spec/uncoil_spec.rb
CHANGED
@@ -1,130 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
require 'uncoil'
|
2
3
|
|
3
4
|
describe Uncoil do
|
4
5
|
|
5
6
|
subject { Uncoil.new(:bitlyuser => "stim371", :bitlykey => "R_7a6f6d845668a8a7bb3e0c80ee3c28d6")}
|
6
7
|
|
7
|
-
context "when cleaning up the url" do
|
8
|
-
|
9
|
-
it "should add the prefix if none exists" do
|
10
|
-
subject.clean_url("cnn.com").should eq "http://cnn.com"
|
11
|
-
subject.clean_url("cnn.com/").should eq "http://cnn.com"
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should not add the prefix if one exists" do
|
15
|
-
subject.clean_url("http://cnn.com").should eq "http://cnn.com"
|
16
|
-
subject.clean_url("http://cnn.com/").should eq "http://cnn.com"
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should not add the prefix if a secure one exists" do
|
20
|
-
subject.clean_url("https://cnn.com").should eq "https://cnn.com"
|
21
|
-
subject.clean_url("https://cnn.com/").should eq "https://cnn.com"
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should remove the trailing slash" do
|
25
|
-
subject.clean_url("http://cnn.com/").should eq "http://cnn.com"
|
26
|
-
subject.clean_url("cnn.com/").should eq "http://cnn.com"
|
27
|
-
end
|
28
|
-
|
29
|
-
it "should not remove characters on the end that aren't slashes" do
|
30
|
-
subject.clean_url("http://cnn.com").should eq "http://cnn.com"
|
31
|
-
subject.clean_url("cnn.com").should eq "http://cnn.com"
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
context "when extracting the domain" do
|
37
|
-
|
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
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
context "when checking a domain" do
|
45
|
-
|
46
|
-
it "should identify pro domains" do
|
47
|
-
subject.check_bitly_pro("cs.pn").should be_true
|
48
|
-
subject.check_bitly_pro("nyti.ms").should be_true
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should identify non-pro domains" do
|
52
|
-
subject.check_bitly_pro("bit.ly").should be_false #the bit.ly domain comes back false since its not a "pro" domain
|
53
|
-
subject.check_bitly_pro("tinyurl.com").should be_false
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
8
|
describe "when using the submethods" do
|
59
9
|
|
60
10
|
context "when trying to undo a bit.ly link" do
|
61
|
-
|
62
11
|
it "should bring back the correct long link" do
|
63
12
|
expected_result = "http://www.cnn.com/"
|
64
13
|
subject.uncoil_bitly("http://bit.ly/2EEjBl").should eq expected_result
|
65
14
|
end
|
66
|
-
|
67
15
|
end
|
68
16
|
|
69
17
|
context "when trying to undo a bit.ly pro link" do
|
70
|
-
|
71
18
|
it "should bring back the correct long link" do
|
72
19
|
expected_result = "http://www.c-spanvideo.org/program/CainNew"
|
73
20
|
subject.uncoil_bitly("http://cs.pn/vsZpra").should eq expected_result
|
74
21
|
end
|
75
|
-
|
76
22
|
end
|
77
23
|
|
78
24
|
context "when trying to undo an is.gd link" do
|
79
|
-
|
80
25
|
it "should bring back the correct long link" do
|
81
26
|
subject.uncoil_isgd("http://is.gd/gbKNRq").should eq "http://www.google.com"
|
82
27
|
end
|
83
|
-
|
84
28
|
end
|
85
29
|
|
86
30
|
context "when trying to undo from other services" do
|
87
|
-
|
88
31
|
it "should bring back the correct long link" do
|
89
32
|
subject.uncoil_other("http://tinyurl.com/736swvl").should eq "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm"
|
90
33
|
end
|
91
|
-
|
92
34
|
end
|
93
35
|
end
|
94
36
|
|
95
|
-
|
96
|
-
|
97
|
-
it "should expand bitly correctly" do
|
98
|
-
expected_result = Hash[:long_url => "http://www.cnn.com/", :short_url => "http://bit.ly/2EEjBl", :error => nil]
|
99
|
-
subject.expand("http://bit.ly/2EEjBl").should eq expected_result
|
100
|
-
end
|
37
|
+
describe "the main expand method" do
|
101
38
|
|
102
|
-
it "should
|
103
|
-
subject.expand("http://
|
39
|
+
it "should return a response object" do
|
40
|
+
subject.expand("http://is.gd/gbKNRq").class.should eq Uncoil::Response
|
104
41
|
end
|
105
42
|
|
106
|
-
it "should
|
107
|
-
subject.expand("
|
43
|
+
it "should raise an error for non-urls" do
|
44
|
+
subject.expand("a").error.should_not be_nil
|
108
45
|
end
|
109
46
|
|
110
|
-
|
111
|
-
short_url = "http://tinyurl.com/736swvl"
|
112
|
-
results_array = Hash[:long_url => "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm", :short_url => "http://tinyurl.com/736swvl", :error => nil]
|
47
|
+
context "and when expanding a link" do
|
113
48
|
|
114
|
-
|
115
|
-
|
49
|
+
def check_response response, expected_result
|
50
|
+
response.long_url.should eq expected_result[:long_url]
|
51
|
+
response.short_url.should eq expected_result[:short_url]
|
52
|
+
response.error.should eq expected_result[:error]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should expand bitly correctly" do
|
56
|
+
expected_result = Hash[:long_url => "http://www.cnn.com/", :short_url => "http://bit.ly/2EEjBl", :error => nil]
|
57
|
+
response = subject.expand("http://bit.ly/2EEjBl")
|
58
|
+
check_response response, expected_result
|
59
|
+
end
|
116
60
|
|
117
|
-
|
118
|
-
|
119
|
-
|
61
|
+
it "should expand bitlypro domains correctly" do
|
62
|
+
expected_result = Hash[:long_url => "http://www.c-spanvideo.org/program/CainNew", :short_url => "http://cs.pn/vsZpra", :error => nil]
|
63
|
+
response = subject.expand("http://cs.pn/vsZpra")
|
64
|
+
check_response response, expected_result
|
65
|
+
end
|
120
66
|
|
121
|
-
|
122
|
-
|
67
|
+
it "should expand isgd domains correctly" do
|
68
|
+
expected_result = Hash[:long_url => "http://www.google.com", :short_url => "http://is.gd/gbKNRq", :error => nil]
|
69
|
+
response = subject.expand("http://is.gd/gbKNRq")
|
70
|
+
check_response response, expected_result
|
71
|
+
end
|
123
72
|
|
124
|
-
|
125
|
-
|
126
|
-
|
73
|
+
it "should expand other shortened urls correctly" do
|
74
|
+
expected_result = Hash[:long_url => "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm", :short_url => "http://tinyurl.com/736swvl", :error => nil]
|
75
|
+
response = subject.expand("http://tinyurl.com/736swvl")
|
76
|
+
check_response response, expected_result
|
77
|
+
end
|
127
78
|
|
79
|
+
context "with an array input" do
|
80
|
+
|
81
|
+
before(:all) {
|
82
|
+
arr_of_links = ["http://bit.ly/2EEjBl","http://is.gd/gbKNRq","http://cs.pn/vsZpra"]
|
83
|
+
@response = subject.expand(arr_of_links)
|
84
|
+
}
|
85
|
+
|
86
|
+
it "should return an array" do
|
87
|
+
@response.class.should eq Array
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should return an array of response objects" do
|
91
|
+
@response.each { |r| r.class.should eq Uncoil::Response }
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should successfully expand all links" do
|
95
|
+
@expected_result = [Hash[:long_url => "http://www.cnn.com/", :short_url => "http://bit.ly/2EEjBl", :error => nil], Hash[:long_url => "http://www.google.com", :short_url => "http://is.gd/gbKNRq", :error => nil],Hash[:long_url => "http://www.c-spanvideo.org/program/CainNew", :short_url => "http://cs.pn/vsZpra", :error => nil]]
|
96
|
+
@response.each_with_index { |response_array, index| check_response response_array, @expected_result[index] }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
128
100
|
end
|
129
|
-
|
130
|
-
end
|
101
|
+
end
|
data/uncoil.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Uncoil::VERSION
|
8
8
|
s.authors = ["Joel Stimson"]
|
9
9
|
s.email = ["contact@cleanroomstudios.com"]
|
10
|
-
s.homepage = "
|
10
|
+
s.homepage = "https://github.com/stim371/uncoil"
|
11
11
|
s.summary = %q{Uncoil is a gem to unshorten urls so you know where obscured links really go.}
|
12
12
|
s.description = %q{Uncoil is a gem to unshorten urls so you know where obscured links really go. If you have bitly login credentials, initialize an instance of Uncoil to use the bitly API.}
|
13
13
|
|
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
s.add_development_dependency "rspec"
|
23
23
|
s.add_development_dependency "guard-rspec"
|
24
|
+
s.add_development_dependency "simplecov"
|
24
25
|
|
25
26
|
s.add_runtime_dependency "bitly"
|
26
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uncoil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2157463580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2157463580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: guard-rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2157463160 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,21 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2157463160
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: simplecov
|
38
|
+
requirement: &2157462740 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2157462740
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: bitly
|
38
|
-
requirement: &
|
49
|
+
requirement: &2157462320 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ! '>='
|
@@ -43,7 +54,7 @@ dependencies:
|
|
43
54
|
version: '0'
|
44
55
|
type: :runtime
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *2157462320
|
47
58
|
description: Uncoil is a gem to unshorten urls so you know where obscured links really
|
48
59
|
go. If you have bitly login credentials, initialize an instance of Uncoil to use
|
49
60
|
the bitly API.
|
@@ -61,9 +72,11 @@ files:
|
|
61
72
|
- Rakefile
|
62
73
|
- lib/uncoil.rb
|
63
74
|
- lib/uncoil/version.rb
|
75
|
+
- spec/helper_method_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
64
77
|
- spec/uncoil_spec.rb
|
65
78
|
- uncoil.gemspec
|
66
|
-
homepage:
|
79
|
+
homepage: https://github.com/stim371/uncoil
|
67
80
|
licenses: []
|
68
81
|
post_install_message:
|
69
82
|
rdoc_options: []
|
@@ -89,4 +102,6 @@ specification_version: 3
|
|
89
102
|
summary: Uncoil is a gem to unshorten urls so you know where obscured links really
|
90
103
|
go.
|
91
104
|
test_files:
|
105
|
+
- spec/helper_method_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
92
107
|
- spec/uncoil_spec.rb
|