diff --git a/spec/invidious/hashtag_spec.cr b/spec/invidious/hashtag_spec.cr index 266ec57b..abc81225 100644 --- a/spec/invidious/hashtag_spec.cr +++ b/spec/invidious/hashtag_spec.cr @@ -27,8 +27,8 @@ Spectator.describe Invidious::Hashtag do expect(video_11.length_seconds).to eq((56.minutes + 41.seconds).total_seconds.to_i32) expect(video_11.views).to eq(40_504_893) - expect(video_11.live_now).to be_false - expect(video_11.premium).to be_false + expect(video_11.badges.live_now?).to be_false + expect(video_11.badges.premium?).to be_false expect(video_11.premiere_timestamp).to be_nil # @@ -49,8 +49,8 @@ Spectator.describe Invidious::Hashtag do expect(video_35.length_seconds).to eq((3.minutes + 14.seconds).total_seconds.to_i32) expect(video_35.views).to eq(30_790_049) - expect(video_35.live_now).to be_false - expect(video_35.premium).to be_false + expect(video_35.badges.live_now?).to be_false + expect(video_35.badges.premium?).to be_false expect(video_35.premiere_timestamp).to be_nil end @@ -80,8 +80,8 @@ Spectator.describe Invidious::Hashtag do expect(video_41.length_seconds).to eq((1.hour).total_seconds.to_i32) expect(video_41.views).to eq(63_240) - expect(video_41.live_now).to be_false - expect(video_41.premium).to be_false + expect(video_41.badges.live_now?).to be_false + expect(video_41.badges.premium?).to be_false expect(video_41.premiere_timestamp).to be_nil # @@ -102,8 +102,8 @@ Spectator.describe Invidious::Hashtag do expect(video_48.length_seconds).to eq((35.minutes + 46.seconds).total_seconds.to_i32) expect(video_48.views).to eq(68_704) - expect(video_48.live_now).to be_false - expect(video_48.premium).to be_false + expect(video_48.badges.live_now?).to be_false + expect(video_48.badges.premium?).to be_false expect(video_48.premiere_timestamp).to be_nil end end diff --git a/src/invidious/channels/channels.cr b/src/invidious/channels/channels.cr index 29546e38..1478c8fc 100644 --- a/src/invidious/channels/channels.cr +++ b/src/invidious/channels/channels.cr @@ -223,7 +223,7 @@ def fetch_channel(ucid, pull_all_videos : Bool) length_seconds = channel_video.try &.length_seconds length_seconds ||= 0 - live_now = channel_video.try &.live_now + live_now = channel_video.try &.badges.live_now? live_now ||= false premiere_timestamp = channel_video.try &.premiere_timestamp @@ -275,7 +275,7 @@ def fetch_channel(ucid, pull_all_videos : Bool) ucid: video.ucid, author: video.author, length_seconds: video.length_seconds, - live_now: video.live_now, + live_now: video.badges.live_now?, premiere_timestamp: video.premiere_timestamp, views: video.views, }) diff --git a/src/invidious/helpers/serialized_yt_data.cr b/src/invidious/helpers/serialized_yt_data.cr index 463d5557..1fef5f93 100644 --- a/src/invidious/helpers/serialized_yt_data.cr +++ b/src/invidious/helpers/serialized_yt_data.cr @@ -1,3 +1,16 @@ +@[Flags] +enum VideoBadges + LiveNow + Premium + ThreeD + FourK + New + EightK + VR180 + VR360 + ClosedCaptions +end + struct SearchVideo include DB::Serializable @@ -9,10 +22,9 @@ struct SearchVideo property views : Int64 property description_html : String property length_seconds : Int32 - property live_now : Bool - property premium : Bool property premiere_timestamp : Time? property author_verified : Bool + property badges : VideoBadges def to_xml(auto_generated, query_params, xml : XML::Builder) query_params["v"] = self.id @@ -88,13 +100,20 @@ struct SearchVideo json.field "published", self.published.to_unix json.field "publishedText", translate(locale, "`x` ago", recode_date(self.published, locale)) json.field "lengthSeconds", self.length_seconds - json.field "liveNow", self.live_now - json.field "premium", self.premium + json.field "liveNow", self.badges.live_now? + json.field "premium", self.badges.premium? json.field "isUpcoming", self.upcoming? if self.premiere_timestamp json.field "premiereTimestamp", self.premiere_timestamp.try &.to_unix end + json.field "isNew", self.badges.new? + json.field "is4k", self.badges.four_k? + json.field "is8k", self.badges.eight_k? + json.field "isVr180", self.badges.vr180? + json.field "isVr360", self.badges.vr360? + json.field "is3d", self.badges.three_d? + json.field "hasCaptions", self.badges.closed_captions? end end diff --git a/src/invidious/routes/feeds.cr b/src/invidious/routes/feeds.cr index e20a7139..ea7fb396 100644 --- a/src/invidious/routes/feeds.cr +++ b/src/invidious/routes/feeds.cr @@ -192,11 +192,9 @@ module Invidious::Routes::Feeds views: views, description_html: description_html, length_seconds: 0, - live_now: false, - paid: false, - premium: false, premiere_timestamp: nil, author_verified: false, + badges: VideoBadges::None, }) end diff --git a/src/invidious/yt_backend/extractors.cr b/src/invidious/yt_backend/extractors.cr index 38dc2c04..7c89f6c4 100644 --- a/src/invidious/yt_backend/extractors.cr +++ b/src/invidious/yt_backend/extractors.cr @@ -108,21 +108,30 @@ private module Parsers length_seconds = 0 end - live_now = false - premium = false - premiere_timestamp = item_contents.dig?("upcomingEventData", "startTime").try { |t| Time.unix(t.as_s.to_i64) } - + badges = VideoBadges::None item_contents["badges"]?.try &.as_a.each do |badge| b = badge["metadataBadgeRenderer"] case b["label"].as_s when "LIVE NOW" - live_now = true - when "New", "4K", "CC" - # TODO + badges |= VideoBadges::LiveNow + when "New" + badges |= VideoBadges::New + when "4K" + badges |= VideoBadges::FourK + when "8K" + badges |= VideoBadges::EightK + when "VR180" + badges |= VideoBadges::VR180 + when "360°" + badges |= VideoBadges::VR360 + when "3D" + badges |= VideoBadges::ThreeD + when "CC" + badges |= VideoBadges::ClosedCaptions when "Premium" # TODO: Potentially available as item_contents["topStandaloneBadge"]["metadataBadgeRenderer"] - premium = true + badges |= VideoBadges::Premium else nil # Ignore end end @@ -136,10 +145,9 @@ private module Parsers views: view_count, description_html: description_html, length_seconds: length_seconds, - live_now: live_now, - premium: premium, premiere_timestamp: premiere_timestamp, author_verified: author_verified, + badges: badges, }) end @@ -563,10 +571,9 @@ private module Parsers views: view_count, description_html: "", length_seconds: duration, - live_now: false, - premium: false, premiere_timestamp: Time.unix(0), author_verified: false, + badges: VideoBadges::None, }) end