noteguard

the nostr relay spam guardian
git clone git://jb55.com/noteguard
Log | Files | Refs | README | LICENSE

commit c85f9cbc3df487ed9ec00c0bbee5a8b0f89d3f77
parent f08e805673ccaf1aee0f9b00cc4a92dbf8bdead1
Author: William Casarin <jb55@jb55.com>
Date:   Tue,  9 Jul 2024 11:05:21 -0700

filter: add kind blacklist filter

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
MREADME.md | 34+++++++++++++++++++++++++++++++---
Mnoteguard.toml | 11++++++++++-
Asrc/filters/kinds.rs | 29+++++++++++++++++++++++++++++
Msrc/filters/mod.rs | 2++
Msrc/main.rs | 3++-
5 files changed, 74 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md @@ -14,15 +14,22 @@ You can add any new filter you want by implementing the `NoteFilter` trait and r The `pipeline` config specifies the order in which filters are run. When the first `reject` or `shadowReject` action is hit, then the pipeline stops and returns the rejection error. ```toml -pipeline = ["protected_events", "whitelist", "ratelimit"] +pipeline = ["protected_events", "kinds", "whitelist", "ratelimit"] [filters.ratelimit] posts_per_minute = 8 whitelist = ["127.0.0.1"] [filters.whitelist] -pubkeys = ["32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"] -ips = ["127.0.0.1", "127.0.0.2"] +pubkeys = ["16c21558762108afc34e4ff19e4ed51d9a48f79e0c34531efc423d21ab435e93"] +ips = ["127.0.0.1"] + +[filters.kinds] +kinds = [30065, 1064] + +[filters.kinds.messages] +30065 = "blocked: files on nostr is dumb" +1064 = "blocked: files on nostr is dumb" [filters.protected_events] ``` @@ -57,6 +64,27 @@ The whitelist filter only allows notes to pass if it matches a particular pubkey Either criteria can match +### Kinds + +* name: `kinds` + +A filter that blacklists certain kinds + +- `kinds`: a list of kind integers to block + +- `kinds.messages` *optional*: a map of kinds to message to deliver when the kind is blocked + +Example: + +```toml +[filters.kinds] +kinds = [30065, 1064] + +[filters.kinds.messages] +30065 = "blocked: files on nostr is dumb" +1064 = "blocked: files on nostr is dumb" +``` + ### Protected Events See [nip70] diff --git a/noteguard.toml b/noteguard.toml @@ -1,5 +1,5 @@ -pipeline = ["protected_events", "whitelist", "ratelimit"] +pipeline = ["protected_events", "kinds", "whitelist", "ratelimit"] [filters.ratelimit] posts_per_minute = 8 @@ -9,4 +9,13 @@ whitelist = ["127.0.0.1"] pubkeys = ["16c21558762108afc34e4ff19e4ed51d9a48f79e0c34531efc423d21ab435e93"] ips = ["127.0.0.1"] +[filters.kinds] +kinds = [30065, 1064, 34550, 4550] + +[filters.kinds.messages] +30065 = "blocked: files on nostr is dumb" +1064 = "blocked: files on nostr is dumb" +34550 = "blocked: please use a dedicated relay for moderated communities" +4550 = "blocked: please use a dedicated relay for moderated communities" + [filters.protected_events] diff --git a/src/filters/kinds.rs b/src/filters/kinds.rs @@ -0,0 +1,29 @@ +use crate::{Action, InputMessage, NoteFilter, OutputMessage}; +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Deserialize, Default)] +pub struct Kinds { + kinds: Vec<i64>, + messages: Option<HashMap<String, String>>, +} + +impl NoteFilter for Kinds { + fn filter_note(&mut self, input: &InputMessage) -> OutputMessage { + let kind = input.event.kind; + if self.kinds.contains(&kind) { + let msg = self + .messages + .as_ref() + .and_then(|msgs| msgs.get(&kind.to_string()).cloned()) + .unwrap_or_else(|| "blocked: note kind is not allowed here".to_string()); + OutputMessage::new(input.event.id.clone(), Action::Reject, Some(msg)) + } else { + OutputMessage::new(input.event.id.clone(), Action::Accept, None) + } + } + + fn name(&self) -> &'static str { + "kinds" + } +} diff --git a/src/filters/mod.rs b/src/filters/mod.rs @@ -1,7 +1,9 @@ +mod kinds; mod protected_events; mod ratelimit; mod whitelist; +pub use kinds::Kinds; pub use protected_events::ProtectedEvents; pub use ratelimit::RateLimit; pub use whitelist::Whitelist; diff --git a/src/main.rs b/src/main.rs @@ -1,4 +1,4 @@ -use noteguard::filters::{ProtectedEvents, RateLimit, Whitelist}; +use noteguard::filters::{Kinds, ProtectedEvents, RateLimit, Whitelist}; use noteguard::{Action, InputMessage, NoteFilter, OutputMessage}; use serde::de::DeserializeOwned; use serde::Deserialize; @@ -43,6 +43,7 @@ impl Noteguard { self.register_filter::<RateLimit>(); self.register_filter::<Whitelist>(); self.register_filter::<ProtectedEvents>(); + self.register_filter::<Kinds>(); } /// Run the loaded filters. You must call `load_config` before calling this, otherwise