use clap::{Parser, Subcommand}; // use time::OffsetDateTime; use forgejo_api::Auth::Token; use forgejo_api::Forgejo; use forgejo_api::structs::CreateReleaseOption; use url::Url; use std::io; pub mod config; #[derive(Debug, Parser)] #[clap( name = "forge-auto", version = "1.0", about = "Automate routine tasks in Forgejo" )] struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Debug, Subcommand)] enum Commands { /// A subcommand with its own subcommands #[clap(subcommand)] Release(ReleaseSubCommands), } #[derive(Debug, Subcommand)] enum ReleaseSubCommands { /// A sub-subcommand New { alias: String, tag: String, #[clap(long, short)] target: Option, }, /// Another sub-subcommand List { alias: String }, } async fn handle_new_release( config: &config::Config, alias: &str, tag: &str, target: &Option, ) -> Result<(), String> { println!("Creating new release with alias: {}, tag: {}", alias, tag); let repo = config.repos.get(alias).map_or_else( || Err(format!("No repository found with alias: {}", alias)), |repo| { println!("Using repository: {} owned by {}", repo.repo, repo.owner); // Here you would typically call the Forgejo API to create a new release // For example: Ok(repo) }, )?; let token = Token(&repo.token); let url = Url::parse(&repo.hostname).map_err(|e| { eprintln!("Failed to parse URL: {}", e); e.to_string() })?; let forgejo = Forgejo::new(token, url).map_err(|e| { eprintln!("Failed to create Forgejo client: {}", e); e.to_string() })?; if target.is_none() { println!("Target not provided for creating a release."); println!("Please confirm by typing 'yes' that you want to create automatically with the latest commit."); let mut input = String::new(); io::stdin() .read_line(&mut input) .expect("Failed to read line"); if input.trim().to_lowercase() != "yes" { return Err("Release creation cancelled by user.".to_string()); } } let option = CreateReleaseOption { tag_name: tag.to_string(), name: Some(format!("{}", tag)), body: Some(format!("Release {}", tag)), hide_archive_links: Some(false), target_commitish: target.clone(), draft: None, prerelease: None, }; forgejo .repo_create_release(&repo.owner, &repo.repo, option) .await .map_err(|e| { eprintln!("Failed to create release: {}", e); e.to_string() })?; Ok(()) } async fn handle_list_releases(config: &config::Config, alias: &str) -> Result<(), String> { println!("Listing releases for all repositories"); let repo = config.repos.get(alias).map_or_else( || Err(format!("No repository found with alias: {}", alias)), |repo| { println!("Using repository: {} owned by {}", repo.repo, repo.owner); // Here you would typically call the Forgejo API to create a new release // For example: Ok(repo) }, )?; let token = Token(&repo.token); let url = Url::parse(&repo.hostname).map_err(|e| { eprintln!("Failed to parse URL: {}", e); e.to_string() })?; let forgejo = Forgejo::new(token, url).map_err(|e| { eprintln!("Failed to create Forgejo client: {}", e); e.to_string() })?; let query = forgejo_api::structs::RepoListReleasesQuery { draft: None, page: None, q: None, pre_release: None, limit: Some(100), }; let result_query = forgejo .repo_list_releases(&repo.owner, &repo.repo, query) .await .map_err(|e| { eprintln!("Failed to list releases: {}", e); e.to_string() })?; for release in result_query.1 { println!( "Release: {}, Tag: {}, Created at: {}", release.name.unwrap_or_default(), release.tag_name.unwrap_or("N/A".to_string()), release.created_at.unwrap() ); } Ok(()) } #[tokio::main] async fn main() -> Result<(), Box> { let args = Cli::parse(); let config = config::load_config("config.ini").expect("Failed to load config"); match args.command { Commands::Release(subcommand) => { match subcommand { ReleaseSubCommands::New { alias, tag, target } => { handle_new_release(&config, &alias, &tag, &target).await? } ReleaseSubCommands::List { alias } => { handle_list_releases(&config, &alias).await?; } } // Uncomment the following lines if you want to use the dispatch macro // dispatch!(subcommand, // SubCommands::SubSubCommand { input } => handle_sub_sub_command(&input), // SubCommands::AnotherSubSubCommand { output } => handle_another_sub_sub_command(&output), // ); } } Ok(()) }