thumbtack 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b204797fab0cc2277a9a96a0fb7f117351e77682
4
- data.tar.gz: e58eb6b1b2e6e82b4c8d90cbef2cda993756884b
3
+ metadata.gz: af013ae7caf72e5d517bd5ce42ef097a804fca78
4
+ data.tar.gz: 35a058f9bc768ab4fadf48882993d3393dd5c627
5
5
  SHA512:
6
- metadata.gz: edcf405a5c45dd0dd17786f292a650a44ba543de43a4318afd363b1acb592abe9b9893f037b32624a9410bc2f654eac5345708529db054919c3e1629bc41d380
7
- data.tar.gz: 625d10851ca09eb39916d42c34edbcebd6db93bb1e8f1d318a9048cab8283c1d2effc35377da3c4c829723e28b7f8e463b54bd5a8bff48fc4ec97bf76b3bda37
6
+ metadata.gz: 73795d3553e3e56dd4cbd6d83cb9e9e47f90750c46963f703811d7a53a6e8019ab8aebf3693f8fe675219e6a8a05adb6779bbd3e2a7af917434a8af740407c85
7
+ data.tar.gz: a33adcc946c096f2e8dccfc3a34a166eec774a4006b396fd2a02a0107750424c7f7b495f3cb0be4c9437fcb7b34c53a78d7d6218d5d79a81e7e03661e6e52c8f
@@ -2,6 +2,11 @@
2
2
 
3
3
  # A simple Pinboard API wrapper
4
4
  module Thumbtack
5
+ # An empty Hash to use for default options
6
+ EMPTY_HASH = {}.freeze
7
+
8
+ # An empty Hash to use for `#fetch` fallbacks
9
+ EMPTY_ARRAY = [].freeze
5
10
  end
6
11
 
7
12
  require 'date'
@@ -22,6 +27,7 @@ require 'thumbtack/types/title'
22
27
  require 'thumbtack/types/url'
23
28
  require 'thumbtack/specification'
24
29
  require 'thumbtack/post'
30
+ require 'thumbtack/suggestion'
25
31
  require 'thumbtack/posts'
26
32
  require 'thumbtack/tags'
27
33
  require 'thumbtack/user'
@@ -1,68 +1,114 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Thumbtack
4
- # Public: Wraps each interaction with the Pinboard API.
4
+ # Wraps each interaction with the Pinboard API
5
5
  class Client
6
- # Public: String of base Pinboard API URL.
6
+ # Raised when the API rate limit has been reached
7
+ class RateLimitError < StandardError; end
8
+
9
+ # The status code for rate limited responses from the Pinboard API
10
+ TOO_MANY_REQUESTS_CODE = '429'.freeze
11
+
12
+ # The base Pinboard API URL.
7
13
  BASE_URL = 'https://api.pinboard.in/v1'.freeze
8
14
 
9
- # Public: Returns the String username being used by the client.
15
+ # Username used by the client to make authenticated requests
16
+ #
17
+ # @return [String]
18
+ #
19
+ # @api public
10
20
  attr_reader :username
11
21
 
12
- # Public: Returns the String API token being used by the client.
22
+ # Token used by the client to make authenticated requests
23
+ #
24
+ # @return [String]
25
+ #
26
+ # @api public
13
27
  attr_reader :token
14
28
 
15
- # Public: Creates a new client.
29
+ # Initialize a Client
30
+ #
31
+ # @example
32
+ # client = Client.new(username, token)
33
+ #
34
+ # @param [String] username
35
+ # the user to authenticate with
36
+ # @param [String] token
37
+ # the API token for the user account, found on the Pinboard settings page
16
38
  #
17
- # username - A String naming the user account to authenticate with.
18
- # token - A String of the API token for the user account. Can be found on
19
- # the user's settings page.
39
+ # @api public
20
40
  def initialize(username, token)
21
41
  @username, @token = username, token
22
42
  end
23
43
 
24
- # Internal: Request JSON from the Pinboard API.
44
+ # Retrieve JSON from the Pinboard API
25
45
  #
26
- # path - A String of the path to fetch from. The is relative from the root
27
- # Pinboard API URL.
28
- # params - A Hash of query parameters to append to the URL for the fetch
29
- # (default: {}).
46
+ # @param [String] path
47
+ # the path to fetch from, relative to from the base Pinboard API URL
30
48
  #
