bitly 1.1.1 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +36 -3
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +5 -2
  7. data/History.txt +32 -1
  8. data/LICENSE.md +1 -1
  9. data/README.md +151 -58
  10. data/Rakefile +6 -9
  11. data/bitly.gemspec +36 -32
  12. data/config/env.yml.example +5 -0
  13. data/lib/bitly.rb +9 -7
  14. data/lib/bitly/api.rb +19 -0
  15. data/lib/bitly/api/base.rb +23 -0
  16. data/lib/bitly/api/bitlink.rb +342 -0
  17. data/lib/bitly/api/bitlink/clicks_summary.rb +35 -0
  18. data/lib/bitly/api/bitlink/deeplink.rb +29 -0
  19. data/lib/bitly/api/bitlink/link_click.rb +75 -0
  20. data/lib/bitly/api/bitlink/paginated_list.rb +52 -0
  21. data/lib/bitly/api/bsd.rb +24 -0
  22. data/lib/bitly/api/click_metric.rb +186 -0
  23. data/lib/bitly/api/client.rb +588 -0
  24. data/lib/bitly/api/group.rb +232 -0
  25. data/lib/bitly/api/group/preferences.rb +73 -0
  26. data/lib/bitly/api/list.rb +22 -0
  27. data/lib/bitly/api/oauth_app.rb +26 -0
  28. data/lib/bitly/api/organization.rb +104 -0
  29. data/lib/bitly/api/shorten_counts.rb +61 -0
  30. data/lib/bitly/api/user.rb +107 -0
  31. data/lib/bitly/error.rb +33 -0
  32. data/lib/bitly/http.rb +10 -0
  33. data/lib/bitly/http/adapters.rb +9 -0
  34. data/lib/bitly/http/adapters/net_http.rb +27 -0
  35. data/lib/bitly/http/client.rb +33 -0
  36. data/lib/bitly/http/request.rb +118 -0
  37. data/lib/bitly/http/response.rb +66 -0
  38. data/lib/bitly/oauth.rb +109 -0
  39. data/lib/bitly/version.rb +3 -1
  40. metadata +82 -111
  41. data/Manifest +0 -37
  42. data/lib/bitly/client.rb +0 -145
  43. data/lib/bitly/config.rb +0 -29
  44. data/lib/bitly/url.rb +0 -103
  45. data/lib/bitly/utils.rb +0 -57
  46. data/lib/bitly/v3.rb +0 -14
  47. data/lib/bitly/v3/bitly.rb +0 -7
  48. data/lib/bitly/v3/client.rb +0 -207
  49. data/lib/bitly/v3/country.rb +0 -13
  50. data/lib/bitly/v3/day.rb +0 -13
  51. data/lib/bitly/v3/missing_url.rb +0 -15
  52. data/lib/bitly/v3/oauth.rb +0 -41
  53. data/lib/bitly/v3/realtime_link.rb +0 -18
  54. data/lib/bitly/v3/referrer.rb +0 -13
  55. data/lib/bitly/v3/url.rb +0 -154
  56. data/lib/bitly/v3/user.rb +0 -135
  57. data/test/bitly/test_client.rb +0 -266
  58. data/test/bitly/test_config.rb +0 -28
  59. data/test/bitly/test_url.rb +0 -167
  60. data/test/bitly/test_utils.rb +0 -79
  61. data/test/fixtures/cnn.json +0 -1
  62. data/test/fixtures/cnn_and_google.json +0 -1
  63. data/test/fixtures/expand_cnn.json +0 -1
  64. data/test/fixtures/expand_cnn_and_google.json +0 -1
  65. data/test/fixtures/google_and_cnn_info.json +0 -1
  66. data/test/fixtures/google_info.json +0 -1
  67. data/test/fixtures/google_stats.json +0 -1
  68. data/test/fixtures/shorten_error.json +0 -1
  69. data/test/test_helper.rb +0 -39
