Add more search replace fields

This commit is contained in:
bytedream 2023-06-20 00:06:09 +02:00 committed by ByteDream
parent 0b044ba27e
commit 4e4a4355f5
2 changed files with 59 additions and 2 deletions

View file

@ -10,7 +10,10 @@ use crunchyroll_rs::{Episode, Locale, MediaCollection, MovieListing, MusicVideo,
#[derive(Debug, clap::Parser)] #[derive(Debug, clap::Parser)]
pub struct Search { pub struct Search {
#[arg(help = "Audio languages to include")] #[arg(help = format!("Audio languages to include. \
Available languages are: {}", Locale::all().into_iter().map(|l| l.to_string()).collect::<Vec<String>>().join(", ")))]
#[arg(long_help = format!("Audio languages to include. \
Available languages are:\n {}", Locale::all().into_iter().map(|l| format!("{:<6} {}", l.to_string(), l.to_human_readable())).collect::<Vec<String>>().join("\n ")))]
#[arg(long, default_values_t = vec![crate::utils::locale::system_locale()])] #[arg(long, default_values_t = vec![crate::utils::locale::system_locale()])]
audio: Vec<Locale>, audio: Vec<Locale>,
@ -41,37 +44,55 @@ pub struct Search {
/// For example, if you want to get the title of an episode, you can use `Title {{episode.title}}` and `{{episode.title}}` will be replaced with the episode title /// For example, if you want to get the title of an episode, you can use `Title {{episode.title}}` and `{{episode.title}}` will be replaced with the episode title
/// ///
/// See the following list for all keywords and their meaning: /// See the following list for all keywords and their meaning:
/// series.id → Series id
/// series.title → Series title /// series.title → Series title
/// series.description → Series description /// series.description → Series description
/// series.release_year → Series release year
/// ///
/// season.id → Season id
/// season.title → Season title /// season.title → Season title
/// season.description → Season description /// season.description → Season description
/// season.number → Season number /// season.number → Season number
/// season.episodes → Number of episodes the season has
/// ///
/// episode.id → Episode id
/// episode.title → Episode title /// episode.title → Episode title
/// episode.description → Episode description /// episode.description → Episode description
/// episode.locale → Episode locale/language /// episode.locale → Episode locale/language
/// episode.number → Episode number /// episode.number → Episode number
/// episode.sequence_number → Episode number. This number is unique unlike `episode.number` which sometimes can be duplicated /// episode.sequence_number → Episode number. This number is unique unlike `episode.number` which sometimes can be duplicated
/// episode.duration → Episode duration in milliseconds
/// episode.air_date → Episode air date as unix timestamp
/// episode.premium_only → If the episode is only available with Crunchyroll premium
/// ///
/// movie_listing.id → Movie listing id
/// movie_listing.title → Movie listing title /// movie_listing.title → Movie listing title
/// movie_listing.description → Movie listing description /// movie_listing.description → Movie listing description
/// ///
/// movie.id → Movie id
/// movie.title → Movie title /// movie.title → Movie title
/// movie.description → Movie description /// movie.description → Movie description
/// movie.duration → Movie duration in milliseconds
/// movie.premium_only → If the movie is only available with Crunchyroll premium
/// ///
/// music_video.id → Music video id
/// music_video.title → Music video title /// music_video.title → Music video title
/// music_video.description → Music video description /// music_video.description → Music video description
/// music_video.duration → Music video duration in milliseconds
/// music_video.premium_only → If the music video is only available with Crunchyroll premium
/// ///
/// concert.id → Concert id
/// concert.title → Concert title /// concert.title → Concert title
/// concert.description → Concert description /// concert.description → Concert description
/// concert.duration → Concert duration in milliseconds
/// concert.premium_only → If the concert is only available with Crunchyroll premium
/// ///
/// stream.locale → Stream locale/language /// stream.locale → Stream locale/language
/// stream.dash_url → Stream url in DASH format /// stream.dash_url → Stream url in DASH format
/// stream.hls_url → Stream url in HLS format /// stream.hls_url → Stream url in HLS format
/// ///
/// subtitle.locale → Subtitle locale/language /// subtitle.locale → Subtitle locale/language
/// subtitle.url → Subtitle url /// subtitle.url → Url to the subtitle
#[arg(short, long, verbatim_doc_comment)] #[arg(short, long, verbatim_doc_comment)]
#[arg(default_value = "S{{season.number}}E{{episode.number}} - {{episode.title}}")] #[arg(default_value = "S{{season.number}}E{{episode.number}} - {{episode.title}}")]
output: String, output: String,

View file

@ -12,59 +12,76 @@ use std::ops::Range;
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatSeries { struct FormatSeries {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub release_year: u32,
} }
impl From<&Series> for FormatSeries { impl From<&Series> for FormatSeries {
fn from(value: &Series) -> Self { fn from(value: &Series) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
release_year: value.series_launch_year.unwrap_or_default(),
} }
} }
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatSeason { struct FormatSeason {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub number: u32, pub number: u32,
pub episodes: u32,
} }
impl From<&Season> for FormatSeason { impl From<&Season> for FormatSeason {
fn from(value: &Season) -> Self { fn from(value: &Season) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
number: value.season_number, number: value.season_number,
episodes: value.number_of_episodes,
} }
} }
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatEpisode { struct FormatEpisode {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub locale: Locale, pub locale: Locale,
pub number: u32, pub number: u32,
pub sequence_number: f32, pub sequence_number: f32,
pub duration: i64,
pub air_date: i64,
pub premium_only: bool,
} }
impl From<&Episode> for FormatEpisode { impl From<&Episode> for FormatEpisode {
fn from(value: &Episode) -> Self { fn from(value: &Episode) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
locale: value.audio_locale.clone(), locale: value.audio_locale.clone(),
number: value.episode_number, number: value.episode_number,
sequence_number: value.sequence_number, sequence_number: value.sequence_number,
duration: value.duration.num_milliseconds(),
air_date: value.episode_air_date.timestamp(),
premium_only: value.is_premium_only,
} }
} }
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatMovieListing { struct FormatMovieListing {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
} }
@ -72,6 +89,7 @@ struct FormatMovieListing {
impl From<&MovieListing> for FormatMovieListing { impl From<&MovieListing> for FormatMovieListing {
fn from(value: &MovieListing) -> Self { fn from(value: &MovieListing) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
} }
@ -80,45 +98,63 @@ impl From<&MovieListing> for FormatMovieListing {
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatMovie { struct FormatMovie {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub duration: i64,
pub premium_only: bool,
} }
impl From<&Movie> for FormatMovie { impl From<&Movie> for FormatMovie {
fn from(value: &Movie) -> Self { fn from(value: &Movie) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
duration: value.duration.num_milliseconds(),
premium_only: value.is_premium_only,
} }
} }
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatMusicVideo { struct FormatMusicVideo {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub duration: i64,
pub premium_only: bool,
} }
impl From<&MusicVideo> for FormatMusicVideo { impl From<&MusicVideo> for FormatMusicVideo {
fn from(value: &MusicVideo) -> Self { fn from(value: &MusicVideo) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
duration: value.duration.num_milliseconds(),
premium_only: value.is_premium_only,
} }
} }
} }
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
struct FormatConcert { struct FormatConcert {
pub id: String,
pub title: String, pub title: String,
pub description: String, pub description: String,
pub duration: i64,
pub premium_only: bool,
} }
impl From<&Concert> for FormatConcert { impl From<&Concert> for FormatConcert {
fn from(value: &Concert) -> Self { fn from(value: &Concert) -> Self {
Self { Self {
id: value.id.clone(),
title: value.title.clone(), title: value.title.clone(),
description: value.description.clone(), description: value.description.clone(),
duration: value.duration.num_milliseconds(),
premium_only: value.is_premium_only,
} }
} }
} }