delicious 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/delicious.gemspec +28 -0
  3. data/lib/delicious.rb +39 -0
  4. data/lib/delicious/api_model.rb +26 -0
  5. data/lib/delicious/bookmarks/api.rb +15 -0
  6. data/lib/delicious/bookmarks/methods/all.rb +112 -0
  7. data/lib/delicious/bookmarks/methods/create.rb +57 -0
  8. data/lib/delicious/bookmarks/methods/delete.rb +23 -0
  9. data/lib/delicious/bundle.rb +43 -0
  10. data/lib/delicious/bundles/api.rb +20 -0
  11. data/lib/delicious/bundles/methods/all.rb +23 -0
  12. data/lib/delicious/bundles/methods/delete.rb +23 -0
  13. data/lib/delicious/bundles/methods/find.rb +26 -0
  14. data/lib/delicious/bundles/methods/set.rb +27 -0
  15. data/lib/delicious/client.rb +57 -0
  16. data/lib/delicious/error.rb +6 -0
  17. data/lib/delicious/post.rb +42 -0
  18. data/lib/delicious/tag.rb +26 -0
  19. data/lib/delicious/tags/api.rb +15 -0
  20. data/lib/delicious/tags/methods/all.rb +24 -0
  21. data/lib/delicious/tags/methods/delete.rb +23 -0
  22. data/lib/delicious/tags/methods/rename.rb +24 -0
  23. data/lib/delicious/version.rb +5 -0
  24. data/spec/delicious/bookmarks/methods/all_spec.rb +122 -0
  25. data/spec/delicious/bookmarks/methods/create_spec.rb +120 -0
  26. data/spec/delicious/bundle_spec.rb +42 -0
  27. data/spec/delicious/bundles/methods/set_spec.rb +78 -0
  28. data/spec/delicious/client_spec.rb +189 -0
  29. data/spec/delicious/post_spec.rb +34 -0
  30. data/spec/delicious/tags/methods/all_spec.rb +70 -0
  31. data/spec/delicious/tags/methods/delete_spec.rb +47 -0
  32. data/spec/delicious/tags/methods/rename_spec.rb +47 -0
  33. data/spec/spec_helper.rb +11 -0
  34. data/spec/support/helpers/request_helper.rb +10 -0
  35. data/spec/support/shared/api_action.rb +13 -0
  36. metadata +175 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 74e4142660e75f2be6e0d7bcd9380325bce9a431
