use atrium_api::com::atproto::repo::put_record::InputData;
use atrium_api::types::string::RecordKey;
use atrium_api::{
agent::atp_agent::{AtpAgent, store::MemorySessionStore},
app::bsky::feed::generator::RecordData,
types::{
TryIntoUnknown,
string::{Datetime, Did, Handle, Nsid},
},
};
use clap::Parser;
#[derive(Parser, Debug)]
struct Args {
#[arg(long)]
name: String,
#[arg(long)]
display_name: String,
#[arg(long)]
description: String,
#[arg(long)]
avatar_filename: Option<String>,
#[arg(long)]
handle: String,
#[arg(long)]
app_password: String,
#[arg(long)]
hostname: String,
}
pub const XRPC_HOST: &str = "https://bsky.social";
#[tokio::main]
async fn main() {
let args = Args::parse();
let handle = args.handle;
let password = args.app_password;
let feed_host_name = args.hostname;
let record_key = RecordKey::new(args.name.to_owned()).expect("Invalid record key name.");
println!("Logging in...");
let agent = AtpAgent::new(
atrium_xrpc_client::reqwest::ReqwestClient::new(XRPC_HOST),
MemorySessionStore::default(),
);
agent
.login(handle.clone(), password)
.await
.expect("Login failed");
println!("Fetching your DID...");
let publisher_did = agent
.api
.com
.atproto
.identity
.resolve_handle(
atrium_api::com::atproto::identity::resolve_handle::ParametersData {
handle: Handle::new(handle.to_owned()).unwrap(),
}
.into(),
)
.await
.unwrap();
let mut avatar = None;
if let Some(path) = args.avatar_filename {
println!("Uploading avatar image...");
let bytes = std::fs::read(path).expect("Couldn't read specified avatar file");
avatar = Some(
agent
.api
.com
.atproto
.repo
.upload_blob(bytes)
.await
.expect("Avatar upload failed"),
);
println!("Uploaded avatar");
}
println!("Publishing feed...");
agent
.api
.com
.atproto
.repo
.put_record(
InputData {
collection: Nsid::new("app.bsky.feed.generator".to_owned()).unwrap(),
record: RecordData {
accepts_interactions: None,
#[allow(unreachable_code)]
avatar: avatar.map(|a| a.blob.clone()),
content_mode: None,
created_at: Datetime::now(),
description: Some(args.description.to_owned()),
description_facets: None,
did: Did::new(format!("did:web:{}", feed_host_name)).unwrap(),
display_name: args.display_name.to_owned(),
labels: None,
}
.try_into_unknown()
.unwrap(),
repo: atrium_api::types::string::AtIdentifier::Did(
publisher_did.to_owned().did.clone(),
),
rkey: record_key,
swap_commit: None,
swap_record: None,
validate: None,
}
.into(),
)
.await
.expect("Publishing failed");
println!("Successfully published");
}