uncoil 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in uncoil.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2, :cli => "--color --format d" do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { "spec" }
7
+ # watch('spec/spec_helper.rb') { "spec" }
8
+ end
data/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ Gemfile
2
+ Gemfile.lock
3
+ Guardfile
4
+ README.md
5
+ Rakefile
6
+ lib/uncoil.rb
7
+ spec/spec_helper.rb
8
+ spec/uncoil_spec.rb
9
+ Manifest
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # uncoil
2
+
3
+ The uncoil gem is a one stop shop for un-shortening urls.
4
+
5
+ The idea is based off of my site http://uncoil.me and I built this as part of my UWE-Ruby fall project.
6
+
7
+ ## Why the heck does this exist?
8
+ This gem is all about transparency and safety, and knowing where you are going on the internet.
9
+
10
+ There are a few instances where it may come in handy:
11
+
12
+ * You want to make sure you're not heading into an obviously sketchy site
13
+ * You're at work and want to keep out the NSFW
14
+
15
+ ## Example
16
+ I have no idea where http://bit.ly/2EEjBl really goes.
17
+
18
+ But by expanding it with uncoil, I can see that it goes to http://www.cnn.com
19
+
20
+ ## How the app works
21
+
22
+ 1. Extract the domain from the url
23
+ 2. See if it matches with any of the supported APIs
24
+ * If so, it calls the correct API method
25
+ * If no matching method is found, it runs through an HTTP loop until it receives a 200 response
26
+ 3. It then returns a hash containing, among other items, the full url
27
+
28
+ ## Current Issues
29
+
30
+ ## Future Enhancements
31
+ Here are a few ideas I have for the future:
32
+
33
+ * Additional APIs as they become available
34
+ * These seem to be faster than a general HTTP request loop
35
+ * Modularized structure with each API's content in its own file
36
+ * Dynamic method assignment based on domain.
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
+ * Better error handling (I'd appreciate any comments on what to catch and what to leave)
39
+ * Offer the code as a gem
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rspec'
5
+
6
+ desc "`rake` will default to running `rake:spec`"
7
+ task :default => :spec
8
+
9
+ desc "Run all the rspec examples"
10
+ task :spec do
11
+ system "bundle exec rspec -c spec"
12
+ end
@@ -0,0 +1,3 @@
1
+ class Uncoil
2
+ VERSION = "0.0.1"
3
+ end
data/lib/uncoil.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'bitly'
2
+ require 'open-uri'
3
+ require 'net/http'
4
+ require 'json'
5
+
6
+ class Uncoil
7
+ ISGD_ROOT_URL = "http://is.gd/forward.php?format=json&shorturl="
8
+ BITLY_DOM_ARRAY = %w[bit.ly, j.mp, bitlypro.com, cs.pn, nyti.ms]
9
+
10
+ def initialize options = {}
11
+ Bitly.use_api_version_3
12
+ @bitly_access = false
13
+
14
+ if options.has_key?(:bitlyuser) && options.has_key?(:bitlykey)
15
+ @bitly_instance = Bitly.new("#{options[:bitlyuser]}", "#{options[:bitlykey]}")
16
+ @bitly_access = true
17
+ end
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
28
+ end
29
+
30
+ def expand url_arr
31
+ out_arr = Array(url_arr).flatten.map do |short_url|
32
+ short_url = clean_url(short_url)
33
+ domain = identify_domain(short_url)
34
+
35
+ @bitly_access.nil? ? error = "Not logged in to Bitly API" : error = nil
36
+
37
+ begin
38
+ if @bitly_access && BITLY_DOM_ARRAY.include?(domain)
39
+ long_url = uncoil_bitly(short_url)
40
+ elsif @bitly_access && check_bitly_pro(domain)
41
+ long_url = uncoil_bitly(short_url)
42
+ elsif domain == "is.gd"
43
+ long_url = uncoil_isgd(short_url)
44
+ else
45
+ long_url = uncoil_other(short_url)
46
+ end
47
+ rescue => exception
48
+ long_url = nil
49
+ error = exception.message
50
+ end
51
+
52
+ { :short_url => short_url , :long_url => long_url, :error => error }
53
+
54
+ end
55
+
56
+ out_arr.length == 1 ? out_arr[0] : out_arr
57
+
58
+ end
59
+
60
+ def check_bitly_pro url_domain
61
+ @bitly_instance.bitly_pro_domain(url_domain)
62
+ end
63
+
64
+ def uncoil_bitly short_url
65
+ @bitly_instance.expand(short_url).long_url
66
+ end
67
+
68
+ def uncoil_isgd short_url
69
+ JSON.parse(open(ISGD_ROOT_URL + "#{short_url}") { |file| file.read } )["url"]
70
+ end
71
+
72
+ def uncoil_other short_url, depth = 10
73
+ url = URI.encode(short_url)
74
+ response = Net::HTTP.get_response(URI.parse(url))
75
+
76
+ case response
77
+ when Net::HTTPSuccess then url
78
+ when Net::HTTPRedirection then uncoil_other(response['location'], depth - 1)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,130 @@
1
+ require 'uncoil'
2
+
3
+ describe Uncoil do
4
+
5
+ subject { Uncoil.new(:bitlyuser => "stim371", :bitlykey => "R_7a6f6d845668a8a7bb3e0c80ee3c28d6")}
6
+
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
+ describe "when using the submethods" do
59
+
60
+ context "when trying to undo a bit.ly link" do
61
+
62
+ it "should bring back the correct long link" do
63
+ expected_result = "http://www.cnn.com/"
64
+ subject.uncoil_bitly("http://bit.ly/2EEjBl").should eq expected_result
65
+ end
66
+
67
+ end
68
+
69
+ context "when trying to undo a bit.ly pro link" do
70
+
71
+ it "should bring back the correct long link" do
72
+ expected_result = "http://www.c-spanvideo.org/program/CainNew"
73
+ subject.uncoil_bitly("http://cs.pn/vsZpra").should eq expected_result
74
+ end
75
+
76
+ end
77
+
78
+ context "when trying to undo an is.gd link" do
79
+
80
+ it "should bring back the correct long link" do
81
+ subject.uncoil_isgd("http://is.gd/gbKNRq").should eq "http://www.google.com"
82
+ end
83
+
84
+ end
85
+
86
+ context "when trying to undo from other services" do
87
+
88
+ it "should bring back the correct long link" do
89
+ subject.uncoil_other("http://tinyurl.com/736swvl").should eq "http://www.chinadaily.com.cn/usa/business/2011-11/08/content_14057648.htm"
90
+ end
91
+
92
+ end
93
+ end
94
+
95
+ context "when using the main expand method" do
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
101
+
102
+ it "should expand bitlypro domains correctly" do
103
+ subject.expand("http://cs.pn/vsZpra").should eq Hash[:long_url => "http://www.c-spanvideo.org/program/CainNew", :short_url => "http://cs.pn/vsZpra", :error => nil]
104
+ end
105
+
106
+ it "should expand isgd domains correctly" do
107
+ subject.expand("http://is.gd/gbKNRq").should eq Hash[:long_url => "http://www.google.com", :short_url => "http://is.gd/gbKNRq", :error => nil]
108
+ end
109
+
110
+ it "should expand other shortened urls correctly" do
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]
113
+
114
+ subject.expand(short_url).should eq results_array
115
+ end
116
+
117
+ it "should also take an array of quotes" do
118
+ arr_of_links = ["http://bit.ly/2EEjBl","http://is.gd/gbKNRq","http://cs.pn/vsZpra"]
119
+ results_array = [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]]
120
+
121
+ subject.expand(arr_of_links).should eq results_array
122
+ end
123
+
124
+ it "should raise an error for non-urls" do
125
+ subject.expand("a")[:error].should_not be_nil
126
+ end
127
+
128
+ end
129
+
130
+ end
data/uncoil.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "uncoil/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "uncoil"
7
+ s.version = Uncoil::VERSION
8
+ s.authors = ["Joel Stimson"]
9
+ s.email = ["contact@cleanroomstudios.com"]
10
+ s.homepage = "http://uncoil.me"
11
+ s.summary = %q{Uncoil is a gem to unshorten urls so you know where obscured links really go.}
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
+
14
+ s.rubyforge_project = "uncoil"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_development_dependency "guard-rspec"
24
+
25
+ s.add_runtime_dependency "bitly"
26
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: uncoil
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joel Stimson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &2154321340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2154321340
25
+ - !ruby/object:Gem::Dependency
26
+ name: guard-rspec
27
+ requirement: &2154320920 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2154320920
36
+ - !ruby/object:Gem::Dependency
37
+ name: bitly
38
+ requirement: &2154320500 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2154320500
47
+ description: Uncoil is a gem to unshorten urls so you know where obscured links really
48
+ go. If you have bitly login credentials, initialize an instance of Uncoil to use
49
+ the bitly API.
50
+ email:
51
+ - contact@cleanroomstudios.com
52
+ executables: []
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - .gitignore
57
+ - Gemfile
58
+ - Guardfile
59
+ - Manifest
60
+ - README.md
61
+ - Rakefile
62
+ - lib/uncoil.rb
63
+ - lib/uncoil/version.rb
64
+ - spec/uncoil_spec.rb
65
+ - uncoil.gemspec
66
+ homepage: http://uncoil.me
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project: uncoil
86
+ rubygems_version: 1.8.10
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Uncoil is a gem to unshorten urls so you know where obscured links really
90
+ go.
91
+ test_files:
92
+ - spec/uncoil_spec.rb