add chat post
This commit is contained in:
75
src/commands/chat_post.rs
Normal file
75
src/commands/chat_post.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -15,3 +15,4 @@ pub mod gpt;
|
|||||||
pub mod oauth;
|
pub mod oauth;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod twofa;
|
pub mod twofa;
|
||||||
|
pub mod chat_post;
|
||||||
|
|||||||
15
src/main.rs
15
src/main.rs
@@ -169,6 +169,18 @@ enum Commands {
|
|||||||
new: bool,
|
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)
|
/// Run MCP server (for Claude Code integration)
|
||||||
#[command(name = "mcp-serve")]
|
#[command(name = "mcp-serve")]
|
||||||
McpServe,
|
McpServe,
|
||||||
@@ -388,6 +400,9 @@ async fn main() -> Result<()> {
|
|||||||
Commands::Chat { message, new } => {
|
Commands::Chat { message, new } => {
|
||||||
lms::chat::run(message.as_deref(), new).await?;
|
lms::chat::run(message.as_deref(), new).await?;
|
||||||
}
|
}
|
||||||
|
Commands::ChatPost { text, did, bot } => {
|
||||||
|
commands::chat_post::post(&text, bot, &did).await?;
|
||||||
|
}
|
||||||
Commands::McpServe => {
|
Commands::McpServe => {
|
||||||
mcp::serve()?;
|
mcp::serve()?;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user