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