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 =
Maximum 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.
36 37 38 |
# File 'app/services/youtube/api_client.rb', line 36 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
163 164 165 |
# File 'app/services/youtube/api_client.rb', line 163 def delete_caption(caption_id) with_service { |yt| yt.delete_caption(caption_id) } end |
#get_video(video_id, parts: 'snippet,contentDetails,status,statistics') ⇒ Object
62 63 64 65 66 67 |
# File 'app/services/youtube/api_client.rb', line 62 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
69 70 71 72 73 74 75 76 |
# File 'app/services/youtube/api_client.rb', line 69 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
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'app/services/youtube/api_client.rb', line 136 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
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'app/services/youtube/api_client.rb', line 78 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, contains_synthetic_media: [:contains_synthetic_media] ) ) 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 ---
129 130 131 132 133 134 |
# File 'app/services/youtube/api_client.rb', line 129 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 ---
51 52 53 54 55 56 57 58 59 60 |
# File 'app/services/youtube/api_client.rb', line 51 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 ---
42 43 44 45 46 47 |
# File 'app/services/youtube/api_client.rb', line 42 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 ---
169 170 171 172 173 174 175 |
# File 'app/services/youtube/api_client.rb', line 169 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
153 154 155 156 157 158 159 160 161 |
# File 'app/services/youtube/api_client.rb', line 153 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
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'app/services/youtube/api_client.rb', line 101 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 |