class Yt::Models::Resource

Constants

CHANNEL_PATTERNS

@return [Array<Regexp>] patterns matching URLs of YouTube channels.

PLAYLIST_PATTERNS

@return [Array<Regexp>] patterns matching URLs of YouTube playlists.

VIDEO_PATTERNS

@return [Array<Regexp>] patterns matching URLs of YouTube videos.

Attributes

auth[R]

@private

Public Class Methods

new(options = {}) click to toggle source

@private

# File lib/yt/models/resource.rb, line 50
def initialize(options = {})
  if options[:url]
    @url = options[:url]
    @match = find_pattern_match
    @id = @match['id']
  else
    @id = options[:id]
  end
  @auth = options[:auth]
  @snippet = Snippet.new(data: options[:snippet]) if options[:snippet]
  @status = Status.new(data: options[:status]) if options[:status]
end

Public Instance Methods

id() click to toggle source

@!attribute [r] id

@return [String] the ID that YouTube uses to identify each resource.
# File lib/yt/models/resource.rb, line 15
def id
  if @id.nil? && @match && @match[:kind] == :channel
    @id ||= fetch_channel_id
  else
    @id
  end
end
kind() click to toggle source

@private

# File lib/yt/models/resource.rb, line 64
def kind
  if @url
    @match[:kind].to_s
  else
    self.class.to_s.demodulize.underscore
  end
end
private?() click to toggle source

@return [Boolean] whether the resource is private.

# File lib/yt/models/resource.rb, line 38
def private?
  privacy_status == 'private'
end
public?() click to toggle source

@return [Boolean] whether the resource is public.

# File lib/yt/models/resource.rb, line 33
def public?
  privacy_status == 'public'
end
unlisted?() click to toggle source

@return [Boolean] whether the resource is unlisted.

# File lib/yt/models/resource.rb, line 43
def unlisted?
  privacy_status == 'unlisted'
end
update(attributes = {}) click to toggle source

@private

# File lib/yt/models/resource.rb, line 73
def update(attributes = {})
  underscore_keys! attributes
  body = build_update_body attributes
  params = {part: body.keys.join(',')}
  do_update params: params, body: body.merge(id: @id) do |data|
    @id = data['id']
    @snippet = Snippet.new data: data['snippet'] if data['snippet']
    @status = Status.new data: data['status'] if data['status']
    true
  end
end

Private Instance Methods

build_update_body(attributes = {}) click to toggle source
# File lib/yt/models/resource.rb, line 172
def build_update_body(attributes = {})
  {}.tap do |body|
    update_parts.each do |name, part|
      if should_include_part_in_update? part, attributes
        body[name] = build_update_body_part name, part, attributes
        sanitize_brackets! body[name] if part[:sanitize_brackets]
      end
    end
  end
end
build_update_body_part(name, part, attributes = {}) click to toggle source
# File lib/yt/models/resource.rb, line 183
def build_update_body_part(name, part, attributes = {})
  {}.tap do |body_part|
    part[:keys].map do |key|
      body_part[camelize key] = attributes.fetch key, public_send(name).public_send(key)
    end
  end
end
camelize(value) click to toggle source
# File lib/yt/models/resource.rb, line 195
def camelize(value)
  value.to_s.camelize(:lower).to_sym
end
delete_params() click to toggle source

@return [Hash] the parameters to submit to YouTube to delete a playlist. @see developers.google.com/youtube/v3/docs/playlists/delete

Calls superclass method Yt::Actions::Delete#delete_params
# File lib/yt/models/resource.rb, line 168
def delete_params
  super.tap{|params| params[:params] = {id: @id}}
end
ensure_complete_snippet(attribute) click to toggle source

Since YouTube API only returns tags on Videos#list, the memoized `@snippet` is erased if the video was instantiated through Video#search (e.g., by calling account.videos or channel.videos), so that the full snippet (with tags and category) is loaded, rather than the partial one.

# File lib/yt/models/resource.rb, line 146
def ensure_complete_snippet(attribute)
  unless snippet.public_send(attribute).present? || snippet.complete?
    @snippet = nil
  end
  snippet.public_send attribute
end
fetch_channel_id() click to toggle source
# File lib/yt/models/resource.rb, line 125
def fetch_channel_id
  response = Net::HTTP.start 'www.youtube.com', 443, use_ssl: true do |http|
    http.request Net::HTTP::Get.new("/#{@match['format']}#{@match['name']}")
  end
  if response.is_a?(Net::HTTPRedirection)
    response = Net::HTTP.start 'www.youtube.com', 443, use_ssl: true do |http|
      http.request Net::HTTP::Get.new(response['location'])
    end
  end
  regex = %r{<meta itemprop="channelId" content="(?<id>UC[a-zA-Z0-9_-]{22})">}
  if data = response.body.match(regex)
    data[:id]
  else
    raise Yt::Errors::NoItems
  end
end
find_pattern_match() click to toggle source
# File lib/yt/models/resource.rb, line 106
def find_pattern_match
  patterns.find do |kind, regex|
    if data = @url.match(regex)
      # Note: With Ruby 2.4, the following is data.named_captures
      break data.names.zip(data.captures).to_h.merge kind: kind
    end
  end || {kind: :unknown}
end
patterns() click to toggle source
# File lib/yt/models/resource.rb, line 115
def patterns
  # @note: :channel *must* be the last since one of its regex eats the
  # remaining patterns. In short, don't change the following order.
  Enumerator.new do |patterns|
    VIDEO_PATTERNS.each {|regex| patterns << [:video, regex]}
    PLAYLIST_PATTERNS.each {|regex| patterns << [:playlist, regex]}
    CHANNEL_PATTERNS.each {|regex| patterns << [:channel, regex]}
  end
end
should_include_part_in_update?(part, attributes = {}) click to toggle source
# File lib/yt/models/resource.rb, line 191
def should_include_part_in_update?(part, attributes = {})
  part[:required] || (part[:keys] & attributes.keys).any?
end
update_params() click to toggle source

TODO: instead of having Video, Playlist etc override this method,

they should define *what* can be updated in their own *update*
method.

@return [Hash] the parameters to submit to YouTube to update a playlist. @see developers.google.com/youtube/v3/docs/playlists/update @see developers.google.com/youtube/v3/docs/videos/update

Calls superclass method Yt::Actions::Update#update_params
# File lib/yt/models/resource.rb, line 159
def update_params
  super.tap do |params|
    params[:request_format] = :json
    params[:expected_response] = Net::HTTPOK
  end
end