4
+ data.tar.gz: 3dcecc74b8d2dde8cec29e100618b80068634e00
5
+ SHA512:
6
+ metadata.gz: 9255873581070289605152cd08bc9eddc3a5279832f00fceb1f3d06eba16a42635fd0cefa8466c92814576ad3e8058a37c9a3398811b167209fb862ff111276b
7
+ data.tar.gz: 077a8f74f29452afc263b67aef2a88166fdc2592e112c0fc719928280a575dfcfcb899a1c190c4723eeacc0d2bf6946da758bfa5587976c765d6c54bae633540
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'delicious/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.add_dependency 'faraday'
7
+ spec.add_dependency 'faraday_middleware'
8
+ spec.add_dependency 'multi_xml'
9
+ spec.add_dependency 'activemodel'
10
+ spec.add_dependency 'activesupport'
11
+
12
+ spec.add_development_dependency 'bundler', '~> 1.0'
13
+
14
+ spec.authors = ['Andrey Chernih']
15
+ spec.description = 'Ruby wrapper for delicious.com API'
16
+ spec.email = %w(andrey.chernih@gmail.com)
17
+ spec.files = %w(delicious.gemspec)
18
+ spec.files += Dir.glob('lib/**/*.rb')
19
+ spec.files += Dir.glob('spec/**/*')
20
+ spec.homepage = 'http://github.com/andreychernih/delicious'
21
+ spec.licenses = ['Apache 2.0']
22
+ spec.name = 'delicious'
23
+ spec.require_paths = %w(lib)
24
+ spec.required_rubygems_version = '>= 1.3.5'
25
+ spec.summary = spec.description
26
+ spec.test_files = Dir.glob('spec/**/*')
27
+ spec.version = Delicious.version
28
+ end
@@ -0,0 +1,39 @@
1
+ module Delicious
2
+ autoload :Client, 'delicious/client'
3
+ autoload :ApiModel, 'delicious/api_model'
4
+ autoload :Post, 'delicious/post'
5
+ autoload :Bundle, 'delicious/bundle'
6
+ autoload :Tag, 'delicious/tag'
7
+ autoload :Error, 'delicious/error'
8
+
9
+ module Bookmarks
10
+ autoload :Api, 'delicious/bookmarks/api'
11
+
12
+ module Methods
13
+ autoload :All, 'delicious/bookmarks/methods/all'
14
+ autoload :Create, 'delicious/bookmarks/methods/create'
15
+ autoload :Delete, 'delicious/bookmarks/methods/delete'
16
+ end
17
+ end
18
+
19
+ module Bundles
20
+ autoload :Api, 'delicious/bundles/api'
21
+
22
+ module Methods
23
+ autoload :Find, 'delicious/bundles/methods/find'
24
+ autoload :All, 'delicious/bundles/methods/all'
25
+ autoload :Delete, 'delicious/bundles/methods/delete'
26
+ autoload :Set, 'delicious/bundles/methods/set'
27
+ end
28
+ end
29
+
30
+ module Tags
31
+ autoload :Api, 'delicious/tags/api'
32
+
33
+ module Methods
34
+ autoload :All, 'delicious/tags/methods/all'
35
+ autoload :Delete, 'delicious/tags/methods/delete'
36
+ autoload :Rename, 'delicious/tags/methods/rename'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+
5
+ module ApiModel
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attr_writer :persisted, :delicious_client
10
+ end
11
+
12
+ def persisted?
13
+ !!@persisted
14
+ end
15
+
16
+ module ClassMethods
17
+ def build_persisted(client, attrs)
18
+ obj = new attrs
19
+ obj.persisted = true
20
+ obj.delicious_client = client
21
+ obj
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,15 @@
1
+ module Delicious
2
+ module Bookmarks
3
+
4
+ class Api
5
+ include Methods::All
6
+ include Methods::Create
7
+ include Methods::Delete
8
+
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,112 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bookmarks
5
+ module Methods
6
+
7
+ module All
8
+ extend ActiveSupport::Concern
9
+
10
+ class Criteria
11
+ include Enumerable
12
+
13
+ def self.param(param)
14
+ method, query_param = param.is_a?(Hash) ? param.first : [param, param]
15
+ define_method method do |value|
16
+ params[query_param] = value
17
+ self
18
+ end
19
+ end
20
+
21
+ # @!method limit(count)
22
+ # Sets the limit
23
+ #
24
+ # @param count [Integer] How many bookmarks server should return at most
25
+ # @return [Criteria]
26
+ param limit: :results
27
+ # @!method offset(count)
28
+ # Sets the offset
29
+ #
30
+ # @param count [Integer] How many bookmarks server should skip
31
+ # @return [Criteria]
32
+ param offset: :start
33
+ # @!method tag(name)
34
+ # Sets tag-based filtering
35
+ #
36
+ # @param name [String] Name of the tag
37
+ # @return [Criteria]
38
+ param :tag
39
+
40
+ def initialize(&block)
41
+ @fetch = block
42
+ end
43
+
44
+ # Sets starting date and time for which you want to get bookmarks
45
+ #
46
+ # @!macro [new] time_criteria
47
+ # @param date [String,Time,DateTime] `String` time represenation or any object which responds to `strftime`
48
+ # @return [Criteria]
49
+ def from(date)
50
+ params[:fromdt] = format_time(date)
51
+ self
52
+ end
53
+
54
+ # Sets ending date and time for which you want to get bookmarks
55
+ #
56
+ # @!macro time_criteria
57
+ def to(date)
58
+ params[:todt] = format_time(date)
59
+ self
60
+ end
61
+
62
+ # Fetches bookmarks from server filtering by current criteria
63
+ def each(&block)
64
+ @fetch.call(self).each(&block)
65
+ end
66
+
67
+ def params
68
+ @params ||= {}
69
+ end
70
+
71
+ private
72
+
73
+ def format_time(time)
74
+ time = Time.parse(time) if time.respond_to?(:to_str)
75
+ time.strftime "%FT%TZ"
76
+ end
77
+ end
78
+
79
+ # Returns all bookmarks associated with given access token. Results can be paginated:
80
+ #
81
+ # ```ruby
82
+ # client.all.offset(150).limit(50).to_a
83
+ # ```
84
+ #
85
+ # And filtered by date and tag:
86
+ #
87
+ # ```ruby
88
+ # client.all.tag('angular').from('2013/11/12 10:23:00').to('2013/11/13 12:10:00')
89
+ # ```
90
+ #
91
+ # @see Criteria
92
+ # @return [Criteria]
93
+ def all
94
+ Criteria.new do |criteria|
95
+ response = @client.connection.get '/v1/posts/all', criteria.params.merge(tag_separator: 'comma')
96
+ posts = response.body['posts'] ? response.body['posts']['post'] : []
97
+ posts.map do |post_attrs|
98
+ Delicious::Post.build_persisted @client,
99
+ url: post_attrs['href'],
100
+ description: post_attrs['description'],
101
+ extended: post_attrs['extended'],
102
+ tags: post_attrs['tag'],
103
+ dt: post_attrs['time'],
104
+ shared: (post_attrs['shared'] == 'yes')
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,57 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bookmarks
5
+ module Methods
6
+
7
+ module Create
8
+ extend ActiveSupport::Concern
9
+
10
+ # Create new bookmark
11
+ #
12
+ # @example
13
+ # client.bookmarks.create url: 'http://example.com',
14
+ # description: 'Example website',
15
+ # extended: 'Extended information',
16
+ # tags: %w(tag1 tag2),
17
+ # dt: '2014-04-15T10:20:00Z',
18
+ # shared: true,
19
+ # replace: false
20
+ #
21
+ # @param attrs [Hash] Bookmark attributes
22
+ # @return [Post]
23
+ def create(attrs)
24
+ post = Delicious::Post.new url: attrs[:url],
25
+ description: attrs[:description],
26
+ extended: attrs[:extended],
27
+ tags: attrs[:tags],
28
+ dt: attrs[:dt],
29
+ shared: attrs[:shared]
30
+
31
+ if post.valid?
32
+ response = @client.connection.post '/v1/posts/add', post_attrs(post, attrs[:replace])
33
+ code = response.body['result']['code']
34
+ fail Delicious::Error, code unless 'done' == code
35
+ post.persisted = true
36
+ post.delicious_client = @client
37
+ end
38
+
39
+ post
40
+ end
41
+
42
+ private
43
+
44
+ def post_attrs(post, replace = false)
45
+ { url: post.url,
46
+ description: post.description,
47
+ extended: post.extended,
48
+ tags: post.tags.join(','),
49
+ dt: post.dt,
50
+ shared: post.shared ? 'yes' : 'no',
51
+ replace: replace ? 'yes' : 'no' }
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bookmarks
5
+ module Methods
6
+
7
+ module Delete
8
+ extend ActiveSupport::Concern
9
+
10
+ # Deletes bookmark with given URL
11
+ #
12
+ # @param url [String] Bookmark URL
13
+ # @return [Boolean] `true` on successful deletion, `false` otherwise
14
+ def delete(url)
15
+ response = @client.connection.post '/v1/posts/delete', url: url
16
+ code = response.body['result']['code']
17
+ 'done' == code
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,43 @@
1
+ require 'active_model'
2
+
3
+ module Delicious
4
+ class Bundle
5
+ include ActiveModel::Model
6
+ include ActiveModel::Validations
7
+ include ApiModel
8
+
9
+ attr_accessor :name, :tags
10
+
11
+ validates :name, presence: true
12
+ validates :tags, presence: true
13
+
14
+ # Deletes this bundle
15
+ #
16
+ # @raise [Delicious::Error] if bundle was not saved yet
17
+ # @return [Boolean] `true` upon successful deletion, `false` otherwise
18
+ def delete
19
+ if persisted? && @delicious_client
20
+ @delicious_client.bundles.delete bundle: name
21
+ else
22
+ fail Delicious::Error, 'Bundle was not saved yet'
23
+ end
24
+ end
25
+
26
+ # Creates or updates bundle
27
+ #
28
+ # @raise [Delicious::Error] if bundle is not associated with Delicious::Client or save failed
29
+ # @return [Boolean] `true` when saved
30
+ def save
31
+ if @delicious_client
32
+ @delicious_client.bundles.set name, tags
33
+ true
34
+ else
35
+ fail 'Bundle was not saved yet'
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ %Q(Delicious::Bundle(name: "#{name}", tags: #{tags}))
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,20 @@
1
+ module Delicious
2
+ module Bundles
3
+
4
+ class Api
5
+ include Methods::Find
6
+ include Methods::All
7
+ include Methods::Delete
8
+ include Methods::Set
9
+
10
+ def self.model_attrs(attrs)
11
+ { name: attrs['name'], tags: attrs['tags'].split(' ') }
12
+ end
13
+
14
+ def initialize(client)
15
+ @client = client
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bundles
5
+ module Methods
6
+
7
+ module All
8
+ extend ActiveSupport::Concern
9
+
10
+ # Get all user bundles
11
+ #
12
+ # @return [Array<Bundle>] List of bundles
13
+ def all
14
+ response = @client.connection.get '/v1/tags/bundles/all'
15
+ response.body['bundles']['bundle'].map do |attrs|
16
+ Bundle.build_persisted @client, self.class.model_attrs(attrs)
17
+ end
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bundles
5
+ module Methods
6
+
7
+ module Delete
8
+ extend ActiveSupport::Concern
9
+
10
+ # Delete bundle with given name
11
+ #
12
+ # @param name [String] Bundle name
13
+ # @return [Boolean] `true` upon a successful deletion, `false` otherwise
14
+ def delete(name)
15
+ response = @client.connection.post '/v1/tags/bundles/delete', bundle: name
16
+ code = response.body['result']['code']
17
+ 'done' == code
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support/concern'
2
+
3
+ module Delicious
4
+ module Bundles
5
+ module Methods
6
+
7
+ module Find
8
+ extend ActiveSupport::Concern
9
+
10
+ # Find a bundle with given name
11
+ #
12
+ # @param name [String] Bundle name
13
+ # @return [Bundle, nil] Found bundle or `nil` if it was not found
14
+ def find(name)
15
+ response = @client.connection.get '/v1/tags/bundles/all', bundle: name
16
+ bundle = response.body['bundles']['bundle']
17
+ Bundle.build_persisted @client, self.class.model_attrs(bundle)
18
+ rescue Faraday::ParsingError => e
19
+ # it's ridiculous, but delicious returns invalid XML response when bundle is missing
20
+ nil
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end