vodpod 0.0.1 → 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/README +40 -58
- data/lib/vodpod.rb +10 -5
- data/lib/vodpod/collection.rb +9 -0
- data/lib/vodpod/collection_video.rb +11 -0
- data/lib/vodpod/comment.rb +7 -0
- data/lib/vodpod/connection.rb +130 -36
- data/lib/vodpod/record.rb +67 -11
- data/lib/vodpod/record_set.rb +17 -0
- data/lib/vodpod/tag.rb +5 -9
- data/lib/vodpod/user.rb +8 -17
- data/lib/vodpod/version.rb +3 -3
- data/lib/vodpod/video.rb +6 -29
- metadata +9 -6
- data/lib/vodpod/pod.rb +0 -119
data/README
CHANGED
@@ -3,75 +3,57 @@ Vodpod - Ruby bindings for the Vodpod API.
|
|
3
3
|
|
4
4
|
Vodpod is a web site that allows you to collect videos. This library lets you
|
5
5
|
interact with those collections and videos over their REST-style API, using
|
6
|
-
clean Ruby.
|
7
|
-
|
8
|
-
management system, or copy videos automatically from a social bookmarking site.
|
9
|
-
Be creative. :-)
|
6
|
+
clean Ruby. Maybe you want to integrate with a content management system, or
|
7
|
+
copy videos automatically from a social bookmarking site. Be creative. :-)
|
10
8
|
|
11
|
-
|
12
|
-
retrieve details on videos and pods, and page through videos in a pod. You can
|
13
|
-
also post new videos to a pod, and update video attributes. Error handling is
|
14
|
-
spotty thus far.
|
9
|
+
You can search for videos, retrieve users, collections, videos, and their tags and comments. You can filter by tags, sort and paginate every dataset, and generally be awesome.
|
15
10
|
|
16
|
-
|
17
|
-
--------
|
11
|
+
Source code: http://github.com/aphyr/ruby-vodpod.
|
18
12
|
|
19
|
-
|
20
|
-
# Get a pod
|
21
|
-
pod = v.pod('aphyr')
|
13
|
+
Gem: gem install vodpod
|
22
14
|
|
23
|
-
|
24
|
-
|
25
|
-
pod.stats # => {"total_views"=>23, "weekly_pod_views"=>2, ...}
|
15
|
+
Examples
|
16
|
+
--------
|
26
17
|
|
27
|
-
|
28
|
-
|
18
|
+
Vodpod.start(:api_key => '...', :auth_key => '...') do |v|
|
19
|
+
# View the user associated with this API key
|
20
|
+
v.me
|
21
|
+
#=> #<Vodpod::User spencer {"name"=>"Spencer", "thumbnail"=>"http://s3.amazonaws.com/vodpod.com.users.image/8.medium.jpg", "videos_count"=>670, "description"=>"Co-founder and Engineer at Vodpod", "key"=>"spencer"}>
|
29
22
|
|
30
|
-
#
|
31
|
-
|
23
|
+
# Attributes are accessed like so...
|
24
|
+
v.me.name #=> "Spencer"
|
32
25
|
|
33
|
-
# Get a
|
34
|
-
|
26
|
+
# Get a user, with some extra attributes
|
27
|
+
v.user :aphyr, :include => [:collections, :followers]
|
28
|
+
#=> #<Vodpod::User aphyr {"name"=>"aphyr", "collections"=>[#<Vodpod::User aphyr {"name"=>"aphyr's videos", "key"=>"aphyr"}>], "followers"=>[#<Vodpod::User spencer {"name"=>"Spencer", "thumbnail"=>"http://s3.amazonaws.com/vodpod.com.users.image/8.medium.jpg", "key"=>"spencer"}>, #<Vodpod::User pkulak {"name"=>"pkulak", "thumbnail"=>"http://s3.amazonaws.com/vodpod.com.users.image/11221.medium.jpg", "key"=>"pkulak"}>], "thumbnail"=>"http://s3.amazonaws.com/vodpod.com.users.image/493234.medium.jpg", "videos_count"=>69, "description"=>"I'm a developer here at Vodpod. I'm also a freelance photographer, Aikido nut, gamer, book enthusiast, and physics and math geek.", "key"=>"aphyr"}>
|
35
29
|
|
36
|
-
#
|
37
|
-
|
38
|
-
# => [
|
30
|
+
# Associated objects are automatically instantiated.
|
31
|
+
v.user(:aphyr, :include => :collections).collections
|
32
|
+
# => [#<Vodpod::Collection aphyr {"name"=>"aphyr's videos", "key"=>"aphyr"}>]
|
39
33
|
|
40
|
-
# You can
|
41
|
-
|
42
|
-
#
|
34
|
+
# You can get more detail about a collection with collection(user_key,
|
35
|
+
# collection_key). Let's build a tag cloud for aphyr's collection named
|
36
|
+
# "aphyr".
|
37
|
+
v.collection(:aphyr, :aphyr, :include => :tags).tags.map { |t| t.count, t.name }
|
38
|
+
# => [[16, "funny"], [12, "awesome"], [6, "music"], [4, "trailer"], [4, "game"], [3, "apple"], [3, "ruby"], [3, "_why"], [3, "math"], [3, "fail"], [3, "robot"], [3, "lego"], [3, "neotokyo"], [2, "future-occupation?"], [2, "microsoft"], [2, "gay"], [2, "cat"], [2, "evil"], [2, "parkour"], [2, "science fiction"]]
|
43
39
|
|
44
|
-
#
|
45
|
-
v.search(
|
46
|
-
# =>
|
40
|
+
# You can find videos by searching...
|
41
|
+
v.search(:kittens, :limit => 1, :offset => 14).first
|
42
|
+
# => #<Vodpod::Video 29740 {"autoplay_embed"=>"<embed src=\"http://www.youtube.com/v/jn0Fo0Mt6xo&autoplay=1&fs=1&showinfo=0&showsearch=0&rel=0&\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" wmode=\"opaque\" width=\"100%\" height=\"100%\" id=\"myytplayer\"></embed>", "total_views"=>77, "created_at"=>#<DateTime: 10602058157/4320,-5/24,2299161>, "title"=>"Samson the Kitten", "video_host"=>{"url"=>"http://www.youtube.com/v/jn0Fo0Mt6xo", "domain"=>"youtube.com", "description"=>"Zachary gets Samson nodding and shaking his head."}, "thumbnail"=>"http://assetscdn.vodpod.com/images/missing_video_100.gif", "down_votes"=>0, "url"=>"http://vodpod.com/watch/29740-samson-the-kitten", "up_votes"=>0, "embed"=>"<embed src=\"http://www.youtube.com/v/jn0Fo0Mt6xo&autoplay=&fs=1&showinfo=0&showsearch=0&rel=0&\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" wmode=\"opaque\" width=\"100%\" height=\"100%\" id=\"myytplayer\"></embed>", "description"=>nil, "key"=>29740}>
|
47
43
|
|
48
|
-
#
|
49
|
-
|
44
|
+
# Or by tags...
|
45
|
+
v.videos(:tags => ['star trek', :bloopers]).total
|
46
|
+
# => 494
|
50
47
|
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
)
|
60
|
-
# => <Vodpod::Video ...>
|
61
|
-
|
62
|
-
# Add a tag "sports" to every video in a pod about frisbee.
|
63
|
-
pod.search('frisbee').each do |video|
|
64
|
-
tags = "#{video.tags} sports"
|
65
|
-
video.update(:tags => tags)
|
66
|
-
end
|
48
|
+
# You can retrieve specific videos if you know their key
|
49
|
+
v.video(29740)
|
50
|
+
# => (same video as from search)
|
51
|
+
|
52
|
+
# You can also get CollectionVideos--the version of a video belonging to a
|
53
|
+
# specific user/collection.
|
54
|
+
v.videos(:spencer, :electro, :limit => 1).first
|
55
|
+
# => #<Vodpod::CollectionVideo 1002751 {"autoplay_embed"=>"<embed src=\"http://www.youtube.com/v/v-3jOg5QpJo&autoplay=1&fs=1&showinfo=0&showsearch=0&rel=0&autoplay=&border=0&rel=0\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" wmode=\"opaque\" width=\"100%\" height=\"100%\" id=\"myytplayer\"></embed>", "total_views"=>3, "created_at"=>#<DateTime: 42417586163/17280,-5/24,2299161>, "title"=>"Crystal Castles - Knights", "video_host"=>{"url"=>"http://www.pitchforkmedia.com/article/download/145440-video-crystal-castles-knights", "domain"=>"pitchforkmedia.com", "description"=>""}, "thumbnail"=>"http://img.vodpod.com/1002751.medium100.jpg", "down_votes"=>0, "url"=>"http://vodpod.com/watch/1002751-crystal-castles-knights?pod=electro", "up_votes"=>1, "embed"=>"<embed src=\"http://www.youtube.com/v/v-3jOg5QpJo&autoplay=&fs=1&showinfo=0&showsearch=0&rel=0&autoplay=&border=0&rel=0\" type=\"application/x-shockwave-flash\" allowscriptaccess=\"always\" allowfullscreen=\"true\" wmode=\"opaque\" width=\"100%\" height=\"100%\" id=\"myytplayer\"></embed>", "description"=>"", "key"=>1002751}>
|
67
56
|
end
|
68
57
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
- Posting videos seems to work--the URL is correct in the returned video JSON,
|
73
|
-
but visiting the page doesn't seem to load. Perhaps a caching issue on
|
74
|
-
Vodpod's end?
|
75
|
-
- Automatic casting for datetimes.
|
76
|
-
- Better error handling
|
77
|
-
- Iterators for acting on all results without thinking about pagination
|
58
|
+
You can contact support@vodpod.com for help with the toolkit. Patches welcome
|
59
|
+
on github!
|
data/lib/vodpod.rb
CHANGED
@@ -8,7 +8,7 @@ require 'uri'
|
|
8
8
|
require 'net/http'
|
9
9
|
|
10
10
|
module Vodpod
|
11
|
-
BASE_URI = 'http://api.vodpod.com/
|
11
|
+
BASE_URI = 'http://api.vodpod.com/v2/'
|
12
12
|
ROOT = File.dirname(__FILE__)
|
13
13
|
|
14
14
|
# Load library
|
@@ -16,9 +16,12 @@ module Vodpod
|
|
16
16
|
require "#{ROOT}/vodpod/error"
|
17
17
|
require "#{ROOT}/vodpod/connection"
|
18
18
|
require "#{ROOT}/vodpod/record"
|
19
|
+
require "#{ROOT}/vodpod/record_set"
|
20
|
+
require "#{ROOT}/vodpod/comment"
|
19
21
|
require "#{ROOT}/vodpod/user"
|
20
22
|
require "#{ROOT}/vodpod/tag"
|
21
|
-
require "#{ROOT}/vodpod/
|
23
|
+
require "#{ROOT}/vodpod/collection"
|
24
|
+
require "#{ROOT}/vodpod/collection_video"
|
22
25
|
require "#{ROOT}/vodpod/video"
|
23
26
|
|
24
27
|
# Performs URI escaping so that you can construct proper
|
@@ -32,13 +35,15 @@ module Vodpod
|
|
32
35
|
module_function :escape
|
33
36
|
|
34
37
|
# Creates a connection with the provided parameter hash, and yields it in a
|
35
|
-
# block. Example:
|
38
|
+
# block if given. Returns the connection. Example:
|
36
39
|
#
|
37
|
-
# Vodpod.start(:api_key => api_key, :
|
40
|
+
# Vodpod.start(:api_key => api_key, :auth_key => auth_key) do |v|
|
38
41
|
# pod = v.pod('aphyr')
|
39
42
|
# p pod.created_at
|
40
43
|
# end
|
41
44
|
def self.start(params)
|
42
|
-
|
45
|
+
c = Connection.new params
|
46
|
+
yield c if block_given?
|
47
|
+
c
|
43
48
|
end
|
44
49
|
end
|
data/lib/vodpod/connection.rb
CHANGED
@@ -1,95 +1,189 @@
|
|
1
1
|
module Vodpod
|
2
2
|
# Connection to vodpod.com; retreives JSON data and handles API key/auth.
|
3
3
|
class Connection
|
4
|
-
|
4
|
+
TIMEOUT = 5
|
5
5
|
attr_accessor :api
|
6
6
|
attr_accessor :auth
|
7
7
|
|
8
8
|
# Creates a new connection. Parameters:
|
9
9
|
#
|
10
10
|
# :api_key => API key
|
11
|
-
# :
|
11
|
+
# :auth_key => Auth key
|
12
|
+
# :timeout => How many seconds to wait before giving up on API calls.
|
12
13
|
def initialize(params = {})
|
13
14
|
@api_key = params[:api_key]
|
14
|
-
@
|
15
|
+
@auth_key = params[:auth_key]
|
16
|
+
@timeout = params[:timeout] || TIMEOUT
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets a collection by user and collection key.
|
20
|
+
def collection(user, collection, *args)
|
21
|
+
Collection.new self, get(:users, user, :collections, collection, *args)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Gets collections belonging to a user.
|
25
|
+
def collections(user, *args)
|
26
|
+
RecordSet.new self, Collection, get(:users, user, :collections, *args)
|
15
27
|
end
|
16
28
|
|
17
29
|
# Request via GET
|
18
|
-
def get(
|
19
|
-
request :get,
|
30
|
+
def get(*args)
|
31
|
+
request :get, *args
|
20
32
|
end
|
21
33
|
|
22
|
-
# Returns
|
23
|
-
def
|
24
|
-
|
34
|
+
# Returns the user associated with this API key.
|
35
|
+
def me(*args)
|
36
|
+
User.new self, get(:me, *args)
|
25
37
|
end
|
26
38
|
|
27
39
|
# Request via POST
|
28
|
-
def post(
|
29
|
-
request :post,
|
40
|
+
def post(*args)
|
41
|
+
request :post, *args
|
42
|
+
end
|
43
|
+
|
44
|
+
# Pings the API with our API key to check whether or not we are ready to
|
45
|
+
# make requests.
|
46
|
+
def ready?
|
47
|
+
get or false
|
30
48
|
end
|
31
49
|
|
32
50
|
# Perform a JSON request to the Vodpod API for a given path and parameter
|
33
51
|
# hash. Returns a parsed JSON document. Automatically provides api_key and
|
34
52
|
# auth params if you do not specify them. Method should be one of :get or
|
35
|
-
# :post--you should use the #get or #post methods for convenience.
|
36
|
-
|
53
|
+
# :post--you should use the #get or #post methods for convenience. Array
|
54
|
+
# values for parameters are joined by commas.
|
55
|
+
#
|
56
|
+
# Example
|
57
|
+
# request :get, :users, :aphyr, :include => [:name]
|
58
|
+
def request(method, *args)
|
37
59
|
defaults = {
|
38
60
|
:api_key => @api_key,
|
39
|
-
:
|
61
|
+
:auth_key => @auth
|
40
62
|
}
|
41
63
|
|
64
|
+
# Get parameters
|
65
|
+
if args.last.kind_of? Hash
|
66
|
+
params = args.pop
|
67
|
+
else
|
68
|
+
params = {}
|
69
|
+
end
|
70
|
+
|
42
71
|
# Construct query fragment
|
43
72
|
query = defaults.merge(params).inject('?') { |s, (k, v)|
|
73
|
+
if v.kind_of? Array
|
74
|
+
v = v.join(',')
|
75
|
+
end
|
44
76
|
s << "#{Vodpod::escape(k)}=#{Vodpod::escape(v)}&"
|
45
77
|
}[0..-2]
|
46
78
|
|
79
|
+
# Join path fragments
|
80
|
+
path = Vodpod::BASE_URI + args.map{|e| Vodpod::escape(e)}.join('/') + '.json'
|
81
|
+
|
47
82
|
begin
|
48
83
|
# Get URI
|
49
84
|
case method
|
50
85
|
when :get
|
51
86
|
# GET request
|
52
|
-
uri = URI.parse(
|
53
|
-
|
87
|
+
uri = URI.parse(path + query)
|
88
|
+
res = Net::HTTP.start(uri.host, uri.port) do |http|
|
89
|
+
http.open_timeout = @timeout
|
90
|
+
http.read_timeout = @timeout
|
91
|
+
http.get(uri.path + query)
|
92
|
+
end
|
54
93
|
when :post
|
55
94
|
# POST request
|
56
|
-
uri = URI.parse(
|
95
|
+
uri = URI.parse(path)
|
57
96
|
res = Net::HTTP.start(uri.host, uri.port) do |http|
|
97
|
+
http.open_timeout = @timeout
|
98
|
+
http.read_timeout = @timeout
|
58
99
|
http.post(uri.path, query[1..-1])
|
59
100
|
end
|
60
|
-
JSON.parse res.body
|
61
101
|
else
|
62
102
|
# Don't know how to do that kind of request
|
63
103
|
raise Error.new("Unsupported request method #{method.inspect}; should be one of :get, :post.")
|
64
104
|
end
|
65
105
|
rescue => e
|
66
|
-
# Error somewhere in the request/parse process.
|
67
106
|
raise Error.new("Error retrieving #{uri.path}#{query}: #{e.message}")
|
68
107
|
end
|
69
|
-
end
|
70
108
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
Video.new(self, store)
|
109
|
+
# Parse response as JSON
|
110
|
+
begin
|
111
|
+
data = JSON.parse res.body
|
112
|
+
rescue => e
|
113
|
+
raise Error, "server returned invalid json: #{e.message}" + "\n\n" + res
|
114
|
+
end
|
115
|
+
|
116
|
+
# Check for errors
|
117
|
+
if data[0] == false
|
118
|
+
raise Error, data[1]['message']
|
82
119
|
end
|
120
|
+
|
121
|
+
# Return data section
|
122
|
+
data[1]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Searches for videos
|
126
|
+
def search(query, opts = {})
|
127
|
+
opts = {:query => query}.merge opts
|
128
|
+
RecordSet.new self, Video, get(:search, opts)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gets a user by key
|
132
|
+
def user(key, *args)
|
133
|
+
User.new self, get(:users, key, *args)
|
83
134
|
end
|
84
135
|
|
85
|
-
#
|
86
|
-
|
87
|
-
|
136
|
+
# Retrieves a specific video by key.
|
137
|
+
# Three senses:
|
138
|
+
#
|
139
|
+
# 1. video(video) => Video
|
140
|
+
# 2. video(user, video) => CollectionVideo
|
141
|
+
# 2. video(user, collection, video) => CollectionVideo
|
142
|
+
#
|
143
|
+
# Which sense is determined by the index of the integer video key, so
|
144
|
+
# you can safely chain calls like:
|
145
|
+
#
|
146
|
+
# video(123, :comments, :page => 2)
|
147
|
+
#
|
148
|
+
# to get the 2nd page of comments associated with the video.
|
149
|
+
def video(*args)
|
150
|
+
key = args.find { |e| Integer === e }
|
151
|
+
i = args.index(key)
|
152
|
+
|
153
|
+
case i
|
154
|
+
when 0
|
155
|
+
Video.new self, get(:videos, *args)
|
156
|
+
when 1
|
157
|
+
CollectionVideo.new self, get(:users, args.shift, :videos, *args)
|
158
|
+
when 2
|
159
|
+
CollectionVideo.new self, get(:users, args.shift, :collections, args.shift, :videos, *args)
|
160
|
+
else
|
161
|
+
raise ArgumentError, "usage: video(video), video(user, video), video(user, collection, video)"
|
162
|
+
end
|
88
163
|
end
|
89
164
|
|
90
|
-
#
|
91
|
-
|
92
|
-
|
165
|
+
# Gets a list of videos
|
166
|
+
# Three senses:
|
167
|
+
#
|
168
|
+
# 1. videos() => An array of Videos
|
169
|
+
# 2. videos(user) => An array of CollectionVideos
|
170
|
+
# 3. videos(user, collection) => An array of CollectionVideos
|
171
|
+
#
|
172
|
+
# The sense is determined by the number of arguments before a hash (or if
|
173
|
+
# no options hash is given, the number of arguments).
|
174
|
+
def videos(*args)
|
175
|
+
opts = args.find { |e| Hash === e }
|
176
|
+
i = args.index(opts) || args.size
|
177
|
+
case i
|
178
|
+
when 0
|
179
|
+
RecordSet.new self, Video, get(:videos, *args)
|
180
|
+
when 1
|
181
|
+
RecordSet.new self, CollectionVideo, get(:users, args.shift, :videos, *args)
|
182
|
+
when 2
|
183
|
+
RecordSet.new self, CollectionVideo, get(:users, args.shift, :collections, args.shift, :videos, *args)
|
184
|
+
else
|
185
|
+
raise ArgumentError, "usage: videos(), videos(user), videos(user, collection)"
|
186
|
+
end
|
93
187
|
end
|
94
188
|
end
|
95
189
|
end
|
data/lib/vodpod/record.rb
CHANGED
@@ -7,27 +7,83 @@ module Vodpod
|
|
7
7
|
# Records are instantiated with a connection object and a default store of an
|
8
8
|
# empty hash.
|
9
9
|
class Record
|
10
|
-
attr_accessor :
|
10
|
+
attr_accessor :values
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def self.casters
|
13
|
+
@casters ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
# Association metaprogramming!
|
17
|
+
def self.cast(name, opts = {})
|
18
|
+
# Total hack :)
|
19
|
+
opts[:class] ||= name.to_s.sub(/s$/, '').capitalize
|
20
|
+
casters[name] = opts
|
21
|
+
end
|
22
|
+
|
23
|
+
# The given attribute is casted to a DateTime
|
24
|
+
def self.date(name, opts = {})
|
25
|
+
cast name, opts.merge(:type => :parse, :class => DateTime)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.one(name, opts = {})
|
29
|
+
cast name, opts.merge(:type => :one)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.many(name, opts = {})
|
33
|
+
cast name, opts.merge(:type => :many)
|
17
34
|
end
|
18
35
|
|
19
36
|
# Create a new Record. Takes two parameters: a Connection object so the
|
20
37
|
# record can perform further requests, and an optional default value for
|
21
|
-
# the
|
22
|
-
def initialize(connection,
|
38
|
+
# the value hash
|
39
|
+
def initialize(connection, values = {})
|
23
40
|
@connection = connection
|
24
|
-
@
|
41
|
+
@values = values
|
42
|
+
|
43
|
+
self.class.casters.each do |name, cast|
|
44
|
+
if values = @values[name.to_s]
|
45
|
+
# Lazily load classes
|
46
|
+
unless cast[:class].kind_of? Class
|
47
|
+
cast[:class] = Vodpod.const_get(cast[:class])
|
48
|
+
end
|
49
|
+
|
50
|
+
# Convert sub-values to objects
|
51
|
+
@values[name.to_s] = case cast[:type]
|
52
|
+
when :one
|
53
|
+
cast[:class].new(@connection, values)
|
54
|
+
when :many
|
55
|
+
values.map do |value|
|
56
|
+
cast[:class].new(@connection, value)
|
57
|
+
end
|
58
|
+
when :parse
|
59
|
+
cast[:class].parse(values)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def ==(other)
|
66
|
+
self.class == other.class and self.key == other.key rescue false
|
67
|
+
end
|
68
|
+
|
69
|
+
def inspect
|
70
|
+
"#<#{self.class} #{key} #{@values.inspect}>"
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
if respond_to? :title
|
75
|
+
title.to_s
|
76
|
+
elsif respond_to? :name
|
77
|
+
name.to_s
|
78
|
+
else
|
79
|
+
key.to_s
|
80
|
+
end
|
25
81
|
end
|
26
82
|
|
27
83
|
# Pass requests to store by default.
|
28
84
|
def method_missing(meth, *args)
|
29
|
-
if @
|
30
|
-
@
|
85
|
+
if @values.include? meth.to_s
|
86
|
+
@values[meth.to_s]
|
31
87
|
end
|
32
88
|
end
|
33
89
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Vodpod
|
2
|
+
class RecordSet < Array
|
3
|
+
# An Array, with an extra method #total which returns the total number of
|
4
|
+
# records available for the query which generated this recordset.
|
5
|
+
|
6
|
+
def initialize(connection, klass, results)
|
7
|
+
@total = results['total']
|
8
|
+
replace(results['results'].map { |result|
|
9
|
+
klass.new connection, result
|
10
|
+
})
|
11
|
+
end
|
12
|
+
|
13
|
+
def total
|
14
|
+
@total
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/vodpod/tag.rb
CHANGED
@@ -1,13 +1,9 @@
|
|
1
1
|
module Vodpod
|
2
|
-
# A Tag, attached to a video.
|
3
|
-
# that I'm aware of, but it might happen in the future.
|
2
|
+
# A Tag, attached to a video.
|
4
3
|
class Tag < Record
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def to_s
|
10
|
-
@store['_value']
|
11
|
-
end
|
4
|
+
many :collection_videos, :class => 'CollectionVideo'
|
5
|
+
many :collections
|
6
|
+
many :users
|
7
|
+
many :videos
|
12
8
|
end
|
13
9
|
end
|
data/lib/vodpod/user.rb
CHANGED
@@ -1,22 +1,13 @@
|
|
1
1
|
module Vodpod
|
2
2
|
# A Vodpod user, associated with a pod and with videos.
|
3
3
|
class User < Record
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"<Vodpod::User #{@store['username']}>"
|
13
|
-
else
|
14
|
-
"<Vodpod::User>"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_s
|
19
|
-
@store['username']
|
20
|
-
end
|
4
|
+
one :collection
|
5
|
+
many :collections
|
6
|
+
date :created_at
|
7
|
+
many :followers, :class => User
|
8
|
+
many :following, :class => User
|
9
|
+
many :tags
|
10
|
+
date :updated_at
|
11
|
+
many :videos
|
21
12
|
end
|
22
13
|
end
|
data/lib/vodpod/version.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Vodpod
|
2
2
|
APP_NAME = 'Vodpod'
|
3
|
-
APP_VERSION = '0.0
|
3
|
+
APP_VERSION = '2.0.0'
|
4
4
|
APP_AUTHOR = 'Kyle Kingsbury'
|
5
|
-
APP_EMAIL = '
|
6
|
-
APP_URL = 'http://aphyr.com/projects/ruby-vodpod'
|
5
|
+
APP_EMAIL = 'support@vodpod.com'
|
6
|
+
APP_URL = 'http://aphyr.com/projects/show/ruby-vodpod-bindings'
|
7
7
|
APP_COPYRIGHT = 'Copyright (c) 2009 Kyle Kingsbury <aphyr@aphyr.com>. All rights reserved.'
|
8
8
|
end
|
data/lib/vodpod/video.rb
CHANGED
@@ -1,34 +1,11 @@
|
|
1
1
|
module Vodpod
|
2
2
|
# A video.
|
3
3
|
class Video < Record
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def to_s
|
12
|
-
@store['title']
|
13
|
-
end
|
14
|
-
|
15
|
-
# Update the title, description, and/or tags for this video. Returns
|
16
|
-
# the updated video. Seems to create video records okay, but they aren't
|
17
|
-
# viewable and don't appear in collections for editing immediately.
|
18
|
-
def update(params)
|
19
|
-
new_params = params.merge(
|
20
|
-
:video_id => @store['video_id']
|
21
|
-
)
|
22
|
-
|
23
|
-
# Post
|
24
|
-
Video.new(@connection.post('video/update', new_params)['video'])
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns the User for this video.
|
28
|
-
def user
|
29
|
-
return nil unless @store['user']
|
30
|
-
|
31
|
-
User.new(@connection, @store['user'])
|
32
|
-
end
|
4
|
+
many :collections
|
5
|
+
many :comments
|
6
|
+
date :created_at
|
7
|
+
many :tags
|
8
|
+
date :updated_at
|
9
|
+
many :users
|
33
10
|
end
|
34
11
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vodpod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Kingsbury
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-21 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,10 +20,10 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ~>
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 1.1.
|
23
|
+
version: 1.1.9
|
24
24
|
version:
|
25
25
|
description:
|
26
|
-
email:
|
26
|
+
email: support@vodpod.com
|
27
27
|
executables: []
|
28
28
|
|
29
29
|
extensions: []
|
@@ -35,17 +35,20 @@ files:
|
|
35
35
|
- lib/vodpod
|
36
36
|
- lib/vodpod/record.rb
|
37
37
|
- lib/vodpod/tag.rb
|
38
|
-
- lib/vodpod/
|
38
|
+
- lib/vodpod/comment.rb
|
39
|
+
- lib/vodpod/collection_video.rb
|
39
40
|
- lib/vodpod/version.rb
|
41
|
+
- lib/vodpod/record_set.rb
|
40
42
|
- lib/vodpod/user.rb
|
41
43
|
- lib/vodpod/video.rb
|
42
44
|
- lib/vodpod/error.rb
|
43
45
|
- lib/vodpod/connection.rb
|
46
|
+
- lib/vodpod/collection.rb
|
44
47
|
- example/test.rb
|
45
48
|
- LICENSE
|
46
49
|
- README
|
47
50
|
has_rdoc: true
|
48
|
-
homepage: http://aphyr.com/projects/ruby-vodpod
|
51
|
+
homepage: http://aphyr.com/projects/show/ruby-vodpod-bindings
|
49
52
|
post_install_message:
|
50
53
|
rdoc_options: []
|
51
54
|
|
data/lib/vodpod/pod.rb
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
module Vodpod
|
2
|
-
# Represents a pod.
|
3
|
-
class Pod < Record
|
4
|
-
# Administrative users
|
5
|
-
def admins
|
6
|
-
if items = @store['users']['admins']
|
7
|
-
case items
|
8
|
-
when {}
|
9
|
-
# No results
|
10
|
-
[]
|
11
|
-
when Array
|
12
|
-
# More than one result
|
13
|
-
items.map do |item|
|
14
|
-
User.new(@connection, item['user'])
|
15
|
-
end
|
16
|
-
else
|
17
|
-
# One result
|
18
|
-
[User.new(@connection, items['user'])]
|
19
|
-
end
|
20
|
-
else
|
21
|
-
[]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Following users
|
26
|
-
def followers
|
27
|
-
if items = @store['users']['followers']
|
28
|
-
case items
|
29
|
-
when {}
|
30
|
-
# No results
|
31
|
-
[]
|
32
|
-
when Array
|
33
|
-
# More than one result
|
34
|
-
items.map do |item|
|
35
|
-
User.new(@connection, item['user'])
|
36
|
-
end
|
37
|
-
else
|
38
|
-
# One result
|
39
|
-
[User.new(@connection, items['user'])]
|
40
|
-
end
|
41
|
-
else
|
42
|
-
[]
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Loads information for this pod from the API.
|
47
|
-
def load!
|
48
|
-
if pod_id
|
49
|
-
@store.merge! @connection.get('pod/details', :pod_id => pod_id)["pod"]
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Posts a new video to a pod. Returns the video posted.
|
54
|
-
#
|
55
|
-
# Optional parameters:
|
56
|
-
# :title => 'Cats with captions!'
|
57
|
-
# :description => 'Ahh the internet...'
|
58
|
-
# :tags => 'foo bar baz' or ['foo', 'bar', 'baz']
|
59
|
-
def post(url, params = {})
|
60
|
-
new_params = params.merge(
|
61
|
-
:pod_id => @store['pod_id'],
|
62
|
-
:url => url
|
63
|
-
)
|
64
|
-
# Convert tags to string if necessary
|
65
|
-
if new_params[:tags].kind_of? Array
|
66
|
-
new_params[:tags] = new_params[:tags].join(' ')
|
67
|
-
end
|
68
|
-
|
69
|
-
# Post
|
70
|
-
Video.new(@connection.post('video/post', new_params)['video'])
|
71
|
-
end
|
72
|
-
|
73
|
-
# Searches for videos. Optionally specify :per_page and :page.
|
74
|
-
def search(query, params = {})
|
75
|
-
# Get list of videos
|
76
|
-
params = params.merge(:pod_id => @store['pod_id'], :query => query)
|
77
|
-
list = @connection.get('pod/search', params)['videos']['items']
|
78
|
-
|
79
|
-
return [] unless list
|
80
|
-
|
81
|
-
# Map results to Videos
|
82
|
-
list.map do |item|
|
83
|
-
store = item['video']
|
84
|
-
#store['video_id'].sub!(/^Video\./, '')
|
85
|
-
Video.new(@connection, store)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Returns an array of Tags associated with this pod, by frequency of use.
|
90
|
-
def tags
|
91
|
-
list = @connection.get('pod/tags', :pod_id => pod_id)['tags']['items']
|
92
|
-
list.map do |item|
|
93
|
-
Tag.new(@connection, item['t'])
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returns the associated user for this pod.
|
98
|
-
def user
|
99
|
-
return nil unless @store['user']
|
100
|
-
|
101
|
-
User.new(@connection, @store['user'])
|
102
|
-
end
|
103
|
-
|
104
|
-
# Videos in a pod. You can use :sort, :per_page, :page, and :tag_id to
|
105
|
-
# paginate and filter.
|
106
|
-
def videos(params = {})
|
107
|
-
# Get list of videos
|
108
|
-
params = params.merge(:pod_id => @store['pod_id'])
|
109
|
-
list = @connection.get('pod/videos', params)['videos']['items']
|
110
|
-
|
111
|
-
return [] unless list
|
112
|
-
|
113
|
-
# Map to objects
|
114
|
-
list.map do |item|
|
115
|
-
Video.new(@connection, item['video'])
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|