youtuberb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env.example +4 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +49 -0
- data/LICENSE.txt +21 -0
- data/README.md +54 -0
- data/Rakefile +4 -0
- data/bin/console +21 -0
- data/bin/setup +8 -0
- data/lib/you_tube/client.rb +54 -0
- data/lib/you_tube/collection.rb +24 -0
- data/lib/you_tube/error.rb +4 -0
- data/lib/you_tube/object.rb +19 -0
- data/lib/you_tube/objects/activity.rb +4 -0
- data/lib/you_tube/objects/playlist.rb +28 -0
- data/lib/you_tube/objects/playlist_item.rb +28 -0
- data/lib/you_tube/objects/video.rb +35 -0
- data/lib/you_tube/resource.rb +57 -0
- data/lib/you_tube/resources/activities.rb +11 -0
- data/lib/you_tube/resources/playlist_items.rb +62 -0
- data/lib/you_tube/resources/playlists.rb +74 -0
- data/lib/you_tube/resources/videos.rb +41 -0
- data/lib/you_tube/version.rb +3 -0
- data/lib/you_tube.rb +26 -0
- data/lib/youtuberb.rb +1 -0
- data/youtuberb.gemspec +34 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 077f18d1405580ce9255dc91b55e8c05a752580a3e1745fa2f86c86ec2209a87
|
4
|
+
data.tar.gz: 76149a42121aeb7ae410429e83db0aa5f646b4b94cfd0bfa0298be163e217cc1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 86b29dcf4cc5b3d5a2e53a816e2f2831dd37f578afeb0bc60e5686f8a847049b2cf7b76eb3923b6d118afe33d51ec0438be6ab84cce9274e1821ac6ecfc2f043
|
7
|
+
data.tar.gz: 18fad6518cd63067765c06786627a1645d1909ee64c57d3690b586d2949aad5a84015726160654ace922f37831569845560638677da4ff220936da210bb1627a
|
data/.env.example
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
youtuberb (0.1.0)
|
5
|
+
faraday (~> 1.7)
|
6
|
+
faraday-multipart (~> 1.0)
|
7
|
+
faraday_middleware (~> 1.1)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
dotenv (2.7.6)
|
13
|
+
faraday (1.8.0)
|
14
|
+
faraday-em_http (~> 1.0)
|
15
|
+
faraday-em_synchrony (~> 1.0)
|
16
|
+
faraday-excon (~> 1.1)
|
17
|
+
faraday-httpclient (~> 1.0.1)
|
18
|
+
faraday-net_http (~> 1.0)
|
19
|
+
faraday-net_http_persistent (~> 1.1)
|
20
|
+
faraday-patron (~> 1.0)
|
21
|
+
faraday-rack (~> 1.0)
|
22
|
+
multipart-post (>= 1.2, < 3)
|
23
|
+
ruby2_keywords (>= 0.0.4)
|
24
|
+
faraday-em_http (1.0.0)
|
25
|
+
faraday-em_synchrony (1.0.0)
|
26
|
+
faraday-excon (1.1.0)
|
27
|
+
faraday-httpclient (1.0.1)
|
28
|
+
faraday-multipart (1.0.3)
|
29
|
+
multipart-post (>= 1.2, < 3)
|
30
|
+
faraday-net_http (1.0.1)
|
31
|
+
faraday-net_http_persistent (1.2.0)
|
32
|
+
faraday-patron (1.0.0)
|
33
|
+
faraday-rack (1.0.0)
|
34
|
+
faraday_middleware (1.2.0)
|
35
|
+
faraday (~> 1.0)
|
36
|
+
multipart-post (2.1.1)
|
37
|
+
rake (13.0.6)
|
38
|
+
ruby2_keywords (0.0.5)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
x86_64-linux
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
dotenv
|
45
|
+
rake (~> 13.0)
|
46
|
+
youtuberb!
|
47
|
+
|
48
|
+
BUNDLED WITH
|
49
|
+
2.3.5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Dean Perry
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# YouTubeRB
|
2
|
+
|
3
|
+
**This library is a work in progress**
|
4
|
+
|
5
|
+
YouTubeRB is a Ruby library for interacting with the YouTube Data v3 API.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'youtuberb'
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### Set Client Details
|
18
|
+
|
19
|
+
Firstly you'll need to set an API Key and an Access Token.
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
@client = YouTube::Client.new(api_key: "", access_token: "")
|
23
|
+
```
|
24
|
+
|
25
|
+
### Videos
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
@client.videos.get_by_id(user_id: 141981764)
|
29
|
+
```
|
30
|
+
|
31
|
+
### Playlists
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# Playlists created by the authenticated user
|
35
|
+
@client.playlists.list
|
36
|
+
|
37
|
+
# Playlists for a Channel
|
38
|
+
@client.playlists.list(channel_id: "channel")
|
39
|
+
|
40
|
+
# Return a set number of results & use the page_token to select the next/previous page
|
41
|
+
@client.playlists.list(max_results: 5, page_token: "page_token")
|
42
|
+
|
43
|
+
@client.playlists.retrieve(id: "playlist_id")
|
44
|
+
@client.playlists.create(title: "My Playlist")
|
45
|
+
@client.playlists.update(id: "playlist_id", title: "My Playlist", privacy_status: "public")
|
46
|
+
@client.playlists.delete(id: "playlist_id")
|
47
|
+
```
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/deanpcmad/youtuberb.
|
51
|
+
|
52
|
+
## License
|
53
|
+
|
54
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "you_tube"
|
6
|
+
|
7
|
+
# Load environment variables from .env file
|
8
|
+
require 'dotenv/load'
|
9
|
+
|
10
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
11
|
+
# with your gem easier. You can also use a different console, if you like.
|
12
|
+
|
13
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
14
|
+
# require "pry"
|
15
|
+
# Pry.start
|
16
|
+
|
17
|
+
# @client = YouTube::Client.new(client_id: ENV["CLIENT_ID"], access_token: ENV["ACCESS_TOKEN"])
|
18
|
+
@client = YouTube::Client.new(api_key: ENV["API_KEY"], access_token: ENV["ACCESS_TOKEN"])
|
19
|
+
|
20
|
+
require "irb"
|
21
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module YouTube
|
2
|
+
class Client
|
3
|
+
BASE_URL = "https://www.googleapis.com/youtube/v3/"
|
4
|
+
|
5
|
+
attr_reader :api_key, :access_token, :adapter
|
6
|
+
|
7
|
+
def initialize(api_key:, access_token:, adapter: Faraday.default_adapter, stubs: nil)
|
8
|
+
@api_key = api_key
|
9
|
+
@access_token = access_token
|
10
|
+
@adapter = adapter
|
11
|
+
|
12
|
+
# Test stubs for requests
|
13
|
+
@stubs = stubs
|
14
|
+
end
|
15
|
+
|
16
|
+
def activities
|
17
|
+
ActivitiesResource.new(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def videos
|
21
|
+
VideosResource.new(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
def playlists
|
25
|
+
PlaylistsResource.new(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def playlist_items
|
29
|
+
PlaylistItemsResource.new(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def connection
|
33
|
+
@connection ||= Faraday.new(BASE_URL) do |conn|
|
34
|
+
conn.request :authorization, :Bearer, access_token
|
35
|
+
conn.request :json
|
36
|
+
|
37
|
+
conn.response :dates
|
38
|
+
conn.response :json, content_type: "application/json"
|
39
|
+
|
40
|
+
conn.adapter adapter, @stubs
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Uses Faraday Multipart (lostisland/faraday-multipart)
|
45
|
+
def connection_upload
|
46
|
+
@connection ||= Faraday.new("https://www.googleapis.com/upload/youtube/v3/") do |conn|
|
47
|
+
conn.request :authorization, :Bearer, access_token
|
48
|
+
conn.request :multipart
|
49
|
+
conn.response :json, content_type: "application/json"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module YouTube
|
2
|
+
class Collection
|
3
|
+
attr_reader :data, :total, :next_page_token, :prev_page_token
|
4
|
+
|
5
|
+
def self.from_response(response, type:)
|
6
|
+
body = response.body
|
7
|
+
|
8
|
+
new(
|
9
|
+
data: body["items"].map { |attrs| type.new(attrs) },
|
10
|
+
total: body["pageInfo"]["totalResults"],
|
11
|
+
next_page_token: body["nextPageToken"],
|
12
|
+
prev_page_token: body["prevPageToken"],
|
13
|
+
# cursor: body.dig("pagination", "cursor")
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(data:, total:, next_page_token:, prev_page_token:)
|
18
|
+
@data = data
|
19
|
+
@total = total
|
20
|
+
@next_page_token = next_page_token
|
21
|
+
@prev_page_token = prev_page_token
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
module YouTube
|
4
|
+
class Object < OpenStruct
|
5
|
+
def initialize(attributes)
|
6
|
+
super to_ostruct(attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_ostruct(obj)
|
10
|
+
if obj.is_a?(Hash)
|
11
|
+
OpenStruct.new(obj.map { |key, val| [key, to_ostruct(val)] }.to_h)
|
12
|
+
elsif obj.is_a?(Array)
|
13
|
+
obj.map { |o| to_ostruct(o) }
|
14
|
+
else # Assumed to be a primitive value
|
15
|
+
obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module YouTube
|
2
|
+
class Playlist < Object
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
super options
|
6
|
+
|
7
|
+
if options["snippet"]
|
8
|
+
self.title = options["snippet"]["title"]
|
9
|
+
self.description = options["snippet"]["description"]
|
10
|
+
self.published_at = options["snippet"]["publishedAt"]
|
11
|
+
|
12
|
+
if options["snippet"]["thumbnails"]
|
13
|
+
thumb = options["snippet"]["thumbnails"]
|
14
|
+
self.thumbnail_default = thumb["default"]["url"] if thumb["default"]
|
15
|
+
self.thumbnail_medium = thumb["medium"]["url"] if thumb["medium"]
|
16
|
+
self.thumbnail_high = thumb["high"]["url"] if thumb["high"]
|
17
|
+
self.thumbnail_standard = thumb["standard"]["url"] if thumb["standard"]
|
18
|
+
self.thumbnail_maxres = thumb["maxres"]["url"] if thumb["maxres"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if options["status"]
|
23
|
+
self.privacy_status = options["status"]["privacyStatus"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module YouTube
|
2
|
+
class PlaylistItem < Object
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
super options
|
6
|
+
|
7
|
+
if options["snippet"]
|
8
|
+
self.title = options["snippet"]["title"]
|
9
|
+
self.description = options["snippet"]["description"]
|
10
|
+
self.published_at = options["snippet"]["publishedAt"]
|
11
|
+
|
12
|
+
if options["snippet"]["thumbnails"]
|
13
|
+
thumb = options["snippet"]["thumbnails"]
|
14
|
+
self.thumbnail_default = thumb["default"]["url"] if thumb["default"]
|
15
|
+
self.thumbnail_medium = thumb["medium"]["url"] if thumb["medium"]
|
16
|
+
self.thumbnail_high = thumb["high"]["url"] if thumb["high"]
|
17
|
+
self.thumbnail_standard = thumb["standard"]["url"] if thumb["standard"]
|
18
|
+
self.thumbnail_maxres = thumb["maxres"]["url"] if thumb["maxres"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if options["status"]
|
23
|
+
self.privacy_status = options["status"]["privacyStatus"]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module YouTube
|
2
|
+
class Video < Object
|
3
|
+
|
4
|
+
def initialize(options = {})
|
5
|
+
super options
|
6
|
+
|
7
|
+
if options["snippet"]
|
8
|
+
self.title = options["snippet"]["title"]
|
9
|
+
self.description = options["snippet"]["description"]
|
10
|
+
self.published_at = options["snippet"]["publishedAt"]
|
11
|
+
self.channel_id = options["snippet"]["channelId"]
|
12
|
+
|
13
|
+
if options["snippet"]["thumbnails"]
|
14
|
+
thumb = options["snippet"]["thumbnails"]
|
15
|
+
self.thumbnail_default = thumb["default"]["url"] if thumb["default"]
|
16
|
+
self.thumbnail_medium = thumb["medium"]["url"] if thumb["medium"]
|
17
|
+
self.thumbnail_high = thumb["high"]["url"] if thumb["high"]
|
18
|
+
self.thumbnail_standard = thumb["standard"]["url"] if thumb["standard"]
|
19
|
+
self.thumbnail_maxres = thumb["maxres"]["url"] if thumb["maxres"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Is a Video is blocked in any countries?
|
24
|
+
if options["contentDetails"]
|
25
|
+
self.blocked = !options["contentDetails"]["regionRestriction"].nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
if options["status"]
|
29
|
+
self.upload_status = options["status"]["uploadStatus"]
|
30
|
+
self.privacy_status = options["status"]["privacyStatus"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module YouTube
|
2
|
+
class Resource
|
3
|
+
attr_reader :client
|
4
|
+
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def get_request(url, params: {}, headers: {})
|
12
|
+
handle_response client.connection.get("#{url}?key=#{client.api_key}", params, headers)
|
13
|
+
end
|
14
|
+
|
15
|
+
def post_request(url, body:, headers: {})
|
16
|
+
handle_response client.connection.post(url, body, headers)
|
17
|
+
end
|
18
|
+
|
19
|
+
def patch_request(url, body:, headers: {})
|
20
|
+
handle_response client.connection.patch(url, body, headers)
|
21
|
+
end
|
22
|
+
|
23
|
+
def put_request(url, body:, headers: {})
|
24
|
+
handle_response client.connection.put(url, body, headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_request(url, params: {}, headers: {})
|
28
|
+
handle_response client.connection.delete(url, params, headers)
|
29
|
+
end
|
30
|
+
|
31
|
+
def handle_response(response)
|
32
|
+
case response.status
|
33
|
+
when 400
|
34
|
+
raise Error, "Error 400: Your request was malformed. '#{response.body["error"]}'"
|
35
|
+
when 401
|
36
|
+
raise Error, "Error 401: You did not supply valid authentication credentials. '#{response.body["error"]["message"]}'"
|
37
|
+
when 403
|
38
|
+
raise Error, "Error 403: You are not allowed to perform that action. '#{response.body["error"]["message"]}'"
|
39
|
+
when 404
|
40
|
+
raise Error, "Error 404: No results were found for your request. '#{response.body["error"]["message"]}'"
|
41
|
+
when 409
|
42
|
+
raise Error, "Error 409: Your request was a conflict. '#{response.body["error"]["message"]}'"
|
43
|
+
when 429
|
44
|
+
raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["error"]["message"]}'"
|
45
|
+
when 500
|
46
|
+
raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["error"]["message"]}'"
|
47
|
+
when 503
|
48
|
+
raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["error"]["message"]}'"
|
49
|
+
when 204
|
50
|
+
# 204 is a response for success on Twitch's API
|
51
|
+
return true
|
52
|
+
end
|
53
|
+
|
54
|
+
response
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module YouTube
|
2
|
+
class ActivitiesResource < Resource
|
3
|
+
|
4
|
+
def list
|
5
|
+
response = get_request "activities", params: {home: true}
|
6
|
+
# response = post_request("games", body: "fields id,name,status,url,created_at,updated_at;")
|
7
|
+
# Collection.from_response(response, type: Game)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module YouTube
|
2
|
+
class PlaylistItemsResource < Resource
|
3
|
+
|
4
|
+
PARTS = "id,snippet,status"
|
5
|
+
|
6
|
+
# Returns Playlist Items for a Playlist
|
7
|
+
# https://developers.google.com/youtube/v3/docs/playlistItems/list
|
8
|
+
def list(playlist_id:)
|
9
|
+
response = get_request "playlistItems", params: {playlistId: playlist_id, part: PARTS}
|
10
|
+
Collection.from_response(response, type: PlaylistItem)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns a Playlist Item for a given ID
|
14
|
+
# https://developers.google.com/youtube/v3/docs/playlistItems/list
|
15
|
+
def retrieve(id:)
|
16
|
+
response = get_request "playlistItems", params: {id: id, part: PARTS}
|
17
|
+
PlaylistItem.new(response.body["items"][0])
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates a Playlist Item
|
21
|
+
# https://developers.google.com/youtube/v3/docs/playlistItems/insert
|
22
|
+
def create(playlist_id:, video_id:, **attributes)
|
23
|
+
attrs = {}
|
24
|
+
attrs[:snippet] = {}
|
25
|
+
attrs[:status] = {}
|
26
|
+
|
27
|
+
attrs[:snippet][:playlistId] = playlist_id
|
28
|
+
attrs[:snippet][:resourceId] = {kind: "youtube#video", videoId: video_id}
|
29
|
+
|
30
|
+
attrs[:snippet][:position] = attributes[:position]
|
31
|
+
|
32
|
+
response = post_request("playlistItems?part=id,snippet,status", body: attrs)
|
33
|
+
|
34
|
+
PlaylistItem.new(response.body) if response.success?
|
35
|
+
end
|
36
|
+
|
37
|
+
# Updates a Playlist Item. ID, Playlist ID and Video ID are required.
|
38
|
+
# https://developers.google.com/youtube/v3/docs/playlistItems/update
|
39
|
+
def update(id:, playlist_id:, video_id:, **attributes)
|
40
|
+
attrs = {}
|
41
|
+
attrs[:id] = id
|
42
|
+
attrs[:snippet] = {}
|
43
|
+
attrs[:status] = {}
|
44
|
+
|
45
|
+
attrs[:snippet][:playlistId] = playlist_id
|
46
|
+
attrs[:snippet][:resourceId] = {kind: "youtube#video", videoId: video_id}
|
47
|
+
|
48
|
+
attrs[:snippet][:position] = attributes[:position]
|
49
|
+
|
50
|
+
response = put_request("playlistItems?part=id,snippet,status", body: attrs)
|
51
|
+
|
52
|
+
PlaylistItem.new(response.body) if response.success?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Deletes a Playlist Item
|
56
|
+
# https://developers.google.com/youtube/v3/docs/playlistItems/delete
|
57
|
+
def delete(id:)
|
58
|
+
delete_request("playlistItems?id=#{id}")
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module YouTube
|
2
|
+
class PlaylistsResource < Resource
|
3
|
+
|
4
|
+
PARTS = "id,snippet,status"
|
5
|
+
|
6
|
+
# Returns Playlists either for a Channel or owned by the authenticated user
|
7
|
+
# https://developers.google.com/youtube/v3/docs/playlists/list
|
8
|
+
def list(channel_id: nil, page_token: nil, max_results: nil)
|
9
|
+
attrs = {}
|
10
|
+
if channel_id
|
11
|
+
attrs[:channelId] = channel_id
|
12
|
+
else
|
13
|
+
attrs[:mine] = true
|
14
|
+
end
|
15
|
+
attrs[:maxResults] = max_results if max_results
|
16
|
+
attrs[:pageToken] = page_token if page_token
|
17
|
+
|
18
|
+
response = get_request "playlists", params: attrs.merge({part: PARTS})
|
19
|
+
Collection.from_response(response, type: Playlist)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a Playlist for a given ID
|
23
|
+
def retrieve(id:)
|
24
|
+
response = get_request "playlists", params: {id: id, part: PARTS}
|
25
|
+
Playlist.new(response.body["items"][0])
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a Playlist
|
29
|
+
# https://developers.google.com/youtube/v3/docs/playlists/insert
|
30
|
+
def create(title:, **attributes)
|
31
|
+
attrs = {}
|
32
|
+
attrs[:snippet] = {}
|
33
|
+
attrs[:status] = {}
|
34
|
+
|
35
|
+
attrs[:snippet][:title] = title
|
36
|
+
|
37
|
+
attrs[:snippet][:description] = attributes[:description]
|
38
|
+
attrs[:snippet][:defaultLanguage] = attributes[:default_language]
|
39
|
+
|
40
|
+
attrs[:status][:privacyStatus] = attributes[:privacy_status]
|
41
|
+
|
42
|
+
response = post_request("playlists?part=id,snippet,status", body: attrs)
|
43
|
+
|
44
|
+
Playlist.new(response.body) if response.success?
|
45
|
+
end
|
46
|
+
|
47
|
+
# Updates a Playlist. ID and Title are required.
|
48
|
+
# https://developers.google.com/youtube/v3/docs/playlists/update
|
49
|
+
def update(id:, title:, **attributes)
|
50
|
+
attrs = {}
|
51
|
+
attrs[:id] = id
|
52
|
+
attrs[:snippet] = {}
|
53
|
+
attrs[:status] = {}
|
54
|
+
|
55
|
+
attrs[:snippet][:title] = title
|
56
|
+
|
57
|
+
attrs[:snippet][:description] = attributes[:description]
|
58
|
+
attrs[:snippet][:defaultLanguage] = attributes[:default_language]
|
59
|
+
|
60
|
+
attrs[:status][:privacyStatus] = attributes[:privacy_status]
|
61
|
+
|
62
|
+
response = put_request("playlists?part=id,snippet,status", body: attrs)
|
63
|
+
|
64
|
+
Playlist.new(response.body) if response.success?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Deletes a Playlist
|
68
|
+
# https://developers.google.com/youtube/v3/docs/playlists/delete
|
69
|
+
def delete(id:)
|
70
|
+
delete_request("playlists?id=#{id}")
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module YouTube
|
2
|
+
class VideosResource < Resource
|
3
|
+
|
4
|
+
PARTS = "id,contentDetails,snippet,statistics,status"
|
5
|
+
AUTH_PARTS = "id,contentDetails,fileDetails,processingDetails,snippet,statistics,status,suggestions"
|
6
|
+
|
7
|
+
# Retrieves Videos by ID. Can be comma separated to retrieve multiple.
|
8
|
+
def list(id:)
|
9
|
+
response = get_request "videos", params: {id: id, part: PARTS}
|
10
|
+
Collection.from_response(response, type: Video)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Retrieves liked Videos for the currently authenticated user
|
14
|
+
def liked
|
15
|
+
response = get_request "videos", params: {myRating: "like", part: PARTS}
|
16
|
+
Collection.from_response(response, type: Video)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Retrieves a Video by the ID. This retrieves extra information so will only work
|
20
|
+
# on videos for an authenticated user
|
21
|
+
def retrieve(id:)
|
22
|
+
response = get_request "videos", params: {id: id, part: AUTH_PARTS}
|
23
|
+
return nil if response.body["pageInfo"]["totalResults"] == 0
|
24
|
+
Video.new(response.body["items"][0])
|
25
|
+
end
|
26
|
+
|
27
|
+
# Uploads a video
|
28
|
+
# Currently just uploads a video
|
29
|
+
# Needs more testing
|
30
|
+
# https://developers.google.com/youtube/v3/docs/videos/insert
|
31
|
+
def upload(file:)
|
32
|
+
payload = {}
|
33
|
+
payload[:media] = Faraday::Multipart::FilePart.new(file, "video/*")
|
34
|
+
|
35
|
+
response = client.connection_upload.post "videos", payload
|
36
|
+
|
37
|
+
response.body
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/you_tube.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "faraday_middleware"
|
3
|
+
require "faraday/multipart"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
require_relative "you_tube/version"
|
7
|
+
|
8
|
+
module YouTube
|
9
|
+
|
10
|
+
autoload :Client, "you_tube/client"
|
11
|
+
autoload :Collection, "you_tube/collection"
|
12
|
+
autoload :Error, "you_tube/error"
|
13
|
+
autoload :Resource, "you_tube/resource"
|
14
|
+
autoload :Object, "you_tube/object"
|
15
|
+
|
16
|
+
autoload :ActivitiesResource, "you_tube/resources/activities"
|
17
|
+
autoload :VideosResource, "you_tube/resources/videos"
|
18
|
+
autoload :PlaylistsResource, "you_tube/resources/playlists"
|
19
|
+
autoload :PlaylistItemsResource, "you_tube/resources/playlist_items"
|
20
|
+
|
21
|
+
autoload :Activity, "you_tube/objects/activity"
|
22
|
+
autoload :Video, "you_tube/objects/video"
|
23
|
+
autoload :Playlist, "you_tube/objects/playlist"
|
24
|
+
autoload :PlaylistItem, "you_tube/objects/playlist_item"
|
25
|
+
|
26
|
+
end
|
data/lib/youtuberb.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "you_tube"
|
data/youtuberb.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/you_tube/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "youtuberb"
|
7
|
+
spec.version = YouTube::VERSION
|
8
|
+
spec.authors = ["Dean Perry"]
|
9
|
+
spec.email = ["dean@deanpcmad.com"]
|
10
|
+
|
11
|
+
spec.summary = "A Ruby library for interacting with the YouTube API"
|
12
|
+
spec.homepage = "https://deanpcmad.com"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
18
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
24
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_dependency "faraday", "~> 1.7"
|
32
|
+
spec.add_dependency "faraday_middleware", "~> 1.1"
|
33
|
+
spec.add_dependency "faraday-multipart", "~> 1.0"
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: youtuberb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dean Perry
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday_middleware
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday-multipart
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- dean@deanpcmad.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".env.example"
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- bin/console
|
69
|
+
- bin/setup
|
70
|
+
- lib/you_tube.rb
|
71
|
+
- lib/you_tube/client.rb
|
72
|
+
- lib/you_tube/collection.rb
|
73
|
+
- lib/you_tube/error.rb
|
74
|
+
- lib/you_tube/object.rb
|
75
|
+
- lib/you_tube/objects/activity.rb
|
76
|
+
- lib/you_tube/objects/playlist.rb
|
77
|
+
- lib/you_tube/objects/playlist_item.rb
|
78
|
+
- lib/you_tube/objects/video.rb
|
79
|
+
- lib/you_tube/resource.rb
|
80
|
+
- lib/you_tube/resources/activities.rb
|
81
|
+
- lib/you_tube/resources/playlist_items.rb
|
82
|
+
- lib/you_tube/resources/playlists.rb
|
83
|
+
- lib/you_tube/resources/videos.rb
|
84
|
+
- lib/you_tube/version.rb
|
85
|
+
- lib/youtuberb.rb
|
86
|
+
- youtuberb.gemspec
|
87
|
+
homepage: https://deanpcmad.com
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata:
|
91
|
+
homepage_uri: https://deanpcmad.com
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 2.6.0
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubygems_version: 3.1.6
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A Ruby library for interacting with the YouTube API
|
111
|
+
test_files: []
|