Class: YouTube::ApiClient
- Inherits:
-
Object
- Object
- YouTube::ApiClient
- Defined in:
- app/services/youtube/api_client.rb
Overview
HTTP client for YouTube Data API v3.
Features:
- Auto-refreshes expired access tokens
- Retries on transient failures (500, 502, 503)
- Wraps the Google API client gem for a simpler interface
Defined Under Namespace
Classes: ApiError, NotFoundError, QuotaExceededError
Constant Summary collapse
- MAX_RETRIES =
3
Instance Method Summary collapse
- #delete_caption(caption_id) ⇒ Object
- #get_video(video_id, parts: 'snippet,contentDetails,status,statistics') ⇒ Object
- #get_videos(video_ids, parts: 'snippet,contentDetails,status,statistics') ⇒ Object
-
#initialize(account: nil, oauth_service: nil) ⇒ ApiClient
constructor
A new instance of ApiClient.
- #insert_caption(video_id, language:, name:, file_path:, content_type: 'text/vtt') ⇒ Object
- #insert_video(metadata, file_path, content_type: 'video/mp4') ⇒ Object
-
#list_captions(video_id) ⇒ Object
--- Captions ---.
-
#list_channel_videos(channel_id:, max_results: 50, page_token: nil) ⇒ Object
--- Videos ---.
-
#my_channel ⇒ Object
--- Channel ---.
-
#set_thumbnail(video_id, file_path, content_type: 'image/jpeg') ⇒ Object
--- Thumbnails ---.
- #update_caption(caption_id, file_path:, content_type: 'text/vtt') ⇒ Object
- #update_video(video_id, snippet_attrs: {}, status_attrs: {}) ⇒ Object
Constructor Details
#initialize(account: nil, oauth_service: nil) ⇒ ApiClient
Returns a new instance of ApiClient.
31 32 33 |
# File 'app/services/youtube/api_client.rb', line 31 def initialize(account: nil, oauth_service: nil) @oauth_service = oauth_service || YouTube::OauthService.new(account: account) end |
Instance Method Details
#delete_caption(caption_id) ⇒ Object
157 158 159 |
# File 'app/services/youtube/api_client.rb', line 157 def delete_caption(caption_id) with_service { |yt| yt.delete_caption(caption_id) } end |
#get_video(video_id, parts: 'snippet,contentDetails,status,statistics') ⇒ Object
57 58 59 60 61 62 |
# File 'app/services/youtube/api_client.rb', line 57 def get_video(video_id, parts: 'snippet,contentDetails,status,statistics') with_service do |yt| response = yt.list_videos(parts, id: video_id) response.items&.first end end |
#get_videos(video_ids, parts: 'snippet,contentDetails,status,statistics') ⇒ Object
64 65 66 67 68 69 70 71 |
# File 'app/services/youtube/api_client.rb', line 64 def get_videos(video_ids, parts: 'snippet,contentDetails,status,statistics') return [] if video_ids.blank? with_service do |yt| response = yt.list_videos(parts, id: video_ids.join(',')) response.items || [] end end |
#insert_caption(video_id, language:, name:, file_path:, content_type: 'text/vtt') ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'app/services/youtube/api_client.rb', line 130 def insert_caption(video_id, language:, name:, file_path:, content_type: 'text/vtt') caption = Google::Apis::YoutubeV3::Caption.new( snippet: Google::Apis::YoutubeV3::CaptionSnippet.new( video_id: video_id, language: language, name: name, is_draft: false ) ) with_service do |yt| yt.insert_caption('snippet', caption, upload_source: file_path, content_type: content_type) end end |
#insert_video(metadata, file_path, content_type: 'video/mp4') ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'app/services/youtube/api_client.rb', line 73 def insert_video(, file_path, content_type: 'video/mp4') video = Google::Apis::YoutubeV3::Video.new( snippet: Google::Apis::YoutubeV3::VideoSnippet.new( title: [:title], description: [:description], tags: [:tags], category_id: [:category_id] || '22', default_language: [:default_language] || 'en' ), status: Google::Apis::YoutubeV3::VideoStatus.new( privacy_status: [:privacy_status] || 'private', self_declared_made_for_kids: false ) ) with_service do |yt| yt.insert_video('snippet,status', video, upload_source: file_path, content_type: content_type) end end |
#list_captions(video_id) ⇒ Object
--- Captions ---
123 124 125 126 127 128 |
# File 'app/services/youtube/api_client.rb', line 123 def list_captions(video_id) with_service do |yt| response = yt.list_captions('snippet', video_id) response.items || [] end end |
#list_channel_videos(channel_id:, max_results: 50, page_token: nil) ⇒ Object
--- Videos ---
46 47 48 49 50 51 52 53 54 55 |
# File 'app/services/youtube/api_client.rb', line 46 def list_channel_videos(channel_id:, max_results: 50, page_token: nil) with_service do |yt| yt.list_searches('snippet', channel_id: channel_id, type: 'video', max_results: [max_results, 50].min, order: 'date', page_token: page_token) end end |
#my_channel ⇒ Object
--- Channel ---
37 38 39 40 41 42 |
# File 'app/services/youtube/api_client.rb', line 37 def my_channel with_service do |yt| response = yt.list_channels('snippet,contentDetails,statistics', mine: true) response.items&.first end end |
#set_thumbnail(video_id, file_path, content_type: 'image/jpeg') ⇒ Object
--- Thumbnails ---
163 164 165 166 167 168 169 |
# File 'app/services/youtube/api_client.rb', line 163 def set_thumbnail(video_id, file_path, content_type: 'image/jpeg') with_service do |yt| yt.set_thumbnail(video_id, upload_source: file_path, content_type: content_type) end end |
#update_caption(caption_id, file_path:, content_type: 'text/vtt') ⇒ Object
147 148 149 150 151 152 153 154 155 |
# File 'app/services/youtube/api_client.rb', line 147 def update_caption(caption_id, file_path:, content_type: 'text/vtt') caption = Google::Apis::YoutubeV3::Caption.new(id: caption_id) with_service do |yt| yt.update_caption('snippet', caption, upload_source: file_path, content_type: content_type) end end |
#update_video(video_id, snippet_attrs: {}, status_attrs: {}) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/services/youtube/api_client.rb', line 95 def update_video(video_id, snippet_attrs: {}, status_attrs: {}) with_service do |yt| fetch_parts = [] fetch_parts << 'snippet' if snippet_attrs.present? fetch_parts << 'status' if status_attrs.present? raise ArgumentError, 'snippet_attrs or status_attrs required' if fetch_parts.empty? # Fetch only the parts we will write back. If we load snippet+status but call # update with part=snippet, the client serializes both into the JSON body and # YouTube returns: unexpectedPart: 'status' (body must not include parts omitted # from the request's `part` parameter). existing = yt.list_videos(fetch_parts.join(','), id: video_id).items&.first raise NotFoundError.new("Video #{video_id} not found on YouTube", status: 404) unless existing if snippet_attrs.present? snippet_attrs.each { |k, v| existing.snippet.send(:"#{k}=", v) if existing.snippet.respond_to?(:"#{k}=") } end if status_attrs.present? status_attrs.each { |k, v| existing.status.send(:"#{k}=", v) if existing.status.respond_to?(:"#{k}=") } end yt.update_video(fetch_parts.join(','), existing) end end |