diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4a89183 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,167 @@ +use std::{error::Error, path::PathBuf}; + +use clap::{arg, command, Parser, Subcommand}; + +use env_logger::Env; +use mp32rss::{de::hms_duration, s3::Access, MP32RSS}; +use tokio::{fs::File, io::AsyncReadExt}; + +#[derive(Parser, Debug)] +#[command(version, about)] +struct Args { + #[arg(short, long)] + bucket: String, + + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand, Debug)] +enum Command { + /// Scan the bucket for new files and regenerate the feed. + Refresh, + + /// Rerender the feed. + Render, + + /// Edit the metadata for an entry. + Edit(EditArgs), + + /// Delete an entry and remove the file from the bucket. + Delete { + /// The key to the file in the bucket. + filename: String, + }, + + /// List the templates. + Templates, + + /// Add or replace a template and regenerate the feed. + AddTemplate(AddTemplateArgs), + + /// Remove a template and the files generated from it. + RemoveTemplate { + /// The template name. + name: String, + }, +} + +#[derive(clap::Args, Debug)] +struct EditArgs { + /// The key to the file in the bucket. + filename: String, + /// The entry title. + #[arg(long)] + title: Option<String>, + /// The entry album. + #[arg(long)] + album: Option<String>, + /// The entry artist. + #[arg(long)] + artist: Option<String>, + /// The file size in bytes. + #[arg(long)] + size: Option<i64>, + /// The track length in h:m:s. + #[arg(long)] + duration: Option<String>, + /// True if the entry should not be published. + #[arg(long)] + hidden: Option<bool>, +} + +#[derive(clap::Args, Debug)] +struct AddTemplateArgs { + /// True if the template should be rendered once for all entries. + #[arg(long)] + index: bool, + #[arg(long)] + partial: bool, + #[arg(long)] + content_type: Option<String>, + #[arg(long)] + filter: Option<String>, + /// The template filename. + filename: PathBuf, + /// The rendered filename. + name: String, +} + +#[tokio::main] +async fn main() -> Result<(), Box<dyn Error>> { + env_logger::Builder::from_env(Env::default().default_filter_or("info")).init(); + + let args = Args::parse(); + let config = aws_config::load_from_env().await; + let client = aws_sdk_s3::Client::new(&config); + + let access = Access::new(client, args.bucket); + let mut feed = MP32RSS::open(access).await?; + + match args.command { + Command::Refresh => feed.refresh().await, + Command::Render => feed.render(|_| true).await, + Command::Edit(edit_args) => update_entry(&mut feed, edit_args).await, + Command::Delete { filename } => feed.delete(&filename).await, + Command::Templates => list_templates(&feed), + Command::AddTemplate(add_template_args) => add_template(&mut feed, add_template_args).await, + Command::RemoveTemplate { name } => feed.delete_template(&name).await, + } +} + +async fn update_entry(feed: &mut MP32RSS, args: EditArgs) -> Result<(), Box<dyn Error>> { + if let Some(entry) = feed.get_mut_entry(&args.filename) { + if let Some(v) = args.title { + entry.title = Some(v); + } + if let Some(v) = args.album { + entry.album = Some(v); + } + if let Some(v) = args.artist { + entry.artist = Some(v); + } + if let Some(v) = args.size { + entry.size = v; + } + if let Some(v) = args.duration { + entry.duration = hms_duration::from_string(v)?; + } + if let Some(v) = args.hidden { + entry.hidden = v; + } + } + feed.render(|e| e.filename == args.filename).await +} + +fn list_templates(feed: &MP32RSS) -> Result<(), Box<dyn Error>> { + println!( + "{:<20} {:<5} {:<7} content-type", + "name", "index", "partial" + ); + println!("{:-<20} {:-<5} {:-<7} {:-<12}", "", "", "", ""); + for template in feed.templates() { + println!( + "{:<20} {:<5} {:<7} {}", + template.name, + if template.index { "index" } else { "" }, + if template.partial { "partial" } else { "" }, + template.content_type.as_deref().unwrap_or("text/html") + ); + } + Ok(()) +} + +async fn add_template(feed: &mut MP32RSS, args: AddTemplateArgs) -> Result<(), Box<dyn Error>> { + let mut file = File::open(&args.filename).await?; + let mut data = String::new(); + file.read_to_string(&mut data).await?; + feed.add_template( + args.name, + data, + args.index, + args.partial, + args.content_type, + args.filter, + ) + .await +} |