yt_data_api 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yt_data_api.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,6 @@
1
+ #Yt_Data_Api
2
+
3
+ Yt_Data_Api adds functionality to access YouTube Data API.
4
+
5
+ # TODO
6
+ Add more descriptions...
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,3 @@
1
+ module YtDataApi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,205 @@
1
+ require "yt_data_api/version"
2
+ require 'net/https'
3
+ require 'open-uri'
4
+ require 'rss'
5
+ require 'xml'
6
+
7
+ module YtDataApi
8
+ class YtDataApiClient
9
+ def initialize(user_id, user_pswd, dev_key)
10
+ self.client_login(user_id, user_pswd, dev_key)
11
+ end
12
+
13
+ def client_login(user_id, user_pswd, dev_key)
14
+ http = Net::HTTP.new("www.google.com", 443)
15
+ http.use_ssl = true
16
+ path = "/accounts/ClientLogin"
17
+
18
+ data = "Email=#{user_id}&Passwd=#{user_pswd}&service=youtube&source=Test"
19
+ headers = {"Content-Type" => "application/x-www-form-urlencoded"}
20
+
21
+ response, data = http.post(path, data, headers)
22
+
23
+ if(response.code != "200")
24
+ raise "Error while authenticating YouTube user - #{response.code}"
25
+ end
26
+
27
+ @client_user_id = user_id
28
+ @client_auth_key = data[/Auth=(.*)/, 1]
29
+ @dev_auth_key = "key=" + dev_key
30
+ end
31
+
32
+ def get_video_id(search_query)
33
+ query_uri = URI.parse("http://gdata.youtube.com/feeds/api/videos?q=#{search_query}&max-results=1")
34
+ rss_query_result = parse_rss(query_uri)
35
+
36
+ rss_query_result.items.each do |item|
37
+ return item.id.to_s[/<id>http:\/\/(.*\/)(.*)<\/id>/, 2]
38
+ end
39
+
40
+ return nil
41
+ end
42
+
43
+ def get_client_playlist_id(playlist_name)
44
+ headers = {"Content-Type" => "application/x-www-form-urlencoded",
45
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
46
+ "X-GData-Key" => @dev_auth_key}
47
+
48
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/users/default/playlists?v=2")
49
+
50
+ xml_client_playlists = Net::HTTP.start(uri.host, uri.port){|http|
51
+ http.get(uri.path, headers)
52
+ }
53
+
54
+ #Parse xml of client's playlists
55
+ source = XML::Parser.string(xml_client_playlists.body)
56
+ content = source.parse
57
+ content.root.namespaces.default_prefix = 'atom'
58
+
59
+ entries = content.root.find('atom:entry')
60
+
61
+ #Get playlist id
62
+ entries.each do |entry|
63
+ if(entry.find_first('atom:title').content.eql?(playlist_name))
64
+ feedlink = entry.find_first('gd:feedLink').attributes["href"]
65
+ return feedlink[/http:\/\/gdata.youtube.com\/feeds\/api\/playlists\/(.+)/, 1]
66
+ end
67
+ end
68
+
69
+ return nil
70
+ end
71
+
72
+ def get_client_playlist_entries(playlist_id)
73
+ headers = {"Content-Type" => "application/x-www-form-urlencoded",
74
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
75
+ "X-GData-Key" => @dev_auth_key}
76
+
77
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/playlists/#{playlist_id}?v=2")
78
+
79
+ xml_client_playlist_videos = Net::HTTP.start(uri.host, uri.port){|http|
80
+ http.get(uri.path, headers)
81
+ }
82
+
83
+ source = XML::Parser.string(xml_client_playlist_videos.body)
84
+ content = source.parse
85
+ content.root.namespaces.default_prefix = 'atom'
86
+
87
+ entries = content.root.find('atom:entry')
88
+
89
+ playlist_entries = []
90
+
91
+ entries.each do |entry|
92
+ entry_id = entry.find_first('atom:id')
93
+ playlist_entry =
94
+ entry_id.content[/http:\/\/.*\/(.+)/, 1]
95
+ playlist_entries << playlist_entry
96
+ end
97
+
98
+ playlist_entries
99
+
100
+ end
101
+
102
+ def add_video_to_playlist(video_id, playlist_id)
103
+ headers = {"Content-Type" => "application/atom+xml",
104
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
105
+ "X-GData-Key" => @dev_auth_key,
106
+ "GData-Version" => "2"}
107
+
108
+ new_row = "<?xml version='1.0' encoding='UTF-8'?>" +
109
+ "<entry xmlns='http://www.w3.org/2005/Atom' " +
110
+ "xmlns:yt='http://gdata.youtube.com/schemas/2007'>" +
111
+ "<id>#{video_id}</id></entry>"
112
+
113
+ headers["Content-Length"] = new_row.bytesize.to_s
114
+
115
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/playlists/#{playlist_id}")
116
+ http = Net::HTTP.new(uri.host, uri.port)
117
+
118
+ post_response = http.post(uri.path, new_row, headers)
119
+
120
+ if(post_response.code != "201")
121
+ raise "Error while adding #{video_id} to #{playlist_id} - #{post_response.code}"
122
+ end
123
+
124
+ post_response.code
125
+ end
126
+
127
+ def create_playlist(playlist_name)
128
+ headers = {"Content-Type" => "application/atom+xml",
129
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
130
+ "X-GData-Key" => @dev_auth_key,
131
+ "GData-Version" => "2"}
132
+
133
+ new_row = "<?xml version='1.0' encoding='UTF-8'?>" +
134
+ "<entry xmlns='http://www.w3.org/2005/Atom' " +
135
+ "xmlns:yt='http://gdata.youtube.com/schemas/2007'>" +
136
+ "<title type='text'>#{playlist_name}</title><summary></summary></entry>"
137
+
138
+ headers["Content-Length"] = new_row.bytesize.to_s
139
+
140
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/users/default/playlists")
141
+ http = Net::HTTP.new(uri.host, uri.port)
142
+
143
+ post_response = http.post(uri.path, new_row, headers)
144
+
145
+ if(post_response.code != "201")
146
+ raise "Error while creating #{playlist_name} - #{post_response.code}"
147
+ end
148
+
149
+ post_response.code
150
+ end
151
+
152
+ def empty_playlist(playlist_id)
153
+ headers = {"Content-Type" => "application/atom+xml",
154
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
155
+ "X-GData-Key" => @dev_auth_key,
156
+ "GData-Version" => "2"}
157
+
158
+ playlist_entries = self.get_client_playlist_entries(playlist_id)
159
+
160
+ playlist_entries.each do |playlist_entry|
161
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/playlists/#{playlist_id}/#{playlist_entry}")
162
+ http = Net::HTTP.new(uri.host, uri.port)
163
+
164
+ delete_response = http.delete(uri.path, headers)
165
+
166
+ if(delete_response.code != "200")
167
+ raise "#{playlist_entry} not deleted from #{@playlist_id} - #{delete_response.code}"
168
+ end
169
+ end
170
+
171
+ self.get_client_playlist_entries(playlist_id).empty?
172
+ end
173
+
174
+ def delete_playlist(playlist_id)
175
+ headers = {"Content-Type" => "application/atom+xml",
176
+ "Authorization" => "GoogleLogin auth=#{@client_auth_key}",
177
+ "X-GData-Key" => @dev_auth_key,
178
+ "GData-Version" => "2"}
179
+
180
+ uri = URI.parse("http://gdata.youtube.com/feeds/api/users/#{@client_user_id}/playlists/#{playlist_id}")
181
+ http = Net::HTTP.new(uri.host, uri.port)
182
+
183
+ delete_response = http.delete(uri.path, headers)
184
+
185
+ if(delete_response.code != "200")
186
+ raise "#{playlist_id} not deleted for #{@client_user_id} - #{delete_response.code}"
187
+ end
188
+
189
+ delete_response.code
190
+ end
191
+
192
+ private
193
+ #Use Ruby RSS Parser to return parseable info from RSS feed
194
+ def parse_rss(rss_feed)
195
+ rss_content = ""
196
+
197
+ #Get feed information
198
+ open (rss_feed) do |f|
199
+ rss_content = f.read
200
+ end
201
+
202
+ RSS::Parser.parse(rss_content, false)
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,3 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'rspec'
3
+ require 'yt_data_api'
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe "YtDataApi::YtDataApiClient" do
4
+ it "should create a new instance using ClientLogin authentication" do
5
+ YtDataApi::YtDataApiClient.new(ENV['YT_USER'], ENV['YT_USER_PSWD'], ENV['YT_DEV_AUTH_KEY'])
6
+ end
7
+
8
+ it "should not create a new instance without credentials for ClientLogin Authentication" do
9
+ lambda{ YtDataApi::YtDataApiClient.new }.should raise_error ArgumentError
10
+ end
11
+
12
+ it "should not create a new instance without valid credentials for ClientLogin Authentication" do
13
+ lambda{ YtDataApi::YtDataApiClient.new("trash", "trash", "trash") }.should raise_error
14
+ end
15
+
16
+ describe "authenticated" do
17
+ before(:each) do
18
+ @client = YtDataApi::YtDataApiClient.new(ENV['YT_USER'], ENV['YT_USER_PSWD'], ENV['YT_DEV_AUTH_KEY'])
19
+ @create_response = @client.create_playlist("test_one")
20
+ @playlist_id = @client.get_client_playlist_id("test_one")
21
+ end
22
+
23
+ it "should create a client's playlist" do
24
+ @create_response.should == "201"
25
+ end
26
+
27
+ it "should get a client's playlist id given the playlist's name" do
28
+ @playlist_id.should_not be nil
29
+ end
30
+
31
+ it "should get a video id given a query string" do
32
+ query = "vampire-weekend-giving-up-the-gun"
33
+ video_id = @client.get_video_id(query)
34
+ video_id.should == "bccKotFwzoY"
35
+ end
36
+
37
+ it "should add a video to a client's playlist" do
38
+ video_id = "bccKotFwzoY"
39
+ post_response = @client.add_video_to_playlist(video_id, @playlist_id)
40
+ post_response.should == "201"
41
+ end
42
+
43
+ it "should remove all videos from a client's playlist" do
44
+ 3.times do
45
+ @client.add_video_to_playlist("bccKotFwzoY", @playlist_id)
46
+ end
47
+
48
+ empty_playlist = @client.empty_playlist(@playlist_id)
49
+ empty_playlist.should == true
50
+ end
51
+
52
+ it "should delete a client's playlist" do
53
+ delete_response = @client.delete_playlist(@playlist_id)
54
+ delete_response.should == "200"
55
+ end
56
+
57
+ after(:each) do
58
+ playlist = @client.get_client_playlist_id("test_one")
59
+ @client.delete_playlist(@playlist_id) unless playlist.nil?
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "yt_data_api/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "yt_data_api"
7
+ s.version = YtDataApi::VERSION
8
+ s.authors = ["Ali Ibrahim"]
9
+ s.email = ["aibrahim2k2@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Adds functionality to access YouTube Data API}
12
+ s.description = %q{Create a new instance of YtDataApi::YtDataApiClient passing
13
+ user credentials (username, password) and YouTube developer key
14
+ to access YouTube Data API using ClientLogin authentication.}
15
+
16
+ s.rubyforge_project = "yt_data_api"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.add_dependency 'libxml-ruby', '~>1.1.3'
24
+
25
+ s.add_development_dependency 'rspec', '~>2.4.0'
26
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yt_data_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ali Ibrahim
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-08-24 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: libxml-ruby
16
+ requirement: &70195100472000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.3
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70195100472000
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70195100474040 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.4.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70195100474040
36
+ description: ! "Create a new instance of YtDataApi::YtDataApiClient passing \n user
37
+ credentials (username, password) and YouTube developer key\n to
38
+ access YouTube Data API using ClientLogin authentication."
39
+ email:
40
+ - aibrahim2k2@gmail.com
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - README.markdown
48
+ - Rakefile
49
+ - lib/yt_data_api.rb
50
+ - lib/yt_data_api/version.rb
51
+ - spec/spec_helper.rb
52
+ - spec/yt_data_api_spec.rb
53
+ - yt_data_api.gemspec
54
+ homepage: ''
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ requirements: []
73
+ rubyforge_project: yt_data_api
74
+ rubygems_version: 1.8.6
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: Adds functionality to access YouTube Data API
78
+ test_files:
79
+ - spec/spec_helper.rb
80
+ - spec/yt_data_api_spec.rb