thumbtack 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|