|
|
|
|
@ -1348,11 +1348,56 @@ class NostrClient {
@@ -1348,11 +1348,56 @@ class NostrClient {
|
|
|
|
|
return parts.length > 0 ? parts.join(' ') : 'empty filter'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Validate that a string is a valid hex pubkey (64 hex characters) |
|
|
|
|
*/ |
|
|
|
|
private isValidPubkey(pubkey: string): boolean { |
|
|
|
|
return typeof pubkey === 'string' && /^[a-f0-9]{64}$/i.test(pubkey); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sanitize filters by removing invalid pubkeys to prevent relay errors |
|
|
|
|
*/ |
|
|
|
|
private sanitizeFilters(filters: Filter[]): Filter[] { |
|
|
|
|
return filters.map(filter => { |
|
|
|
|
if (filter.authors && filter.authors.length > 0) { |
|
|
|
|
// Filter out invalid pubkeys
|
|
|
|
|
const validAuthors = filter.authors.filter(author => this.isValidPubkey(author)); |
|
|
|
|
if (validAuthors.length === 0) { |
|
|
|
|
// If no valid authors remain, remove the authors field entirely
|
|
|
|
|
const { authors, ...rest } = filter; |
|
|
|
|
return rest; |
|
|
|
|
} |
|
|
|
|
return { ...filter, authors: validAuthors }; |
|
|
|
|
} |
|
|
|
|
return filter; |
|
|
|
|
}).filter(filter => { |
|
|
|
|
// Remove filters that have no valid query parameters
|
|
|
|
|
return (filter.ids && filter.ids.length > 0) || |
|
|
|
|
(filter.authors && filter.authors.length > 0) || |
|
|
|
|
(filter.kinds && filter.kinds.length > 0) || |
|
|
|
|
(filter['#e'] && filter['#e'].length > 0) || |
|
|
|
|
(filter['#p'] && filter['#p'].length > 0) || |
|
|
|
|
(filter['#d'] && filter['#d'].length > 0) || |
|
|
|
|
filter.since !== undefined || |
|
|
|
|
filter.until !== undefined || |
|
|
|
|
filter.search !== undefined; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async fetchEvents( |
|
|
|
|
filters: Filter[], |
|
|
|
|
relays: string[], |
|
|
|
|
options: FetchOptions = {} |
|
|
|
|
): Promise<NostrEvent[]> { |
|
|
|
|
// Sanitize filters to remove invalid pubkeys before processing
|
|
|
|
|
filters = this.sanitizeFilters(filters); |
|
|
|
|
|
|
|
|
|
// If all filters were invalid, return empty array
|
|
|
|
|
if (filters.length === 0) { |
|
|
|
|
return []; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const { cacheResults = true, onUpdate, timeout = 10000, priority = 'medium', caller: providedCaller } = options; |
|
|
|
|
const caller = providedCaller || this.getCallerInfo(); |
|
|
|
|
|
|
|
|
|
|