uncoil 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/.travis.yml +7 -0
- data/.yardoc/checksums +3 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +2 -0
- data/README.md +48 -8
- data/lib/uncoil.rb +52 -24
- data/lib/uncoil/version.rb +1 -1
- data/lib/uncoil_submethods.rb +38 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/uncoil_response_spec.rb +21 -0
- data/spec/uncoil_spec.rb +16 -15
- data/uncoil.gemspec +1 -0
- metadata +29 -10
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/.yardoc/checksums
ADDED
Binary file
|
data/.yardoc/proxy_types
ADDED
data/README.md
CHANGED
@@ -1,21 +1,63 @@
|
|
1
|
-
# uncoil
|
1
|
+
# uncoil - the link unshortening gem
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/stim371/uncoil.png)](http://travis-ci.org/stim371/uncoil)
|
2
4
|
|
3
5
|
The uncoil gem is a one stop shop for un-shortening urls.
|
4
6
|
|
5
7
|
The idea is based off of my site http://uncoil.me and I built this as part of my UWE-Ruby fall project.
|
6
8
|
|
7
9
|
## Why the heck does this exist?
|
8
|
-
This gem is all about transparency
|
10
|
+
This gem is all about transparency, safety and knowing where you are going on the internet.
|
11
|
+
|
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.**
|
9
13
|
|
10
14
|
There are a few instances where it may come in handy:
|
11
15
|
|
12
16
|
* You want to make sure you're not heading into an obviously sketchy site
|
13
17
|
* You're at work and want to keep out the NSFW
|
14
18
|
|
15
|
-
##
|
16
|
-
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Install the gem:
|
22
|
+
|
23
|
+
gem install uncoil
|
24
|
+
|
25
|
+
Add it to your file:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'uncoil'
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
* If you have Bitly login credentials, use them to create a new instance:
|
17
33
|
|
18
|
-
|
34
|
+
```ruby
|
35
|
+
@a = Bitly.new(:bitlyuser => 'YOURAPIUSERNAME', :bitlykey => 'YOURAPIKEY')
|
36
|
+
# Or if you don't have any auth criteria
|
37
|
+
@a = Bitly.new
|
38
|
+
# in which case it will use a standard HTTP loop to find bitly destination urls
|
39
|
+
```
|
40
|
+
|
41
|
+
* Use the `expand` method to see where the short link goes:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
@a.expand('http://bit.ly/2EEjBl')
|
45
|
+
# or pass in an array of links
|
46
|
+
@a.expand(['http://bit.ly/2EEjBl','http://is.gd/gbKNRq'])
|
47
|
+
```
|
48
|
+
|
49
|
+
For each link you pass in, you will get a separate `Uncoil::Response` object out with parameters for `long_url`, `short_url` and `error`
|
50
|
+
|
51
|
+
A full usage cycle may look like this:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
@a = Bitly.new(:bitlyuser => 'YOURAPIUSERNAME', :bitlykey => 'YOURAPIKEY')
|
55
|
+
@b = @a.expand('http://bit.ly/2EEjBl') # => <Uncoil::Response:0x00000100a0d948 @long_url="http://www.cnn.com/" @short_url="http://bit.ly/2EEjBl" @error=nil>
|
56
|
+
|
57
|
+
@b.long_url # => "http://www.cnn.com/"
|
58
|
+
@b.short_url # => "http://bit.ly/2EEjBl"
|
59
|
+
@b.error # => nil
|
60
|
+
```
|
19
61
|
|
20
62
|
## How the app works
|
21
63
|
|
@@ -23,9 +65,7 @@ But by expanding it with uncoil, I can see that it goes to http://www.cnn.com
|
|
23
65
|
2. See if it matches with any of the supported APIs
|
24
66
|
* If so, it calls the correct API method
|
25
67
|
* If no matching method is found, it runs through an HTTP loop until it receives a 200 response
|
26
|
-
3. It then returns a
|
27
|
-
|
28
|
-
## Current Issues
|
68
|
+
3. It then returns a Response object containing, among other items, the full url
|
29
69
|
|
30
70
|
## Future Enhancements
|
31
71
|
Here are a few ideas I have for the future:
|
data/lib/uncoil.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
require 'bitly'
|
2
|
-
|
3
|
-
require 'net/http'
|
4
|
-
require 'json'
|
2
|
+
require_relative 'uncoil_submethods'
|
5
3
|
|
4
|
+
# @author Joel Stimson
|
6
5
|
class Uncoil
|
7
6
|
ISGD_ROOT_URL = "http://is.gd/forward.php?format=json&shorturl="
|
8
7
|
BITLY_DOM_ARRAY = %w[bit.ly, j.mp, bitlypro.com, cs.pn, nyti.ms]
|
9
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
|
+
#
|
10
19
|
def initialize options = {}
|
11
20
|
Bitly.use_api_version_3
|
12
21
|
@bitly_access = false
|
@@ -17,11 +26,28 @@ class Uncoil
|
|
17
26
|
@bitly_access = true
|
18
27
|
end
|
19
28
|
end
|
29
|
+
|
30
|
+
# A class method version of the main expand method. This will not have access to the bit.ly API, but it's faster than having to create an instance and then use it for a one-off request.
|
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)
|
39
|
+
end
|
20
40
|
|
41
|
+
# The main method used for all requests. This method will delegate to submethods based on the domain of the link given.
|
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
|
+
#
|
21
47
|
def expand url_arr
|
22
48
|
output_array = Array(url_arr).flatten.map do |short_url|
|
23
|
-
short_url
|
24
|
-
domain
|
49
|
+
short_url = clean_url(short_url)
|
50
|
+
domain = identify_domain(short_url)
|
25
51
|
|
26
52
|
begin
|
27
53
|
long_url =
|
@@ -43,34 +69,29 @@ class Uncoil
|
|
43
69
|
output_array.length == 1 ? output_array[0] : output_array
|
44
70
|
end
|
45
71
|
|
72
|
+
|
73
|
+
# Contacts the bit.ly API to see if the domain is a bitlypro domain, which are custom domains purchased by 3rd parties but managed by bit.ly
|
74
|
+
#
|
75
|
+
# @param [String] url_domain The domain to check against the bit.ly API.
|
76
|
+
#
|
46
77
|
def check_bitly_pro url_domain
|
47
78
|
@bitly_instance.bitly_pro_domain(url_domain)
|
48
79
|
end
|
49
|
-
|
50
|
-
def uncoil_bitly short_url
|
51
|
-
@bitly_instance.expand(short_url).long_url
|
52
|
-
end
|
53
|
-
|
54
|
-
def uncoil_isgd short_url
|
55
|
-
JSON.parse(open(ISGD_ROOT_URL + "#{short_url}") { |file| file.read } )["url"]
|
56
|
-
end
|
57
|
-
|
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)
|
65
|
-
end
|
66
|
-
end
|
67
80
|
|
68
|
-
# helper methods to clean up the code above
|
69
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
|
+
#
|
70
86
|
def identify_domain short_url
|
71
87
|
clean_url(short_url).split("/")[2].to_s
|
72
88
|
end
|
89
|
+
|
73
90
|
|
91
|
+
# Standardizes the url by adding a protocol if there isn't one and removing trailing slashes
|
92
|
+
#
|
93
|
+
# @param [String] short_url A single url to be cleaned up.
|
94
|
+
#
|
74
95
|
def clean_url short_url
|
75
96
|
short_url = "http://" << short_url unless short_url =~ /^https?:\/\//
|
76
97
|
short_url.chop! if short_url[-1] == "/"
|
@@ -79,9 +100,16 @@ class Uncoil
|
|
79
100
|
|
80
101
|
end
|
81
102
|
|
103
|
+
|
82
104
|
class Uncoil::Response
|
83
105
|
attr_reader :long_url, :short_url, :error
|
84
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
|
+
#
|
85
113
|
def initialize(long_url, short_url, error)
|
86
114
|
@long_url = long_url
|
87
115
|
@short_url = short_url
|
data/lib/uncoil/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
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/spec_helper.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'uncoil'
|
3
|
+
|
4
|
+
describe "the response object" do
|
5
|
+
|
6
|
+
subject { Uncoil.new(:bitlyuser => CREDENTIALS['bitlyuser'], :bitlykey => CREDENTIALS['bitlykey'])}
|
7
|
+
|
8
|
+
before(:all) {
|
9
|
+
@subject = subject.expand("http://is.gd/gbKNRq")
|
10
|
+
}
|
11
|
+
|
12
|
+
it "should return a response object" do
|
13
|
+
@subject.class.should eq Uncoil::Response
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should respond to getter methods" do
|
17
|
+
@subject.long_url.should_not eq nil
|
18
|
+
@subject.short_url.should_not eq nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/spec/uncoil_spec.rb
CHANGED
@@ -3,21 +3,26 @@ require 'uncoil'
|
|
3
3
|
|
4
4
|
describe Uncoil do
|
5
5
|
|
6
|
-
subject { Uncoil.new(:bitlyuser =>
|
6
|
+
subject { Uncoil.new(:bitlyuser => CREDENTIALS['bitlyuser'], :bitlykey => CREDENTIALS['bitlykey'])}
|
7
7
|
|
8
|
-
describe "
|
8
|
+
describe "#expand class method" do
|
9
|
+
it "should successfully return a response object" do
|
10
|
+
Uncoil.expand("http://tinyurl.com/736swvl").class.should eq Uncoil::Response
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
subject.uncoil_bitly("http://bit.ly/2EEjBl").should eq expected_result
|
14
|
-
end
|
13
|
+
it "should bring back the correct link" do
|
14
|
+
response = Uncoil.expand("http://tinyurl.com/736swvl")
|
15
|
+
response.long_url.should eq "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm"
|
15
16
|
end
|
17
|
+
end
|
16
18
|
|
17
|
-
|
19
|
+
describe "when using the submethods" do
|
20
|
+
|
21
|
+
context "when trying to undo a bit.ly and bit.ly pro link" do
|
18
22
|
it "should bring back the correct long link" do
|
19
|
-
|
20
|
-
subject.uncoil_bitly(
|
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
|
+
}
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
@@ -36,15 +41,11 @@ describe Uncoil do
|
|
36
41
|
|
37
42
|
describe "the main expand method" do
|
38
43
|
|
39
|
-
it "should return a response object" do
|
40
|
-
subject.expand("http://is.gd/gbKNRq").class.should eq Uncoil::Response
|
41
|
-
end
|
42
|
-
|
43
44
|
it "should raise an error for non-urls" do
|
44
45
|
subject.expand("a").error.should_not be_nil
|
45
46
|
end
|
46
47
|
|
47
|
-
context "
|
48
|
+
context "when expanding a link" do
|
48
49
|
|
49
50
|
def check_response response, expected_result
|
50
51
|
response.long_url.should eq expected_result[:long_url]
|
data/uncoil.gemspec
CHANGED
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: 1.
|
4
|
+
version: 1.1.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-
|
12
|
+
date: 2012-03-07 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2152984160 !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: *2152984160
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: guard-rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &2152983000 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2152983000
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: simplecov
|
38
|
-
requirement: &
|
38
|
+
requirement: &2152981500 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,21 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2152981500
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &2152980660 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152980660
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: bitly
|
49
|
-
requirement: &
|
60
|
+
requirement: &2152979620 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ! '>='
|
@@ -54,7 +65,7 @@ dependencies:
|
|
54
65
|
version: '0'
|
55
66
|
type: :runtime
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *2152979620
|
58
69
|
description: Uncoil is a gem to unshorten urls so you know where obscured links really
|
59
70
|
go. If you have bitly login credentials, initialize an instance of Uncoil to use
|
60
71
|
the bitly API.
|
@@ -65,6 +76,10 @@ extensions: []
|
|
65
76
|
extra_rdoc_files: []
|
66
77
|
files:
|
67
78
|
- .gitignore
|
79
|
+
- .travis.yml
|
80
|
+
- .yardoc/checksums
|
81
|
+
- .yardoc/objects/root.dat
|
82
|
+
- .yardoc/proxy_types
|
68
83
|
- Gemfile
|
69
84
|
- Guardfile
|
70
85
|
- Manifest
|
@@ -72,8 +87,10 @@ files:
|
|
72
87
|
- Rakefile
|
73
88
|
- lib/uncoil.rb
|
74
89
|
- lib/uncoil/version.rb
|
90
|
+
- lib/uncoil_submethods.rb
|
75
91
|
- spec/helper_method_spec.rb
|
76
92
|
- spec/spec_helper.rb
|
93
|
+
- spec/uncoil_response_spec.rb
|
77
94
|
- spec/uncoil_spec.rb
|
78
95
|
- uncoil.gemspec
|
79
96
|
homepage: https://github.com/stim371/uncoil
|
@@ -104,4 +121,6 @@ summary: Uncoil is a gem to unshorten urls so you know where obscured links real
|
|
104
121
|
test_files:
|
105
122
|
- spec/helper_method_spec.rb
|
106
123
|
- spec/spec_helper.rb
|
124
|
+
- spec/uncoil_response_spec.rb
|
107
125
|
- spec/uncoil_spec.rb
|
126
|
+
has_rdoc:
|