cotweet-bitly 0.5.2

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.
@@ -0,0 +1,60 @@
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
+ meta = class << self; self; end
20
+ meta.class_eval { attr_reader k.to_sym }
21
+ end
22
+
23
+ def instance_variablise(obj,variables)
24
+ if obj.is_a? Hash
25
+ obj.each do |k,v|
26
+ if v.is_a? Hash
27
+ instance_variablise(v,variables)
28
+ else
29
+ attr_define(underscore(k),v) if variables.include?(underscore(k))
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def create_url(resource="",args={})
36
+ args = args.merge({:login => @login, :apiKey => @api_key, :version => API_VERSION})
37
+ url = URI.join(API_URL,resource)
38
+ long_urls = args.delete(:long_urls)
39
+ url.query = args.map { |k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
40
+ url.query << "&" + long_urls.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless long_urls.nil?
41
+ url
42
+ end
43
+
44
+ def get_result(request)
45
+ begin
46
+ json = Net::HTTP.get(request)
47
+ # puts json.inspect
48
+ result = Crack::JSON.parse(json)
49
+ rescue
50
+ result = {'errorMessage' => 'JSON Parse Error(Bit.ly messed up)', 'errorCode' => 69, 'statusCode' => 'ERROR'}
51
+ end
52
+ if result['statusCode'] == "OK"
53
+ result = result['results']
54
+ else
55
+ raise BitlyError.new(result['errorMessage'],result['errorCode'])
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,9 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'httparty'
4
+ require 'cgi'
5
+
6
+ require 'v3/bitly'
7
+ require 'v3/client'
8
+ require 'v3/url'
9
+ require 'v3/missing_url'
@@ -0,0 +1,16 @@
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
8
+
9
+ class BitlyError < StandardError
10
+ attr_reader :code
11
+ alias :msg :message
12
+ def initialize(msg, code)
13
+ @code = code
14
+ super("#{msg} - '#{code}'")
15
+ end
16
+ end
@@ -0,0 +1,143 @@
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 'http://api.bit.ly/v3/'
9
+
10
+ # Requires a login and api key. Get yours from your account page at http://bit.ly/a/account
11
+ def initialize(login, api_key)
12
+ @default_query_opts = { :login => login, :apiKey => api_key }
13
+ end
14
+
15
+ # Validates a login and api key
16
+ def validate(x_login, x_api_key)
17
+ response = get('/validate', :query => { :x_login => x_login, :x_apiKey => x_api_key })
18
+ return response['data']['valid'] == 1
19
+ end
20
+ alias :valid? :validate
21
+
22
+ # Checks whether a domain is a bitly.Pro domain
23
+ def bitly_pro_domain(domain)
24
+ response = get('/bitly_pro_domain', :query => { :domain => domain })
25
+ return response['data']['bitly_pro_domain']
26
+ end
27
+ alias :pro? :bitly_pro_domain
28
+
29
+ # Shortens a long url
30
+ #
31
+ # Options can be:
32
+ #
33
+ # [domain] choose bit.ly or j.mp (bit.ly is default)
34
+ #
35
+ # [x_login and x_apiKey] add this link to another user's history (both required)
36
+ #
37
+ def shorten(long_url, opts={})
38
+ query = { :longUrl => long_url }.merge(opts)
39
+ response = get('/shorten', :query => query)
40
+ return Bitly::V3::Url.new(self, response['data'])
41
+ end
42
+
43
+ # Expands either a hash, short url or array of either.
44
+ #
45
+ # Returns the results in the order they were entered
46
+ def expand(input)
47
+ get_method(:expand, input)
48
+ end
49
+
50
+ # Expands either a hash, short url or array of either and gets click data too.
51
+ #
52
+ # Returns the results in the order they were entered
53
+ def clicks(input)
54
+ get_method(:clicks, input)
55
+ end
56
+
57
+ # Like expand, but gets the title of the page and who created it
58
+ def info(input)
59
+ get_method(:info, input)
60
+ end
61
+
62
+ # Provides a list of referring sites for a specified bit.ly short link, and the number of clicks per referrer.
63
+ def referrers(input)
64
+ if is_a_short_url?(input)
65
+ query = { :shortUrl => CGI.escape(input) }
66
+ else
67
+ query = { :hash => CGI.escape(input) }
68
+ end
69
+ get("/referrers", :query => query)["data"]
70
+ end
71
+
72
+ # Looks up the short url and global hash of a url or array of urls
73
+ #
74
+ # Returns the results in the order they were entered
75
+ def lookup(input)
76
+ input = [input] if input.is_a?(String)
77
+ query = input.inject([]) { |query, i| query << "url=#{CGI.escape(i)}" }
78
+ query = "/lookup?" + query.join('&')
79
+ response = get(query)
80
+ results = response['data']['lookup'].inject([]) do |results, url|
81
+ url['long_url'] = url['url']
82
+ url['url'] = nil
83
+ if url['error'].nil?
84
+ # builds the results array in the same order as the input
85
+ results[input.index(url['long_url'])] = Bitly::V3::Url.new(self, url)
86
+ # remove the key from the original array, in case the same hash/url was entered twice
87
+ input[input.index(url['long_url'])] = nil
88
+ else
89
+ results[input.index(url['long_url'])] = Bitly::V3::MissingUrl.new(url)
90
+ input[input.index(url['long_url'])] = nil
91
+ end
92
+ results
93
+ end
94
+ return results.length > 1 ? results : results[0]
95
+ end
96
+
97
+ private
98
+
99
+ def get(method, opts={})
100
+ opts[:query] ||= {}
101
+ opts[:query].merge!(@default_query_opts)
102
+ response = self.class.get(method, opts)
103
+ if response['status_code'] == 200
104
+ return response
105
+ else
106
+ raise BitlyError.new(response['status_txt'], response['status_code'])
107
+ end
108
+ end
109
+
110
+ def is_a_short_url?(input)
111
+ input.match(/^http:\/\//)
112
+ end
113
+
114
+ def get_method(method, input)
115
+ input = [input] if input.is_a? String
116
+ query = input.inject([]) do |query,i|
117
+ if is_a_short_url?(i)
118
+ query << "shortUrl=#{CGI.escape(i)}"
119
+ else
120
+ query << "hash=#{CGI.escape(i)}"
121
+ end
122
+ end
123
+ query = "/#{method}?" + query.join('&')
124
+ response = get(query)
125
+ results = response['data'][method.to_s].inject([]) do |results, url|
126
+ result_index = input.index(url['short_url'] || url['hash']) || input.index(url['global_hash'])
127
+ if url['error'].nil?
128
+ # builds the results array in the same order as the input
129
+ results[result_index] = Bitly::V3::Url.new(self, url)
130
+ # remove the key from the original array, in case the same hash/url was entered twice
131
+ input[result_index] = nil
132
+ else
133
+ results[result_index] = Bitly::V3::MissingUrl.new(url)
134
+ input[result_index] = nil
135
+ end
136
+ results
137
+ end
138
+ return results.length > 1 ? results : results[0]
139
+ end
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,15 @@
1
+ module Bitly
2
+ module V3
3
+ class MissingUrl
4
+ attr_accessor :short_url, :user_hash, :long_url, :error
5
+ def initialize(opts={})
6
+ if opts
7
+ @short_url = opts['short_url']
8
+ @user_hash = opts['hash']
9
+ @long_url = opts['long_url']
10
+ @error = opts['error']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,77 @@
1
+ module Bitly
2
+ module V3
3
+ # Url objects should only be created by the client object as it collects the correct information
4
+ # from the API.
5
+ class Url
6
+ attr_reader :short_url, :long_url, :user_hash, :global_hash
7
+
8
+ # Initialize with a bitly client and optional hash to fill in the details for the url.
9
+ def initialize(client, opts={})
10
+ @client = client
11
+ if opts
12
+ @short_url = opts['url'] || opts['short_url']
13
+ @long_url = opts['long_url']
14
+ @user_hash = opts['hash'] || opts['user_hash']
15
+ @global_hash = opts['global_hash']
16
+ @new_hash = (opts['new_hash'] == 1)
17
+ @user_clicks = opts['user_clicks']
18
+ @global_clicks = opts['global_clicks']
19
+ @title = opts['title']
20
+ @created_by = opts['created_by']
21
+ end
22
+ @short_url = "http://bit.ly/#{@user_hash}" unless @short_url
23
+ end
24
+
25
+ # Returns true if the user hash was created first for this call
26
+ def new_hash?
27
+ @new_hash
28
+ end
29
+
30
+ # If the url already has click statistics, returns the user clicks.
31
+ # IF there are no click statistics or <tt>:force => true</tt> is passed,
32
+ # updates the stats and returns the user clicks
33
+ def user_clicks(opts={})
34
+ update_clicks_data if @global_clicks.nil? || opts[:force]
35
+ @user_clicks
36
+ end
37
+
38
+ # If the url already has click statistics, returns the global clicks.
39
+ # IF there are no click statistics or <tt>:force => true</tt> is passed,
40
+ # updates the stats and returns the global clicks
41
+ def global_clicks(opts={})
42
+ update_clicks_data if @global_clicks.nil? || opts[:force]
43
+ @global_clicks
44
+ end
45
+
46
+ # If the url already has the title, return it.
47
+ # IF there is no title or <tt>:force => true</tt> is passed,
48
+ # updates the info and returns the title
49
+ def title(opts={})
50
+ update_info if @title.nil? || opts[:force]
51
+ @title
52
+ end
53
+
54
+ # If the url already has the creator, return it.
55
+ # IF there is no creator or <tt>:force => true</tt> is passed,
56
+ # updates the info and returns the creator
57
+ def created_by(opts={})
58
+ update_info if @created_by.nil? || opts[:force]
59
+ @created_by
60
+ end
61
+
62
+ private
63
+
64
+ def update_clicks_data
65
+ full_url = @client.clicks(@user_hash || @short_url)
66
+ @global_clicks = full_url.global_clicks
67
+ @user_clicks = full_url.user_clicks
68
+ end
69
+
70
+ def update_info
71
+ full_url = @client.info(@user_hash || @short_url)
72
+ @created_by = full_url.created_by
73
+ @title = full_url.title
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module Bitly
2
+ VERSION = '0.5.3'
3
+ end
@@ -0,0 +1,215 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'test_helper.rb')
2
+
3
+ class TestClient < Test::Unit::TestCase
4
+ context "bitly module" do
5
+ should "create a new bitly client" do
6
+ b = Bitly.new(login, api_key)
7
+ assert_equal Bitly::Client, b.class
8
+ end
9
+ end
10
+ context "using the bitly client" do
11
+ setup do
12
+ @bitly = Bitly.new(login, api_key)
13
+ end
14
+
15
+ context "shortening" do
16
+ context "a single link" do
17
+ setup do
18
+ stub_get(/^http:\/\/api.bit.ly\/shorten\?.*longUrl=.*cnn.com.*$/,"cnn.json")
19
+ @url = @bitly.shorten('http://cnn.com')
20
+ end
21
+ should "return a Bitly::Url" do
22
+ assert_kind_of Bitly::Url, @url
23
+ end
24
+ should "return a short bitly url" do
25
+ assert_equal "http://bit.ly/15DlK", @url.short_url
26
+ assert_equal "http://bit.ly/15DlK", @url.bitly_url
27
+ end
28
+ should "return a short jmp url" do
29
+ assert_equal "http://j.mp/15DlK", @url.jmp_url
30
+ end
31
+ should "save the long url" do
32
+ assert_equal "http://cnn.com", @url.long_url
33
+ end
34
+ end
35
+ context "multiple links" do
36
+ setup do
37
+ stub_get(/^http:\/\/api.bit.ly\/shorten\?.*longUrl=.*longUrl=.*$/,"cnn_and_google.json")
38
+ @urls = @bitly.shorten(['http://cnn.com', 'http://google.com'])
39
+ end
40
+ should "return an array of Bitly::Urls" do
41
+ assert_kind_of Array, @urls
42
+ assert_kind_of Bitly::Url, @urls[0]
43
+ end
44
+ should "shorten the urls in order" do
45
+ assert_equal "http://bit.ly/15DlK", @urls[0].short_url
46
+ assert_equal "http://bit.ly/11etr", @urls[1].short_url
47
+ end
48
+ should "save the long urls" do
49
+ assert_equal "http://cnn.com", @urls[0].long_url
50
+ assert_equal "http://google.com", @urls[1].long_url
51
+ end
52
+ end
53
+ context "no links" do
54
+ should "raise an ArgumentError" do
55
+ assert_raise ArgumentError do
56
+ @bitly.shorten
57
+ end
58
+ end
59
+ end
60
+ end
61
+ context "expanding" do
62
+ context "a hash" do
63
+ setup do
64
+ stub_get(/^http:\/\/api.bit.ly\/expand\?.*hash=31IqMl.*$/,"expand_cnn.json")
65
+ @url = @bitly.expand("31IqMl")
66
+ end
67
+ should "return a Bitly::Url" do
68
+ assert_kind_of Bitly::Url, @url
69
+ end
70
+ should "return the expanded url" do
71
+ assert_equal "http://cnn.com/", @url.long_url
72
+ end
73
+ should "save the hash" do
74
+ assert_equal "31IqMl", @url.hash
75
+ end
76
+ should "save the short url" do
77
+ assert_equal "http://bit.ly/31IqMl", @url.short_url
78
+ end
79
+ end
80
+ context "a short bitly url" do
81
+ setup do
82
+ stub_get(/^http:\/\/api.bit.ly\/expand\?.*hash=31IqMl.*$/,"expand_cnn.json")
83
+ @url = @bitly.expand("http://bit.ly/31IqMl")
84
+ end
85
+ should "return a Bitly::Url" do
86
+ assert_kind_of Bitly::Url, @url
87
+ end
88
+ should "return the expanded url" do
89
+ assert_equal "http://cnn.com/", @url.long_url
90
+ end
91
+ should "save the hash" do
92
+ assert_equal "31IqMl", @url.hash
93
+ end
94
+ should "save the bitly url" do
95
+ assert_equal "http://bit.ly/31IqMl", @url.bitly_url
96
+ end
97
+ should "save a jmp url" do
98
+ assert_equal "http://j.mp/31IqMl", @url.jmp_url
99
+ end
100
+ end
101
+ context "a short jmp url" do
102
+ setup do
103
+ stub_get(/^http:\/\/api.bit.ly\/expand\?.*hash=31IqMl.*$/,"expand_cnn.json")
104
+ @url = @bitly.expand("http://j.mp/31IqMl")
105
+ end
106
+ should "return a Bitly::Url" do
107
+ assert_kind_of Bitly::Url, @url
108
+ end
109
+ should "return the expanded url" do
110
+ assert_equal "http://cnn.com/", @url.long_url
111
+ end
112
+ should "save the hash" do
113
+ assert_equal "31IqMl", @url.hash
114
+ end
115
+ should "save the bitly url" do
116
+ assert_equal "http://bit.ly/31IqMl", @url.bitly_url
117
+ end
118
+ should "save a jmp url" do
119
+ assert_equal "http://j.mp/31IqMl", @url.jmp_url
120
+ end
121
+ end
122
+ context "multiple hashes" do
123
+ setup do
124
+ stub_get(/^http:\/\/api.bit.ly\/expand\?.*hash=15DlK.*3j4ir4.*$/,"expand_cnn_and_google.json")
125
+ @urls = @bitly.expand(["15DlK","3j4ir4"])
126
+ end
127
+ should "return an array of Bitly::Urls" do
128
+ assert_kind_of Array, @urls
129
+ assert_kind_of Bitly::Url, @urls[0]
130
+ assert_kind_of Bitly::Url, @urls[1]
131
+ end
132
+ should "expand the hashes in order" do
133
+ assert_equal "http://cnn.com/", @urls[0].long_url
134
+ assert_equal "http://google.com/", @urls[1].long_url
135
+ end
136
+ should "save the hash to each url" do
137
+ assert_equal "15DlK", @urls[0].hash
138
+ assert_equal "3j4ir4", @urls[1].hash
139
+ end
140
+ end
141
+ end
142
+ context "to get info on" do
143
+ context "a single link" do
144
+ setup do
145
+ stub_get(/^http:\/\/api.bit.ly\/info\?.*hash=3j4ir4.*$/,"google_info.json")
146
+ @url = @bitly.info('http://bit.ly/3j4ir4')
147
+ end
148
+ should "return a Bitly::Url" do
149
+ assert_kind_of Bitly::Url, @url
150
+ end
151
+ should "return an info object with the url" do
152
+ assert_not_nil @url.info
153
+ end
154
+ end
155
+ context "a single hash" do
156
+ setup do
157
+ stub_get(/^http:\/\/api.bit.ly\/info\?.*hash=3j4ir4.*$/,"google_info.json")
158
+ @url = @bitly.info('3j4ir4')
159
+ end
160
+ should "return a Bitly::Url" do
161
+ assert_kind_of Bitly::Url, @url
162
+ end
163
+ should "return an info object with the url" do
164
+ assert_not_nil @url.info
165
+ end
166
+ end
167
+ context "a list of hashes" do
168
+ setup do
169
+ stub_get(/^http:\/\/api.bit.ly\/info\?.*hash=3j4ir4.*31IqMl.*$/,"google_and_cnn_info.json")
170
+ @urls = @bitly.info(['3j4ir4','31IqMl'])
171
+ end
172
+ should "return a Bitly::Url" do
173
+ assert_kind_of Array, @urls
174
+ end
175
+ should "return an info object with the url" do
176
+ assert_not_nil @urls[0].info
177
+ assert_not_nil @urls[1].info
178
+ end
179
+ end
180
+ end
181
+ context "to get stats on" do
182
+ context "a single link" do
183
+ setup do
184
+ stub_get(/^http:\/\/api.bit.ly\/stats\?.*hash=3j4ir4.*$/,"google_stats.json")
185
+ @url = @bitly.stats('http://bit.ly/3j4ir4')
186
+ end
187
+ should "return a Bitly::Url" do
188
+ assert_kind_of Bitly::Url, @url
189
+ end
190
+ should "return an stats object" do
191
+ assert_not_nil @url.stats
192
+ end
193
+ end
194
+ context "a single hash" do
195
+ setup do
196
+ stub_get(/^http:\/\/api.bit.ly\/stats\?.*hash=3j4ir4.*$/,"google_stats.json")
197
+ @url = @bitly.stats('3j4ir4')
198
+ end
199
+ should "return a Bitly::Url" do
200
+ assert_kind_of Bitly::Url, @url
201
+ end
202
+ should "return an stats object" do
203
+ assert_not_nil @url.stats
204
+ end
205
+ end
206
+ context "a list of hashes" do
207
+ should "return an argument error" do
208
+ assert_raise ArgumentError do
209
+ @bitly.stats(['3j4ir4','31IqMl'])
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end