31
- # Examples
49
+ # @param [Hash] params
50
+ # query parameters to append to the URL
32
51
  #
33
- # get('/posts/update')
34
- # # => {'update_time' => '2014-06-24T15:39:46Z'}
52
+ # @return [Hash] the response parsed from the JSON
35
53
  #
36
- # get('/posts/suggest', url: 'http://theinternate.com/')
37
- # # => [{'popular' => []}, {'recommended' => []}]
54
+ # @raise [RateLimitError] if the response is rate-limited
38
55
  #
39
- # Returns a parsed JSON response from Pinboard's API.
40
- def get(path, params = {})
56
+ # @api private
57
+ def get(path, params = EMPTY_HASH)
41
58
  uri = URI("#{BASE_URL}#{path}")
42
59
 
43
60
  base_params = { auth_token: "#{@username}:#{@token}", format: 'json' }
44
61
  uri.query = URI.encode_www_form(params.merge(base_params))
45
62
 
46
63
  response = Net::HTTP.get_response(uri)
64
+ fail Client::RateLimitError if response.code == TOO_MANY_REQUESTS_CODE
47
65
  JSON.parse(response.body)
48
66
  end
49
67
 
50
- # Public: Access posts-related API calls.
68
+ # Access posts-related API calls
69
+ #
70
+ # @example
71
+ # posts = client.posts
72
+ #
73
+ # @return [Posts]
74
+ #
75
+ # @api public
51
76
  def posts
52
77
  Posts.new(self)
53
78
  end
54
79
 
55
- # Public: Access tags-related API calls.
80
+ # Access tags-related API calls
81
+ #
82
+ # @example
83
+ # tags = client.tags
84
+ #
85
+ # @return [Tags]
86
+ #
87
+ # @api public
56
88
  def tags
57
89
  Tags.new(self)
58
90
  end
59
91
 
60
- # Public: Access user-related API calls.
92
+ # Access user-related API calls
93
+ #
94
+ # @example
95
+ # user = client.user
96
+ #
97
+ # @return [User]
98
+ #
99
+ # @api public
61
100
  def user
62
101
  User.new(self)
63
102
  end
64
103
 
65
- # Public: Access notes-related API calls.
104
+ # Access notes-related API calls
105
+ #
106
+ # @example
107
+ # notes = client.notes
108
+ #
109
+ # @return [Notes]
110
+ #
111
+ # @api public
66
112
  def notes
67
113
  Notes.new(self)
68
114
  end
@@ -1,9 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Thumbtack
4
- # Public: Represents a note.
4
+ # Represents a note
5
+ #
6
+ # @api public
5
7
  class Note
6
- # Private: The attributes for a Note.
8
+ # The attributes for a Note
9
+ #
10
+ # @api private
7
11
  ATTRIBUTES = [
8
12
  :id,
9
13
  :title,
@@ -14,21 +18,77 @@ module Thumbtack
14
18
  :length
15
19
  ].freeze
16
20
 
17
- attr_reader(*ATTRIBUTES)
21
+ # The identifier for the note
22
+ #
23
+ # @return [String]
24
+ #
25
+ # @api public
26
+ attr_reader :id
27
+
28
+ # The title of the note
29
+ #
30
+ # @return [String]
31
+ #
32
+ # @api public
33
+ attr_reader :title
34
+
35
+ # The time at which the note was created
36
+ #
37
+ # @return [String]
38
+ #
39
+ # @api public
40
+ attr_reader :created_at
41
+
42
+ # The time at which the note was last updated
43
+ #
44
+ # @return [String]
45
+ #
46
+ # @api public
47
+ attr_reader :updated_at
48
+
49
+ # 20 character hexadecimal SHA1 hash of the note text
50
+ #
51
+ # @return [String]
52
+ #
53
+ # @api public
54
+ attr_reader :digest
55
+
56
+ # The text of the note
57
+ #
58
+ # @return [String]
59
+ #
60
+ # @api public
61
+ attr_reader :text
62
+
63
+ # The length of the note text
64
+ #
65
+ # @return [Integer]
66
+ #
67
+ # @api public
68
+ attr_reader :length
18
69
 
19
- # Internal: Creates a new Note from a Hash, usually a Client#get response.
70
+ # Creates a new Note from a Hash
20
71
  #
21
- # hash - A Hash of attributes of the note.
72
+ # @param [Hash{#to_sym => Object}] hash
73
+ # Note attributes
74
+ #
75
+ # @return [Note]
76
+ #
77
+ # @api private
78
+ # @see Client#get
22
79
  def self.from_hash(hash)
