invidious/src/invidious/yt_backend/extractors_utils.cr
2024-07-17 12:39:40 -07:00

88 lines
2.4 KiB
Crystal

# Extracts text from InnerTube response
#
# InnerTube can package text in three different formats
# "runs": [
# {"text": "something"},
# {"text": "cont"},
# ...
# ]
#
# "SimpleText": "something"
#
# Or sometimes just none at all as with the data returned from
# category continuations.
#
# In order to facilitate calling this function with `#[]?`:
# A nil will be accepted. Of course, since nil cannot be parsed,
# another nil will be returned.
def extract_text(item : JSON::Any?) : String?
if item.nil?
return nil
end
if text_container = item["simpleText"]?
return text_container.as_s
elsif text_container = item["runs"]?
return text_container.as_a.map(&.["text"].as_s).join("")
else
nil
end
end
# Check if an "ownerBadges" or a "badges" element contains a verified badge.
# There is currently two known types of verified badges:
#
# "ownerBadges": [{
# "metadataBadgeRenderer": {
# "icon": { "iconType": "CHECK_CIRCLE_THICK" },
# "style": "BADGE_STYLE_TYPE_VERIFIED",
# "tooltip": "Verified",
# "accessibilityData": { "label": "Verified" }
# }
# }],
#
# "ownerBadges": [{
# "metadataBadgeRenderer": {
# "icon": { "iconType": "OFFICIAL_ARTIST_BADGE" },
# "style": "BADGE_STYLE_TYPE_VERIFIED_ARTIST",
# "tooltip": "Official Artist Channel",
# "accessibilityData": { "label": "Official Artist Channel" }
# }
# }],
#
def has_verified_badge?(badges : JSON::Any?)
return false if badges.nil?
badges.as_a.each do |badge|
style = badge.dig("metadataBadgeRenderer", "style").as_s
return true if style == "BADGE_STYLE_TYPE_VERIFIED"
return true if style == "BADGE_STYLE_TYPE_VERIFIED_ARTIST"
end
return false
rescue ex
LOGGER.debug("Unable to parse owner badges. Got exception: #{ex.message}")
LOGGER.trace("Owner badges data: #{badges.to_json}")
return false
end
# This function extracts SearchVideo items from a Category.
# Categories are commonly returned in search results and trending pages.
def extract_category(category : Category) : Array(SearchVideo)
return category.contents.select(SearchVideo)
end
# :ditto:
def extract_category(category : Category, &)
category.contents.select(SearchVideo).each do |item|
yield item
end
end
def extract_selected_tab(tabs)
# Extract the selected tab from the array of tabs Youtube returns
return tabs.as_a.select(&.["tabRenderer"]?.try &.["selected"]?.try &.as_bool)[0]["tabRenderer"]
end