chore: remove CLAUDE.md and stale config files

This commit is contained in:
Dorian
2026-04-12 12:11:00 -04:00
parent c71d543f4c
commit 53bea2124d
13 changed files with 198 additions and 249 deletions

View File

@@ -9,6 +9,7 @@ impl ApiHandler {
#[derive(serde::Deserialize)]
struct Incoming {
from_pubkey: Option<String>,
from_name: Option<String>,
message: Option<String>,
signature: Option<String>,
#[serde(default)]
@@ -67,7 +68,8 @@ impl ApiHandler {
tracing::info!("Received message from {}: {}", safe_from, safe_msg);
let clean_from = sanitize_html(from);
let clean_msg = sanitize_html(&plaintext);
node_msg::store_received(&clean_from, &clean_msg).await;
let clean_name = incoming.from_name.as_deref().map(sanitize_html);
node_msg::store_received(&clean_from, &clean_msg, clean_name.as_deref()).await;
}
Ok(build_response(StatusCode::OK, "application/json", hyper::Body::from(r#"{"ok":true}"#)))
}

View File

@@ -288,6 +288,7 @@ impl RpcHandler {
"mesh.peers" => self.handle_mesh_peers().await,
"mesh.messages" => self.handle_mesh_messages(params).await,
"mesh.send" => self.handle_mesh_send(params).await,
"mesh.send-channel" => self.handle_mesh_send_channel(params).await,
"mesh.broadcast" => self.handle_mesh_broadcast().await,
"mesh.configure" => self.handle_mesh_configure(params).await,
"mesh.send-invoice" => self.handle_mesh_send_invoice(params).await,

View File

@@ -40,6 +40,42 @@ impl RpcHandler {
}))
}
/// mesh.send-channel — Send a text message to a mesh channel (broadcast).
pub(in crate::api::rpc) async fn handle_mesh_send_channel(
&self,
params: Option<serde_json::Value>,
) -> Result<serde_json::Value> {
let params = params.ok_or_else(|| anyhow::anyhow!("Missing params"))?;
let channel = params
.get("channel")
.and_then(|v| v.as_u64())
.unwrap_or(0) as u8;
let message = params
.get("message")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("Missing message"))?;
if message.is_empty() {
anyhow::bail!("Message cannot be empty");
}
let service = self.mesh_service.read().await;
let svc = service
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Mesh service not running. Enable mesh first."))?;
let msg = svc.send_channel_message(channel, message).await?;
info!(channel, "Sent mesh channel message");
Ok(serde_json::json!({
"sent": true,
"message_id": msg.id,
"channel": channel,
}))
}
/// mesh.broadcast — Broadcast our node identity over mesh.
pub(in crate::api::rpc) async fn handle_mesh_broadcast(&self) -> Result<serde_json::Value> {
let service = self.mesh_service.read().await;

View File

@@ -101,12 +101,16 @@ impl RpcHandler {
|| format!("{}.onion", n.onion) == onion)
.map(|n| n.pubkey.clone());
// Include our node name so the recipient can display it
let node_name = data.server_info.name.clone();
node_message::send_to_peer(
onion,
&pubkey,
message,
Some(node_id.signing_key()),
recipient_pubkey.as_deref(),
node_name.as_deref(),
).await?;
Ok(serde_json::json!({ "ok": true, "sent_to": onion }))
}

View File

@@ -509,6 +509,59 @@ impl MeshService {
Ok(msg)
}
/// Send a message to a mesh channel (broadcast).
/// Routes through the background listener which owns the serial port.
pub async fn send_channel_message(&self, channel: u8, text: &str) -> Result<MeshMessage> {
let status = self.state.status.read().await;
if !status.device_connected {
anyhow::bail!("No mesh device connected");
}
drop(status);
let payload = text.as_bytes().to_vec();
if payload.len() > protocol::MAX_MESSAGE_LEN {
anyhow::bail!(
"Message too large for LoRa: {} bytes (max {})",
payload.len(),
protocol::MAX_MESSAGE_LEN
);
}
// Send through the listener's command channel
self.state
.cmd_tx
.send(listener::MeshCommand::BroadcastChannel {
channel,
payload,
})
.await
.map_err(|_| anyhow::anyhow!("Mesh listener not running"))?;
let chan_contact_id = u32::MAX - (channel as u32);
let chan_name = format!("Channel {}", channel);
let msg_id = self.state.next_id().await;
let msg = MeshMessage {
id: msg_id,
direction: MessageDirection::Sent,
peer_contact_id: chan_contact_id,
peer_name: Some(chan_name),
plaintext: text.to_string(),
timestamp: chrono::Utc::now().to_rfc3339(),
delivered: false,
encrypted: false,
};
self.state.store_message(msg.clone()).await;
{
let mut status = self.state.status.write().await;
status.messages_sent += 1;
}
Ok(msg)
}
/// Broadcast our advertisement over mesh so other nodes can discover us.
/// Sends an immediate advert via the listener's command channel.
pub async fn broadcast_identity(&self) -> Result<()> {

View File

@@ -14,6 +14,9 @@ pub struct IncomingMessage {
pub from_pubkey: String,
#[serde(default)]
pub from_onion: Option<String>,
/// Sender's node name (for display in group chat).
#[serde(default)]
pub from_name: Option<String>,
pub message: String,
pub timestamp: String,
/// "sent" or "received"
@@ -73,7 +76,7 @@ fn persist() {
}
/// Store a received message (called from HTTP handler).
pub fn store_received_sync(from_pubkey: &str, message: &str) {
pub fn store_received_sync(from_pubkey: &str, message: &str, from_name: Option<&str>) {
let ts = chrono::Utc::now().to_rfc3339();
let mut guard = store().lock().unwrap_or_else(|e| e.into_inner());
@@ -89,6 +92,7 @@ pub fn store_received_sync(from_pubkey: &str, message: &str) {
guard.messages.push(IncomingMessage {
from_pubkey: from_pubkey.to_string(),
from_onion: None,
from_name: from_name.map(|s| s.to_string()),
message: message.to_string(),
timestamp: ts,
direction: "received".to_string(),
@@ -98,8 +102,8 @@ pub fn store_received_sync(from_pubkey: &str, message: &str) {
persist();
}
pub async fn store_received(from_pubkey: &str, message: &str) {
store_received_sync(from_pubkey, message);
pub async fn store_received(from_pubkey: &str, message: &str, from_name: Option<&str>) {
store_received_sync(from_pubkey, message, from_name);
}
/// Store a sent message (for display in Archipelago channel).
@@ -231,6 +235,7 @@ pub async fn send_to_peer(
message: &str,
signing_key: Option<&ed25519_dalek::SigningKey>,
recipient_pubkey: Option<&str>,
from_name: Option<&str>,
) -> Result<()> {
validate_onion(onion)?;
@@ -255,12 +260,15 @@ pub async fn send_to_peer(
_ => (message.to_string(), false),
};
let body = serde_json::json!({
let mut body = serde_json::json!({
"from_pubkey": from_pubkey,
"message": payload_message,
"timestamp": chrono::Utc::now().to_rfc3339(),
"encrypted": encrypted,
});
if let Some(name) = from_name {
body["from_name"] = serde_json::Value::String(name.to_string());
}
let proxy = reqwest::Proxy::all(crate::constants::TOR_SOCKS_PROXY).context("Invalid Tor proxy")?;
let client = reqwest::Client::builder()