kippt 1.1.0 → 2.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.
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -0
- data/README.md +20 -3
- data/TODO.md +43 -0
- data/kippt.gemspec +6 -6
- data/lib/kippt/client.rb +46 -8
- data/lib/kippt/clip.rb +83 -4
- data/lib/kippt/clip_collection.rb +4 -0
- data/lib/kippt/clips.rb +8 -4
- data/lib/kippt/collection.rb +22 -9
- data/lib/kippt/collection_resource.rb +25 -8
- data/lib/kippt/comment.rb +25 -0
- data/lib/kippt/comment_collection.rb +10 -0
- data/lib/kippt/comments.rb +43 -0
- data/lib/kippt/connection.rb +14 -8
- data/lib/kippt/follow_relationship.rb +50 -0
- data/lib/kippt/followers.rb +26 -0
- data/lib/kippt/following.rb +26 -0
- data/lib/kippt/like.rb +48 -0
- data/lib/kippt/likes.rb +48 -0
- data/lib/kippt/list.rb +29 -4
- data/lib/kippt/list_collection.rb +4 -0
- data/lib/kippt/resource.rb +106 -9
- data/lib/kippt/saves.rb +25 -0
- data/lib/kippt/user.rb +59 -0
- data/lib/kippt/user_clips.rb +39 -0
- data/lib/kippt/user_collection.rb +14 -0
- data/lib/kippt/user_lists.rb +32 -0
- data/lib/kippt/users.rb +51 -0
- data/lib/kippt/version.rb +1 -1
- data/spec/fixtures/clip.json +1 -1
- data/spec/fixtures/comment.json +1 -0
- data/spec/fixtures/comments.json +1 -0
- data/spec/fixtures/feed.json +1 -0
- data/spec/fixtures/list.json +1 -1
- data/spec/fixtures/user.json +1 -0
- data/spec/fixtures/users.json +2 -0
- data/spec/fixtures/users_with_multiple_pages.json +1 -0
- data/spec/kippt/client_spec.rb +63 -8
- data/spec/kippt/clip_collection_spec.rb +3 -3
- data/spec/kippt/clip_spec.rb +109 -4
- data/spec/kippt/clips_spec.rb +18 -7
- data/spec/kippt/comment_spec.rb +25 -0
- data/spec/kippt/comments_spec.rb +103 -0
- data/spec/kippt/follow_relationship_spec.rb +34 -0
- data/spec/kippt/followers_spec.rb +17 -0
- data/spec/kippt/following_spec.rb +17 -0
- data/spec/kippt/list_collection_spec.rb +3 -3
- data/spec/kippt/list_spec.rb +92 -6
- data/spec/kippt/lists_spec.rb +2 -1
- data/spec/kippt/saves_spec.rb +20 -0
- data/spec/kippt/user_clips_spec.rb +29 -0
- data/spec/kippt/user_collection_spec.rb +14 -0
- data/spec/kippt/user_lists_spec.rb +13 -0
- data/spec/kippt/user_spec.rb +71 -0
- data/spec/kippt/users_spec.rb +59 -0
- data/spec/spec_helper.rb +60 -4
- metadata +106 -24
- data/lib/kippt/account.rb +0 -10
- data/spec/kippt/account_spec.rb +0 -28
@@ -0,0 +1,25 @@
|
|
1
|
+
require "kippt/resource"
|
2
|
+
require "kippt/user"
|
3
|
+
require "kippt/clip"
|
4
|
+
|
5
|
+
class Kippt::Comment
|
6
|
+
include Kippt::Resource
|
7
|
+
|
8
|
+
attributes :body, :id, :resource_uri,
|
9
|
+
:created => Time, :user => Kippt::User
|
10
|
+
|
11
|
+
writable_attributes :body
|
12
|
+
|
13
|
+
attr_reader :clip
|
14
|
+
|
15
|
+
def initialize(attributes = {}, client = nil, clip = nil)
|
16
|
+
super(attributes, client)
|
17
|
+
@clip = clip
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def collection_resource
|
23
|
+
@collection_resource ||= client.collection_resource_for(Kippt::Comments, clip)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "kippt/comment_collection"
|
2
|
+
require "kippt/comment"
|
3
|
+
|
4
|
+
class Kippt::Comments
|
5
|
+
include Kippt::CollectionResource
|
6
|
+
|
7
|
+
attr_reader :clip
|
8
|
+
|
9
|
+
def initialize(client, clip)
|
10
|
+
@client = client
|
11
|
+
@clip = clip
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.valid_filter_parameters
|
15
|
+
[:limit, :offset]
|
16
|
+
end
|
17
|
+
|
18
|
+
def object_class
|
19
|
+
Kippt::Comment
|
20
|
+
end
|
21
|
+
|
22
|
+
def collection_class
|
23
|
+
Kippt::CommentCollection
|
24
|
+
end
|
25
|
+
|
26
|
+
def base_uri
|
27
|
+
"clips/#{clip.id}/comments"
|
28
|
+
end
|
29
|
+
|
30
|
+
def all(options = {})
|
31
|
+
validate_collection_options(options)
|
32
|
+
|
33
|
+
if options.empty? && @clip.all_comments_embedded?
|
34
|
+
collection_class.new({"objects" => @clip.comments_data}, client)
|
35
|
+
else
|
36
|
+
collection_class.new(client.get(base_uri, options).body, client)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build(attributes = {})
|
41
|
+
object_class.new(attributes, client, clip)
|
42
|
+
end
|
43
|
+
end
|
data/lib/kippt/connection.rb
CHANGED
@@ -2,6 +2,8 @@ require "multi_json"
|
|
2
2
|
require "faraday_middleware/response_middleware"
|
3
3
|
|
4
4
|
module Kippt::Connection
|
5
|
+
HOST = "kippt.com"
|
6
|
+
|
5
7
|
class ParseMultiJson < FaradayMiddleware::ResponseMiddleware
|
6
8
|
define_parser do |body|
|
7
9
|
begin
|
@@ -31,22 +33,26 @@ module Kippt::Connection
|
|
31
33
|
private
|
32
34
|
|
33
35
|
def connection
|
34
|
-
@connection ||= Faraday.new("https
|
36
|
+
@connection ||= Faraday.new("https://#{HOST}/api") do |builder|
|
35
37
|
builder.use Kippt::Connection::ParseMultiJson
|
36
|
-
|
38
|
+
builder.use Faraday::Response::Logger if debug?
|
37
39
|
builder.adapter Faraday.default_adapter
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
def request(method, url, options)
|
44
|
+
if @password
|
45
|
+
connection.basic_auth(@username, @password)
|
46
|
+
end
|
47
|
+
|
42
48
|
response = connection.send(method) do |req|
|
43
49
|
set_default_headers(req)
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
unless @password
|
52
|
+
if @username && @token
|
53
|
+
req.headers["X-Kippt-Username"] = @username
|
54
|
+
req.headers["X-Kippt-API-Token"] = @token
|
55
|
+
end
|
50
56
|
end
|
51
57
|
|
52
58
|
if method == :get
|
@@ -56,7 +62,7 @@ module Kippt::Connection
|
|
56
62
|
req.body = MultiJson.dump(options[:data])
|
57
63
|
end
|
58
64
|
end
|
59
|
-
|
65
|
+
|
60
66
|
if response.status == 401
|
61
67
|
raise Kippt::APIError.new(response.body["message"])
|
62
68
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Kippt::FollowRelationship
|
2
|
+
attr_reader :user
|
3
|
+
|
4
|
+
def initialize(client, user)
|
5
|
+
@client = client
|
6
|
+
@user = user
|
7
|
+
end
|
8
|
+
|
9
|
+
def following?
|
10
|
+
response = client.get("users/#{user.id}/relationship/")
|
11
|
+
|
12
|
+
if response.success?
|
13
|
+
response.body["following"]
|
14
|
+
else
|
15
|
+
raise Kippt::APIError.new("Resource could not be loaded: #{response.body["message"]}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def follow
|
20
|
+
response = update_following(true)
|
21
|
+
|
22
|
+
if response.success?
|
23
|
+
true
|
24
|
+
else
|
25
|
+
raise Kippt::APIError.new("Problem with following: #{response.body["message"]}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def unfollow
|
30
|
+
response = update_following(false)
|
31
|
+
|
32
|
+
if response.success?
|
33
|
+
true
|
34
|
+
else
|
35
|
+
raise Kippt::APIError.new("Problem with unfollowing: #{response.body["message"]}")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def update_following(value)
|
42
|
+
follow_value = value ? "follow" : "unfollow"
|
43
|
+
|
44
|
+
client.post("users/#{user.id}/relationship/", :data => {:action => follow_value})
|
45
|
+
end
|
46
|
+
|
47
|
+
def client
|
48
|
+
@client
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "kippt/collection_resource"
|
2
|
+
require "kippt/user_collection"
|
3
|
+
require "kippt/user"
|
4
|
+
|
5
|
+
class Kippt::Followers
|
6
|
+
include Kippt::CollectionResource
|
7
|
+
|
8
|
+
attr_reader :user
|
9
|
+
|
10
|
+
def initialize(client, user)
|
11
|
+
@client = client
|
12
|
+
@user = user
|
13
|
+
end
|
14
|
+
|
15
|
+
def object_class
|
16
|
+
Kippt::User
|
17
|
+
end
|
18
|
+
|
19
|
+
def collection_class
|
20
|
+
Kippt::UserCollection
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_uri
|
24
|
+
"users/#{user.id}/followers"
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "kippt/collection_resource"
|
2
|
+
require "kippt/user_collection"
|
3
|
+
require "kippt/user"
|
4
|
+
|
5
|
+
class Kippt::Following
|
6
|
+
include Kippt::CollectionResource
|
7
|
+
|
8
|
+
attr_reader :user
|
9
|
+
|
10
|
+
def initialize(client, user)
|
11
|
+
@client = client
|
12
|
+
@user = user
|
13
|
+
end
|
14
|
+
|
15
|
+
def object_class
|
16
|
+
Kippt::User
|
17
|
+
end
|
18
|
+
|
19
|
+
def collection_class
|
20
|
+
Kippt::UserCollection
|
21
|
+
end
|
22
|
+
|
23
|
+
def base_uri
|
24
|
+
"users/#{user.id}/following"
|
25
|
+
end
|
26
|
+
end
|
data/lib/kippt/like.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "kippt/users"
|
2
|
+
|
3
|
+
class Kippt::Like
|
4
|
+
def initialize(client, clip)
|
5
|
+
@client = client
|
6
|
+
@errors = []
|
7
|
+
@clip = clip
|
8
|
+
end
|
9
|
+
|
10
|
+
def id
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def collection_resource_class
|
15
|
+
Kippt::Likes
|
16
|
+
end
|
17
|
+
|
18
|
+
def writable_attributes_hash
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def save
|
23
|
+
@errors = []
|
24
|
+
response = collection_resource.save_resource(self)
|
25
|
+
if response[:error_message]
|
26
|
+
errors << response[:error_message]
|
27
|
+
end
|
28
|
+
response[:success]
|
29
|
+
end
|
30
|
+
|
31
|
+
def destroy
|
32
|
+
collection_resource.destroy_resource(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def collection_resource
|
38
|
+
@collection_resource ||= client.collection_resource_for(collection_resource_class, clip)
|
39
|
+
end
|
40
|
+
|
41
|
+
def client
|
42
|
+
@client
|
43
|
+
end
|
44
|
+
|
45
|
+
def clip
|
46
|
+
@clip
|
47
|
+
end
|
48
|
+
end
|
data/lib/kippt/likes.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "kippt/user_collection"
|
2
|
+
require "kippt/user"
|
3
|
+
require "kippt/like"
|
4
|
+
|
5
|
+
class Kippt::Likes
|
6
|
+
include Kippt::CollectionResource
|
7
|
+
|
8
|
+
attr_reader :clip
|
9
|
+
|
10
|
+
def initialize(client, clip)
|
11
|
+
@client = client
|
12
|
+
@clip = clip
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.valid_filter_parameters
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
|
19
|
+
def object_class
|
20
|
+
Kippt::User
|
21
|
+
end
|
22
|
+
|
23
|
+
def collection_class
|
24
|
+
Kippt::UserCollection
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_uri
|
28
|
+
"clips/#{clip.id}/likes"
|
29
|
+
end
|
30
|
+
|
31
|
+
def all(options = {})
|
32
|
+
validate_collection_options(options)
|
33
|
+
|
34
|
+
if options.empty? && @clip.all_likes_embedded?
|
35
|
+
collection_class.new({"objects" => @clip.likes_data}, client)
|
36
|
+
else
|
37
|
+
collection_class.new(client.get(base_uri, options).body, client)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def build
|
42
|
+
Kippt::Like.new(client, clip)
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy_resource(resource)
|
46
|
+
client.delete(base_uri).success?
|
47
|
+
end
|
48
|
+
end
|
data/lib/kippt/list.rb
CHANGED
@@ -1,10 +1,35 @@
|
|
1
|
-
require "
|
1
|
+
require "kippt/user"
|
2
2
|
|
3
3
|
class Kippt::List
|
4
4
|
include Kippt::Resource
|
5
5
|
|
6
|
-
attributes :
|
7
|
-
:
|
6
|
+
attributes :app_url, :id, :rss_url, :title,
|
7
|
+
:slug, :resource_uri, :description,
|
8
|
+
:updated => Time, :created => Time,
|
9
|
+
:user => Kippt::User
|
10
|
+
boolean_attributes :is_private
|
8
11
|
|
9
|
-
writable_attributes :title
|
12
|
+
writable_attributes :title, :description
|
13
|
+
|
14
|
+
def collection_resource_class
|
15
|
+
Kippt::Lists
|
16
|
+
end
|
17
|
+
|
18
|
+
def collaborators
|
19
|
+
attributes.collaborators["data"].map {|collborator_data|
|
20
|
+
Kippt::User.new(collborator_data, client)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def follow
|
25
|
+
response = client.post("#{resource_uri}relationship", :data => {:action => "follow"})
|
26
|
+
raise Kippt::APIError.new("There was an error with the request: #{response.body["message"]}") unless response.success?
|
27
|
+
response.success?
|
28
|
+
end
|
29
|
+
|
30
|
+
def unfollow
|
31
|
+
response = client.post("#{resource_uri}relationship", :data => {:action => "unfollow"})
|
32
|
+
raise Kippt::APIError.new("There was an error with the request: #{response.body["message"]}") unless response.success?
|
33
|
+
response.success?
|
34
|
+
end
|
10
35
|
end
|
data/lib/kippt/resource.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
1
3
|
module Kippt::Resource
|
2
4
|
def self.included(base)
|
3
5
|
base.instance_eval do
|
4
6
|
extend Forwardable
|
5
7
|
attr_reader :attributes, :errors
|
6
8
|
|
7
|
-
def_delegators "self.class", :writable_attribute_names, :attribute_names
|
9
|
+
def_delegators "self.class", :writable_attribute_names, :attribute_names, :embedded_attribute_names
|
8
10
|
end
|
9
11
|
|
10
12
|
base.extend(ClassMethods)
|
@@ -13,31 +15,116 @@ module Kippt::Resource
|
|
13
15
|
module ClassMethods
|
14
16
|
attr_reader :writable_attribute_names, :attribute_names
|
15
17
|
|
18
|
+
def embedded_attribute_names
|
19
|
+
@embedded_attribute_names || []
|
20
|
+
end
|
21
|
+
|
16
22
|
def attributes(*attribs)
|
17
|
-
@attribute_names
|
18
|
-
|
23
|
+
@attribute_names ||= []
|
24
|
+
hashes, other = attribs.partition {|attrib| attrib.is_a? Hash }
|
25
|
+
|
26
|
+
attribute_names = convert_to_symbols(other)
|
27
|
+
def_delegators :attributes, *attribute_names
|
28
|
+
@attribute_names += attribute_names
|
29
|
+
|
30
|
+
mappings = hashes.reduce({}, :update)
|
31
|
+
mappings.each do |attrib, object_class|
|
32
|
+
if object_class.to_s == "Time"
|
33
|
+
define_method(attrib) do
|
34
|
+
Time.at(attributes.send(attrib))
|
35
|
+
end
|
36
|
+
else
|
37
|
+
reified_class = _get_class(object_class)
|
38
|
+
define_method(attrib) do
|
39
|
+
value = attributes.send(attrib)
|
40
|
+
reified_class.new(value) unless value.nil?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@attribute_names += convert_to_symbols(mappings.keys)
|
45
|
+
end
|
46
|
+
|
47
|
+
def boolean_attributes(*attribs)
|
48
|
+
@attribute_names ||= []
|
49
|
+
attribute_names = convert_to_symbols(attribs)
|
50
|
+
def_delegators :attributes, *attribute_names
|
51
|
+
@attribute_names += attribute_names
|
52
|
+
|
53
|
+
attribs.each do |attribute_name|
|
54
|
+
if result = attribute_name.to_s.match(/\Ais\_(.*)/)
|
55
|
+
define_method "#{result[1]}?" do
|
56
|
+
send(attribute_name) if respond_to?(attribute_name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
19
60
|
end
|
20
61
|
|
21
62
|
def writable_attributes(*attribs)
|
22
|
-
@writable_attribute_names = attribs
|
63
|
+
@writable_attribute_names = convert_to_symbols(attribs)
|
23
64
|
@writable_attribute_names.freeze
|
24
|
-
def_delegators :attributes, *(@writable_attribute_names.map {|attrib| attrib.to_s + "=" })
|
65
|
+
def_delegators :attributes, *(@writable_attribute_names.map {|attrib| attrib.to_s + "=" }).dup
|
66
|
+
end
|
67
|
+
|
68
|
+
def embedded_attributes(*attribs)
|
69
|
+
mappings = attribs.reduce({}, :update)
|
70
|
+
@embedded_attribute_names = convert_to_symbols(mappings.keys)
|
71
|
+
@embedded_attribute_names.freeze
|
72
|
+
|
73
|
+
mappings.each do |attrib, attribute_class|
|
74
|
+
reified_class = _get_class(attribute_class)
|
75
|
+
define_method(attrib) do
|
76
|
+
value = attributes.send(attrib)
|
77
|
+
if value.is_a? String
|
78
|
+
client.resource_from_url(reified_class, value)
|
79
|
+
elsif value.is_a? reified_class
|
80
|
+
value
|
81
|
+
else
|
82
|
+
reified_class.new(value, client)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def convert_to_symbols(list)
|
91
|
+
list.map {|item| item.to_sym }
|
92
|
+
end
|
93
|
+
|
94
|
+
protected
|
95
|
+
|
96
|
+
def _get_class(camel_cased_word)
|
97
|
+
if camel_cased_word.is_a? Class
|
98
|
+
camel_cased_word
|
99
|
+
else
|
100
|
+
names = camel_cased_word.split('::')
|
101
|
+
names.shift if names.empty? || names.first.empty?
|
102
|
+
|
103
|
+
constant = Object
|
104
|
+
names.each do |name|
|
105
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
106
|
+
end
|
107
|
+
constant
|
108
|
+
end
|
25
109
|
end
|
26
110
|
end
|
27
111
|
|
28
|
-
def initialize(attributes = {},
|
112
|
+
def initialize(attributes = {}, client = nil)
|
29
113
|
@attributes = OpenStruct.new(attributes)
|
30
114
|
@errors = []
|
31
|
-
@
|
115
|
+
@client = client
|
32
116
|
end
|
33
117
|
|
34
118
|
def destroy
|
35
|
-
|
119
|
+
collection_resource.destroy_resource(self)
|
36
120
|
end
|
37
121
|
|
38
122
|
def writable_attributes_hash
|
39
123
|
writable_attribute_names.inject({}) do |parameters, attribute_name|
|
40
124
|
value = self.send(attribute_name)
|
125
|
+
if embedded_attribute_names.include?(attribute_name) && !value.is_a?(String)
|
126
|
+
value = value.resource_uri
|
127
|
+
end
|
41
128
|
unless value.nil?
|
42
129
|
parameters[attribute_name] = value
|
43
130
|
end
|
@@ -47,7 +134,7 @@ module Kippt::Resource
|
|
47
134
|
|
48
135
|
def save
|
49
136
|
@errors = []
|
50
|
-
response =
|
137
|
+
response = collection_resource.save_resource(self)
|
51
138
|
if response[:error_message]
|
52
139
|
errors << response[:error_message]
|
53
140
|
else
|
@@ -60,4 +147,14 @@ module Kippt::Resource
|
|
60
147
|
end
|
61
148
|
response[:success]
|
62
149
|
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def collection_resource
|
154
|
+
@collection_resource ||= client.collection_resource_for(collection_resource_class)
|
155
|
+
end
|
156
|
+
|
157
|
+
def client
|
158
|
+
@client
|
159
|
+
end
|
63
160
|
end
|