use0mk 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (8) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +27 -0
  3. data/Manifest +6 -0
  4. data/README +64 -0
  5. data/Rakefile +11 -0
  6. data/lib/use0mk.rb +389 -0
  7. data/use0mk.gemspec +33 -0
  8. metadata +95 -0
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ v0.1.1. Documentation changes.
2
+ v0.1. Ready.
3
+
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+
2
+ = License
3
+
4
+ Use0MK is licensed under the terms of the MIT License. The license text is as follows.
5
+
6
+ == MIT License
7
+
8
+ Copyright © 2010 Stojan Dimitrovski <s.dimitrovski@gmail.com>
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in
18
+ all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26
+ THE SOFTWARE.
27
+
data/Manifest ADDED
@@ -0,0 +1,6 @@
1
+ CHANGELOG
2
+ LICENSE
3
+ Manifest
4
+ README
5
+ Rakefile
6
+ lib/use0mk.rb
data/README ADDED
@@ -0,0 +1,64 @@
1
+
2
+ = Use0MK
3
+
4
+ Use0MK is a Ruby interface for the {http://0.mk} URL shortening service. It uses standard Ruby conventions in exposing 0.mk's API and allows developers to more easily utilize 0.mk.
5
+
6
+ == Installation
7
+
8
+ Use0MK requires the +json+ gem in order to work properly.
9
+
10
+ Use0MK as a gem is hosted on {http://gemcutter.org}. After adding gemcutter to your gem sources, install it with:
11
+
12
+ gem install use0mk
13
+
14
+ == Examples
15
+
16
+ === Shortening a URL
17
+
18
+ require "use0mk"
19
+
20
+ # Pass your username as the first argument and your API key as
21
+ # the second. You can safely use this without them.
22
+ zeromk = Use0MK::Interface.new
23
+
24
+ # It is probably a good idea to watch for exceptions when
25
+ # calling any method on Use0MK::Interface or Use0MK::ShortenedURI
26
+ # in order to check if something went wrong. Watch for the exceptions
27
+ # thrown by URI.parse, Net::HTTP errors and the Use0MK errors.
28
+ short = zeromk.shorten("http://google.com")
29
+
30
+ puts "Shortened #{short.title}[#{short.long_uri}] to #{short.short_uri},"
31
+ puts "with #{short.short_name}. Use #{short.delete_uri} with this"
32
+ puts "delete code #{short.delete_code} to delete this shortened URL."
33
+ puts "You can view the stats on this shortened URL by following"
34
+ puts "#{short.stats_uri}, too."
35
+
36
+ puts
37
+
38
+ puts "Too late, now your shortened URL has been deleted.\n" if short.delete
39
+
40
+
41
+ === Previewing a URL
42
+
43
+ require "use0mk"
44
+
45
+ zeromk = Use0MK::Interface.new # username, API key
46
+
47
+ # It's a good idea to watch for URI, Net::HTTP and Use0MK errors here.
48
+ # Pass a hash of :uri, or :short_name to preview in order to have it
49
+ # work out for you.
50
+ preview = zeromk.preview :uri => "http://0.mk/use0mkrb"
51
+
52
+ deletable = preview.delete
53
+
54
+ puts "The #{preview.short_uri} links to #{preview.long_uri}."
55
+ puts "Too bad, tho, it was created by #{preview.origin}ing a"
56
+ puts "given URL/shortname. Now you #{deletable ? 'can' : 'cannot'}"
57
+ puts "delete the short URL. #{deletable ? ':)' : ':(' }"
58
+
59
+ puts
60
+
61
+ == Copyright
62
+
63
+ Use0MK is Copyright © 2010 Stojan Dimitrovski. Refer to the LICENSE file included in this distribution for more information on the copyrights.
64
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rubygems"
2
+ require "echoe"
3
+
4
+ Echoe.new("use0mk") do |g|
5
+ g.author = "Stojan Dimitrovski"
6
+ g.email = "s.dimitrovski@gmail.com"
7
+ g.summary = "Ruby interface for the 0.mk URL shortening service."
8
+ g.url = "http://github.com/hf/use0mk"
9
+ g.runtime_dependencies = ["json"]
10
+ end
11
+
data/lib/use0mk.rb ADDED
@@ -0,0 +1,389 @@
1
+ #
2
+ # Copyright (c) 2010 Stojan Dimitrovski <s.dimitrovski@gmail.com>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ require "rubygems"
23
+ require "net/http"
24
+ require "json"
25
+
26
+ module Use0MK
27
+ SHORTEN_URI = "http://api.0.mk/v2/skrati"
28
+ PREVIEW_URI = "http://api.0.mk/v2/pregled"
29
+ ORIGINS = [:shorten, :preview]
30
+
31
+ # ERRORS defined below
32
+ end
33
+
34
+ # Standard error class concerning {Use0MK} errors.
35
+ class Use0MK::Error < StandardError
36
+ # the message returned by 0.mk
37
+ # @return [String]
38
+ attr_reader :message
39
+ # the status ID for the error
40
+ # @return [Integer]
41
+ attr_reader :status
42
+ end
43
+
44
+ # Too many redirects while attempting an API call.
45
+ #
46
+ # *status*: 100
47
+ class Use0MK::RedirectError < Use0MK::Error
48
+ def initialize(message)
49
+ @message = message
50
+ @status = 100
51
+ end
52
+ end
53
+
54
+ # Provided link (any URI concerning any API call) was empty.
55
+ #
56
+ # *status*: 1
57
+ class Use0MK::EmptyLinkError < Use0MK::Error
58
+ def initialize(message)
59
+ @message = message
60
+ @status = 1
61
+ end
62
+ end
63
+
64
+ # Provided link (any URI concerning any API call) was invalid.
65
+ #
66
+ # *status*: 2
67
+ class Use0MK::InvalidLinkError < Use0MK::Error
68
+ def initialize(message)
69
+ @message = message
70
+ @status = 2
71
+ end
72
+ end
73
+
74
+ # Provided format parameter was invalid. Probably an internal error.
75
+ #
76
+ # *status*: 3
77
+ class Use0MK::InvalidFormatError < Use0MK::Error
78
+ def initialize(message)
79
+ @message = message
80
+ @status = 3
81
+ end
82
+ end
83
+
84
+ # Provided (custom) short name was invalid.
85
+ #
86
+ # *status*: 4
87
+ class Use0MK::InvalidShortNameError < Use0MK::Error
88
+ def initialize(message)
89
+ @message = message
90
+ @status = 4
91
+ end
92
+ end
93
+
94
+ # Provided API key was invalid.
95
+ #
96
+ # *status*: 5
97
+ class Use0MK::InvalidAPIKey < Use0MK::Error
98
+ def initialize(message)
99
+ @message = message
100
+ @status = 5
101
+ end
102
+ end
103
+
104
+ # Provided credentials were invalid.
105
+ #
106
+ # *status*: 6
107
+ class Use0MK::InvalidCredentials < Use0MK::Error
108
+ def initialize(message)
109
+ @message = message
110
+ @status = 6
111
+ end
112
+ end
113
+
114
+ # API call not supported by 0.mk. Check {Use0MK::SHORTEN_URI} and
115
+ # {Use0MK::PREVIEW_URI} to see which API is being used. Probably an
116
+ # internal error.
117
+ #
118
+ # *status*: 7
119
+ class Use0MK::InvalidAPICall < Use0MK::Error
120
+ def initialize(message)
121
+ @message = message
122
+ @status = 7
123
+ end
124
+ end
125
+
126
+ module Use0MK
127
+ APIERRORS = [
128
+ Use0MK::EmptyLinkError,
129
+ Use0MK::InvalidLinkError,
130
+ Use0MK::InvalidFormatError,
131
+ Use0MK::InvalidShortNameError,
132
+ Use0MK::InvalidAPIKey,
133
+ Use0MK::InvalidCredentials,
134
+ Use0MK::InvalidAPICall
135
+ ]
136
+ end
137
+
138
+ # Represents a shortened URI from 0.mk. It contains only the information
139
+ # retrieved by the API call to 0.mk. The volume of information with any
140
+ # API call is not consistent therefore any attribute of this class that
141
+ # is +nil+ or +empty+ should be ignored.
142
+ #
143
+ # The origin (the API call which generated the object of this class)
144
+ # of this object can be tracked with the +origin+ attribute. The origin
145
+ # is a Symbol which is a member of {Use0MK::ORIGINS}.
146
+ #
147
+ # It is not a good idea to create instances of this class by hand, as
148
+ # it contains only data available from API calls to 0.mk.
149
+ #
150
+ class Use0MK::ShortenedURI
151
+ # a member of {Use0MK::ORIGINS}
152
+ # @return [Symbol]
153
+ attr_reader :origin
154
+ # the long URI
155
+ # @return [String, nil]
156
+ attr_reader :long_uri
157
+ # the shortened URI
158
+ # @return [String, nil]
159
+ attr_reader :short_uri
160
+ # the short name (+http://0.mk/short_name+)
161
+ # @return [String, nil]
162
+ attr_reader :short_name
163
+ # the stats URI
164
+ # @return [String, nil]
165
+ attr_reader :stats_uri
166
+ # the document title of the long URI
167
+ # @return [String, nil]
168
+ attr_reader :title
169
+ # the deletion URI
170
+ # @return [String, nil]
171
+ attr_reader :delete_uri
172
+ # the deletion code
173
+ # @return [String, nil]
174
+ attr_reader :delete_code
175
+ # whether this URI is deleted
176
+ # @return [true, false]
177
+ attr_reader :deleted
178
+
179
+ # Initializes this class. Usually called from either +shorten+ or +preview+.
180
+ #
181
+ # @param [Symbol] origin origin of this class (which API call created it), a member of {Use0MK::ORIGINS}
182
+ # @param [Hash] attributes hash of the attributes needed to create the object
183
+ def initialize(origin, attributes = {})
184
+
185
+ if !(Use0MK::ORIGINS.member? origin)
186
+ raise ArgumentError, "origin should be a member of Use0MK::ORIGINS"
187
+ end
188
+
189
+ @origin = origin
190
+ @deleted = @origin != :shorten
191
+
192
+ @long_uri = attributes[:long_uri]
193
+ @short_uri = attributes[:short_uri]
194
+ @short_name = attributes[:short_name]
195
+ @stats_uri = attributes[:stats_uri]
196
+ @title = attributes[:title]
197
+ @delete_uri = attributes[:delete_uri]
198
+ @delete_code = attributes[:delete_code]
199
+ end
200
+
201
+ # Deletes the shortened URI.
202
+ # This method calls {Use0MK::Interface.delete} internally.
203
+ #
204
+ # @return [true, false] wheter deletion succeeds (usually +true+ when +origin+ is +:shorten+)
205
+ def delete
206
+ if @deleted
207
+ return false
208
+ end
209
+
210
+ @deleted = Use0MK::Interface.delete(@delete_uri, @delete_code)
211
+ end
212
+ end
213
+
214
+ # This class represents the main interface through which one can operate on
215
+ # the 0.mk API.
216
+ class Use0MK::Interface
217
+ # the username associated with 0.mk
218
+ # @return [String, nil]
219
+ attr_accessor :username
220
+ # the API key for 0.mk
221
+ # @return [String, nil]
222
+ attr_accessor :apikey
223
+
224
+ # Initializes the {Use0MK::Interface}.
225
+ #
226
+ # @param [String] username 0.mk username
227
+ # @param [String] apikey 0.mk API key
228
+ def initialize(username = nil, apikey = nil)
229
+ @username = username
230
+ @apikey = apikey
231
+ end
232
+
233
+ # Deletes a shortened URI from 0.mk.
234
+ # This method does not raise or handles any exceptions. It also does not
235
+ # handle redirection.
236
+ #
237
+ # @param [String] delete_uri the 0.mk URI to delete
238
+ # @param [String] delete_code the 0.mk delete code associated with the 0.mk URI
239
+ # @return [true, false] wheter the delete succeeded
240
+ def self.delete(delete_uri, delete_code)
241
+ delete_uri = URI.parse(delete_uri)
242
+
243
+ response = Net::HTTP.post_form(delete_uri,
244
+ {'brisiKod' => delete_code})
245
+
246
+ case response
247
+ when Net::HTTPSuccess
248
+ return true # phew, that was hard work, that delete
249
+ end
250
+
251
+ return false
252
+ end
253
+
254
+ # Shortens a URI.
255
+ # This method can raise several exceptions of which most importantly:
256
+ # * {URI::Error}
257
+ # * {Net::HTTPException}
258
+ # * {Use0MK::Error}
259
+ #
260
+ # It is a wise thing to watch for any of those exceptions.
261
+ #
262
+ # @param [String] uri the _long_ URI to shorten
263
+ # @param [String] short_name a custom short name to use when shortening the long URI (+http://0.mk/short_name+)
264
+ # @return [Use0MK::ShortenedURI] the shortened URI
265
+ def shorten(uri, short_name = nil)
266
+ uri = URI.parse(uri)
267
+
268
+ _shorten(uri, short_name)
269
+ end
270
+
271
+ # Inspects an already shortened URI.
272
+ # This method can raise several exceptions of which most importantly:
273
+ # * {URI::Error}
274
+ # * {Net::HTTPException}
275
+ # * {Use0MK::Error}
276
+ #
277
+ # It is a wise idea to watch for any of these.
278
+ #
279
+ # @param [Hash] link provide +:short_name+ to inspect only the short name of an URI, or +:uri+ to inspect a whole +http://0.mk/short_name+ URI
280
+ # @return [Use0MK::ShortenedURI] the shortened URI (volume of data varies)
281
+ def preview(link = {:short_name => nil, :uri => nil})
282
+ uri = nil
283
+
284
+ if !link[:short_name].nil? and !link[:short_name].empty?
285
+ uri = "http://0.mk/#{link[:short_name]}"
286
+ elsif !link[:uri].nil? and !link[:uri].empty?
287
+ uri = link[:uri] if (link[:uri] =~ /http:\/\/0\.mk\/.*/)
288
+ end
289
+
290
+ if uri.nil?
291
+ raise ArgumentError, ':uri should be a valid http://0.mk shortened URI.'
292
+ end
293
+
294
+ _preview(uri)
295
+ end
296
+
297
+ private
298
+ def _queryize(hash = {})
299
+ pairs = []
300
+
301
+ hash.each do |key, value|
302
+ if !(key.nil? or value.nil?)
303
+ pairs << key.to_s.strip + "=" + value.to_s.strip
304
+ end
305
+ end
306
+
307
+ return pairs.join("&")
308
+ end
309
+
310
+ def _generate_uri(link, short_name = nil, apicall = Use0MK::SHORTEN_URI)
311
+ uri = URI.parse(apicall)
312
+
313
+ query = {
314
+ :korisnik => @username,
315
+ :apikey => @apikey,
316
+ :format => 'json',
317
+ :nastavka => short_name
318
+ }
319
+
320
+ uri.query = _queryize(query) + "&link=#{link}"
321
+
322
+ return uri
323
+ end
324
+
325
+ def _fetch(uri, link, redirect = 5)
326
+ raise Use0MK::RedirectError, "Redirect level too deep (max 5)." if redirect <= 0
327
+
328
+ response = Net::HTTP.get_response(uri)
329
+ case response
330
+ when Net::HTTPSuccess then return response
331
+ when Net::HTTPRedirection then _fetch(response['location'], redirect - 1)
332
+ else
333
+ response.error!
334
+ end
335
+
336
+ end
337
+
338
+ def _parse(origin, json)
339
+ if json['status'] != 1
340
+ raise Use0MK::APIERRORS[json['greskaId'].to_i - 1], json['greskaMsg'].to_s.strip
341
+ end
342
+
343
+ assign = {
344
+ 'dolg' => :long_uri,
345
+ 'kratok' => :short_uri,
346
+ 'nastavka' => :short_name,
347
+ 'urlNaslov' => :title,
348
+ 'statsLink' => :stats_uri,
349
+ 'brisiLink' => :delete_uri,
350
+ 'brisiKod' => :delete_code
351
+ }
352
+
353
+ attributes = {}
354
+ json.each do |key, value|
355
+ if assign.has_key? key
356
+ attributes[assign[key]] = value
357
+ end
358
+ end
359
+
360
+ assign.keys.each do |key|
361
+ if !attributes.has_key? key
362
+ attributes[key] = nil
363
+ end
364
+ end
365
+
366
+ shortened = Use0MK::ShortenedURI.new(origin, attributes)
367
+ end
368
+
369
+ def _shorten(uri, short_name)
370
+ request_uri = _generate_uri(uri, short_name)
371
+
372
+ response = _fetch(request_uri, uri)
373
+ body = JSON.parse(response.body)
374
+
375
+ _parse(:shorten, body)
376
+ end
377
+
378
+ def _preview(uri)
379
+ request_uri = _generate_uri(uri, nil, Use0MK::PREVIEW_URI)
380
+
381
+ response = _fetch(request_uri, uri)
382
+ body = JSON.parse(response.body)
383
+
384
+ _parse(:preview, body)
385
+ end
386
+
387
+
388
+ end
389
+
data/use0mk.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{use0mk}
5
+ s.version = "0.1.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Stojan Dimitrovski"]
9
+ s.date = %q{2010-12-09}
10
+ s.description = %q{Ruby interface for the 0.mk URL shortening service.}
11
+ s.email = %q{s.dimitrovski@gmail.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/use0mk.rb"]
13
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "lib/use0mk.rb", "use0mk.gemspec"]
14
+ s.homepage = %q{http://github.com/hf/use0mk}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Use0mk", "--main", "README"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{use0mk}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Ruby interface for the 0.mk URL shortening service.}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<json>, [">= 0"])
27
+ else
28
+ s.add_dependency(%q<json>, [">= 0"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<json>, [">= 0"])
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: use0mk
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Stojan Dimitrovski
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-09 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Ruby interface for the 0.mk URL shortening service.
36
+ email: s.dimitrovski@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - CHANGELOG
43
+ - LICENSE
44
+ - README
45
+ - lib/use0mk.rb
46
+ files:
47
+ - CHANGELOG
48
+ - LICENSE
49
+ - Manifest
50
+ - README
51
+ - Rakefile
52
+ - lib/use0mk.rb
53
+ - use0mk.gemspec
54
+ has_rdoc: true
55
+ homepage: http://github.com/hf/use0mk
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --line-numbers
61
+ - --inline-source
62
+ - --title
63
+ - Use0mk
64
+ - --main
65
+ - README
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ hash: 11
83
+ segments:
84
+ - 1
85
+ - 2
86
+ version: "1.2"
87
+ requirements: []
88
+
89
+ rubyforge_project: use0mk
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Ruby interface for the 0.mk URL shortening service.
94
+ test_files: []
95
+