aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/sources/comments/src/info_json.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-20 16:10:21 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-20 16:14:26 +0200
commit368cb6b0d25db2ae23be42ad51584de059997e51 (patch)
tree3282e45d3ebced63c8498a47e83a255c35de620b /pkgs/sources/comments/src/info_json.rs
parentrefactor(hm): Rename to `modules/home` (diff)
downloadnixos-config-368cb6b0d25db2ae23be42ad51584de059997e51.zip
refactor(sys): Modularize and move to `modules/system` or `pkgs`
Diffstat (limited to 'pkgs/sources/comments/src/info_json.rs')
-rw-r--r--pkgs/sources/comments/src/info_json.rs223
1 files changed, 223 insertions, 0 deletions
diff --git a/pkgs/sources/comments/src/info_json.rs b/pkgs/sources/comments/src/info_json.rs
new file mode 100644
index 00000000..eca4fae3
--- /dev/null
+++ b/pkgs/sources/comments/src/info_json.rs
@@ -0,0 +1,223 @@
+use std::collections::HashMap;
+
+use serde::{Deserialize, Deserializer};
+
+#[derive(Debug, Deserialize)]
+pub struct InfoJson {
+ pub id: String,
+ pub title: String,
+ pub formats: Vec<Format>,
+ pub thumbnails: Vec<ThumbNail>,
+ pub thumbnail: String,
+ pub description: String,
+ pub channel_id: String,
+ pub channel_url: String,
+ pub duration: u32,
+ pub view_count: u32,
+ pub age_limit: u32,
+ pub webpage_url: String,
+ pub categories: Vec<String>,
+ pub tags: Vec<String>,
+ pub playable_in_embed: bool,
+ pub live_status: String,
+ _format_sort_fields: Vec<String>,
+ pub automatic_captions: HashMap<String, Vec<Caption>>,
+ pub subtitles: Subtitles,
+ pub comment_count: u32,
+ pub like_count: u32,
+ pub channel: String,
+ pub channel_follower_count: u32,
+ pub channel_is_verified: Option<bool>,
+ pub uploader: String,
+ pub uploader_id: String,
+ pub uploader_url: String,
+ pub upload_date: String,
+ pub availability: String,
+ pub webpage_url_basename: String,
+ pub webpage_url_domain: String,
+ pub extractor: String,
+ pub extractor_key: String,
+ pub display_id: String,
+ pub fulltitle: String,
+ pub duration_string: String,
+ pub is_live: bool,
+ pub was_live: bool,
+ pub epoch: u32,
+ pub comments: Vec<Comment>,
+ pub sponsorblock_chapters: Option<Vec<SponsorblockChapter>>,
+ pub format: String,
+ pub format_id: String,
+ pub ext: String,
+ pub protocol: String,
+ pub language: Option<String>,
+ pub format_note: String,
+ pub filesize_approx: u64,
+ pub tbr: f64,
+ pub width: u32,
+ pub height: u32,
+ pub resolution: String,
+ pub fps: f64,
+ pub dynamic_range: String,
+ pub vcodec: String,
+ pub vbr: f64,
+ pub aspect_ratio: f64,
+ pub acodec: String,
+ pub abr: f64,
+ pub asr: u32,
+ pub audio_channels: u32,
+ _type: String,
+ _version: Version,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Subtitles {}
+
+#[derive(Debug, Deserialize)]
+pub struct Version {
+ pub version: String,
+ pub release_git_head: String,
+ pub repository: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct SponsorblockChapter {}
+
+#[derive(Debug, Deserialize, Clone)]
+#[serde(from = "String")]
+pub enum Parent {
+ Root,
+ Id(String),
+}
+
+impl Parent {
+ pub fn id(&self) -> Option<&str> {
+ if let Self::Id(id) = self {
+ Some(id)
+ } else {
+ None
+ }
+ }
+}
+
+impl From<String> for Parent {
+ fn from(value: String) -> Self {
+ if value == "root" {
+ Self::Root
+ } else {
+ Self::Id(value)
+ }
+ }
+}
+
+#[derive(Debug, Deserialize, Clone)]
+#[serde(from = "String")]
+pub struct Id {
+ pub id: String,
+}
+impl From<String> for Id {
+ fn from(value: String) -> Self {
+ Self {
+ // Take the last element if the string is split with dots, otherwise take the full id
+ id: value.split('.').last().unwrap_or(&value).to_owned(),
+ }
+ }
+}
+
+#[derive(Debug, Deserialize, Clone)]
+pub struct Comment {
+ pub id: Id,
+ pub text: String,
+ #[serde(default = "zero")]
+ pub like_count: u32,
+ pub author_id: String,
+ #[serde(default = "unknown")]
+ pub author: String,
+ pub author_thumbnail: String,
+ pub parent: Parent,
+ #[serde(deserialize_with = "edited_from_time_text", alias = "_time_text")]
+ pub edited: bool,
+ // Can't also be deserialized, as it's already used in 'edited'
+ // _time_text: String,
+ pub timestamp: i64,
+ pub author_url: String,
+ pub author_is_uploader: bool,
+ pub is_favorited: bool,
+}
+fn unknown() -> String {
+ "<Unknown>".to_string()
+}
+fn zero() -> u32 {
+ 0
+}
+fn edited_from_time_text<'de, D>(d: D) -> Result<bool, D::Error>
+where
+ D: Deserializer<'de>,
+{
+ let s = String::deserialize(d)?;
+ if s.contains(" (edited)") {
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Caption {
+ pub ext: String,
+ pub url: String,
+ pub name: Option<String>,
+ pub protocol: Option<String>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct ThumbNail {
+ pub url: String,
+ pub preference: i32,
+ pub id: String,
+ pub height: Option<u32>,
+ pub width: Option<u32>,
+ pub resolution: Option<String>,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Format {
+ pub format_id: String,
+ pub format_note: Option<String>,
+ pub ext: String,
+ pub protocol: String,
+ pub acodec: Option<String>,
+ pub vcodec: String,
+ pub url: String,
+ pub width: Option<u32>,
+ pub height: Option<u32>,
+ pub fps: Option<f64>,
+ pub rows: Option<u32>,
+ pub columns: Option<u32>,
+ pub fragments: Option<Vec<Fragment>>,
+ pub resolution: String,
+ pub aspect_ratio: Option<f64>,
+ pub http_headers: HttpHeader,
+ pub audio_ext: String,
+ pub video_ext: String,
+ pub vbr: Option<f64>,
+ pub abr: Option<f64>,
+ pub format: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct HttpHeader {
+ #[serde(alias = "User-Agent")]
+ pub user_agent: String,
+ #[serde(alias = "Accept")]
+ pub accept: String,
+ #[serde(alias = "Accept-Language")]
+ pub accept_language: String,
+ #[serde(alias = "Sec-Fetch-Mode")]
+ pub sec_fetch_mode: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Fragment {
+ pub url: String,
+ pub duration: f64,
+}