refactor: Remove unused imports and handle unused results
Build and Push Docker Image / build_docker_image (push) Successful in 16m28s

This commit performs general code cleanup to improve quality and address compiler warnings.

Unused import statements have been removed from several files, including `HashSet`, `anyhow`, `log::error`, `serde::Deserialize`, and `serde_json::Value`. This declutters the code and makes dependencies clearer.

Additionally, the `Result` returned by `RelayMessage::send_ok` and `RelayMessage::send_notice` is now explicitly ignored. This resolves `must_use` warnings for these fire-and-forget message sending functions, where error handling is not critical to the application's flow.
This commit is contained in:
2025-09-22 16:56:00 +08:00
parent 7ac67102ef
commit b64ec550e0
7 changed files with 128 additions and 51 deletions
-1
View File
@@ -4,7 +4,6 @@ use anyhow::Result;
use log::error; use log::error;
use sqlx::sqlite::SqlitePool; use sqlx::sqlite::SqlitePool;
use sqlx::{Row, query}; use sqlx::{Row, query};
use std::collections::HashSet;
pub async fn init_database(pool: &SqlitePool) -> Result<()> { pub async fn init_database(pool: &SqlitePool) -> Result<()> {
let create_events_table = r#" let create_events_table = r#"
+1 -2
View File
@@ -1,6 +1,5 @@
use anyhow::{Result, anyhow}; use anyhow::Result;
use httparse::{EMPTY_HEADER, Request}; use httparse::{EMPTY_HEADER, Request};
use log::{error, info};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::nostr::Filter; use crate::nostr::Filter;
use serde::{Deserialize, Serialize}; use serde::Serialize;
use std::collections::HashMap; use std::collections::HashMap;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use uuid::Uuid; use uuid::Uuid;
+18 -13
View File
@@ -1,9 +1,9 @@
use anyhow::Result; use anyhow::Result;
use log::{debug, error, info}; use log::{debug, info};
use secp256k1::{ use secp256k1::{
Message as SecpMessage, Secp256k1, XOnlyPublicKey, schnorr::Signature as SchnorrSignature, Message as SecpMessage, Secp256k1, XOnlyPublicKey, schnorr::Signature as SchnorrSignature,
}; };
use serde_json::{Value, json}; use serde_json::json;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use sqlx::SqlitePool; use sqlx::SqlitePool;
use std::{ use std::{
@@ -31,7 +31,7 @@ pub trait NostrEventExt {
impl NostrEventExt for NostrEvent { impl NostrEventExt for NostrEvent {
// 根据 Nostr 协议规则序列化事件,用于计算事件 ID // 根据 Nostr 协议规则序列化事件,用于计算事件 ID
fn serialize_for_id(&self) -> String { fn serialize_for_id(&self) -> String {
let serialized = json!([ json!([
0, // 用于 ID 计算的协议版本,Nostr 当前为 0 0, // 用于 ID 计算的协议版本,Nostr 当前为 0
self.pubkey, self.pubkey,
self.created_at, self.created_at,
@@ -39,8 +39,7 @@ impl NostrEventExt for NostrEvent {
self.tags, self.tags,
self.content self.content
]) ])
.to_string(); .to_string()
serialized
} }
// 验证事件的有效性(ID、时间戳、标签数量、签名) // 验证事件的有效性(ID、时间戳、标签数量、签名)
@@ -259,7 +258,7 @@ impl NostrEventExt for NostrEvent {
) -> Result<(), anyhow::Error> { ) -> Result<(), anyhow::Error> {
// 1. 验证事件类型是否为 NIP-42 认证事件 (kind 22242) // 1. 验证事件类型是否为 NIP-42 认证事件 (kind 22242)
if self.kind != 22242 { if self.kind != 22242 {
RelayMessage::send_ok( let _ = RelayMessage::send_ok(
&self.id, &self.id,
false, false,
"AUTH event must be kind 22242".to_string(), // 根据协议,OK 消息应包含事件 ID "AUTH event must be kind 22242".to_string(), // 根据协议,OK 消息应包含事件 ID
@@ -271,8 +270,11 @@ impl NostrEventExt for NostrEvent {
// 2. 验证事件签名是否有效 // 2. 验证事件签名是否有效
if !self.verify() { if !self.verify() {
RelayMessage::send_notice("Invalid AUTH event signature".to_string(), to_client_msg_tx) let _ = RelayMessage::send_notice(
.await; "Invalid AUTH event signature".to_string(),
to_client_msg_tx,
)
.await;
return Ok(()); return Ok(());
} }
@@ -293,7 +295,7 @@ impl NostrEventExt for NostrEvent {
let challenge = match challenge { let challenge = match challenge {
Some(c) => c, Some(c) => c,
None => { None => {
RelayMessage::send_notice( let _ = RelayMessage::send_notice(
"AUTH event missing challenge tag".to_string(), "AUTH event missing challenge tag".to_string(),
to_client_msg_tx, to_client_msg_tx,
) )
@@ -318,8 +320,11 @@ impl NostrEventExt for NostrEvent {
}; };
if !is_valid_challenge { if !is_valid_challenge {
RelayMessage::send_notice("Invalid or expired challenge".to_string(), to_client_msg_tx) let _ = RelayMessage::send_notice(
.await; "Invalid or expired challenge".to_string(),
to_client_msg_tx,
)
.await;
return Ok(()); return Ok(());
} }
@@ -329,7 +334,7 @@ impl NostrEventExt for NostrEvent {
.unwrap_or(Duration::ZERO) .unwrap_or(Duration::ZERO)
.as_secs(); .as_secs();
if self.created_at < now.saturating_sub(60) || self.created_at > now + 60 { if self.created_at < now.saturating_sub(60) || self.created_at > now + 60 {
RelayMessage::send_notice( let _ = RelayMessage::send_notice(
"AUTH event timestamp out of acceptable range (must be within 60s of now)" "AUTH event timestamp out of acceptable range (must be within 60s of now)"
.to_string(), .to_string(),
to_client_msg_tx, to_client_msg_tx,
@@ -347,7 +352,7 @@ impl NostrEventExt for NostrEvent {
info!("Client authenticated with pubkey: {}", self.pubkey); info!("Client authenticated with pubkey: {}", self.pubkey);
// 根据 NIP-42,认证成功也应该回复 OK 消息 // 根据 NIP-42,认证成功也应该回复 OK 消息
RelayMessage::send_ok( let _ = RelayMessage::send_ok(
&self.id, &self.id,
true, true,
"Authentication successful.".to_string(), "Authentication successful.".to_string(),
-1
View File
@@ -2,7 +2,6 @@ use anyhow::Result;
use log::debug; use log::debug;
use sqlx::sqlite::SqlitePool; use sqlx::sqlite::SqlitePool;
use sqlx::{Execute, QueryBuilder, Row}; use sqlx::{Execute, QueryBuilder, Row};
use std::collections::HashMap;
use crate::constants::{DEFAULT_LIMIT, MAX_LIMIT}; use crate::constants::{DEFAULT_LIMIT, MAX_LIMIT};
use crate::nostr::Filter; use crate::nostr::Filter;
+56 -17
View File
@@ -3,6 +3,7 @@ use log::error;
use serde_json; use serde_json;
use tokio::sync::mpsc; use tokio::sync::mpsc;
pub struct RelayMessage; pub struct RelayMessage;
use anyhow::{Result, anyhow};
impl RelayMessage { impl RelayMessage {
// 发送 OK 消息 (NIP-20) // 发送 OK 消息 (NIP-20)
@@ -23,27 +24,46 @@ impl RelayMessage {
event: &NostrEvent, event: &NostrEvent,
sub_id: &str, sub_id: &str,
to_client_msg_tx: &mpsc::Sender<String>, to_client_msg_tx: &mpsc::Sender<String>,
) { ) -> Result<()> {
// 尝试将 NostrEvent 序列化为 JSON 字符串 // 尝试将 NostrEvent 序列化为 JSON 字符串
let event_json = match serde_json::to_string(event) { let event_json = match serde_json::to_string(event) {
Ok(json) => json, Ok(json) => json,
Err(e) => { Err(e) => {
error!("Failed to serialize event {} for sending: {}", event.id, e); error!("Failed to serialize event {} for sending: {}", event.id, e);
return; // 序列化失败则不发送 return Err(anyhow!(
"Failed to serialize event {} for sending: {}",
event.id,
e
));
} }
}; };
let msg = format!("[\"EVENT\", \"{}\", {}]", sub_id, event_json); let msg = format!("[\"EVENT\", \"{}\", {}]", sub_id, event_json);
if let Err(e) = to_client_msg_tx.send(msg).await { match to_client_msg_tx.send(msg).await {
// 此错误通常表示客户端的接收端已关闭(客户端已断开) Ok(_) => Ok(()),
error!("Failed to send EVENT message (sub_id: {}): {}", sub_id, e); Err(e) => {
error!("Failed to send EVENT message (sub_id: {}): {}", sub_id, e);
Err(anyhow!(
"Failed to send EVENT message (sub_id: {}): {}",
sub_id,
e
))
}
} }
} }
// 发送 EOSE 消息 (NIP-15) // 发送 EOSE 消息 (NIP-15)
pub async fn send_eose(sub_id: &str, to_client_msg_tx: &mpsc::Sender<String>) { pub async fn send_eose(sub_id: &str, to_client_msg_tx: &mpsc::Sender<String>) -> Result<()> {
let msg = format!("[\"EOSE\", \"{}\"]", sub_id); let msg = format!("[\"EOSE\", \"{}\"]", sub_id);
if let Err(e) = to_client_msg_tx.send(msg).await { match to_client_msg_tx.send(msg).await {
error!("Failed to send EOSE message (sub_id: {}): {}", sub_id, e); Ok(_) => Ok(()),
Err(e) => {
error!("Failed to send EOSE message (sub_id: {}): {}", sub_id, e);
Err(anyhow!(
"Failed to send EOSE message (sub_id: {}): {}",
sub_id,
e
))
}
} }
} }
@@ -52,21 +72,40 @@ impl RelayMessage {
sub_id: &str, sub_id: &str,
message: String, message: String,
to_client_msg_tx: &mpsc::Sender<String>, to_client_msg_tx: &mpsc::Sender<String>,
) { ) -> Result<()> {
let msg = format!("[\"CLOSED\", \"{}\", \"{}\"]", sub_id, message); let msg = format!("[\"CLOSED\", \"{}\", \"{}\"]", sub_id, message);
if let Err(e) = to_client_msg_tx.send(msg).await { match to_client_msg_tx.send(msg).await {
error!("Failed to send CLOSED message (sub_id: {}): {}", sub_id, e); Ok(_) => Ok(()),
Err(e) => {
error!("Failed to send CLOSED message (sub_id: {}): {}", sub_id, e);
Err(anyhow!(
"Failed to send CLOSED message (sub_id: {}): {}",
sub_id,
e
))
}
} }
} }
// 发送 NOTICE 消息 (NIP-01) // 发送 NOTICE 消息 (NIP-01)
pub async fn send_notice(message: String, to_client_msg_tx: &mpsc::Sender<String>) { pub async fn send_notice(
message: String,
to_client_msg_tx: &mpsc::Sender<String>,
) -> Result<()> {
let msg = format!("[\"NOTICE\", \"{}\"]", message); let msg = format!("[\"NOTICE\", \"{}\"]", message);
if let Err(e) = to_client_msg_tx.send(msg).await { match to_client_msg_tx.send(msg).await {
error!( Ok(_) => Ok(()),
"Failed to send NOTICE message (message: {}): {}", Err(e) => {
message, e error!(
); "Failed to send NOTICE message (message: {}): {}",
message, e
);
Err(anyhow!(
"Failed to send NOTICE message (message: {}): {}",
message,
e
))
}
} }
} }
} }
+52 -16
View File
@@ -9,7 +9,7 @@ use std::{
}; };
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::sync::{RwLock, broadcast, mpsc}; use tokio::sync::{RwLock, broadcast, mpsc};
use tokio_tungstenite::{WebSocketStream, accept_async, tungstenite::protocol::Message}; use tokio_tungstenite::{accept_async, tungstenite::protocol::Message};
use uuid::Uuid; use uuid::Uuid;
use crate::constants::{CLIENT_CHANNEL_SIZE, MAX_FILTERS_PER_REQ, MAX_SUBSCRIPTIONS, SERVER_INFO}; use crate::constants::{CLIENT_CHANNEL_SIZE, MAX_FILTERS_PER_REQ, MAX_SUBSCRIPTIONS, SERVER_INFO};
@@ -18,7 +18,7 @@ use crate::nostr::event::NostrEventExt;
use crate::nostr::filter::FilterExt; use crate::nostr::filter::FilterExt;
use crate::nostr::messages::RelayMessage; use crate::nostr::messages::RelayMessage;
use crate::nostr::utils::extract_p_tags_from_vec; use crate::nostr::utils::extract_p_tags_from_vec;
use crate::nostr::{ClientMessage, Filter, NostrEvent}; use crate::nostr::{Filter, NostrEvent};
pub async fn handle_ws_connection( pub async fn handle_ws_connection(
stream: TcpStream, stream: TcpStream,
@@ -77,7 +77,13 @@ pub async fn handle_ws_connection(
let conn = client_conn_for_send.read().await; let conn = client_conn_for_send.read().await;
for (sub_id, subscription) in &conn.subscriptions { for (sub_id, subscription) in &conn.subscriptions {
if subscription.filters.iter().any(|filter| filter.matches(&event)) { if subscription.filters.iter().any(|filter| filter.matches(&event)) {
RelayMessage::send_event(&event, sub_id, &conn.sender).await; match RelayMessage::send_event(&event, sub_id, &conn.sender).await {
Ok(()) => debug!("Sent event to client {}", client_id),
Err(e) => {
error!("Failed to send event to client {}: {}", client_id, e);
break;
},
}
} }
} }
} }
@@ -124,8 +130,21 @@ pub async fn handle_ws_connection(
.await .await
{ {
error!("Error handling message for client {}: {}", client_id, e); error!("Error handling message for client {}: {}", client_id, e);
RelayMessage::send_notice(format!("Invalid message: {}", e), &client_tx) match RelayMessage::send_notice(
.await; format!("Invalid message: {}", e),
&client_tx,
)
.await
{
Ok(()) => debug!("Sent error notice to client {}", client_id),
Err(e) => {
debug!(
"Failed to send error notice to client {}: {}",
client_id, e
);
return;
}
};
} }
}); });
} }
@@ -185,7 +204,7 @@ pub async fn handle_message(
.to_string(), .to_string(),
to_client_msg_tx, to_client_msg_tx,
) )
.await; .await?;
return Ok(()); return Ok(());
} }
let sub_id = arr let sub_id = arr
@@ -203,7 +222,7 @@ pub async fn handle_message(
format!("Maximum subscriptions ({}) exceeded", MAX_SUBSCRIPTIONS), format!("Maximum subscriptions ({}) exceeded", MAX_SUBSCRIPTIONS),
to_client_msg_tx, to_client_msg_tx,
) )
.await; .await?;
return Ok(()); return Ok(());
} }
} }
@@ -215,7 +234,7 @@ pub async fn handle_message(
format!("Maximum filters ({}) exceeded", MAX_FILTERS_PER_REQ), format!("Maximum filters ({}) exceeded", MAX_FILTERS_PER_REQ),
to_client_msg_tx, to_client_msg_tx,
) )
.await; .await?;
return Ok(()); return Ok(());
} }
let filter: Filter = serde_json::from_value(arr[i].clone()) let filter: Filter = serde_json::from_value(arr[i].clone())
@@ -239,12 +258,12 @@ pub async fn handle_message(
for filter in &filters { for filter in &filters {
let events = filter.select(pool).await?; // 使用 FilterExt let events = filter.select(pool).await?; // 使用 FilterExt
for event in events { for event in events {
RelayMessage::send_event(&event, &sub_id, to_client_msg_tx).await; RelayMessage::send_event(&event, &sub_id, to_client_msg_tx).await?;
} }
} }
// 发送 EOSE 消息,表示历史事件已发送完毕 // 发送 EOSE 消息,表示历史事件已发送完毕
RelayMessage::send_eose(&sub_id, to_client_msg_tx).await; RelayMessage::send_eose(&sub_id, to_client_msg_tx).await?;
Ok(()) Ok(())
} }
@@ -279,26 +298,43 @@ pub async fn handle_message(
if SERVER_INFO.auth_required { if SERVER_INFO.auth_required {
let conn = client_conn_clone.read().await; let conn = client_conn_clone.read().await;
if !conn.authenticated { if !conn.authenticated {
RelayMessage::send_closed( match RelayMessage::send_closed(
// NIP-42 Auth: Forbid unauthenticated EVENT // NIP-42 Auth: Forbid unauthenticated EVENT
&conn.id.to_string(), // 使用 client_id 作为 sub_id 来匹配 AUTH 挑战 &conn.id.to_string(), // 使用 client_id 作为 sub_id 来匹配 AUTH 挑战
"auth-required: Authentication required to publish events".to_string(), "auth-required: Authentication required to publish events".to_string(),
&to_client_msg_tx_clone, &to_client_msg_tx_clone,
) )
.await; .await
{
Ok(_) => debug!("Client {}: Authentication challenge sent.", conn.id),
Err(e) => {
debug!("Failed to send authentication challenge: {}", e);
return;
}
};
debug!("Client {}: Not authenticated, event rejected.", conn.id); debug!("Client {}: Not authenticated, event rejected.", conn.id);
return; return;
} }
let trust_accounts_guard = trust_accounts_clone.read().await; let trust_accounts_guard = trust_accounts_clone.read().await;
if !trust_accounts_guard.contains(&event_clone.pubkey) { if !trust_accounts_guard.contains(&event_clone.pubkey) {
RelayMessage::send_closed( match RelayMessage::send_closed(
// NIP-42 Auth: Forbid unauthorized EVENT // NIP-42 Auth: Forbid unauthorized EVENT
&conn.id.to_string(), &conn.id.to_string(),
"restricted: You are not in the trust list to publish events" "restricted: You are not in the trust list to publish events"
.to_string(), .to_string(),
&to_client_msg_tx_clone, &to_client_msg_tx_clone,
) )
.await; .await
{
Ok(_) => debug!(
"Client {}: Pubkey {} not in trust list, authentication challenge sent.",
conn.id, event_clone.pubkey
),
Err(e) => {
error!("Failed to send authentication challenge: {}", e);
return;
}
};
debug!( debug!(
"Client {}: Pubkey {} not in trust list, event rejected.", "Client {}: Pubkey {} not in trust list, event rejected.",
conn.id, event_clone.pubkey conn.id, event_clone.pubkey
@@ -369,7 +405,7 @@ pub async fn handle_message(
"Subscription cancelled".to_string(), "Subscription cancelled".to_string(),
to_client_msg_tx, to_client_msg_tx,
) )
.await; .await?;
Ok(()) Ok(())
} }
@@ -379,7 +415,7 @@ pub async fn handle_message(
"AUTH message requires an event: [\"AUTH\", <auth_event>]".to_string(), "AUTH message requires an event: [\"AUTH\", <auth_event>]".to_string(),
to_client_msg_tx, to_client_msg_tx,
) )
.await; .await?;
return Ok(()); return Ok(());
} }