rujira 0.4.1

This module provides an API for working with Jira
Documentation
use clap::{arg, Args, Parser, Subcommand};
use dotenv::dotenv;
use rujira::{agile, api, Rujira};
use serde_json::json;
use tracing_subscriber::{fmt, EnvFilter};

#[derive(Parser, Debug)]
#[command(name = "itcast")]
pub struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Debug, Subcommand)]
enum Commands {
    Project(ProjectArgs),
    Issue(IssueArgs),
    Board(BoardArgs),
    Sprint(SprintArgs),
    Myself,
}

#[derive(Debug, Args)]
struct ProjectArgs {
    #[command(subcommand)]
    command: ProjectCommands,
}
#[derive(Debug, Args)]
struct IssueArgs {
    #[command(subcommand)]
    command: IssueCommands,
}
#[derive(Debug, Args)]
struct BoardArgs {
    #[command(subcommand)]
    command: BoardCommands,
}
#[derive(Debug, Args)]
struct SprintArgs {
    #[command(subcommand)]
    command: SprintCommands,
}
#[derive(Debug, Subcommand)]
enum ProjectCommands {
    Create {
        key: String,
        #[arg(short, long)]
        name: String,
        #[arg(short, long, default_value_t = String::from("software"))]
        r#type: String,
        #[arg(short, long)]
        lead: String,
    },
    Delete {
        key: String,
    },
    Update {
        key: String,
        #[arg(short, long)]
        expand: Option<String>,
        #[arg(short, long)]
        update: String,
    },
    List {
        #[arg(short, long)]
        include_archive: Option<bool>,
        #[arg(short, long)]
        browse_archive: Option<bool>,
        #[arg(short, long)]
        expand: Option<String>,
        #[arg(short, long)]
        recent: Option<u8>,
    },
}
#[derive(Debug, Subcommand)]
enum IssueCommands {
    Create {
        project: String,
        #[arg(short, long)]
        summary: String,
        #[arg(short, long)]
        description: String,
        #[arg(short, long, default_value_t = String::from("Task"))]
        r#type: String,
    },
    Edit {
        key: String,
        #[arg(short, long)]
        sprint: String,
    },
    Get {
        key: String,
    },
    Delete {
        key: String,
    },
}
#[derive(Debug, Subcommand)]
enum BoardCommands {
    Get { key: String },
    List {},
}
#[derive(Debug, Subcommand)]
enum SprintCommands {
    List { board: String },
    Get { key: String },
    Issue { key: String, task: String },
}

#[tokio::main]
async fn main() {
    dotenv().ok();
    fmt()
        .with_env_filter(EnvFilter::from_default_env())
        .compact()
        .init();
    let bot = Rujira::new().from_env_handler();
    let args = Cli::parse();
    match args.command {
        Commands::Myself => {
            let me = match crate::api::myself::get(bot).apply().await {
                Ok(rs) => rs,
                Err(e) => {
                    eprintln!("{e}");
                    panic!();
                }
            };
            println!("{me:#?}");
        }
        Commands::Issue(s) => match s.command {
            IssueCommands::Create {
                project,
                summary,
                description,
                r#type,
            } => {
                let fields = json!({
                    "project": { "key": &project },
                    "summary": &summary,
                    "description": &description,
                    "issuetype": { "name": &r#type },
                });
                let issue = crate::api::issue::create(bot.clone(), fields, false)
                    .apply()
                    .await
                    .unwrap();
                println!("{issue:#?}");
            }
            IssueCommands::Edit { key, sprint } => {
                let payload = json!({
                    "sprint": { "name": sprint }
                });
                let issue = crate::api::issue::edit(bot.clone(), &key, None, Some(payload), None)
                    .apply()
                    .await
                    .unwrap();
                println!("{issue:#?}");
            }
            IssueCommands::Get { key } => {
                let issue = crate::api::issue::get(bot.clone(), &key, None, None, None, None)
                    .apply()
                    .await
                    .unwrap();
                println!("{issue:#?}");
            }
            _ => todo!(),
        },
        Commands::Project(s) => match s.command {
            ProjectCommands::Update {
                key,
                update,
                expand,
            } => {
                // ### Example
                // ```
                // cargo run --example cli -- project update T1 -u '{"name":"new"}'
                // ```
                let update = serde_json::from_str(&update).unwrap();
                let project = api::project::update(bot.clone(), &key, update, expand.as_deref())
                    .apply()
                    .await
                    .unwrap();
                println!("{project:#?}");
            }
            ProjectCommands::List {
                include_archive,
                browse_archive,
                expand,
                recent,
            } => {
                let projects = api::project::list(
                    bot.clone(),
                    include_archive,
                    browse_archive,
                    // TOASK: Why it is as_deref working?
                    expand.as_deref(),
                    recent,
                )
                .apply()
                .await
                .unwrap();
                println!("{projects:#?}");
            }
            ProjectCommands::Create {
                key,
                name,
                r#type,
                lead,
            } => {
                api::project::create(bot.clone(), &key, &name, &r#type, &lead)
                    .apply()
                    .await
                    .unwrap();
            }
            ProjectCommands::Delete { key } => {
                api::project::delete(bot.clone(), &key)
                    .apply()
                    .await
                    .unwrap();
            }
        },
        Commands::Board(s) => match s.command {
            BoardCommands::List {} => {
                let boards = agile::board::list(bot.clone(), None, None, None, None, None)
                    .apply()
                    .await
                    .unwrap();
                println!("{boards:#?}");
            }
            BoardCommands::Get { key } => {
                let board = agile::board::get(bot.clone(), &key).apply().await.unwrap();
                println!("{board:#?}");
            }
        },
        Commands::Sprint(s) => match s.command {
            SprintCommands::List { board } => {
                let sprints = agile::sprint::list(bot.clone(), &board, None, None, None)
                    .apply()
                    .await
                    .unwrap();
                println!("{sprints:#?}");
            }
            SprintCommands::Get { key } => {
                let sprint = agile::sprint::get(bot.clone(), &key).apply().await.unwrap();
                println!("{sprint:#?}");
            }
            SprintCommands::Issue { key, task } => {
                let payload = json!([task]);
                let sprint = agile::sprint::issue(bot.clone(), &key, payload)
                    .apply()
                    .await
                    .unwrap();
                println!("{sprint:#?}");
            }
        },
    }
}