1use clap::Parser;
2use jacquard::CowStr;
3use jacquard::api::com_whtwnd::blog::entry::Entry;
4use jacquard::client::{Agent, FileAuthStore};
5use jacquard::oauth::atproto::AtprotoClientMetadata;
6use jacquard::oauth::client::OAuthClient;
7use jacquard::oauth::loopback::LoopbackConfig;
8use jacquard::types::string::Datetime;
9use jacquard::xrpc::XrpcClient;
10use miette::IntoDiagnostic;
11use url::Url;
12
13#[derive(Parser, Debug)]
14#[command(author, version, about = "Create a WhiteWind blog post")]
15struct Args {
16 /// Handle (e.g., alice.bsky.social), DID, or PDS URL
17 input: CowStr<'static>,
18
19 /// Blog post title
20 #[arg(short, long)]
21 title: String,
22
23 /// Blog post content (markdown)
24 #[arg(short, long)]
25 content: String,
26
27 /// Optional subtitle
28 #[arg(short, long)]
29 subtitle: Option<String>,
30
31 /// Path to auth store file (will be created if missing)
32 #[arg(long, default_value = "/tmp/jacquard-oauth-session.json")]
33 store: String,
34}
35
36#[tokio::main]
37async fn main() -> miette::Result<()> {
38 let args = Args::parse();
39
40 let oauth = OAuthClient::with_default_config(FileAuthStore::new(&args.store));
41 let session = oauth
42 .login_with_local_server(args.input, Default::default(), LoopbackConfig::default())
43 .await?;
44
45 let agent: Agent<_> = Agent::from(session);
46
47 // Create a WhiteWind blog entry
48 // The content field accepts markdown
49 let entry = Entry {
50 title: Some(CowStr::from(args.title)),
51 subtitle: args.subtitle.map(CowStr::from),
52 content: CowStr::from(args.content),
53 created_at: Some(Datetime::now()),
54 visibility: Some(CowStr::from("url")), // "url" = public with link, "author" = public on profile
55 theme: None,
56 ogp: None,
57 blobs: None,
58 is_draft: None,
59 extra_data: Default::default(),
60 };
61
62 let mut output = agent.create_record(entry, None).await?;
63 println!("Created WhiteWind blog post: {}", output.uri);
64 let url = Url::parse(format!(
65 "https://whtwnd.nat.vg/{}/{}",
66 output.uri.authority(),
67 output.uri.rkey().map(|r| r.as_ref()).unwrap_or("")
68 ))
69 .into_diagnostic()?;
70 println!("View at: {}", url);
71
72 Ok(())
73}