133 lines
3.6 KiB
Rust
133 lines
3.6 KiB
Rust
use serde::Deserialize;
|
|
use time::OffsetDateTime;
|
|
|
|
use crate::util;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct ChannelRss {
|
|
#[serde(rename = "channelId")]
|
|
pub channel_id: String,
|
|
pub title: String,
|
|
pub author: Author,
|
|
#[serde(rename = "published", with = "time::serde::rfc3339")]
|
|
pub create_date: OffsetDateTime,
|
|
#[serde(default)]
|
|
pub entry: Vec<Entry>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Entry {
|
|
#[serde(rename = "videoId")]
|
|
pub video_id: String,
|
|
#[serde(rename = "channelId")]
|
|
pub channel_id: String,
|
|
pub title: String,
|
|
#[serde(with = "time::serde::rfc3339")]
|
|
pub published: OffsetDateTime,
|
|
#[serde(with = "time::serde::rfc3339")]
|
|
pub updated: OffsetDateTime,
|
|
#[serde(rename = "group")]
|
|
pub media_group: MediaGroup,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct MediaGroup {
|
|
pub thumbnail: Thumbnail,
|
|
pub description: String,
|
|
pub community: Community,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Thumbnail {
|
|
#[serde(rename = "@url")]
|
|
pub url: String,
|
|
#[serde(rename = "@width")]
|
|
pub width: u32,
|
|
#[serde(rename = "@height")]
|
|
pub height: u32,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Community {
|
|
#[serde(rename = "starRating")]
|
|
pub rating: Rating,
|
|
pub statistics: Statistics,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Rating {
|
|
#[serde(rename = "@count")]
|
|
pub count: u64,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Statistics {
|
|
#[serde(rename = "@views")]
|
|
pub views: u64,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) struct Author {
|
|
pub uri: String,
|
|
}
|
|
|
|
impl From<Thumbnail> for crate::model::Thumbnail {
|
|
fn from(tn: Thumbnail) -> Self {
|
|
crate::model::Thumbnail {
|
|
url: tn.url,
|
|
width: tn.width,
|
|
height: tn.height,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ChannelRss> for crate::model::ChannelRss {
|
|
fn from(feed: ChannelRss) -> Self {
|
|
let id = if feed.channel_id.is_empty() {
|
|
feed.entry
|
|
.iter()
|
|
.find_map(|entry| {
|
|
if !entry.channel_id.is_empty() {
|
|
Some(entry.channel_id.to_owned())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.or_else(|| {
|
|
feed.author
|
|
.uri
|
|
.strip_prefix("https://www.youtube.com/channel/")
|
|
.and_then(|id| {
|
|
if util::CHANNEL_ID_REGEX.is_match(id) {
|
|
Some(id.to_owned())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
})
|
|
.unwrap_or_default()
|
|
} else {
|
|
feed.channel_id
|
|
};
|
|
|
|
Self {
|
|
id,
|
|
name: feed.title,
|
|
videos: feed
|
|
.entry
|
|
.into_iter()
|
|
.map(|item| crate::model::ChannelRssVideo {
|
|
id: item.video_id,
|
|
name: item.title,
|
|
description: item.media_group.description,
|
|
thumbnail: item.media_group.thumbnail.into(),
|
|
publish_date: item.published,
|
|
update_date: item.updated,
|
|
view_count: item.media_group.community.statistics.views,
|
|
like_count: item.media_group.community.rating.count,
|
|
})
|
|
.collect(),
|
|
create_date: feed.create_date,
|
|
}
|
|
}
|
|
}
|