chore: remove CLAUDE.md and stale config files
This commit is contained in:
@@ -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}"#)))
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 }))
|
||||
}
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user