23
80
  attrs = hash.dup
24
81
  digest = attrs.delete('hash')
25
82
  new(Hash[attrs.map { |k, v| [k.to_sym, v] }].merge(digest: digest))
26
83
  end
27
84
 
28
- # Internal: Initialize a Note.
85
+ # Initialize a Note
86
+ #
87
+ # @param [Hash] attrs
88
+ # Note attributes
29
89
  #
30
- # attrs - A Hash of attributes of the Note.
31
- def initialize(attrs = {})
90
+ # @api private
91
+ def initialize(attrs = EMPTY_HASH)
32
92
  ATTRIBUTES.each do |attribute|
33
93
  instance_variable_set "@#{attribute}", attrs.fetch(attribute)
34
94
  end
@@ -1,32 +1,87 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Thumbtack
4
- # Public: Represents a note summary as returned from Notes#list.
4
+ # Represents a note summary as returned from Notes#list.
5
+ #
6
+ # @api public
7
+ # @see Notes#list
5
8
  class NoteSummary
6
- # Private: The attributes for a NoteSummary.
9
+ # The attributes for a NoteSummary
10
+ #
11
+ # @api private
7
12
  ATTRIBUTES = [
8
13
  :id,
9
14
  :title,
10
- :hash,
15
+ :digest,
11
16
  :created_at,
12
17
  :updated_at,
13
18
  :length
14
19
  ].freeze
15
20
 
16
- attr_reader(*ATTRIBUTES)
21
+ # The identifier for the note
22
+ #
23
+ # @return [String]
24
+ #
25
+ # @api public
26
+ attr_reader :id
27
+
28
+ # The title of the note
29
+ #
30
+ # @return [String]
31
+ #
32
+ # @api public
33
+ attr_reader :title
17
34
 
18
- # Internal: Creates a new NoteSummary from a Hash, usually a Client#get
19
- # response.
35
+ # The time at which the note was created
20
36
  #
21
- # hash - A Hash of attributes of the note.
37
+ # @return [String]
38
+ #
39
+ # @api public
40
+ attr_reader :created_at
41
+
42
+ # The time at which the note was last updated
43
+ #
44
+ # @return [String]
45
+ #
46
+ # @api public
47
+ attr_reader :updated_at
48
+
49
+ # 20 character hexadecimal SHA1 hash of the note text
50
+ #
51
+ # @return [String]
52
+ #
53
+ # @api public
54
+ attr_reader :digest
55
+
56
+ # The length of the note text
57
+ #
58
+ # @return [Integer]
59
+ #
60
+ # @api public
61
+ attr_reader :length
62
+
63
+ # Creates a new NoteSummary from a Hash
64
+ #
65
+ # @param [Hash{#to_sym => Object}] hash
66
+ # NoteSummary attributes
67
+ #
68
+ # @return [NoteSummary]
69
+ #
70
+ # @api private
71
+ # @see Client#get
22
72
  def self.from_hash(hash)
23
- new(Hash[hash.map { |key, value| [key.to_sym, value] }])
73
+ attrs = hash.dup
74
+ digest = attrs.delete('hash')
75
+ new(Hash[attrs.map { |k, v| [k.to_sym, v] }].merge(digest: digest))
24
76
  end
25
77
 
26
- # Internal: Initialize a NoteSummary.
78
+ # Initialize a NoteSummary
79
+ #
80
+ # @param [Hash] attrs
81
+ # NoteSummary attributes
27
82
  #
28
- # attrs - A Hash of attributes of the NoteSummary.
29
- def initialize(attrs = {})
83
+ # @api private
84
+ def initialize(attrs = EMPTY_HASH)
30
85
  ATTRIBUTES.each do |attribute|
31
86
  instance_variable_set "@#{attribute}", attrs.fetch(attribute)
32
87
  end
@@ -1,24 +1,48 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Thumbtack
4
- # Internal: Wraps API calls related to notes.
4
+ # Wraps API calls related to notes
5
5
  class Notes
6
- # Internal: Creates a new Notes.
6
+ # Initialize a Notes
7
7
  #
8
- # client - a Thumbtack::Client to communicate with the Pinboard API.
8
+ # @param [Client] client
9
+ # client to communicate with the Pinboard API
10
+ #
11
+ # @api private
9
12
  def initialize(client)
