summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs167
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
+}