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 +4 -4
- data/lib/thumbtack.rb +6 -0
- data/lib/thumbtack/client.rb +70 -24
- data/lib/thumbtack/note.rb +68 -8
- data/lib/thumbtack/note_summary.rb +66 -11
- data/lib/thumbtack/notes.rb +30 -6
- data/lib/thumbtack/post.rb +82 -8
- data/lib/thumbtack/posts.rb +143 -85
- data/lib/thumbtack/specification.rb +12 -8
- data/lib/thumbtack/suggestion.rb +59 -0
- data/lib/thumbtack/tags.rb +41 -11
- data/lib/thumbtack/types.rb +4 -3
- data/lib/thumbtack/types/boolean.rb +20 -12
- data/lib/thumbtack/types/date.rb +20 -13
- data/lib/thumbtack/types/date_time.rb +21 -14
- data/lib/thumbtack/types/identity.rb +11 -6
- data/lib/thumbtack/types/integer.rb +12 -8
- data/lib/thumbtack/types/md5.rb +12 -9
- data/lib/thumbtack/types/tags.rb +23 -18
- data/lib/thumbtack/types/text.rb +11 -7
- data/lib/thumbtack/types/title.rb +11 -7
- data/lib/thumbtack/types/url.rb +12 -7
- data/lib/thumbtack/user.rb +26 -5
- data/lib/thumbtack/version.rb +1 -1
- data/test/test_helper.rb +4 -10
- data/test/thumbtack/client_test.rb +1 -1
- data/test/thumbtack/integration/client_test.rb +5 -2
- data/test/thumbtack/note_summary_test.rb +1 -1
- data/test/thumbtack/notes_test.rb +1 -7
- data/test/thumbtack/posts_test.rb +6 -13
- data/test/thumbtack/suggestion_test.rb +16 -0
- data/test/thumbtack/tags_test.rb +0 -6
- data/test/thumbtack/user_test.rb +0 -6
- metadata +15 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af013ae7caf72e5d517bd5ce42ef097a804fca78
|
4
|
+
data.tar.gz: 35a058f9bc768ab4fadf48882993d3393dd5c627
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73795d3553e3e56dd4cbd6d83cb9e9e47f90750c46963f703811d7a53a6e8019ab8aebf3693f8fe675219e6a8a05adb6779bbd3e2a7af917434a8af740407c85
|
7
|
+
data.tar.gz: a33adcc946c096f2e8dccfc3a34a166eec774a4006b396fd2a02a0107750424c7f7b495f3cb0be4c9437fcb7b34c53a78d7d6218d5d79a81e7e03661e6e52c8f
|
data/lib/thumbtack.rb
CHANGED
@@ -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'
|
data/lib/thumbtack/client.rb
CHANGED
@@ -1,68 +1,114 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Thumbtack
|
4
|
-
#
|
4
|
+
# Wraps each interaction with the Pinboard API
|
5
5
|
class Client
|
6
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
44
|
+
# Retrieve JSON from the Pinboard API
|
25
45
|
#
|
26
|
-
#
|
27
|
-
#
|
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
|
-
#
|
49
|
+
# @param [Hash] params
|
50
|
+
# query parameters to append to the URL
|
32
51
|
#
|
33
|
-
#
|
34
|
-
# # => {'update_time' => '2014-06-24T15:39:46Z'}
|
52
|
+
# @return [Hash] the response parsed from the JSON
|
35
53
|
#
|
36
|
-
#
|
37
|
-
# # => [{'popular' => []}, {'recommended' => []}]
|
54
|
+
# @raise [RateLimitError] if the response is rate-limited
|
38
55
|
#
|
39
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
data/lib/thumbtack/note.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Thumbtack
|
4
|
-
#
|
4
|
+
# Represents a note
|
5
|
+
#
|
6
|
+
# @api public
|
5
7
|
class Note
|
6
|
-
#
|
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
|
-
|
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
|
-
#
|
70
|
+
# Creates a new Note from a Hash
|
20
71
|
#
|
21
|
-
#
|
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
|
-
#
|
85
|
+
# Initialize a Note
|
86
|
+
#
|
87
|
+
# @param [Hash] attrs
|
88
|
+
# Note attributes
|
29
89
|
#
|
30
|
-
#
|
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
|
-
#
|
4
|
+
# Represents a note summary as returned from Notes#list.
|
5
|
+
#
|
6
|
+
# @api public
|
7
|
+
# @see Notes#list
|
5
8
|
class NoteSummary
|
6
|
-
#
|
9
|
+
# The attributes for a NoteSummary
|
10
|
+
#
|
11
|
+
# @api private
|
7
12
|
ATTRIBUTES = [
|
8
13
|
:id,
|
9
14
|
:title,
|
10
|
-
:
|
15
|
+
:digest,
|
11
16
|
:created_at,
|
12
17
|
:updated_at,
|
13
18
|
:length
|
14
19
|
].freeze
|
15
20
|
|
16
|
-
|
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
|
-
#
|
19
|
-
# response.
|
35
|
+
# The time at which the note was created
|
20
36
|
#
|
21
|
-
#
|
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
|
-
|
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
|
-
#
|
78
|
+
# Initialize a NoteSummary
|
79
|
+
#
|
80
|
+
# @param [Hash] attrs
|
81
|
+
# NoteSummary attributes
|
27
82
|
#
|
28
|
-
#
|
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
|
data/lib/thumbtack/notes.rb
CHANGED
@@ -1,24 +1,48 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Thumbtack
|
4
|
-
#
|
4
|
+
# Wraps API calls related to notes
|
5
5
|
class Notes
|
6
|
-
#
|
6
|
+
# Initialize a Notes
|
7
7
|
#
|
8
|
-
#
|
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
|
-
#
|
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',
|
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
|
-
#
|
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
|
data/lib/thumbtack/post.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Thumbtack
|
4
|
-
#
|
4
|
+
# Represents a bookmark
|
5
|
+
#
|
6
|
+
# @api public
|
5
7
|
class Post
|
6
|
-
#
|
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
|
-
|
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
|
-
#
|
72
|
+
# If true, this post is marked unread
|
22
73
|
#
|
23
|
-
#
|
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
|
-
#
|
99
|
+
# Initialize a Post
|
100
|
+
#
|
101
|
+
# @param [Hash] attrs
|
102
|
+
# Post attributes
|
29
103
|
#
|
30
|
-
#
|
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
|