10
13
  @client = client
11
14
  end
12
15
 
13
- # Public: Returns a list of summaries of the user's notes.
16
+ # List of summaries of the user's notes
17
+ #
18
+ # @example
19
+ # summaries = notes.list
20
+ #
21
+ # @return [Array<NoteSummary>]
22
+ #
23
+ # @api public
24
+ #
25
+ # @see https://pinboard.in/api/#notes_list
14
26
  def list
15
27
  response = @client.get('/notes/list')
16
- response.fetch('notes', []).map do |note_hash|
28
+ response.fetch('notes', EMPTY_ARRAY).map do |note_hash|
17
29
  NoteSummary.from_hash(note_hash)
18
30
  end
19
31
  end
20
32
 
21
- # Public: Return an individual note.
33
+ # Fetch a note
34
+ #
35
+ # @example
36
+ # note = notes.get(id)
37
+ #
38
+ # @param [#to_s] id
39
+ # the id of the note to fetch
40
+ #
41
+ # @return [Note]
42
+ #
43
+ # @api public
44
+ #
45
+ # @see https://pinboard.in/api/#notes_id
22
46
  def get(id)
23
47
  Note.from_hash @client.get("/notes/#{id}")
24
48
  end
@@ -1,9 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Thumbtack
4
- # Public: Represents a bookmark.
4
+ # Represents a bookmark
5
+ #
6
+ # @api public
5
7
  class Post
6
- # Private: The attributes for a Post.
8
+ # The attributes for a Post
9
+ #
10
+ # @api private
7
11
  ATTRIBUTES = [
8
12
  :href,
9
13
  :description,
@@ -16,19 +20,89 @@ module Thumbtack
16
20
  :tags
17
21
  ].freeze
18
22
 
19
- attr_reader(*ATTRIBUTES)
23
+ # The url of the post
24
+ #
25
+ # @return [String]
26
+ #
27
+ # @api public
28
+ attr_reader :href
29
+
30
+ # The title of the post
31
+ #
32
+ # @return [String]
33
+ #
34
+ # @api public
35
+ attr_reader :description
36
+
37
+ # The description of the post
38
+ #
39
+ # @return [String]
40
+ #
41
+ # @api public
42
+ attr_reader :extended
43
+
44
+ # 32 character hexadecimal MD5 hash tag 'version' of the post
45
+ #
46
+ # @return [String]
47
+ #
48
+ # @api public
49
+ attr_reader :meta
50
+
51
+ # 32 character hexadecimal MD5 hash of the post URL
52
+ #
53
+ # @return [String]
54
+ #
55
+ # @api public
56
+ attr_reader :hash
57
+
58
+ # The time at which the post was created
59
+ #
60
+ # @return [String]
61
+ #
62
+ # @api public
63
+ attr_reader :time
64
+
65
+ # If true, this post is public
66
+ #
67
+ # @return [Boolean]
68
+ #
69
+ # @api public
70
+ attr_reader :shared
20
71
 
21
- # Internal: Creates a new post from a Hash, usually a Client#get response.
72
+ # If true, this post is marked unread
22
73
  #
23
- # hash - A Hash of attributes of the Post.
74
+ # @return [Boolean]
75
+ #
76
+ # @api public
77
+ attr_reader :toread
78
+
79
+ # The tags for this post, space-seperated
80
+ #
81
+ # @return [String]
82
+ #
83
+ # @api public
84
+ attr_reader :tags
85
+
86
+ # Creates a new Post from a Hash
87
+ #
88
+ # @param [Hash{#to_sym => Object}] hash
89
+ # Post attributes
90
+ #
91
+ # @return [Post]
92
+ #
93
+ # @api private
94
+ # @see Client#get
24
95
  def self.from_hash(hash)
25
96
  new(Hash[hash.map { |key, value| [key.to_sym, value] }])
26
97
  end
27
98
 
28
- # Internal: Initialize a Post.
99
+ # Initialize a Post
100
+ #
101
+ # @param [Hash] attrs
102
+ # Post attributes
29
103
  #
30
- # attrs - A Hash of attributes of the Post.
31
- def initialize(attrs = {})
104
+ # @api private
105
+ def initialize(attrs = EMPTY_HASH)
32
106
  ATTRIBUTES.each do |attribute|
33
107
  instance_variable_set "@#{attribute}", attrs.fetch(attribute)
34
108
  end