use clap::{Parser, Subcommand};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Parser)]
#[command(name = "autoreply")]
#[command(about = "Bluesky profile and post search utility", long_about = None)]
#[command(version)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
#[arg(short, long, global = true)]
pub verbose: bool,
#[arg(long, global = true)]
pub quiet: bool,
}
#[derive(Subcommand)]
pub enum Commands {
Profile(ProfileArgs),
Search(SearchArgs),
Login(LoginCommand),
}
#[derive(Parser, JsonSchema, Deserialize, Serialize, Clone, Debug)]
pub struct ProfileArgs {
#[arg(short = 'a', long)]
#[schemars(description = "Handle (alice.bsky.social) or DID (did:plc:...)")]
pub account: String,
}
#[derive(Parser, JsonSchema, Deserialize, Serialize, Clone, Debug)]
pub struct SearchArgs {
#[arg(short = 'a', long)]
#[schemars(description = "Handle or DID")]
pub account: String,
#[arg(short = 'q', long)]
#[schemars(description = "Search terms (case-insensitive)")]
pub query: String,
#[arg(short = 'l', long)]
#[schemars(description = "Maximum number of results (default 50, max 200)")]
pub limit: Option<usize>,
}
#[derive(Parser, Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct LoginCommand {
#[command(subcommand)]
pub command: Option<LoginSubcommands>,
#[arg(short = 'u', long, global = true)]
pub handle: Option<String>,
#[arg(short = 'p', long, num_args = 0..=1, default_missing_value = "", global = true)]
pub password: Option<String>,
#[arg(short = 's', long, global = true)]
pub service: Option<String>,
#[arg(skip = Option::<String>::None)]
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(description = "Opaque prompt identifier used when responding to MCP login prompts")]
pub prompt_id: Option<String>,
}
#[derive(Subcommand, Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub enum LoginSubcommands {
List,
Default {
handle: String,
},
Delete {
#[arg(short = 'u', long)]
handle: Option<String>,
},
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_profile_args() {
let args = ProfileArgs {
account: "alice.bsky.social".to_string(),
};
assert_eq!(args.account, "alice.bsky.social");
}
#[test]
fn test_search_args() {
let args = SearchArgs {
account: "bob.bsky.social".to_string(),
query: "rust programming".to_string(),
limit: Some(10),
};
assert_eq!(args.account, "bob.bsky.social");
assert_eq!(args.query, "rust programming");
assert_eq!(args.limit, Some(10));
}
}