diff --git a/packages/worker-relay/src/sqlite/sqlite-relay.ts b/packages/worker-relay/src/sqlite/sqlite-relay.ts index 550d9176..7923b533 100644 --- a/packages/worker-relay/src/sqlite/sqlite-relay.ts +++ b/packages/worker-relay/src/sqlite/sqlite-relay.ts @@ -321,9 +321,9 @@ export class SqliteRelay extends EventEmitter implements Rel operation = "delete"; } let sql = `${operation} from events`; - const tags = Object.entries(req).filter(([k]) => k.startsWith("#")); + const orTags = Object.entries(req).filter(([k]) => k.startsWith("#")); let tx = 0; - for (const [key, values] of tags) { + for (const [key, values] of orTags) { const vArray = values as Array; sql += ` inner join tags t_${tx} on events.id = t_${tx}.event_id and t_${tx}.key = ? and t_${tx}.value in (${this.#repeatParams( vArray.length, @@ -332,6 +332,15 @@ export class SqliteRelay extends EventEmitter implements Rel params.push(...vArray); tx++; } + const andTags = Object.entries(req).filter(([k]) => k.startsWith("&")); + for (const [key, values] of andTags) { + for (const value of values as Array) { + sql += ` inner join tags t_${tx} on events.id = t_${tx}.event_id and t_${tx}.key = ? and t_${tx}.value = ?`; + params.push(key.slice(1)); + params.push(value); + tx++; + } + } if (req.search) { sql += " inner join search_content on search_content.id = events.id"; conditions.push("search_content match ?"); diff --git a/packages/worker-relay/src/types.ts b/packages/worker-relay/src/types.ts index b5a0a64e..a04bab7c 100644 --- a/packages/worker-relay/src/types.ts +++ b/packages/worker-relay/src/types.ts @@ -101,8 +101,8 @@ export function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) { if (!(filter.kinds?.includes(ev.kind) ?? true)) { return false; } - const tags = Object.entries(filter).filter(([k]) => k.startsWith("#")); - for (const [k, v] of tags) { + const orTags = Object.entries(filter).filter(([k]) => k.startsWith("#")); + for (const [k, v] of orTags) { const vargs = v as Array; for (const x of vargs) { if (!ev.tags.find(a => a[0] === k.slice(1) && a[1] === x)) { @@ -110,6 +110,14 @@ export function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) { } } } + const andTags = Object.entries(filter).filter(([k]) => k.startsWith("&")); + for (const [k, v] of andTags) { + const vargs = v as Array; + const allMatch = vargs.every(x => ev.tags.some(tag => tag[0] === k.slice(1) && tag[1] === x)); + if (!allMatch) { + return false; + } + } return true; }