···11+-- Add up migration script here
22+33+CREATE TABLE denylist (
44+ subject TEXT NOT NULL,
55+ reason TEXT NOT NULL,
66+ updated_at DATETIME NOT NULL DEFAULT (datetime('now')),
77+ PRIMARY KEY (subject)
88+);
99+
+24-1
src/consumer.rs
···1616use crate::storage;
1717use crate::storage::consumer_control_get;
1818use crate::storage::consumer_control_insert;
1919+use crate::storage::denylist_exists;
1920use crate::storage::feed_content_update;
2021use crate::storage::feed_content_upsert;
2122use crate::storage::StoragePool;
···178179 }
179180 let event_value = event_value.unwrap();
180181181181- for feed_matcher in self.feed_matchers.0.iter() {
182182+ // Assumption: Performing a query for each event will cost more in the
183183+ // long-term than evaluating each event against all matchers and if there's a
184184+ // match, then checking both the event DID and the AT-URI DID.
185185+ 'matchers_loop: for feed_matcher in self.feed_matchers.0.iter() {
182186 if let Some(Match(op, aturi)) = feed_matcher.matches(&event_value) {
183187 tracing::debug!(feed_id = ?feed_matcher.feed, "matched event");
188188+189189+ let aturi_did = did_from_aturi(&aturi);
190190+ let dids = vec![event.did.as_str(), aturi_did.as_str()];
191191+ if denylist_exists(&self.pool, &dids).await? {
192192+ break 'matchers_loop;
193193+ }
194194+184195 let feed_content = storage::model::FeedContent{
185196 feed_id: feed_matcher.feed.clone(),
186197 uri: aturi,
···206217207218 Ok(())
208219 }
220220+}
221221+222222+fn did_from_aturi(aturi: &str) -> String {
223223+ let aturi_len = aturi.len();
224224+ if aturi_len < 6 {
225225+ return "".to_string();
226226+ }
227227+ let collection_start = aturi[5..]
228228+ .find("/")
229229+ .map(|value| value + 5)
230230+ .unwrap_or(aturi_len);
231231+ aturi[5..collection_start].to_string()
209232}
210233211234pub(crate) mod model {