drcapulet-shorty 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +3 -0
  2. data/README.rdoc +66 -0
  3. data/Rakefile +67 -0
  4. data/VERSION +1 -0
  5. data/features/bitly.feature +4 -0
  6. data/features/step_definitions/api.rb +18 -0
  7. data/features/step_definitions/common_steps.rb +163 -0
  8. data/features/support/common.rb +29 -0
  9. data/features/support/env.rb +14 -0
  10. data/features/support/matchers.rb +11 -0
  11. data/features/trim.feature +8 -0
  12. data/lib/shorty/bitly.rb +101 -0
  13. data/lib/shorty/cligs.rb +56 -0
  14. data/lib/shorty/isgd.rb +14 -0
  15. data/lib/shorty/supr.rb +100 -0
  16. data/lib/shorty/tinyurl.rb +14 -0
  17. data/lib/shorty/trim.rb +110 -0
  18. data/lib/shorty/twurl.rb +32 -0
  19. data/lib/shorty.rb +17 -0
  20. data/test/bitly_test.rb +32 -0
  21. data/test/cligs_test.rb +18 -0
  22. data/test/fixtures/bitly-expand-cnn.json +10 -0
  23. data/test/fixtures/bitly-shorten-cnn.json +1 -0
  24. data/test/fixtures/bitly-stats-cnn.json +1 -0
  25. data/test/fixtures/cligs-shorten-google.txt +1 -0
  26. data/test/fixtures/isgd-shorten-google.txt +1 -0
  27. data/test/fixtures/supr-expand-cnn-error.json +1 -0
  28. data/test/fixtures/supr-expand-cnn.json +1 -0
  29. data/test/fixtures/supr-shorten-cnn.json +1 -0
  30. data/test/fixtures/tinyurl-shorten-google.txt +1 -0
  31. data/test/fixtures/trim-trim-simple.txt +1 -0
  32. data/test/fixtures/trim-trim-url.xml +7 -0
  33. data/test/fixtures/twurl-shorten-google.txt +1 -0
  34. data/test/isgd_test.rb +18 -0
  35. data/test/shory_test.rb +7 -0
  36. data/test/supr_test.rb +69 -0
  37. data/test/test_helper.rb +9 -0
  38. data/test/tinyurl_test.rb +18 -0
  39. data/test/trim_test.rb +24 -0
  40. data/test/twurl_test.rb +18 -0
  41. metadata +120 -0
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ doc/
3
+ features/
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ = Shorty
2
+
3
+ shorty makes interfacing with url shortening services easy, so far the following are supported:
4
+ - http://bit.ly
5
+ - http://tr.im - only URL API implemented, not media ones
6
+ - http://is.gd
7
+ - http://tinyurl.com
8
+ - http://cli.gs - only shorten implemented, expand not
9
+ - http://twurl.nl
10
+ - http://su.pr
11
+
12
+ == Install
13
+
14
+ sudo gem install drcapulet-shorty
15
+
16
+ == Usage
17
+
18
+ Yeah just read the rdocs.
19
+
20
+ == Possible Additions
21
+
22
+ - http://ow.ly - currently no API, says it is coming soon
23
+
24
+ == Other Possible Gems
25
+
26
+ - http://post.ly - Not really a shortener
27
+ - http://ping.fm - Not really a shortener
28
+ - http://ff.im - Not a shortener either
29
+ - http://yfrog.com - Not a shortener, maybe expand this gem or a media gem. API docs: http://code.google.com/p/imageshackapi
30
+ - http://twitpic.com - Same as yfrog. API docs: http://twitpic.com/api.do
31
+
32
+ == Other Ideas
33
+
34
+ * Possibly use OpenStruct to make data access easier
35
+ * Possibly set a user agent using
36
+
37
+ class Foo
38
+ include HTTParty
39
+ headers 'Accept' => 'text/html'
40
+ end
41
+
42
+ * Also possibly create a command line app
43
+
44
+
45
+ == License
46
+
47
+ Copyright (c) 2009 Alex Coomans
48
+
49
+ Permission is hereby granted, free of charge, to any person obtaining
50
+ a copy of this software and associated documentation files (the
51
+ "Software"), to deal in the Software without restriction, including
52
+ without limitation the rights to use, copy, modify, merge, publish,
53
+ distribute, sublicense, and/or sell copies of the Software, and to
54
+ permit persons to whom the Software is furnished to do so, subject to
55
+ the following conditions:
56
+
57
+ The above copyright notice and this permission notice shall be
58
+ included in all copies or substantial portions of the Software.
59
+
60
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
61
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
62
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
63
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
64
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
65
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
66
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,67 @@
1
+
2
+
3
+ # begin
4
+ # require 'cucumber/rake/task'
5
+ #
6
+ # Cucumber::Rake::Task.new(:features) do |t|
7
+ # t.fork = true
8
+ # t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
9
+ # end
10
+ # rescue LoadError
11
+ # desc 'Cucumber rake task not available'
12
+ # task :features do
13
+ # abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
14
+ # end
15
+ # end
16
+
17
+ begin
18
+ require 'jeweler'
19
+ Jeweler::Tasks.new do |gemspec|
20
+ gemspec.name = "shorty"
21
+ gemspec.summary = "Gem that talks to APIs for shortening urls"
22
+ gemspec.description = "Makes it easy to shorten URLs"
23
+ gemspec.email = "alex@alexcoomans.com"
24
+ gemspec.homepage = "http://github.com/drcapulet/shorty"
25
+ gemspec.authors = ["Alex Coomans"]
26
+ gemspec.add_dependency('httparty', '>= 0.4.4')
27
+ gemspec.add_dependency('crack', '>= 0.1.4')
28
+ end
29
+ rescue LoadError
30
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
31
+ end
32
+
33
+ require 'rake/testtask'
34
+ Rake::TestTask.new(:test) do |test|
35
+ test.libs << 'lib' << 'test'
36
+ test.pattern = 'test/**/*_test.rb'
37
+ test.verbose = true
38
+ end
39
+
40
+ begin
41
+ require 'rcov/rcovtask'
42
+ Rcov::RcovTask.new do |test|
43
+ test.libs << 'test'
44
+ test.pattern = 'test/**/*_test.rb'
45
+ test.verbose = true
46
+ end
47
+ rescue LoadError
48
+ task :rcov do
49
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
50
+ end
51
+ end
52
+
53
+ task :default => :test
54
+
55
+ require 'rake/rdoctask'
56
+ Rake::RDocTask.new do |rdoc|
57
+ if File.exist?('VERSION')
58
+ version = File.read('VERSION')
59
+ else
60
+ version = ""
61
+ end
62
+
63
+ rdoc.rdoc_dir = 'doc'
64
+ rdoc.title = "shorty #{version}"
65
+ rdoc.rdoc_files.include('README*')
66
+ rdoc.rdoc_files.include('lib/**/*.rb')
67
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,4 @@
1
+ Feature: Interface with the bit.ly API
2
+ As a user
3
+ I want to be able to interface with the bit.ly API
4
+ So that I can shorten URLs
@@ -0,0 +1,18 @@
1
+ Given /I have created a new (.*) instance/ do |n|
2
+ @instance = Shorty::Trim.new()
3
+ end
4
+
5
+ Given /I want to shorten (.*)/ do |n|
6
+ @url = @instance.shorten(n)
7
+ end
8
+
9
+ Then /^I should see "([^\"]*)"$/ do |text|
10
+ actual_output = File.read(@stdout)
11
+ actual_output.should contain(text)
12
+ end
13
+
14
+ Then /the URL should look like "([^\"]*)"$/ do |text|
15
+ @url.should contain(text)
16
+ end
17
+
18
+
@@ -0,0 +1,163 @@
1
+ # Given /^this project is active project folder/ do
2
+ # @active_project_folder = File.expand_path(File.dirname(__FILE__) + "/../..")
3
+ # end
4
+ #
5
+ # Given /^env variable \$([\w_]+) set to "(.*)"/ do |env_var, value|
6
+ # ENV[env_var] = value
7
+ # end
8
+ #
9
+ # Given /"(.*)" folder is deleted/ do |folder|
10
+ # in_project_folder { FileUtils.rm_rf folder }
11
+ # end
12
+ #
13
+ # When /^I invoke "(.*)" generator with arguments "(.*)"$/ do |generator, arguments|
14
+ # @stdout = StringIO.new
15
+ # in_project_folder do
16
+ # if Object.const_defined?("APP_ROOT")
17
+ # APP_ROOT.replace(FileUtils.pwd)
18
+ # else
19
+ # APP_ROOT = FileUtils.pwd
20
+ # end
21
+ # run_generator(generator, arguments.split(' '), SOURCES, :stdout => @stdout)
22
+ # end
23
+ # File.open(File.join(@tmp_root, "generator.out"), "w") do |f|
24
+ # @stdout.rewind
25
+ # f << @stdout.read
26
+ # end
27
+ # end
28
+ #
29
+ # When /^I run executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
30
+ # @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
31
+ # in_project_folder do
32
+ # system "#{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
33
+ # end
34
+ # end
35
+ #
36
+ # When /^I run project executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
37
+ # @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
38
+ # in_project_folder do
39
+ # system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
40
+ # end
41
+ # end
42
+ #
43
+ # When /^I run local executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
44
+ # @stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
45
+ # executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin", executable))
46
+ # in_project_folder do
47
+ # system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
48
+ # end
49
+ # end
50
+ #
51
+ # When /^I invoke task "rake (.*)"/ do |task|
52
+ # @stdout = File.expand_path(File.join(@tmp_root, "tests.out"))
53
+ # in_project_folder do
54
+ # system "rake #{task} --trace > #{@stdout} 2> #{@stdout}"
55
+ # end
56
+ # end
57
+ #
58
+ # Then /^folder "(.*)" (is|is not) created/ do |folder, is|
59
+ # in_project_folder do
60
+ # File.exists?(folder).should(is == 'is' ? be_true : be_false)
61
+ # end
62
+ # end
63
+ #
64
+ # Then /^file "(.*)" (is|is not) created/ do |file, is|
65
+ # in_project_folder do
66
+ # File.exists?(file).should(is == 'is' ? be_true : be_false)
67
+ # end
68
+ # end
69
+ #
70
+ # Then /^file with name matching "(.*)" is created/ do |pattern|
71
+ # in_project_folder do
72
+ # Dir[pattern].should_not be_empty
73
+ # end
74
+ # end
75
+ #
76
+ # Then /^file "(.*)" contents (does|does not) match \/(.*)\// do |file, does, regex|
77
+ # in_project_folder do
78
+ # actual_output = File.read(file)
79
+ # (does == 'does') ?
80
+ # actual_output.should(match(/#{regex}/)) :
81
+ # actual_output.should_not(match(/#{regex}/))
82
+ # end
83
+ # end
84
+ #
85
+ # Then /gem file "(.*)" and generated file "(.*)" should be the same/ do |gem_file, project_file|
86
+ # File.exists?(gem_file).should be_true
87
+ # File.exists?(project_file).should be_true
88
+ # gem_file_contents = File.read(File.dirname(__FILE__) + "/../../#{gem_file}")
89
+ # project_file_contents = File.read(File.join(@active_project_folder, project_file))
90
+ # project_file_contents.should == gem_file_contents
91
+ # end
92
+ #
93
+ # Then /^(does|does not) invoke generator "(.*)"$/ do |does_invoke, generator|
94
+ # actual_output = File.read(@stdout)
95
+ # does_invoke == "does" ?
96
+ # actual_output.should(match(/dependency\s+#{generator}/)) :
97
+ # actual_output.should_not(match(/dependency\s+#{generator}/))
98
+ # end
99
+ #
100
+ # Then /help options "(.*)" and "(.*)" are displayed/ do |opt1, opt2|
101
+ # actual_output = File.read(@stdout)
102
+ # actual_output.should match(/#{opt1}/)
103
+ # actual_output.should match(/#{opt2}/)
104
+ # end
105
+ #
106
+ # Then /^I should see$/ do |text|
107
+ # actual_output = File.read(@stdout)
108
+ # actual_output.should contain(text)
109
+ # end
110
+ #
111
+ # Then /^I should not see$/ do |text|
112
+ # actual_output = File.read(@stdout)
113
+ # actual_output.should_not contain(text)
114
+ # end
115
+ #
116
+ # Then /^I should see exactly$/ do |text|
117
+ # actual_output = File.read(@stdout)
118
+ # actual_output.should == text
119
+ # end
120
+ #
121
+ # Then /^I should see all (\d+) tests pass/ do |expected_test_count|
122
+ # expected = %r{^#{expected_test_count} tests, \d+ assertions, 0 failures, 0 errors}
123
+ # actual_output = File.read(@stdout)
124
+ # actual_output.should match(expected)
125
+ # end
126
+ #
127
+ # Then /^I should see all (\d+) examples pass/ do |expected_test_count|
128
+ # expected = %r{^#{expected_test_count} examples?, 0 failures}
129
+ # actual_output = File.read(@stdout)
130
+ # actual_output.should match(expected)
131
+ # end
132
+ #
133
+ # Then /^yaml file "(.*)" contains (\{.*\})/ do |file, yaml|
134
+ # in_project_folder do
135
+ # yaml = eval yaml
136
+ # YAML.load(File.read(file)).should == yaml
137
+ # end
138
+ # end
139
+ #
140
+ # Then /^Rakefile can display tasks successfully/ do
141
+ # @stdout = File.expand_path(File.join(@tmp_root, "rakefile.out"))
142
+ # in_project_folder do
143
+ # system "rake -T > #{@stdout} 2> #{@stdout}"
144
+ # end
145
+ # actual_output = File.read(@stdout)
146
+ # actual_output.should match(/^rake\s+\w+\s+#\s.*/)
147
+ # end
148
+ #
149
+ # Then /^task "rake (.*)" is executed successfully/ do |task|
150
+ # @stdout.should_not be_nil
151
+ # actual_output = File.read(@stdout)
152
+ # actual_output.should_not match(/^Don't know how to build task '#{task}'/)
153
+ # actual_output.should_not match(/Error/i)
154
+ # end
155
+ #
156
+ # Then /^gem spec key "(.*)" contains \/(.*)\// do |key, regex|
157
+ # in_project_folder do
158
+ # gem_file = Dir["pkg/*.gem"].first
159
+ # gem_spec = Gem::Specification.from_yaml(`gem spec #{gem_file}`)
160
+ # spec_value = gem_spec.send(key.to_sym)
161
+ # spec_value.to_s.should match(/#{regex}/)
162
+ # end
163
+ # end
@@ -0,0 +1,29 @@
1
+ module CommonHelpers
2
+ def in_tmp_folder(&block)
3
+ FileUtils.chdir(@tmp_root, &block)
4
+ end
5
+
6
+ def in_project_folder(&block)
7
+ project_folder = @active_project_folder || @tmp_root
8
+ FileUtils.chdir(project_folder, &block)
9
+ end
10
+
11
+ def in_home_folder(&block)
12
+ FileUtils.chdir(@home_path, &block)
13
+ end
14
+
15
+ def force_local_lib_override(project_name = @project_name)
16
+ rakefile = File.read(File.join(project_name, 'Rakefile'))
17
+ File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
18
+ f << "$:.unshift('#{@lib_path}')\n"
19
+ f << rakefile
20
+ end
21
+ end
22
+
23
+ def setup_active_project_folder project_name
24
+ @active_project_folder = File.join(@tmp_root, project_name)
25
+ @project_name = project_name
26
+ end
27
+ end
28
+
29
+ World(CommonHelpers)
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + "/../../lib/shorty"
2
+
3
+ gem 'cucumber'
4
+ require 'cucumber'
5
+ gem 'rspec'
6
+ require 'spec'
7
+
8
+ Before do
9
+ @tmp_root = File.dirname(__FILE__) + "/../../tmp"
10
+ @home_path = File.expand_path(File.join(@tmp_root, "home"))
11
+ FileUtils.rm_rf @tmp_root
12
+ FileUtils.mkdir_p @home_path
13
+ ENV['HOME'] = @home_path
14
+ end
@@ -0,0 +1,11 @@
1
+ module Matchers
2
+ def contain(expected)
3
+ simple_matcher("contain #{expected.inspect}") do |given, matcher|
4
+ matcher.failure_message = "expected #{given.inspect} to contain #{expected.inspect}"
5
+ matcher.negative_failure_message = "expected #{given.inspect} not to contain #{expected.inspect}"
6
+ given.index expected
7
+ end
8
+ end
9
+ end
10
+
11
+ World(Matchers)
@@ -0,0 +1,8 @@
1
+ Feature: Interface with the tr.im API
2
+ As a user
3
+ I want to be able to interface with the tr.im API
4
+ So that I can shorten URLs
5
+
6
+ Scenario: Shorten URL
7
+ Given I want to shorten "http://google.com"
8
+ Then the URL should look like "http://tr.im/szkO"
@@ -0,0 +1,101 @@
1
+ module Shorty
2
+ # The bit.ly API class. API documentation: http://code.google.com/p/bitly-api/wiki/ApiDocumentation
3
+ # For testing, use:
4
+ # require 'lib/shorty'
5
+ # bitly = Shorty::Bitly.new('bitlyapidemo', 'R_0da49e0a9118ff35f52f629d2d71bf07')
6
+ class Bitly
7
+ attr_reader :options
8
+ include HTTParty
9
+
10
+ # Standard Error Class
11
+ class Error < StandardError; end
12
+
13
+ API_URL = 'api.bit.ly'
14
+ API_VERSION = '2.0.1'
15
+ base_uri API_URL
16
+
17
+ # Options to pass:
18
+ #
19
+ # - login
20
+ # - apikey
21
+ def initialize(login, apikey)
22
+ @options = {
23
+ :login => login,
24
+ :apiKey => apikey,
25
+ :version => API_VERSION
26
+ }
27
+ end
28
+
29
+ # shorten, pass:
30
+ #
31
+ # - longurl: the URL to be shortened
32
+ def shorten( longurl )
33
+ query = {:longUrl => longurl}
34
+ query.merge!(@options)
35
+ short = self.class.get('/shorten', :query => query)
36
+ short = Crack::JSON.parse(short)
37
+ short["errorCode"].zero? ? short["results"][longurl]["shortUrl"] : raise_error(short["errorCode"], short["errorMessage"])
38
+ end
39
+
40
+ # expand- given a bit.ly url, returns long source url, takes:
41
+ #
42
+ # - shorturl: the bit.ly url, can either be the full url or missing http://bit.ly
43
+ def expand(shorturl)
44
+ shorturl = gsub_url(shorturl)
45
+ query = {:hash => shorturl}
46
+ query.merge!(@options)
47
+ expand = self.class.get('/expand', :query => query)
48
+ expand = Crack::JSON.parse(expand)
49
+ expand["errorCode"].zero? ? expand["results"][shorturl]["longUrl"] : raise_error(expand["errorCode"], expand["errorMessage"])
50
+ end
51
+
52
+ # info - Given a bit.ly url or hash, return information about that page, such as the long source url, ...
53
+ def info(urlorhash, keys = [])
54
+ urlhash = gsub_url(urlorhash)
55
+ if keys != []
56
+ query = {:hash => urlhash, :keys => keys.join(',')}
57
+ else
58
+ query = {:hash => urlhash}
59
+ end
60
+ query.merge!(@options)
61
+ stats = self.class.get('/info', :query => query)
62
+ stats = Crack::JSON.parse(stats)
63
+ stats["errorCode"].zero? ? stats["results"][urlhash] : raise_error(stats["errorCode"], stats["errorMessage"])
64
+ end
65
+
66
+ # stats - get stats on clicks and reffers, pass either:
67
+ #
68
+ # - shortURL: A single bitly url, eg: http://bit.ly/1RmnUT
69
+ # - hash: A single hash, eg: 1RmnUT
70
+ #
71
+ # Example:
72
+ # bitly = Shorty::Bitly.new('login', 'apikey')
73
+ # bitly.expand('1RmnUT')
74
+ # Or:
75
+ # bitly = Shorty::Bitly.new('login', 'apikey')
76
+ # bitly.expand('http://bit.ly/1RmnUT')
77
+ def stats(urlorhash)
78
+ urlhash = gsub_url(urlorhash)
79
+ query = {:hash => urlhash}
80
+ query.merge!(@options)
81
+ stats = self.class.get('/stats', :query => query)
82
+ stats = Crack::JSON.parse(stats)
83
+ stats["errorCode"].zero? ? stats["results"] : raise_error(stats["errorCode"], stats["errorMessage"])
84
+ end
85
+
86
+
87
+ protected
88
+
89
+ def gsub_url(shorturl)
90
+ shorturl.split('/').last
91
+ # shorturl = shorturl.gsub(/http:\/\//, '') if shorturl.include?('http://')
92
+ # shorturl = shorturl.gsub(/bit.ly\//, '') if shorturl.include?('bit.ly/')
93
+ end
94
+
95
+ def raise_error(code, message = '(no error message)')
96
+ error = message + " (error code: #{code})"
97
+ raise Shorty::Bitly::Error, error
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,56 @@
1
+ module Shorty
2
+ # The cli.gs API class. API documentation: http://blog.cli.gs/api
3
+ # For testing, use:
4
+ # require 'lib/shorty'
5
+ # cligs = Shorty::Cligs.new
6
+ class Cligs
7
+ attr_reader :options
8
+ include HTTParty
9
+
10
+ # Standard Error Class
11
+ class Error < StandardError; end
12
+
13
+ API_URL = 'http://cli.gs/api/v1/cligs'
14
+ API_VERSION = '1'
15
+ base_uri API_URL
16
+
17
+ # Options to pass:
18
+ #
19
+ # - API key: f given it associates the new clig with a user account so that they can view the traffic statistics. If not given, then a Public clig is created.
20
+ # - AppId: a simple string, HTML allowed, that identifies your App when the API usage is listed in the user’s control panel. Keep it short and simple please.
21
+ #
22
+ # cligs = Shorty::Cligs.new(:apikey => 'apikey', :appid => 'appid')
23
+ def initialize(options = {})
24
+ @options = {}
25
+ @options[:key] = options[:apikey] if options[:apikey]
26
+ @options[:appid] = options[:appid] if options[:appid]
27
+ end
28
+
29
+ # shorten. pass:
30
+ #
31
+ # - url: the url to shorten
32
+ def shorten(url)
33
+ query = {:url => url}
34
+ query.merge!(@options)
35
+ self.class.get('/create', :query => query)
36
+ end
37
+
38
+ # expand. pass either:
39
+ #
40
+ # - A valid clig ID, like Ts8p6Y
41
+ # - A clig URL, like http://cli.gs/Ts8p6Y
42
+ #
43
+ # Currently not implemented due to the fact this method wont work for demo.
44
+ def expand(urlorhash)
45
+ raise StandardError, 'Method not implemented'
46
+ end
47
+
48
+ protected
49
+
50
+ def raise_error(code, message = '(no error message)')
51
+ error = message + " (error code: #{code})"
52
+ raise Shorty::Bitly::Error, error
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,14 @@
1
+ module Shorty
2
+ # is.gd API as defined http://is.gd/api_info.php
3
+ class Isgd
4
+ include HTTParty
5
+
6
+ def shorten(url)
7
+ self.class.get('http://is.gd/api.php', :query => {:longurl => url})
8
+ end
9
+
10
+ def self.shorten(url)
11
+ get('http://is.gd/api.php', :query => {:longurl => url})
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,100 @@
1
+ module Shorty
2
+ # The su.pr API class. API documentation: http://www.stumbleupon.com/developers/Supr:API_documentation/
3
+ class Supr
4
+ attr_reader :options
5
+ include HTTParty
6
+
7
+ # Standard Error Class
8
+ class Error < StandardError; end
9
+
10
+ API_URL = 'http://su.pr/api'
11
+ API_VERSION = '1.0'
12
+ base_uri API_URL
13
+
14
+ # Options to pass, optional, but both must be passed when used
15
+ # - login: Your Su.pr username (also your StumbleUpon username)
16
+ # - apikey: Your private API key. This can be generated on your Su.pr settings page.
17
+ def initialize(login = nil, apikey = nil)
18
+ @options = {
19
+ :version => API_VERSION
20
+ }
21
+ if login && apikey
22
+ @options.merge({:login => login, :apiKey => apikey})
23
+ elsif (login || apikey)
24
+ raise Shorty::Supr::Error, 'Both the API key and login values must be passed when you want to use authentication'
25
+ end
26
+ end
27
+
28
+ # shorten. pass:
29
+ # - url: The long URL you wish to shorten
30
+ # Will return the full url unless you pass false for the second parameter, then it only returns the hash
31
+ def shorten(url, full = true)
32
+ query = {:longUrl => url}
33
+ query.merge!(@options)
34
+ short = self.class.get('/shorten', :query => query)
35
+ short = Crack::JSON.parse(short)
36
+ if full
37
+ short["errorCode"].zero? ? short["results"][url]["shortUrl"] : raise_error(short["errorCode"], short["errorMessage"])
38
+ else
39
+ short["errorCode"].zero? ? short["results"][url]["hash"] : raise_error(short["errorCode"], short["errorMessage"])
40
+ end
41
+ end
42
+
43
+ # self.shorten. see shorten
44
+ def self.shorten(url, full = true)
45
+ query = {:longUrl => url}
46
+ query.merge!(@options) if @options
47
+ short = get('/shorten', :query => query)
48
+ short = Crack::JSON.parse(short)
49
+ if full
50
+ short["errorCode"].zero? ? short["results"][url]["shortUrl"] : raise_error(short["errorCode"], short["errorMessage"])
51
+ else
52
+ short["errorCode"].zero? ? short["results"][url]["hash"] : raise_error(short["errorCode"], short["errorMessage"])
53
+ end
54
+ end
55
+
56
+ # expand. pass either:
57
+ # - shortUrl: he Su.pr URL you wish to expand
58
+ # - hash: The six character hash you wish to expand
59
+ def expand(urlorhash)
60
+ hash = gsub_url(urlorhash)
61
+ query = {:hash => hash}
62
+ query.merge!(@options)
63
+ expand = self.class.get('/expand', :query => query)
64
+ expand = Crack::JSON.parse(expand)
65
+ expand["errorCode"].zero? ? expand["results"][hash]["longUrl"] : raise_error(expand["errorCode"], expand["errorMessage"])
66
+ end
67
+
68
+ # self.expand. see expand
69
+ def self.expand(urlorhash)
70
+ hash = gsub_url(urlorhash)
71
+ query = {:hash => hash}
72
+ query.merge!(@options) if @options
73
+ expand = get('/expand', :query => query)
74
+ expand = Crack::JSON.parse(expand)
75
+ expand["errorCode"].zero? ? expand["results"][hash]["longUrl"] : raise_error(expand["errorCode"], expand["errorMessage"])
76
+ end
77
+
78
+
79
+ protected
80
+
81
+ def gsub_url(shorturl)
82
+ shorturl.split('/').last
83
+ end
84
+
85
+ def self.gsub_url(shorturl)
86
+ shorturl.split('/').last
87
+ end
88
+
89
+ def raise_error(code, message = '(no error message)')
90
+ error = message + " (error code: #{code})"
91
+ raise Shorty::Supr::Error, error
92
+ end
93
+
94
+ def self.raise_error(code, message = '(no error message)')
95
+ error = message + " (error code: #{code})"
96
+ raise Shorty::Supr::Error, error
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,14 @@
1
+ module Shorty
2
+ # The tinyurl.com API. Not much here, undocumented API
3
+ class Tinyurl
4
+ include HTTParty
5
+
6
+ def shorten(url)
7
+ self.class.get('http://tinyurl.com/api-create.php', :query => {:url => url})
8
+ end
9
+
10
+ def self.shorten(url)
11
+ get('http://tinyurl.com/api-create.php', :query => {:url => url})
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,110 @@
1
+
2
+ module Shorty
3
+ # The tr.im API class. API documentation: http://tr.im/website/api
4
+ class Trim
5
+ include HTTParty
6
+ attr_reader :options
7
+ # API Error
8
+ class APIError < StandardError; end
9
+ class APIKeyInvalid < StandardError; end
10
+ class APIKeyRequired < StandardError; end
11
+ # Submitted URL Invalid.
12
+ class URLInvalid < StandardError; end
13
+ # Submitted URL is Already a Shortened URL.
14
+ class AlreadyShortened < StandardError; end
15
+ class URLMissing < StandardError; end
16
+ class URLDoesntExist < StandardError; end
17
+ class URLAlreadyClaimed < StandardError; end
18
+ # The URL has been Flagged as Spam and Rejected.
19
+ class FlaggedSpam < StandardError; end
20
+ # The Custom tr.im URL Requested is Already in Us.
21
+ class AlreadyInUse < StandardError; end
22
+ class AuthenticationInvalid < StandardError; end
23
+ class ReferenceCodeNonExistent< StandardError; end
24
+ # Media
25
+ class MediaTypeUnsupported < StandardError; end
26
+ class MediaTooLarge < StandardError; end
27
+ class MediaInvalidDimensions < StandardError; end
28
+ # Invalid Errors
29
+ class InvalidCharacters < StandardError; end
30
+ class InvalidParameter < StandardError; end
31
+ class UnknownError < StandardError; end
32
+ # Required Parameter URL Not Submitted.
33
+ class MissingParameter < StandardError; end
34
+
35
+
36
+ base_uri 'api.tr.im/api'
37
+
38
+ # TODO: We should take the api_key, username and or password here and authenticate them if needed (need to look into that)
39
+ def initialize(api_key = nil)
40
+ @options = {}
41
+ @options << {:api_key => api_key} if api_key
42
+ end
43
+
44
+ # The trim_simple API method as defined: http://tr.im/website/api#trim_simple
45
+ # Can only be passed a site URL, only returns a URL, and no error handling occurs
46
+ # api = Shorty::Trim.new
47
+ # api.shorten('http://google.com') => http://tr.im/szMj
48
+ def shorten( website_url )
49
+ self.class.get( '/trim_simple', :query => { :url => website_url } )
50
+ end
51
+
52
+
53
+ # The trim_url API method as defined: http://tr.im/website/api#trim_url
54
+ # The following options can be passed:
55
+ #
56
+ # - url: the URL you want to shorten
57
+ # - custom: A custom URL that is preferred to an auto-generated URL.
58
+ # - searchtags: A search string value to attach to a tr.im URL.
59
+ # - privacycode: A string value that must be appended after the URL.
60
+ # - newtrim: If present with any value, it will force the creation of a new tr.im URL.
61
+ # - sandbox: If present with any value a test data set will be returned, and no URL created. This is intended for testing so that you do not consume API calls or insert pointless data while in development.
62
+ #
63
+ # require 'shorty'
64
+ # api = Shorty::Trim.new
65
+ # api.trim_url(:url => 'http://google.com', :custom => 'thisismygoogle', :sandbox => 'true') # => http://tr.im/szMj
66
+
67
+ def trim_url( options = {} )
68
+ options.merge!(@options)
69
+ response = self.class.get( '/trim_url.xml', :query => options )
70
+ response = Crack::XML.parse(response)
71
+ raise_error(response['trim']['status']['code'], response['trim']['status']['message']) if response['trim']['status']['code'] >= '205'
72
+ return response['trim']['url']
73
+ end
74
+
75
+ TRIM_ERRORS = {
76
+ 400 => Shorty::Trim::MissingParameter, # Required Parameter URL Not Submitted.
77
+ 401 => Shorty::Trim::URLInvalid, # Submitted URL Invalid.
78
+ 402 => Shorty::Trim::AlreadyShortened, # Submitted URL is Already a Shortened URL.
79
+ 403 => Shorty::Trim::FlaggedSpam, # The URL has been Flagged as Spam and Rejected.
80
+ 404 => Shorty::Trim::AlreadyInUse, # The Custom tr.im URL Requested is Already in Us.
81
+ 405 => Shorty::Trim::InvalidCharacters, # Requested Custom URL Contains Invalid Characters.
82
+ 406 => Shorty::Trim::InvalidCharacters, # Requested Privacy Code Contains Invalid Characters.
83
+ 407 => Shorty::Trim::InvalidCharacters, # Requested Search Tags Contains Invalid Characters.
84
+ 410 => Shorty::Trim::AuthenticationInvalid, # Required Authentication Not Submitted or Invalid.
85
+ 411 => Shorty::Trim::MissingParameter, # URL Reference Code Not Submitted.
86
+ 412 => Shorty::Trim::ReferenceCodeNonExistent, # URL Reference Code Not Does Not Exist.
87
+ 413 => Shorty::Trim::URLMissing, # tr.im URL Path Not Submitted.
88
+ 414 => Shorty::Trim::URLDoesntExist, # tr.im URL Does Not Exist.
89
+ 415 => Shorty::Trim::URLAlreadyClaimed, # tr.im URL Referenced Already Claimed.
90
+ 420 => Shorty::Trim::MediaTypeUnsupported, # Media Type Uploaded Not Supported.
91
+ 421 => Shorty::Trim::MediaTooLarge, # Media Uploaded too Large.
92
+ 422 => Shorty::Trim::MediaInvalidDimensions, # Media Uploaded XY Dimensions too Small.
93
+ 425 => Shorty::Trim::APIError, # API Rate Limit Exceeded.
94
+ 426 => Shorty::Trim::APIKeyInvalid, # API Key Submitted Does Not Exist or is Invalid.
95
+ 427 => Shorty::Trim::APIKeyRequired, # API Key Required.
96
+ 445 => Shorty::Trim::InvalidParameter, # Parameter Data Within the Request is Invalid.
97
+ 446 => Shorty::Trim::MissingParameter, # "Required Parameter Missing within the Request."
98
+ 450 => Shorty::Trim::UnknownError # "An Unknown Error Occurred. Please email api@tr.im."
99
+ }
100
+
101
+ private
102
+ # Raise an error depending on the problem
103
+ def raise_error(code, message = '(no error message)')
104
+ # raise Shorty::Trim::APIError.new(TRIM_ERRORS[code])
105
+ raise TRIM_ERRORS[code], message
106
+ end
107
+ end
108
+ end
109
+
110
+
@@ -0,0 +1,32 @@
1
+ module Shorty
2
+ # The twurl.nl API class. API documentation: http://tweetburner.com/api
3
+ class Twurl
4
+ attr_reader :options
5
+ include HTTParty
6
+
7
+ # Standard Error Class
8
+ class Error < StandardError; end
9
+
10
+ API_URL = 'http://tweetburner.com'
11
+ base_uri API_URL
12
+
13
+ # shorten. pass:
14
+ # - url: the url to be shortened
15
+ # So to use:
16
+ # twurl = Shorty::Truwl.new
17
+ # twurl.shorten('http://google.com')
18
+ def shorten(url)
19
+ query = { :'link[url]' => url }
20
+ self.class.post("/links", :query => query)
21
+ end
22
+
23
+ # Same as the shorten method, you can just call the following instead:
24
+ #
25
+ # Shorty::Truwl.shorten('http://google.com')
26
+ def self.shorten(url)
27
+ query = { :'link[url]' => url }
28
+ post("/links", :query => query)
29
+ end
30
+
31
+ end
32
+ end
data/lib/shorty.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'httparty'
2
+ require 'crack'
3
+
4
+ module Shorty
5
+ class API
6
+ include HTTParty
7
+ end
8
+
9
+ require 'shorty/trim'
10
+ require 'shorty/bitly'
11
+ require 'shorty/tinyurl'
12
+ require 'shorty/isgd'
13
+ require 'shorty/cligs'
14
+ require 'shorty/twurl'
15
+ require 'shorty/supr'
16
+ end
17
+
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class BitlyTest < Test::Unit::TestCase
4
+ context "A bit.ly instance" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://api.bit.ly/shorten?apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&version=2.0.1&longUrl=http%3A%2F%2Fcnn.com&login=bitlyapidemo", :body => File.join(File.dirname(__FILE__), 'fixtures', 'bitly-shorten-cnn.json'))
7
+ FakeWeb.register_uri(:get, "http://api.bit.ly/expand?apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&version=2.0.1&login=bitlyapidemo&hash=15DlK", :body => File.join(File.dirname(__FILE__), 'fixtures', 'bitly-expand-cnn.json'))
8
+ FakeWeb.register_uri(:get, "http://api.bit.ly/stats?hash=15DlK&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&version=2.0.1&login=bitlyapidemo", :body => File.join(File.dirname(__FILE__), 'fixtures', 'bitly-stats-cnn.json'))
9
+ @bitly = Shorty::Bitly.new('bitlyapidemo', 'R_0da49e0a9118ff35f52f629d2d71bf07')
10
+ end
11
+
12
+ should "exist" do
13
+ assert @bitly
14
+ end
15
+
16
+ should "return a shortened url" do
17
+ assert_equal 'http://bit.ly/15DlK', @bitly.shorten('http://cnn.com')
18
+ end
19
+
20
+ should "return an expanded url when passed a hash" do
21
+ assert_equal 'http://cnn.com/', @bitly.expand('15DlK')
22
+ end
23
+
24
+ should "return an expanded url when passed a full url" do
25
+ assert_equal 'http://cnn.com/', @bitly.expand('http://bit.ly/15DlK')
26
+ end
27
+
28
+ should "return the stats for a url" do
29
+ assert_equal 3046, @bitly.stats('http://bit.ly/15DlK')["clicks"]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class CligsTest < Test::Unit::TestCase
4
+ context "A cli.gs instance" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://cli.gs/api/v1/cligs/create?url=http%3A%2F%2Fgoogle.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'cligs-shorten-google.txt'))
7
+ @cligs = Shorty::Cligs.new
8
+ end
9
+
10
+ should "exist" do
11
+ assert @cligs
12
+ end
13
+
14
+ should "return a shortened url" do
15
+ assert_equal 'http://cli.gs/g5nmE', @cligs.shorten('http://google.com')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ {
2
+ "errorCode": 0,
3
+ "errorMessage": "",
4
+ "results": {
5
+ "15DlK": {
6
+ "longUrl": "http://cnn.com/"
7
+ }
8
+ },
9
+ "statusCode": "OK"
10
+ }
@@ -0,0 +1 @@
1
+ { "errorCode": 0, "errorMessage": "", "results": { "http://cnn.com": { "hash": "31IqMl", "shortKeywordUrl": "", "shortUrl": "http://bit.ly/15DlK", "userHash": "15DlK" } }, "statusCode": "OK" }
@@ -0,0 +1 @@
1
+ { "errorCode": 0, "errorMessage": "", "results": { "clicks": 3046, "hash": "31IqMl", "referrers": { "": { "/index.html": 1, "None": 5, "direct": 2255 }, "api.bit.ly": { "/shorten": 2 }, "benny-web": { "/jseitel/bitly/install.html": 1 }, "bit.ly": { "/": 3, "/app/demos/info.html": 102, "/app/demos/stats.html": 402, "/app/demos/statsModule.html": 2, "/info/14tP6": 1, "/info/15DlK": 1, "/info/27I9Ll": 1, "/info/31IqMl": 4, "/info/J066u": 1, "/info/SiNn6": 1, "/info/hic4E": 1 }, "code.google.com": { "/p/bitly-api/wiki/ApiDocumentation": 1 }, "dev.chartbeat.com": { "/static/bitly.html": 1 }, "dev.unhub.com": { "/pnG8/": 1 }, "klout.net": { "/profiledetail.php": 1 }, "localhost": { "/New Folder/test1.php": 1, "/index2.html": 1 }, "mail.google.com": { "/mail/": 1 }, "partners.bit.ly": { "/td": 9 }, "powertwitter.me": { "/": 1 }, "quietube.com": { "/getbitly.php": 1 }, "search.twitter.com": { "/search": 3 }, "sfbay.craigslist.org": { "/sfc/rnr/891043787.html": 8 }, "spreadsheets.google.com": { "/ccc": 27, "/ccc2": 1 }, "strat.corp.advertising.com": { "/brandmaker/bitly.php": 4 }, "taggytext.com": { "/ganja": 1 }, "twitter.com": { "/": 11, "/SuperTestAcct": 2, "/TattoosOn": 1, "/WilliamWoods": 1, "/home": 6, "/ibiboisms": 2, "/kshanns": 1, "/matraji": 1, "/nathanfolkman": 1, "/pantaleonescu": 1, "/rubyisbeautiful": 1, "/williamwoods": 1 }, "twitter.mattz.dev.buddymedia.com": { "/twitter/": 1 }, "twitturls.com": { "/": 21 }, "twitturly.com": { "": 17, "/urlinfo/url/2168a5e81280538cdbf6ad4c4ab019db/": 1 }, "uploaddownloadperform.net": { "/Test/TestPage2": 1 }, "url.ly": { "/": 19, "/info/27I9Ll": 1, "/info/31IqMl": 3 }, "urly.local:3600": { "/": 7 }, "v2.blogg.no": { "/test.cfm": 1 }, "www.facebook.com": { "/home.php": 1 }, "www.longurlplease.com": { "/": 3 }, "www.microblogbuzz.com": { "": 5 } }, "userClicks": 373, "userHash": "15DlK", "userReferrers": { "": { "None": 1, "direct": 366 }, "api.bit.ly": { "/shorten": 2 }, "code.google.com": { "/p/bitly-api/wiki/ApiDocumentation": 1 }, "twitter.com": { "/TattoosOn": 1, "/rubyisbeautiful": 1 }, "www.longurlplease.com": { "/": 1 } } }, "statusCode": "OK" }
@@ -0,0 +1 @@
1
+ http://cli.gs/g5nmE
@@ -0,0 +1 @@
1
+ http://is.gd/2iE2G
@@ -0,0 +1 @@
1
+ {"errorCode":1204,"errorMessage":"Invalid Su.pr hash","statusCode":"ERROR"}
@@ -0,0 +1 @@
1
+ {"errorCode":0,"errorMessage":"","results":{"2yw2PP":{"longUrl":"http:\/\/cnn.com\/"}},"statusCode":"OK"}
@@ -0,0 +1 @@
1
+ {"errorCode":0,"errorMessage":"","results":{"http:\/\/cnn.com":{"hash":"2yw2PP","shortUrl":"http:\/\/su.pr\/2yw2PP"}},"statusCode":"OK"}
@@ -0,0 +1 @@
1
+ http://tinyurl.com/2x6rgl
@@ -0,0 +1 @@
1
+ http://tr.im/w5Pm
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <trim>
3
+ <status result="OK" code="200" message="tr.im URL Added."/>
4
+ <url>http://tr.im/thisismygoogletesting</url>
5
+ <reference>CRzMDvkYP7VYKrpBWsUAU4fAbT7MUg</reference>
6
+ <trimpath>thisismygoogletesting</trimpath>
7
+ </trim>
@@ -0,0 +1 @@
1
+ http://twurl.nl/jnlwyb
data/test/isgd_test.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class IsgdTest < Test::Unit::TestCase
4
+ context "Using is.gd" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://is.gd/api.php?longurl=http%3A%2F%2Fgoogle.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'isgd-shorten-google.txt'))
7
+ end
8
+
9
+ should "return a shortened url (class method)" do
10
+ assert_equal 'http://is.gd/2iE2G', Shorty::Isgd.shorten('http://google.com')
11
+ end
12
+
13
+ should "return a shortened url (instance method)" do
14
+ @isgd = Shorty::Isgd.new
15
+ assert_equal 'http://is.gd/2iE2G', @isgd.shorten('http://google.com')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class ShortyTest < Test::Unit::TestCase
4
+ should "do nothing" do
5
+ true
6
+ end
7
+ end
data/test/supr_test.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'test_helper'
2
+
3
+ class SuprTest < Test::Unit::TestCase
4
+ context "A su.pr instance" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://su.pr/api/shorten?version=1.0&longUrl=http%3A%2F%2Fcnn.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-shorten-cnn.json'))
7
+ FakeWeb.register_uri(:get, "http://su.pr/api/shorten?longUrl=http%3A%2F%2Fcnn.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-shorten-cnn.json'))
8
+ FakeWeb.register_uri(:get, "http://su.pr/api/expand?hash=2yw2PP&version=1.0", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-expand-cnn.json'))
9
+ FakeWeb.register_uri(:get, "http://su.pr/api/expand?hash=2yw2PP", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-expand-cnn.json'))
10
+ FakeWeb.register_uri(:get, "http://su.pr/api/expand?hash=15DlK&version=1.0", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-expand-cnn-error.json'))
11
+ FakeWeb.register_uri(:get, "http://su.pr/api/expand?hash=15DlK", :body => File.join(File.dirname(__FILE__), 'fixtures', 'supr-expand-cnn-error.json'))
12
+ end
13
+
14
+ context "when using instance methods" do
15
+ setup do
16
+ @supr = Shorty::Supr.new
17
+ end
18
+
19
+ should "exist" do
20
+ assert @supr
21
+ end
22
+
23
+ should "return a shortened url" do
24
+ assert_equal 'http://su.pr/2yw2PP', @supr.shorten('http://cnn.com')
25
+ end
26
+
27
+ should "return an expanded url when passed a hash" do
28
+ assert_equal 'http://cnn.com/', @supr.expand('2yw2PP')
29
+ end
30
+
31
+ should "return an expanded url when passed a full url" do
32
+ assert_equal 'http://cnn.com/', @supr.expand('http://su.pr/2yw2PP')
33
+ end
34
+
35
+ should "raise an error when passed an invalid hash to expand" do
36
+ assert_raise Shorty::Supr::Error do
37
+ @supr.expand('15DlK')
38
+ end
39
+ end
40
+
41
+ should "raise an error when an instance is being created and is missing a paramter" do
42
+ assert_raise Shorty::Supr::Error do
43
+ Shorty::Supr.new('dummyapi')
44
+ end
45
+ end
46
+ end
47
+
48
+ context "when using class methods" do
49
+ should "return a shortened url" do
50
+ assert_equal 'http://su.pr/2yw2PP', Shorty::Supr.shorten('http://cnn.com')
51
+ end
52
+
53
+ should "return an expanded url when passed a hash" do
54
+ assert_equal 'http://cnn.com/', Shorty::Supr.expand('2yw2PP')
55
+ end
56
+
57
+ should "return an expanded url when passed a full url" do
58
+ assert_equal 'http://cnn.com/', Shorty::Supr.expand('http://su.pr/2yw2PP')
59
+ end
60
+
61
+ should "return an error when passed an invalid hash to expand" do
62
+ assert_raise Shorty::Supr::Error do
63
+ Shorty::Supr.expand('15DlK')
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'fakeweb'
5
+ FakeWeb.allow_net_connect = false
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require 'shorty'
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class TinyurlTest < Test::Unit::TestCase
4
+ context "Using tinyurl.com" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://tinyurl.com/api-create.php?url=http%3A%2F%2Fgoogle.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'tinyurl-shorten-google.txt'))
7
+ end
8
+
9
+ should "return a shortened url (class method)" do
10
+ assert_equal 'http://tinyurl.com/2x6rgl', Shorty::Tinyurl.shorten('http://google.com')
11
+ end
12
+
13
+ should "return a shortened url (instance method)" do
14
+ @tinyurl = Shorty::Tinyurl.new
15
+ assert_equal 'http://tinyurl.com/2x6rgl', @tinyurl.shorten('http://google.com')
16
+ end
17
+ end
18
+ end
data/test/trim_test.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class TrimTest < Test::Unit::TestCase
4
+ context "A tr.im instance" do
5
+ setup do
6
+ FakeWeb.register_uri(:get, "http://api.tr.im/api/trim_simple?url=http%3A%2F%2Fgoogle.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'trim-trim-simple.txt'))
7
+ FakeWeb.register_uri(:get, "http://api.tr.im/api/trim_url.xml?url=http%3A%2F%2Fgoogle.com&custom=thisismygoogletesting", :body => File.join(File.dirname(__FILE__), 'fixtures', 'trim-trim-url.xml'))
8
+ # FakeWeb.register_uri(:get, "http://api.bit.ly/stats?hash=15DlK&apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&version=2.0.1&login=bitlyapidemo", :body => File.join(File.dirname(__FILE__), 'fixtures', 'bitly-stats-cnn.json'))
9
+ @trim = Shorty::Trim.new
10
+ end
11
+
12
+ should "exist" do
13
+ assert @trim
14
+ end
15
+
16
+ should "return a shortened url using trim_simple" do
17
+ assert_equal 'http://tr.im/w5Pm', @trim.shorten('http://google.com')
18
+ end
19
+
20
+ should "return a shortened url using trim_url" do
21
+ assert_equal 'http://tr.im/thisismygoogletesting', @trim.trim_url(:url => 'http://google.com', :custom => 'thisismygoogletesting')
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class TwurlTest < Test::Unit::TestCase
4
+ context "Using twurl.nl" do
5
+ setup do
6
+ FakeWeb.register_uri(:post, "http://tweetburner.com/links?link[url]=http%3A%2F%2Fgoogle.com", :body => File.join(File.dirname(__FILE__), 'fixtures', 'twurl-shorten-google.txt'))
7
+ end
8
+
9
+ should "return a shortened url (class method)" do
10
+ assert_equal 'http://twurl.nl/jnlwyb', Shorty::Twurl.shorten('http://google.com')
11
+ end
12
+
13
+ should "return a shortened url (instance method)" do
14
+ @twurl = Shorty::Twurl.new
15
+ assert_equal 'http://twurl.nl/jnlwyb', @twurl.shorten('http://google.com')
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: drcapulet-shorty
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alex Coomans
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httparty
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: crack
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.4
34
+ version:
35
+ description: Makes it easy to shorten URLs
36
+ email: alex@alexcoomans.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - .gitignore
45
+ - README.rdoc
46
+ - Rakefile
47
+ - VERSION
48
+ - features/bitly.feature
49
+ - features/step_definitions/api.rb
50
+ - features/step_definitions/common_steps.rb
51
+ - features/support/common.rb
52
+ - features/support/env.rb
53
+ - features/support/matchers.rb
54
+ - features/trim.feature
55
+ - lib/shorty.rb
56
+ - lib/shorty/bitly.rb
57
+ - lib/shorty/cligs.rb
58
+ - lib/shorty/isgd.rb
59
+ - lib/shorty/supr.rb
60
+ - lib/shorty/tinyurl.rb
61
+ - lib/shorty/trim.rb
62
+ - lib/shorty/twurl.rb
63
+ - test/bitly_test.rb
64
+ - test/cligs_test.rb
65
+ - test/fixtures/bitly-expand-cnn.json
66
+ - test/fixtures/bitly-shorten-cnn.json
67
+ - test/fixtures/bitly-stats-cnn.json
68
+ - test/fixtures/cligs-shorten-google.txt
69
+ - test/fixtures/isgd-shorten-google.txt
70
+ - test/fixtures/supr-expand-cnn-error.json
71
+ - test/fixtures/supr-expand-cnn.json
72
+ - test/fixtures/supr-shorten-cnn.json
73
+ - test/fixtures/tinyurl-shorten-google.txt
74
+ - test/fixtures/trim-trim-simple.txt
75
+ - test/fixtures/trim-trim-url.xml
76
+ - test/fixtures/twurl-shorten-google.txt
77
+ - test/isgd_test.rb
78
+ - test/shory_test.rb
79
+ - test/supr_test.rb
80
+ - test/test_helper.rb
81
+ - test/tinyurl_test.rb
82
+ - test/trim_test.rb
83
+ - test/twurl_test.rb
84
+ has_rdoc: false
85
+ homepage: http://github.com/drcapulet/shorty
86
+ licenses:
87
+ post_install_message:
88
+ rdoc_options:
89
+ - --charset=UTF-8
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: "0"
97
+ version:
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: "0"
103
+ version:
104
+ requirements: []
105
+
106
+ rubyforge_project:
107
+ rubygems_version: 1.3.5
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Gem that talks to APIs for shortening urls
111
+ test_files:
112
+ - test/bitly_test.rb
113
+ - test/cligs_test.rb
114
+ - test/isgd_test.rb
115
+ - test/shory_test.rb
116
+ - test/supr_test.rb
117
+ - test/test_helper.rb
118
+ - test/tinyurl_test.rb
119
+ - test/trim_test.rb
120
+ - test/twurl_test.rb