require 'json' require 'net/http' require 'uri' module Youtube class ApiClient ENDPOINT = 'https://www.googleapis.com/youtube/v3' def initialize api_key: ENV.fetch('YOUTUBE_API_KEY') @api_key = api_key end def search_videos q:, published_after:, page_token: nil get_json('/search', { part: 'snippet', type: 'video', q: q, order: 'date', maxResults: 50, publishedAfter: published_after.iso8601, pageToken: page_token }.compact) end def videos ids return { 'items' => [] } if ids.empty? get_json('/videos', part: 'snippet,status,contentDetails', id: ids.join(',')) end def playlist_items playlist_id:, page_token: nil get_json('/playlistItems', { part: 'snippet,contentDetails,status', playlistId: playlist_id, maxResults: 50, pageToken: page_token }.compact) end def channel id: nil, handle: nil params = { part: 'snippet,contentDetails' } params[:id] = id if id params[:forHandle] = handle if handle get_json('/channels', params) end private def get_json path, params uri = URI(ENDPOINT + path) uri.query = URI.encode_www_form(params.merge(key: @api_key)) response = Net::HTTP.start(uri.host, uri.port, use_ssl: true, open_timeout: 10, read_timeout: 30) do |http| http.get(uri) end unless response.is_a?(Net::HTTPSuccess) raise "YouTube API error: #{ response.code } #{ response.body }" end JSON.parse(response.body) end end end