delicious 1.0.0

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.
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