feat: add history item dates, extend timeago parser

This commit is contained in:
ThetaDev 2025-01-03 19:15:28 +01:00
parent 65ada37214
commit 320a8c2c24
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6
28 changed files with 6507 additions and 2160 deletions

View file

@ -209,6 +209,14 @@ pub(crate) struct TextBox {
pub text: String,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct SimpleHeaderRenderer {
#[serde_as(as = "Text")]
pub title: String,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]

View file

@ -4,7 +4,7 @@ use serde_with::{rust::deserialize_ignore_any, serde_as, DefaultOnError, VecSkip
use crate::{
model::{
self, traits::FromYtItem, AlbumId, AlbumItem, AlbumType, ArtistId, ArtistItem, ChannelId,
MusicItem, MusicItemType, MusicPlaylistItem, TrackItem, UserItem,
HistoryItem, MusicItem, MusicItemType, MusicPlaylistItem, TrackItem, UserItem,
},
param::Language,
serializer::{
@ -18,7 +18,7 @@ use super::{
url_endpoint::{
BrowseEndpointWrap, MusicPage, MusicPageType, MusicVideoType, NavigationEndpoint, PageType,
},
ContentsRenderer, MusicContinuationData, Thumbnails, ThumbnailsWrap,
ContentsRenderer, MusicContinuationData, SimpleHeaderRenderer, Thumbnails, ThumbnailsWrap,
};
#[serde_as]
@ -39,6 +39,8 @@ pub(crate) enum ItemSection {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct MusicShelf {
#[serde_as(as = "Option<Text>")]
pub title: Option<String>,
/// Playlist ID (only for playlists)
pub playlist_id: Option<String>,
pub contents: MapResult<Vec<MusicResponseItem>>,
@ -396,15 +398,7 @@ pub(crate) struct GridRenderer {
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct GridHeader {
pub grid_header_renderer: GridHeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct GridHeaderRenderer {
#[serde_as(as = "Text")]
pub title: String,
pub grid_header_renderer: SimpleHeaderRenderer,
}
#[derive(Debug, Deserialize)]
@ -419,14 +413,6 @@ pub(crate) struct SimpleHeader {
pub music_header_renderer: SimpleHeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct SimpleHeaderRenderer {
#[serde_as(as = "Text")]
pub title: String,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) enum TrackBadge {
@ -1257,6 +1243,26 @@ impl MusicListMapper {
warnings: self.warnings,
}
}
pub fn conv_history_items(
self,
date_txt: Option<String>,
res: &mut MapResult<Vec<HistoryItem<TrackItem>>>,
) {
res.warnings.extend(self.warnings);
res.c.extend(
self.items
.into_iter()
.filter_map(TrackItem::from_ytm_item)
.map(|item| HistoryItem {
item,
playback_date: date_txt.as_deref().and_then(|s| {
timeago::parse_textual_date_to_d(self.lang, s, &mut res.warnings)
}),
playback_date_txt: date_txt.clone(),
}),
);
}
}
/// Map TextComponents containing artist names to a list of artists and a 'Various Artists' flag

View file

@ -4,9 +4,12 @@ use serde_with::{
};
use time::OffsetDateTime;
use super::{ChannelBadge, ContentImage, ContinuationEndpoint, PhMetadataView, Thumbnails};
use super::{
ChannelBadge, ContentImage, ContinuationEndpoint, PhMetadataView, SimpleHeaderRenderer,
Thumbnails,
};
use crate::{
model::{Channel, ChannelItem, ChannelTag, PlaylistItem, VideoItem, YouTubeItem},
model::{Channel, ChannelItem, ChannelTag, HistoryItem, PlaylistItem, VideoItem, YouTubeItem},
param::Language,
serializer::{
text::{AttributedText, Text, TextComponent},
@ -63,6 +66,7 @@ pub(crate) enum YouTubeListItem {
/// GridRenderer: contains videos on channel page
#[serde(alias = "expandedShelfContentsRenderer", alias = "gridRenderer")]
ItemSectionRenderer {
header: Option<ItemSectionHeader>,
#[serde(alias = "items")]
contents: MapResult<Vec<YouTubeListItem>>,
},
@ -294,6 +298,12 @@ pub(crate) struct YouTubeListRenderer {
pub contents: MapResult<Vec<YouTubeListItem>>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ItemSectionHeader {
pub item_section_header_renderer: SimpleHeaderRenderer,
}
#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -833,7 +843,7 @@ impl YouTubeListMapper<YouTubeItem> {
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
YouTubeListItem::ItemSectionRenderer { mut contents, .. } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}
@ -881,7 +891,7 @@ impl YouTubeListMapper<VideoItem> {
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
YouTubeListItem::ItemSectionRenderer { mut contents, .. } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}
@ -893,6 +903,23 @@ impl YouTubeListMapper<VideoItem> {
self.warnings.append(&mut res.warnings);
res.c.into_iter().for_each(|item| self.map_item(item));
}
pub(crate) fn conv_history_items(
self,
date_txt: Option<String>,
res: &mut MapResult<Vec<HistoryItem<VideoItem>>>,
) {
res.warnings.extend(self.warnings);
res.c.extend(self.items.into_iter().map(|item| {
HistoryItem {
item,
playback_date: date_txt.as_deref().and_then(|s| {
timeago::parse_textual_date_to_d(self.lang, s, &mut res.warnings)
}),
playback_date_txt: date_txt.clone(),
}
}));
}
}
impl YouTubeListMapper<PlaylistItem> {
@ -916,7 +943,7 @@ impl YouTubeListMapper<PlaylistItem> {
YouTubeListItem::RichItemRenderer { content } => {
self.map_item(*content);
}
YouTubeListItem::ItemSectionRenderer { mut contents } => {
YouTubeListItem::ItemSectionRenderer { mut contents, .. } => {
self.warnings.append(&mut contents.warnings);
contents.c.into_iter().for_each(|it| self.map_item(it));
}