@@ -1,145 +0,0 @@
1
- require 'rubygems'
2
- require 'net/http'
3
- require 'uri'
4
-
5
- module Bitly
6
- extend Config
7
- API_URL = 'https://api-ssl.bitly.com/'
8
- API_VERSION = '2.0.1'
9
-
10
- def self.new(login, api_key = nil, timeout=nil)
11
- if api_version == 3
12
- Bitly::V3::Client.new(login, api_key, timeout)
13
- else
14
- Bitly::Client.new(login,api_key)
15
- end
16
- end
17
-
18
- def self.use_api_version_3
19
- self.api_version = 3
20
- end
21
-
22
- def self.use_api_version_2
23
- self.api_version = 2
24
- end
25
-
26
- # get and initialize a client if configured using Config
27
- def self.client
28
- # api_verison, login, and api_key are set in Config
29
- if api_version == 3
30
- Bitly::V3::Client.new(login, api_key, timeout)
31
- else
32
- Bitly::Client.new(login, api_key)
33
- end
34
- end
35
-
36
- class Client
37
-
38
- include Bitly::Utils
39
- attr_accessor *Config::OPTION_KEYS
40
-
41
- def initialize(login,api_key)
42
- warn "[DEPRECATION] The bit.ly version 2 API has been superseded by version 3 and will be removed. See the README for details"
43
- @login = login
44
- @api_key = api_key
45
- end
46
-
47
- def shorten(input, opts={})
48
- if input.is_a? String
49
- request = create_url("shorten", :longUrl => input, :history => (opts[:history] ? 1 : nil))
50
- result = get_result(request)
51
- result = {:long_url => input}.merge result[input]
52
- Bitly::Url.new(@login,@api_key,result)
53
- elsif input.is_a? Array
54
- request = create_url("shorten", :history => (opts[:history] ? 1 : nil))
55
- request.query << "&" + input.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless input.nil?
56
- result = get_result(request)
57
- input.map do |long_url|
58
- new_url = {:long_url => long_url}.merge result[long_url]
59
- long_url = Bitly::Url.new(@login,@api_key,new_url)
60
- end
61
- else
62
- raise ArgumentError.new("Shorten requires either a url or an array of urls")
63
- end
64
- end
65
-
66
- def expand(input)
67
- if input.is_a? String
68
- if input.include?('bit.ly/') || input.include?('j.mp/')
69
- hash = create_hash_from_url(input)
70
- request = create_url "expand", :hash => hash
71
- result = get_result(request)
72
- result = { :short_url => input, :hash => hash }.merge result[hash]
73
- else
74
- request = create_url "expand", :hash => input
75
- result = get_result(request)
76
- result = { :hash => input, :short_url => "http://bit.ly/#{input}" }.merge result[input]
77
- end
78
- Bitly::Url.new(@login,@api_key,result)
79
- elsif input.is_a? Array
80
- request = create_url "expand", :hash => input.join(',')
81
- result = get_result(request)
82
- input.map do |hsh|
83
- new_url = {:hash => hsh, :short_url => "http://bit.ly/#{hsh}"}.merge result[hsh]
84
- hsh = Bitly::Url.new(@login,@api_key,new_url)
85
- end
86
- else
87
- raise ArgumentError('Expand requires either a short url, a hash or an array of hashes')
88
- end
89
- end
90
-
91
- def info(input)
92
- if input.is_a? String
93
- if input.include? "bit.ly/"
94
- hash = create_hash_from_url(input)
95
- request = create_url 'info', :hash => hash
96
- result = get_result(request)
97
- result = { :short_url => "http://bit.ly/#{hash}", :hash => hash }.merge result[hash]
98
- else
99
- request = create_url 'info', :hash => input
100
- result = get_result(request)
101
- result = { :short_url => "http://bit.ly/#{input}", :hash => input }.merge result[input]
102
- end
103
- Bitly::Url.new(@login,@api_key,result)
104
- elsif input.is_a? Array
105
- request = create_url "info", :hash => input.join(',')
106
- result = get_result(request)
107
- input.map do |hsh|
108
- new_url = {:hash => hsh, :short_url => "http://bit.ly/#{hsh}"}.merge result[hsh]
109
- hsh = Bitly::Url.new(@login,@api_key,:info => new_url)
110
- end
111
- else
112
- raise ArgumentError.new('Info requires either a short url, a hash or an array of hashes')
113
- end
114
- end
115
-
116
- def stats(input)
117
- if input.is_a? String
118
- if input.include? "bit.ly/"
119
- hash = create_hash_from_url(input)
120
- request = create_url 'stats', :hash => hash
121
- result = get_result(request)
122
- result = { :short_url => "http://bit.ly/#{hash}", :hash => hash }.merge result
123
- else
124
- request = create_url 'stats', :hash => input
125
- result = get_result(request)
126
- result = { :short_url => "http://bit.ly/#{input}", :hash => input }.merge result
127
- end
128
- Bitly::Url.new(@login,@api_key,:stats => result)
129
- else
130
- raise ArgumentError.new("Stats requires either a short url or a hash")
131
- end
132
- end
133
-
134
- end
135
-
136
- end
137
-
138
- class BitlyError < StandardError
139
- attr_reader :code
140
- alias :msg :message
141
- def initialize(msg, code)
142
- @code = code
143
- super("#{msg} - '#{code}'")
144
- end
145
- end
@@ -1,29 +0,0 @@
1
- module Bitly
2
- module Config
3
-
4
- # bitly client options
5
- OPTION_KEYS = [
6
- :login,
7
- :api_key,
8
- :api_version,
9
- :timeout
10
- ]
11
-
12
- attr_accessor *OPTION_KEYS
13
-
14
- alias_method :access_token, :login
15
- alias_method :access_token=, :login=
16
-
17
- def configure
18
- yield self
19
- self
20
- end
21
-
22
- def options
23
- options = {}
24
- OPTION_KEYS.each{|key| options[key] = send(key)}
25
- options
26
- end
27
-
28
- end
29
- end
@@ -1,103 +0,0 @@
1
- module Bitly
2
-
3
- class Url
4
- include Bitly::Utils
5
-
6
- attr_accessor :long_url, :short_url, :hash, :user_hash
7
- VARIABLES = ['long_url', 'short_url', 'hash', 'user_hash']
8
-
9
- def initialize(login,api_key,obj=nil)
10
- unless obj.nil?
11
- raise BitlyError.new(obj['errorMessage'],obj['errorCode']) if obj['statusCode'] == "ERROR"
12
- instance_variablise(obj, VARIABLES)
13
- @info = obj.fetch(:info, nil)
14
- @stats = obj.fetch(:stats, nil)
15
- end
16
- @login = login
17
- @api_key = api_key
18
- raise ArgumentError.new("Please provide a login and api_key") if @login.nil? || @api_key.nil?
19
- end
20
-
21
- def shorten(opts = {})
22
- return @short_url if defined? @short_url
23
- if defined? @long_url
24
- request = create_url("shorten", :longUrl => @long_url, :history => (opts[:history] ? 1 : nil))
25
- result = get_result(request)[@long_url.gsub(/\/$/,'')]
26
- if result['statusCode'] == "ERROR"
27
- raise BitlyError.new(result['errorMessage'],result['errorCode'])
28
- else
29
- instance_variablise(result,VARIABLES)
30
- return @short_url
31
- end
32
- else
33
- raise ArgumentError.new("You need a long_url in order to shorten it")
34
- end
35
- end
36
-
37
- def expand
38
- return @long_url if defined? @long_url
39
- unless !(short_url || hash)
40
- unless defined? @hash
41
- @hash = create_hash_from_url(@short_url)
42
- end
43
- request = create_url("expand", :hash => @hash)
44
- result = get_result(request)[@hash]
45
- if result['statusCode'] == "ERROR"
46
- raise BitlyError.new(result['errorMessage'],result['errorCode'])
47
- else
48
- instance_variablise(result,VARIABLES)
49
- return @long_url
50
- end
51
- else
52
- raise ArgumentError.new("You need a short_url or a hash in order to expand it")
53
- end
54
- end
55
-
56
- def info
57
- if @info.nil?
58
- if defined? @hash
59
- request = create_url "info", :hash => @hash
60
- result = get_result(request)[@hash]
61
- instance_variablise(result, VARIABLES)
62
- @info = result
63
- elsif defined? @short_url
64
- @hash = create_hash_from_url(@short_url)
65
- request = create_url "info", :hash => hash
66
- result = get_result(request)[hash]
67
- instance_variablise(result, VARIABLES)
68
- @info = result
69
- else
70
- raise ArgumentError.new("You need a hash or short_url in order to get info")
71
- end
72
- return @info
73
- else
74
- @info
75
- end
76
- end
77
-
78
- def stats
79
- if @stats.nil?
80
- if defined? @hash
81
- request = create_url "stats", :hash => @hash
82
- elsif defined? @short_url
83
- @hash = create_hash_from_url(@short_url)
84
- request = create_url "stats", :hash => @hash
85
- else
86
- raise ArgumentError.new("You need a hash or short_url in order to get stats")
87
- end
88
- @stats = get_result(request)
89
- else
90
- @stats
91
- end
92
- end
93
-
94
- def bitly_url
95
- @short_url.nil? ? nil : @short_url.gsub(/j\.mp/,'bit.ly')
96
- end
97
-
98
- def jmp_url
99
- @short_url.nil? ? nil : @short_url.gsub(/bit\.ly/,'j.mp')
100
- end
101
- end
102
-
103
- end
@@ -1,57 +0,0 @@
1
- require 'cgi'
2
-
3
- module Bitly
4
- module Utils
5
- def underscore(camel_cased_word) # stolen from rails
6
- camel_cased_word.to_s.gsub(/::/, '/').
7
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
8
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
9
- tr("-", "_").
10
- downcase
11
- end
12
-
13
- def create_hash_from_url(url)
14
- url.gsub(/^.*(bit\.ly|j\.mp)\//,'')
15
- end
16
-
17
- def attr_define(k,v)
18
- instance_variable_set("@#{k}", v)
19
- end
20
-
21
- def instance_variablise(obj,variables)
22
- if obj.is_a? Hash
23
- obj.each do |k,v|
24
- if v.is_a? Hash
25
- instance_variablise(v,variables)
26
- else
27
- attr_define(underscore(k),v) if variables.include?(underscore(k))
28
- end
29
- end
30
- end
31
- end
32
-
33
- def create_url(resource="",args={})
34
- args = args.merge({:login => @login, :apiKey => @api_key, :version => API_VERSION})
35
- url = URI.join(API_URL,resource)
36
- long_urls = args.delete(:long_urls)
37
- url.query = args.map { |k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
38
- url.query << "&" + long_urls.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless long_urls.nil?
39
- url
40
- end
41
-
42
- def get_result(request)
43
- begin
44
- json = Net::HTTP.get(request)
45
- result = MultiJson.load(json)
46
- rescue MultiJson::DecodeError
47
- result = {'errorMessage' => 'JSON Parse Error(Bit.ly messed up)', 'errorCode' => 69, 'statusCode' => 'ERROR'}
48
- end
49
- if result['statusCode'] == "OK"
50
- result = result['results']
51
- else
52
- raise BitlyError.new(result['errorMessage'],result['errorCode'])
53
- end
54
- end
55
-
56
- end
57
- end
@@ -1,14 +0,0 @@
1
- require 'httparty'
2
- require 'cgi'
3
- require 'oauth2'
4
-
5
- require 'bitly/v3/bitly'
6
- require 'bitly/v3/client'
7
- require 'bitly/v3/url'
8
- require 'bitly/v3/referrer'
9
- require 'bitly/v3/day'
10
- require 'bitly/v3/country'
11
- require 'bitly/v3/missing_url'
12
- require 'bitly/v3/realtime_link'
13
- require 'bitly/v3/oauth'
14
- require 'bitly/v3/user'
@@ -1,7 +0,0 @@
1
- module Bitly
2
- module V3
3
- def self.new(login, api_key)
4
- Bitly::V3::Client.new(login, api_key)
5
- end
6
- end
7
- end
@@ -1,207 +0,0 @@
1
- module Bitly
2
- module V3
3
- # The client is the main part of this gem. You need to initialize the client with your
4
- # username and API key and then you will be able to use the client to perform
5
- # all the rest of the actions available through the API.
6
- class Client
7
- include HTTParty
8
- base_uri 'https://api-ssl.bitly.com/v3/'
9
-
10
- # Requires a generic OAuth2 access token or -deprecated- login and api key.
11
- # http://dev.bitly.com/authentication.html#apikey
12
- # Generic OAuth2 access token: https://bitly.com/a/oauth_apps
13
- # ApiKey: Get yours from your account page at https://bitly.com/a/your_api_key
14
- # Visit your account at http://bit.ly/a/account
15
- def initialize(*args)
16
- args.compact!
17
- self.timeout = args.last.is_a?(0.class) ? args.pop : nil
18
- if args.count == 1
19
- # Set generic OAuth2 access token
20
- @default_query_opts = { :access_token => args.first }
21
- else
22
- # Deprecated ApiKey authentication
23
- @default_query_opts = {
24
- :login => args[0],
25
- :apiKey => args[1]
26
- }
27
- end
28
- end
29
-
30
- # Validates a login and api key
31
- def validate(x_login, x_api_key)
32
- response = get('/validate', :query => { :x_login => x_login, :x_apiKey => x_api_key })
33
- return response['data']['valid'] == 1
34
- end
35
- alias :valid? :validate
36
-
37
- # Checks whether a domain is a bitly.Pro domain
38
- def bitly_pro_domain(domain)
39
- response = get('/bitly_pro_domain', :query => { :domain => domain })
40
- return response['data']['bitly_pro_domain']
41
- end
42
- alias :pro? :bitly_pro_domain
43
-
44
- # Shortens a long url
45
- #
46
- # Options can be:
47
- #
48
- # [domain] choose bit.ly or j.mp (bit.ly is default)
49
- #
50
- # [x_login and x_apiKey] add this link to another user's history (both required)
51
- #
52
- def shorten(long_url, opts={})
53
- query = { :longUrl => long_url }.merge(opts)
54
- response = get('/shorten', :query => query)
55
- return Bitly::V3::Url.new(self, response['data'])
56
- end
57
-
58
- # Expands either a hash, short url or array of either.
59
- #
60
- # Returns the results in the order they were entered
61
- def expand(input)
62
- get_method(:expand, input)
63
- end
64
-
65
- # Expands either a hash, short url or array of either and gets click data too.
66
- #
67
- # Returns the results in the order they were entered
68
- def clicks(input)
69
- get_method(:clicks, input)
70
- end
71
-
72
- # Like expand, but gets the title of the page and who created it
73
- def info(input)
74
- get_method(:info, input)
75
- end
76
-
77
- # Looks up the short url and global hash of a url or array of urls
78
- #
79
- # Returns the results in the order they were entered
80
- def lookup(input)
81
- input = arrayize(input)
82
- query = input.inject([]) { |query, i| query << "url=#{CGI.escape(i)}" }
83
- query = "/lookup?" + query.join('&')
84
- response = get(query)
85
- results = response['data']['lookup'].inject([]) do |results, url|
86
- url['long_url'] = url['url']
87
- url['url'] = nil
88
- if url['error'].nil?
89
- # builds the results array in the same order as the input
90
- results[input.index(url['long_url'])] = Bitly::V3::Url.new(self, url)
91
- # remove the key from the original array, in case the same hash/url was entered twice
92
- input[input.index(url['long_url'])] = nil
93
- else
94
- results[input.index(url['long_url'])] = Bitly::V3::MissingUrl.new(url)
95
- input[input.index(url['long_url'])] = nil
96
- end
97
- results
98
- end
99
- return results.length > 1 ? results : results[0]
100
- end
101
-
102
- # Expands either a short link or hash and gets the referrer data for that link
103
- #
104
- # This method does not take an array as an input
105
- def referrers(input)
106
- get_single_method('referrers', input)
107
- end
108
-
109
- # Expands either a short link or hash and gets the country data for that link
110
- #
111
- # This method does not take an array as an input
112
- def countries(input)
113
- get_single_method('countries', input)
114
- end
115
-
116
- # Takes a short url, hash or array of either and gets the clicks by minute of each of the last hour
117
- def clicks_by_minute(input)
118
- get_method(:clicks_by_minute, input)
119
- end
120
-
121
- # Takes a short url, hash or array of either and gets the clicks by day
122
- def clicks_by_day(input, opts={})
123
- opts.reject! { |k, v| k.to_s != 'days' }
124
- get_method(:clicks_by_day, input, opts)
125
- end
126
-
127
- def timeout=(timeout=nil)
128
- self.class.default_timeout(timeout) if timeout
129
- end
130
-
131
- private
132
-
133
- def arrayize(arg)
134
- if arg.is_a?(String)
135
- [arg]
136
- else
137
- arg.dup
138
- end
139
- end
140
-
141
- def get(method, opts={})
142
- opts[:query] ||= {}
143
- opts[:query].merge!(@default_query_opts)
144
-
145
- begin
146
- response = self.class.get(method, opts)
147
- rescue Timeout::Error
148
- raise BitlyTimeout.new("Bitly didn't respond in time", "504")
149
- end
150
-
151
- if response['status_code'] == 200
152
- return response
153
- else
154
- raise BitlyError.new(response['status_txt'], response['status_code'])
155
- end
156
- end
157
-
158
- def is_a_short_url?(input)
159
- input.match(/^http:\/\//)
160
- end
161
-
162
- def get_single_method(method, input)
163
- raise ArgumentError.new("This method only takes a hash or url input") unless input.is_a? String
164
- if is_a_short_url?(input)
165
- query = "shortUrl=#{CGI.escape(input)}"
166
- else
167
- query = "hash=#{CGI.escape(input)}"
168
- end
169
- query = "/#{method}?" + query
170
- response = get(query)
171
- return Bitly::V3::Url.new(self,response['data'])
172
- end
173
-
174
- def get_method(method, input, opts={})
175
- input = arrayize(input)
176
- query = input.inject([]) do |query,i|
177
- if is_a_short_url?(i)
178
- query << "shortUrl=#{CGI.escape(i)}"
179
- else
180
- query << "hash=#{CGI.escape(i)}"
181
- end
182
- end
183
- query = opts.inject(query) do |query, (k,v)|
184
- query << "#{k}=#{v}"
185
- end
186
- query = "/#{method}?" + query.join('&')
187
- response = get(query)
188
- results = response['data'][method.to_s].inject([]) do |results, url|
189
- result_index = input.index(url['short_url'] || url['hash']) || input.index(url['global_hash'])
190
- if url['error'].nil?
191
- # builds the results array in the same order as the input
192
- results[result_index] = Bitly::V3::Url.new(self, url)
193
- # remove the key from the original array, in case the same hash/url was entered twice
194
- input[result_index] = nil
195
- else
196
- results[result_index] = Bitly::V3::MissingUrl.new(url)
197
- input[result_index] = nil
198
- end
199
- results
200
- end
201
- return results.length > 1 ? results : results[0]
202
- end
203
- end
204
- end
205
- end
206
-
207
- class BitlyTimeout < BitlyError; end