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