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 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. Typically one interacts with the Vodpod API through javascript, but
7
- maybe you've got bigger plans. Maybe you want to integrate with a content
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
- Right now you can search for videos across the site and in a specific pod,
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
- Examples
17
- --------
11
+ Source code: http://github.com/aphyr/ruby-vodpod.
18
12
 
19
- Vodpod.start(:api_key => '...', :auth => '...') do |v|
20
- # Get a pod
21
- pod = v.pod('aphyr')
13
+ Gem: gem install vodpod
22
14
 
23
- # Basic information about a pod is loaded by default
24
- pod.name # => "aphyr's videos"
25
- pod.stats # => {"total_views"=>23, "weekly_pod_views"=>2, ...}
15
+ Examples
16
+ --------
26
17
 
27
- # Retrieve tags (also works on videos)
28
- pod.tags # => [<Vodpod::Tag neotokyo (1)>, <Vodpod::Tag game (1)>, ...]
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
- # Look at who's following this pod
31
- pod.followers # => [<Vodpod::User foo>, <Vodpod::User bar>, ...]
23
+ # Attributes are accessed like so...
24
+ v.me.name #=> "Spencer"
32
25
 
33
- # Get a full dump of an object's contents (works on Tags, Users, Videos, ...)
34
- pod.store # => {"name"=>"aphyr's videos", "created_at" => ...}
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
- # List some videos
37
- pod.videos.map { |video| video.title }
38
- # => ["Official Neotokyo Trailer", "Kittens Attack!"]
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 page through results and filter by tags
41
- pod.videos(:tags => 'music', :page => 2, :per_page => 16)
42
- # => [<Vodpod::Video ...>, <Vodpod::Video ...>, ...]
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
- # Find videos by searching (Also works on pods)
45
- v.search('obama', :per_page => 48)
46
- # => [<Vodpod::Video ...>, <Vodpod::Video ...>, ...]
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
- # Get a specific video by ID
49
- vid = v.video(1063027) # => <Vodpod::Video ...>
44
+ # Or by tags...
45
+ v.videos(:tags => ['star trek', :bloopers]).total
46
+ # => 494
50
47
 
51
- # Show the associated user
52
- vid.user # => <Vodpod::User scarrfase>
53
-
54
- # Post a new video to a pod. Returns the new video.
55
- pod.post('http://www.youtube.com/watch?v=E0ewUBTSlvQ',
56
- :title => 'Neotokyo Recon Demo',
57
- :description => 'Demo footage of the in-development Neotokyo mod',
58
- :tags => ['game', 'neotokyo', 'trailer']
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
- Roadmap
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!
@@ -8,7 +8,7 @@ require 'uri'
8
8
  require 'net/http'
9
9
 
10
10
  module Vodpod
11
- BASE_URI = 'http://api.vodpod.com/api/'
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/pod"
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, :auth => auth) do |v|
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
- yield Connection.new(params)
45
+ c = Connection.new params
46
+ yield c if block_given?
47
+ c
43
48
  end
44
49
  end
@@ -0,0 +1,9 @@
1
+ module Vodpod
2
+ # A collection of videos.
3
+ class Collection < Record
4
+ date :created_at
5
+ many :tags
6
+ date :updated_at
7
+ many :videos, :class => 'CollectionVideo'
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Vodpod
2
+ # A video.
3
+ class CollectionVideo < Record
4
+ one :collection
5
+ many :collection_comments
6
+ many :comments
7
+ date :created_at
8
+ many :tags
9
+ one :user
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Vodpod
2
+ # A comment on a video or collectionvideo.
3
+ class Comment < Record
4
+ date :created_at
5
+ one :user
6
+ end
7
+ end
@@ -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
- # :auth => Auth key
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
- @auth = params[:auth]
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(path, params = {})
19
- request :get, path, params
30
+ def get(*args)
31
+ request :get, *args
20
32
  end
21
33
 
22
- # Returns a pod by ID.
23
- def pod(id)
24
- Pod.load(self, 'pod_id' => id)
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(path, params = {})
29
- request :post, path, params
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
- def request(method, path, params = {})
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
- :auth => @auth
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(Vodpod::BASE_URI + path + '.js' + query)
53
- JSON.parse Net::HTTP.get(uri)
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(Vodpod::BASE_URI + path + '.js')
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
- # Searches for videos. Optionally specify :per_page and :page.
72
- def search(query, params = {})
73
- list = get('video/search', params.merge(:query => query))['videos']['items']
74
- return [] unless list
75
-
76
- # Map results to Videos
77
- list.map do |item|
78
- # These results use Video.1234... as the ID, so we need to strip.
79
- store = item['video']
80
- store['video_id'] = store['video_id'].sub(/^Video\./, '').to_i
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
- # Returns a user by ID.
86
- def user(id)
87
- User.new(self, 'user_id' => id)
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
- # Returns a video by ID.
91
- def video(id)
92
- Video.load(self, 'video_id' => id)
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
@@ -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 :store
10
+ attr_accessor :values
11
11
 
12
- # Like Record.new, but also calls load!
13
- def self.load(*params)
14
- record = new(*params)
15
- record.load! if record.respond_to? :load!
16
- record
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 store.
22
- def initialize(connection, store = {})
38
+ # the value hash
39
+ def initialize(connection, values = {})
23
40
  @connection = connection
24
- @store = store
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 @store.include? meth.to_s
30
- @store[meth.to_s]
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
@@ -1,13 +1,9 @@
1
1
  module Vodpod
2
- # A Tag, attached to a video. There isn't a way yet to go from tags to videos
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
- def inspect
6
- "<Vodpod::Tag #{@store['_value']} (#{count})>"
7
- end
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
@@ -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
- # Returns recent activity by people related to this user. Not working
5
- # yet--maybe a Vodpod bug?
6
- def network_activity
7
- @connection.get('user/network_activity', :user_id => user_id)
8
- end
9
-
10
- def inspect
11
- if @store
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
@@ -1,8 +1,8 @@
1
1
  module Vodpod
2
2
  APP_NAME = 'Vodpod'
3
- APP_VERSION = '0.0.1'
3
+ APP_VERSION = '2.0.0'
4
4
  APP_AUTHOR = 'Kyle Kingsbury'
5
- APP_EMAIL = 'aphyr@aphyr.com'
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
@@ -1,34 +1,11 @@
1
1
  module Vodpod
2
2
  # A video.
3
3
  class Video < Record
4
- # Loads information on this video by video_id
5
- def load!
6
- if video_id
7
- @store.merge! @connection.get('video/details', :video_id => video_id)["video"]
8
- end
9
- end
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.1
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-05-08 00:00:00 -05:00
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.4
23
+ version: 1.1.9
24
24
  version:
25
25
  description:
26
- email: aphyr@aphyr.com
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/pod.rb
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
 
@@ -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