2
0

add chat post

This commit is contained in:
2026-03-24 20:39:32 +09:00
parent bf33706688
commit 72a3d34395
3 changed files with 91 additions and 0 deletions

75
src/commands/chat_post.rs Normal file
View File

@@ -0,0 +1,75 @@
use anyhow::{Context, Result};
use serde_json::{json, Value};
use super::auth;
use super::token;
use crate::xrpc::XrpcClient;
const CHAT_PROXY_HEADER: &str = "did:web:bsky.syu.is#bsky_chat";
/// Load chat proxy DID from config or use default
fn load_chat_proxy() -> Result<String> {
let config = token::load_config()?;
if let Some(network) = config["network"].as_str() {
Ok(format!("did:web:bsky.{}#bsky_chat", network))
} else {
Ok(CHAT_PROXY_HEADER.to_string())
}
}
/// Send a DM via chat.bsky.convo.sendMessage
pub async fn post(text: &str, is_bot: bool, did: &str) -> Result<()> {
let session = if is_bot {
auth::refresh_bot_session().await?
} else {
auth::refresh_session().await?
};
let pds = session.pds.as_deref().unwrap_or("syu.is");
let client = if is_bot {
XrpcClient::new_bot(pds)
} else {
XrpcClient::new(pds)
};
let proxy = load_chat_proxy()?;
// Get or create convo with the target DID
let convo_resp: Value = client
.query_auth_proxy(
"chat.bsky.convo.getConvoForMembers",
&[("members", did)],
&session.access_jwt,
&proxy,
)
.await
.context("Failed to get convo for members")?;
let convo_id = convo_resp["convo"]["id"]
.as_str()
.context("No convo id in response")?;
// Send message
let send_body = json!({
"convoId": convo_id,
"message": {
"text": text
}
});
let result: Value = client
.call_proxy(
"chat.bsky.convo.sendMessage",
&send_body,
&session.access_jwt,
&proxy,
)
.await
.context("Failed to send message")?;
let msg_id = result["id"].as_str().unwrap_or("unknown");
println!("{}", json!({
"id": msg_id,
"convoId": convo_id,
}));
Ok(())
}

View File

@@ -15,3 +15,4 @@ pub mod gpt;
pub mod oauth;
pub mod setup;
pub mod twofa;
pub mod chat_post;

View File

@@ -169,6 +169,18 @@ enum Commands {
new: bool,
},
/// Send a DM via chat.bsky.convo
ChatPost {
/// Message text
text: String,
/// Target user DID
#[arg(short, long)]
did: String,
/// Send as bot (uses bot.json)
#[arg(long)]
bot: bool,
},
/// Run MCP server (for Claude Code integration)
#[command(name = "mcp-serve")]
McpServe,
@@ -388,6 +400,9 @@ async fn main() -> Result<()> {
Commands::Chat { message, new } => {
lms::chat::run(message.as_deref(), new).await?;
}
Commands::ChatPost { text, did, bot } => {
commands::chat_post::post(&text, bot, &did).await?;
}
Commands::McpServe => {
mcp::serve()?;
}