downthetube 0.0.9 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md ADDED
@@ -0,0 +1,4 @@
1
+ ## v1.0.0
2
+
3
+ * Added test coverage with RSpec
4
+ * Fixed some bugs
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ gemspec
3
+ gem 'rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ downthetube (0.0.9)
5
+ gdata_19 (>= 1.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.1.3)
11
+ gdata_19 (1.1.3)
12
+ rspec (2.7.0)
13
+ rspec-core (~> 2.7.0)
14
+ rspec-expectations (~> 2.7.0)
15
+ rspec-mocks (~> 2.7.0)
16
+ rspec-core (2.7.1)
17
+ rspec-expectations (2.7.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.7.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ downthetube!
26
+ rspec
data/README CHANGED
@@ -16,61 +16,21 @@ require 'downthetube'
16
16
 
17
17
  And then play. I've tried to make it do what you would expect:
18
18
 
19
- irb(main):018:0> pl = Youtube::Playlist.new "76E01802262A6694"
20
- => #<Youtube::Playlist:0x7ff91ce51f38 @url="http://gdata.youtube.com/feeds/api/playlists/76E01802262A6694">
21
-
22
- irb(main):019:0> playlists = Youtube.playlists_for "stephensam"
23
- => [#<Youtube::Playlist:0x7ff91ce214c8 @client=#<GData::Client::YouTube:0x7ff91ce1e9a8 @source="AnonymousApp", @http_service=GData::HTTP::DefaultService, @clientlogin_url="https://www.google.com/youtube/accounts/ClientLogin", @authsub_scope="http://gdata.youtube.com", @version="2", @headers={}, @clientlogin_service="youtube">, @url="http://gdata.youtube.com/feeds/api/playlists/76E01802262A6694", @author="stephensam", @xml=<entry gd:etag='W/&quot;CUQGR347eCp7ImA9WhZVGEk.&quot;'> ... </>, @title="Capoeira Angola", @id="76E01802262A6694">]
24
-
25
- irb(main):021:0> playlists.first.title
26
- => "Capoeira Angola"
27
-
28
- irb(main):022:0> playlists.class
29
- => Array
30
-
31
- irb(main):023:0> vids = playlists.first.videos 2
32
- => [#<Youtube::Video:0x7ff91cf63098 @xml=<entry gd:etag='W/&quot;AkQDQ3s-fCp7ImA9WhZUEkk.&quot;'> ... </>>, #<Youtube::Video:0x7ff91cf59bd8 @xml=<entry gd:etag='W/&quot;AkQDQ3s-fCp7ImA9WhZUEkk.&quot;'> ... </>>]
33
-
34
- irb(main):024:0> vid = vids.last
35
- => #<Youtube::Video:0x7ff91cf59bd8 @xml=<entry gd:etag='W/&quot;AkQDQ3s-fCp7ImA9WhZUEkk.&quot;'> ... </>>
36
-
37
- irb(main):025:0> vid.title
38
- => "Mestre Jogo De Dentro e Mestra Tisza,Ilheus 2008"
39
-
40
- irb(main):026:0> vid.description
41
- => "Roda de fim de ano na praca de Ilheus 2008,gravado por CM Denis."
42
-
43
- irb(main):027:0> vid.url
44
- => "http://www.youtube.com/watch?v=4I_4JgV-y8s"
45
-
46
- irb(main):028:0> vid.thumbnail :large
47
- => "http://i.ytimg.com/vi/4I_4JgV-y8s/hqdefault.jpg"
48
-
49
- irb(main):029:0> itapua = Youtube::Video.new "5Pg6a3TbF68"
50
- => #<Youtube::Video:0x7ff91cf097a0 @url="http://gdata.youtube.com/feeds/api/videos/5Pg6a3TbF68?v=2">
51
-
52
- irb(main):030:0> itapua.thumbnail
53
- => "http://i.ytimg.com/vi/5Pg6a3TbF68/default.jpg"
54
-
55
- irb(main):031:0> itapua.title
56
- => "Itapuã e Gibi - Roda Lavradio"
57
-
58
- irb(main):032:0> itapua.url
59
- => "http://www.youtube.com/watch?v=5Pg6a3TbF68"
60
-
61
- You can also get the video object to return a hash of its important info by calling to_h:
62
-
63
- irb(main):009:0> vid = Youtube::Video.new "QSiGw6noULA"
64
- => #<Youtube::Video:0x7fec0cbc9300 @url="http://gdata.youtube.com/feeds/api/videos/QSiGw6noULA?v=2">
65
-
66
- irb(main):010:0> vid.to_h
67
- => {:title=>"Semente do Jogo de Angola - Tradição - Parte 1", :small_thumbnail=>"http://i.ytimg.com/vi/QSiGw6noULA/default.jpg", :description=>"Video produzido pelo Grupo de capoeira Semente do Jogo de Angola - Mestre Jogo de Dentro\nwww.sementedojogodeangola.org.br", :large_thumbnail=>"http://i.ytimg.com/vi/QSiGw6noULA/hqdefault.jpg", :uploader=>"valmirmauricio", :duration=>"120", :url=>"http://www.youtube.com/watch?v=QSiGw6noULA", :id=>"QSiGw6noULA"}
19
+ Youtube::Playlist.new("76E01802262A6694")
20
+ playlists = Youtube.playlists_for "stephensam"
21
+ playlists.first.title # "Capoeira Angola"
22
+ vids = playlists.first.videos 2
23
+ vid = vids.last
24
+ vid.title # "Mestre Jogo De Dentro e Mestra Tisza,Ilheus 2008"
25
+ vid.description # "Roda de fim de ano na praca de Ilheus 2008,gravado por CM Denis."
26
+ vid.url # "http://www.youtube.com/watch?v=4I_4JgV-y8s"
27
+ vid.thumbnail(:large) # "http://i.ytimg.com/vi/4I_4JgV-y8s/hqdefault.jpg"
68
28
 
69
29
  LICENSE:
70
30
 
71
31
  (The MIT License)
72
32
 
73
- Copyright © 2010 - 2011 Mike Williamson
33
+ Copyright © 2011 Mike Williamson
74
34
 
75
35
 
76
36
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
data/downthetube.gemspec CHANGED
@@ -1,18 +1,18 @@
1
1
  specification = Gem::Specification.new do |spec|
2
2
  # Descriptive and source information for this gem.
3
3
  spec.name = "downthetube"
4
- spec.version = "0.0.9"
4
+ spec.version = "1.0"
5
5
  spec.description = "A library to make downloading playlists and videos from Youtube less nasty."
6
6
  spec.summary = "Downloads playlists and videos from Youtube."
7
7
  spec.author = "Mike Williamson"
8
8
  spec.email = "blessedbyvirtuosity@gmail.com"
9
- spec.homepage = ""
9
+ spec.homepage = "http://mikewilliamson.wordpress.com"
10
10
  require 'rake'
11
- spec.files = %w(README lib/downthetube.rb lib/youtube.rb lib/video.rb lib/play_list.rb downthetube.gemspec)
12
- spec.has_rdoc = false
11
+ spec.files = %w(README CHANGELOG.md Gemfile Gemfile.lock lib/downthetube.rb lib/youtube.rb lib/video.rb lib/play_list.rb downthetube.gemspec)
12
+ spec.has_rdoc = true
13
13
  spec.add_dependency("gdata_19", ">= 1.0.0")
14
14
  spec.extra_rdoc_files = ["README"]
15
15
  spec.require_path = ["lib"]
16
- #spec.test_files = ["spec"]
16
+ spec.test_files = ["spec"]
17
17
  end
18
18
 
data/lib/play_list.rb CHANGED
@@ -1,7 +1,21 @@
1
1
  module Youtube
2
- class Playlist
3
- #TODO reduce the duplication between this and the video class
2
+ ##
3
+ # Represents an individual playlist. A single Playlist object can be
4
+ # instantiated with a playlist id. The id can be found in the url
5
+ # and a few other places: gdata.youtube.com/feeds/api/playlists/<b>AAE42E282C4AD007</b>?v=2
6
+ #
7
+ # === Example
8
+ # playlist = Youtube::Playlist.new "AAE42E282C4AD007"
9
+ # playlist.title # "Mestre Jogo de Dentro & Seus Alunos"
10
+ # playlist.id # "AAE42E282C4AD007"
11
+ # playlist.author # "stephensam"
12
+ # playlist.url #"\http://gdata.youtube.com/feeds/api/playlists/AAE42E282C4AD007"
13
+ # videos = playlist.videos(3) # returns 3 videos
4
14
 
15
+ class Playlist
16
+ #--
17
+ # TODO reduce the duplication between this and the video class
18
+ #++
5
19
  #include Naming from ActiveRecord if its here.
6
20
  begin
7
21
  self.extend ActiveModel::Naming
@@ -9,54 +23,45 @@ module Youtube
9
23
  #do nothing
10
24
  end
11
25
 
12
- attr_reader :url
13
-
26
+ ##
27
+ # Instantiate individual instances of this class with a
28
+ # YouTube id.
29
+
14
30
  def initialize entry
15
31
 
16
32
  define_attrs
17
33
 
18
34
  if ((entry) && (entry.class == REXML::Element))
19
35
  @xml = entry
36
+ @id = /\w{16}/.match(@xml.elements['id'].text).to_s
20
37
  populate_attrs
21
38
 
22
39
  elsif((entry.class==String)&&(entry =~ /\w{16}/))
23
40
  @url = "http://gdata.youtube.com/feeds/api/playlists/#{entry}"
41
+ @id = entry.to_s
24
42
  else
25
43
  raise "The Playlist class did not understand the parameter it was initialized with."
26
44
  end
27
45
  end
28
46
 
29
- def populate_attrs
30
- @client ||= GData::Client::YouTube.new
31
- @xml ||= @client.get(self.url).to_xml
32
47
 
33
- @id = @xml.get_text('yt:playlistId')
34
- @title = @xml.get_text('title')
35
- @author = @xml.get_text('author/name')
36
- @xml.each_element_with_attribute('src'){|a| @url = a.attribute('src').to_s }
37
- end
38
-
39
-
40
- def define_attrs
41
- [:title, :author, :id].each do |attr|
42
- method_def = <<-EOM
43
- def #{attr}
44
- if @#{attr}
45
- @#{attr}
46
- else
47
- populate_attrs
48
- @#{attr}
49
- end
50
- end
51
- EOM
52
- Playlist.class_eval method_def
53
- end
54
- end
55
48
 
56
- def self.name
49
+ def self.name # :nodoc:
57
50
  "Playlist"
58
51
  end
52
+
53
+ ##
54
+ # Returns the gdata api url of the playlist.
55
+ # If you want the human friendly url pass in :human as an argument.
56
+ def url type = :api
57
+ type == :human ? @human_url : @url
58
+ end
59
59
 
60
+ ##
61
+ # This is the main raison d'être of the Playlist class:
62
+ # to retrieve a set of videos. If you want/need to you can
63
+ # pass a integer like 5 to limit the number of videos returned.
64
+ #
60
65
  def videos limit=nil
61
66
 
62
67
  case
@@ -77,6 +82,31 @@ module Youtube
77
82
 
78
83
  private
79
84
 
85
+ def populate_attrs # :nodoc:
86
+ @client ||= GData::Client::YouTube.new
87
+ @xml ||= @client.get(self.url).to_xml
88
+
89
+ @title = @xml.elements['title'].text
90
+ @author = @xml.elements['author/name'].text
91
+ @human_url = @xml.elements['link'].attribute('href').value
92
+ @url = @xml.elements.collect('link'){|l| l}[1].attribute('href').value
93
+ end
94
+
95
+ def define_attrs # :nodoc:
96
+ [:title, :author, :id].each do |attr|
97
+ method_def = <<-EOM
98
+ def #{attr}
99
+ if @#{attr}
100
+ @#{attr}.to_s
101
+ else
102
+ populate_attrs
103
+ @#{attr}.to_s
104
+ end
105
+ end
106
+ EOM
107
+ Playlist.class_eval method_def
108
+ end
109
+ end
80
110
  def get_videos number=nil
81
111
  @client ||= GData::Client::YouTube.new
82
112
  feed = @client.get(self.url).to_xml
@@ -85,13 +115,13 @@ module Youtube
85
115
  if number
86
116
  feed.elements.each('entry') do |entry|
87
117
  if counter <= number
88
- @videos<< Video.new(entry)
118
+ @videos<< Youtube::Video.new(entry)
89
119
  counter += 1
90
120
  end
91
121
  end
92
122
  else
93
123
  feed.elements.each('entry') do |entry|
94
- @videos<< Video.new(entry)
124
+ @videos<< Youtube::Video.new(entry)
95
125
  end
96
126
  end
97
127
  end
data/lib/video.rb CHANGED
@@ -1,6 +1,20 @@
1
+ require 'open-uri'
1
2
  module Youtube
3
+ ##
4
+ # The video class rather unsurprisingly represents an individual
5
+ # YouTube video.
6
+ #
7
+ # === Example
8
+ # video = playlist.videos.first
9
+ # video.title # "Semeando 2010 - Mestre Jogo de Dentro"
10
+ # video.duration #returns number of seconds: "93"
11
+ # video.description # "2010 o VII Encontro Internacional de Capoeira Angola... "
12
+ # video.thumbnail(:large) # "\http://i.ytimg.com/vi/4YMMWt2808U/hqdefault.jpg"
13
+ # video.id # "4YMMWt2808U"
14
+ # video.uploader # "micheldezen"
15
+ # video.url # "http://www.youtube.com/watch?v=4YMMWt2808U"
16
+
2
17
  class Video
3
- require 'gdata'
4
18
  #include Naming from ActiveRecord if its here.
5
19
  begin
6
20
  self.extend ActiveModel::Naming
@@ -8,8 +22,6 @@ module Youtube
8
22
  #do nothing
9
23
  end
10
24
 
11
- attr_reader :url
12
-
13
25
  def initialize entry
14
26
 
15
27
  define_attrs
@@ -23,27 +35,22 @@ module Youtube
23
35
  end
24
36
  end
25
37
 
26
- def define_attrs
27
- [:title, :description, :id, :uploader, :duration].each do |attr|
28
- method_def = <<-EOM
29
- def #{attr}
30
- if @#{attr}
31
- @#{attr}
32
- else
33
- populate_attrs
34
- @#{attr}
35
- end
36
- end
37
- EOM
38
- Video.class_eval method_def
39
- end
38
+ ##
39
+ # Returns the url of the video
40
+ def url
41
+ populate_attrs unless @url
42
+ @url
40
43
  end
41
44
 
42
45
 
43
- def self.name
46
+ def self.name # :nodoc:
44
47
  "Video"
45
48
  end
46
49
 
50
+ ##
51
+ # Returns the url of the thumbnail image for the video.
52
+ # If you want the large thumbnail pass :large as a parameter.
53
+
47
54
  def thumbnail size=:small
48
55
  populate_attrs unless @large_thumbnail && @small_thumbnail
49
56
  if size == :large
@@ -52,7 +59,41 @@ module Youtube
52
59
  @small_thumbnail
53
60
  end
54
61
  end
62
+
63
+ ##
64
+ # Returns that the video was instantiated with.
65
+ def to_xml
66
+ @xml.to_s
67
+ end
68
+
69
+ ##
70
+ # Returns a hash with the video attributes in it.
71
+ def to_h
72
+ populate_attrs unless @xml
73
+ h = {}
74
+ instance_variables.each do |var|
75
+ h[var.to_s.gsub('@', '').to_sym]= self.instance_variable_get(var.to_sym).to_s unless [:@client, :@xml].include? var
76
+ end
77
+ h
78
+ end
55
79
 
80
+ private
81
+
82
+ def define_attrs
83
+ [:title, :description, :id, :uploader, :duration].each do |attr|
84
+ method_def = <<-EOM
85
+ def #{attr}
86
+ if @#{attr}
87
+ @#{attr}.to_s
88
+ else
89
+ populate_attrs
90
+ @#{attr}.to_s
91
+ end
92
+ end
93
+ EOM
94
+ Video.class_eval method_def
95
+ end
96
+ end
56
97
 
57
98
  def populate_attrs
58
99
 
@@ -77,20 +118,6 @@ module Youtube
77
118
  end
78
119
  end
79
120
  end
80
-
81
- def to_xml
82
- @xml.to_s
83
- end
84
-
85
- def to_h
86
- populate_attrs unless @xml
87
- h = {}
88
- instance_variables.each do |var|
89
- h[var.gsub('@', '').to_sym]= self.instance_variable_get(var.to_sym).to_s unless %w( @client @xml ).include? var
90
- end
91
- h
92
- end
93
-
94
121
  end
95
122
  end
96
123
 
data/lib/youtube.rb CHANGED
@@ -2,17 +2,44 @@ module Youtube
2
2
  require 'rubygems'
3
3
  require 'gdata'
4
4
  require 'rexml/document'
5
+
6
+ ##
7
+ # This is the main entry point. It accepts a YouTube
8
+ # username such as <tt>stephensam</tt> and returning an array
9
+ # of playlists belonging to that user.
10
+ #
11
+ # === Example
12
+ # playlists = Youtube.playlists_for("stephensam") # returns playlists for user <tt>stephensam</tt>
13
+
14
+
5
15
  def Youtube.playlists_for user
6
- @client = GData::Client::YouTube.new
7
- feed = @client.get("http://gdata.youtube.com/feeds/api/users/#{user}/playlists?v=2").to_xml
16
+ youtube = YT.new()
17
+ feed = youtube.feed_for(user)
8
18
  playlists = []
9
19
  feed.elements.each('entry') do |entry|
10
20
  playlists<< Playlist.new(entry)
11
21
  end
12
22
  playlists
13
23
  end
14
-
15
-
16
-
17
-
24
+
25
+
26
+ class RetrievalError < StandardError
27
+ end
28
+
29
+ class YT # :nodoc: all
30
+
31
+ def feed_for user
32
+ client = get_client
33
+ begin
34
+ response = client.get("http://gdata.youtube.com/feeds/api/users/#{user}/playlists?v=2")
35
+ response.to_xml
36
+ rescue Exception => e
37
+ raise Youtube::RetrievalError.new(e.message)
38
+ end
39
+ end
40
+
41
+ def get_client
42
+ client = GData::Client::YouTube.new
43
+ end
44
+ end
18
45
  end
metadata CHANGED
@@ -1,87 +1,66 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: downthetube
3
- version: !ruby/object:Gem::Version
4
- hash: 13
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 9
10
- version: 0.0.9
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Mike Williamson
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-09-22 00:00:00 -04:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2011-11-30 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: gdata_19
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &21505680 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 23
30
- segments:
31
- - 1
32
- - 0
33
- - 0
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
34
21
  version: 1.0.0
35
22
  type: :runtime
36
- version_requirements: *id001
37
- description: A library to make downloading playlists and videos from Youtube less nasty.
23
+ prerelease: false
24
+ version_requirements: *21505680
25
+ description: A library to make downloading playlists and videos from Youtube less
26
+ nasty.
38
27
  email: blessedbyvirtuosity@gmail.com
39
28
  executables: []
40
-
41
29
  extensions: []
42
-
43
- extra_rdoc_files:
30
+ extra_rdoc_files:
44
31
  - README
45
- files:
32
+ files:
46
33
  - README
34
+ - CHANGELOG.md
35
+ - Gemfile
36
+ - Gemfile.lock
47
37
  - lib/downthetube.rb
48
38
  - lib/youtube.rb
49
39
  - lib/video.rb
50
40
  - lib/play_list.rb
51
41
  - downthetube.gemspec
52
- has_rdoc: true
53
- homepage: ""
42
+ homepage: http://mikewilliamson.wordpress.com
54
43
  licenses: []
55
-
56
44
  post_install_message:
57
45
  rdoc_options: []
58
-
59
- require_paths:
46
+ require_paths:
60
47
  - - lib
61
- required_ruby_version: !ruby/object:Gem::Requirement
48
+ required_ruby_version: !ruby/object:Gem::Requirement
62
49
  none: false
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- hash: 3
67
- segments:
68
- - 0
69
- version: "0"
70
- required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
55
  none: false
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- hash: 3
76
- segments:
77
- - 0
78
- version: "0"
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
79
60
  requirements: []
80
-
81
61
  rubyforge_project:
82
- rubygems_version: 1.5.3
62
+ rubygems_version: 1.8.10
83
63
  signing_key:
84
64
  specification_version: 3
85
65
  summary: Downloads playlists and videos from Youtube.
86
66
  test_files: []
87
-