diff options
Diffstat (limited to 'src/videos/display/mod.rs')
-rw-r--r-- | src/videos/display/mod.rs | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/src/videos/display/mod.rs b/src/videos/display/mod.rs deleted file mode 100644 index d919dd2..0000000 --- a/src/videos/display/mod.rs +++ /dev/null @@ -1,314 +0,0 @@ -// yt - A fully featured command line YouTube client -// -// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Yt. -// -// You should have received a copy of the License along with this program. -// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. - -use std::path::PathBuf; - -use chrono::DateTime; -use format_video::FormatVideo; -use owo_colors::OwoColorize; -use url::Url; - -use crate::{ - app::App, - select::selection_file::duration::Duration, - storage::video_database::{getters::get_video_opts, Video}, -}; - -use anyhow::{Context, Result}; - -pub mod format_video; - -macro_rules! get { - ($value:expr, $key:ident, $name:expr, $code:tt) => { - if let Some(value) = &$value.$key { - $code(value) - } else { - concat!("[No ", $name, "]").to_owned() - } - }; -} - -/// This is identical to a [`FormattedVideo`], but has colorized fields. -pub struct ColorizedFormattedVideo(FormattedVideo); - -impl FormattedVideo { - pub fn colorize(self) -> ColorizedFormattedVideo { - let Self { - cache_path, - description, - duration, - extractor_hash, - last_status_change, - parent_subscription_name, - priority, - publish_date, - status, - status_change, - thumbnail_url, - title, - url, - video_options, - } = self; - - ColorizedFormattedVideo(Self { - cache_path: cache_path.blue().bold().to_string(), - description, - duration: duration.cyan().bold().to_string(), - extractor_hash: extractor_hash.bright_purple().italic().to_string(), - last_status_change: last_status_change.bright_cyan().to_string(), - parent_subscription_name: parent_subscription_name.bright_magenta().to_string(), - priority, - publish_date: publish_date.bright_white().bold().to_string(), - status: status.red().bold().to_string(), - status_change, - thumbnail_url, - title: title.green().bold().to_string(), - url: url.italic().to_string(), - video_options: video_options.bright_green().to_string(), - }) - } -} - -/// This is a version of [`Video`] that has all the fields of the original [`Video`] structure -/// turned to [`String`]s to facilitate displaying it. -/// -/// This structure provides a way to display a [`Video`] in a coherent way, as it enforces to -/// always use the same colors for one field. -#[derive(Debug)] -pub struct FormattedVideo { - cache_path: String, - description: String, - duration: String, - extractor_hash: String, - last_status_change: String, - parent_subscription_name: String, - priority: String, - publish_date: String, - status: String, - status_change: String, - thumbnail_url: String, - title: String, - url: String, - /// This string contains the video options (speed, subtitle_languages, etc.). - /// It already starts with an extra whitespace, when these are not empty. - video_options: String, -} - -impl Video { - pub async fn to_formatted_video_owned(self, app: &App) -> Result<FormattedVideo> { - Self::to_formatted_video(&self, app).await - } - - pub async fn to_formatted_video(&self, app: &App) -> Result<FormattedVideo> { - fn date_from_stamp(stamp: i64) -> String { - DateTime::from_timestamp(stamp, 0) - .expect("The timestamps should always be valid") - .format("%Y-%m-%d") - .to_string() - } - - let cache_path: String = get!( - self, - cache_path, - "Cache Path", - (|value: &PathBuf| value.to_string_lossy().to_string()) - ); - let description = get!( - self, - description, - "Description", - (|value: &str| value.to_owned()) - ); - let duration = Duration::from(self.duration); - let extractor_hash = self - .extractor_hash - .into_short_hash(app) - .await - .with_context(|| { - format!( - "Failed to format extractor hash, whilst formatting video: '{}'", - self.title - ) - })?; - let last_status_change = date_from_stamp(self.last_status_change); - let parent_subscription_name = get!( - self, - parent_subscription_name, - "author", - (|sub: &str| sub.replace('"', "'")) - ); - let priority = self.priority; - let publish_date = get!( - self, - publish_date, - "release date", - (|date: &i64| date_from_stamp(*date)) - ); - // TODO: We might support `.trim()`ing that, as the extra whitespace could be bad in the - // selection file. <2024-10-07> - let status = self.status.as_command(); - let status_change = self.status_change; - let thumbnail_url = get!( - self, - thumbnail_url, - "thumbnail URL", - (|url: &Url| url.to_string()) - ); - let title = self.title.replace(['"', '„', '”'], "'"); - let url = self.url.as_str().replace('"', "\\\""); - - let video_options = { - let opts = get_video_opts(app, &self.extractor_hash) - .await - .with_context(|| { - format!("Failed to get video options for video: '{}'", self.title) - })? - .to_cli_flags(app); - let opts_white = if !opts.is_empty() { " " } else { "" }; - format!("{}{}", opts_white, opts) - }; - - Ok(FormattedVideo { - cache_path, - description, - duration: duration.to_string(), - extractor_hash: extractor_hash.to_string(), - last_status_change, - parent_subscription_name, - priority: priority.to_string(), - publish_date, - status: status.to_string(), - status_change: status_change.to_string(), - thumbnail_url, - title, - url, - video_options, - }) - } -} - -impl<'a> FormatVideo for &'a FormattedVideo { - type Output = &'a str; - - fn cache_path(&self) -> Self::Output { - &self.cache_path - } - - fn description(&self) -> Self::Output { - &self.description - } - - fn duration(&self) -> Self::Output { - &self.duration - } - - fn extractor_hash(&self) -> Self::Output { - &self.extractor_hash - } - - fn last_status_change(&self) -> Self::Output { - &self.last_status_change - } - - fn parent_subscription_name(&self) -> Self::Output { - &self.parent_subscription_name - } - - fn priority(&self) -> Self::Output { - &self.priority - } - - fn publish_date(&self) -> Self::Output { - &self.publish_date - } - - fn status(&self) -> Self::Output { - &self.status - } - - fn status_change(&self) -> Self::Output { - &self.status_change - } - - fn thumbnail_url(&self) -> Self::Output { - &self.thumbnail_url - } - - fn title(&self) -> Self::Output { - &self.title - } - - fn url(&self) -> Self::Output { - &self.url - } - - fn video_options(&self) -> Self::Output { - &self.video_options - } -} -impl<'a> FormatVideo for &'a ColorizedFormattedVideo { - type Output = &'a str; - - fn cache_path(&self) -> Self::Output { - &self.0.cache_path - } - - fn description(&self) -> Self::Output { - &self.0.description - } - - fn duration(&self) -> Self::Output { - &self.0.duration - } - - fn extractor_hash(&self) -> Self::Output { - &self.0.extractor_hash - } - - fn last_status_change(&self) -> Self::Output { - &self.0.last_status_change - } - - fn parent_subscription_name(&self) -> Self::Output { - &self.0.parent_subscription_name - } - - fn priority(&self) -> Self::Output { - &self.0.priority - } - - fn publish_date(&self) -> Self::Output { - &self.0.publish_date - } - - fn status(&self) -> Self::Output { - &self.0.status - } - - fn status_change(&self) -> Self::Output { - &self.0.status_change - } - - fn thumbnail_url(&self) -> Self::Output { - &self.0.thumbnail_url - } - - fn title(&self) -> Self::Output { - &self.0.title - } - - fn url(&self) -> Self::Output { - &self.0.url - } - - fn video_options(&self) -> Self::Output { - &self.0.video_options - } -} |