uncoil 0.0.1

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 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