import { Filter, SimplePool } from 'nostr-tools' import { RelayList } from 'nostr-tools/kinds' import { Event } from 'nostr-tools' import { localCache } from '../services' import { ONE_WEEK_IN_MS, SIGIT_RELAY } from './const.ts' import { RelayMap, RelaySet } from '../types' const READ_MARKER = 'read' const WRITE_MARKER = 'write' /** * Attempts to find a relay list from the provided lookUpRelays. * If the relay list is found, it will be added to the user relay list metadata. * @param lookUpRelays * @param hexKey * @return found relay list or null */ const findRelayListAndUpdateCache = async ( lookUpRelays: string[], hexKey: string ): Promise => { try { const eventFilter: Filter = { kinds: [RelayList], authors: [hexKey] } const pool = new SimplePool() const event = await pool.get(lookUpRelays, eventFilter) if (event) { await localCache.addUserRelayListMetadata(event) } return event } catch (error) { console.error(error) return null } } /** * Attempts to find a relay list in cache. If it is present, it will check that the cached event is not * older than one week. * @param hexKey * @return RelayList event if it's not older than a week; otherwise null */ const findRelayListInCache = async (hexKey: string): Promise => { try { // Attempt to retrieve the metadata event from the local cache const cachedRelayListMetadataEvent = await localCache.getUserRelayListMetadata(hexKey) // Check if the cached event is not older than one week if ( cachedRelayListMetadataEvent && isOlderThanOneWeek(cachedRelayListMetadataEvent.cachedAt) ) { return cachedRelayListMetadataEvent.event } return null } catch (error) { console.error(error) return null } } /** * Transforms a list of relay tags from a Nostr Event to a RelaySet. * @param tags */ const getUserRelaySet = (tags: string[][]): RelaySet => { return tags .filter(isRelayTag) .reduce(toRelaySet, getDefaultRelaySet()) } const getDefaultRelaySet = (): RelaySet => ({ read: [SIGIT_RELAY], write: [SIGIT_RELAY] }) const getDefaultRelayMap = (): RelayMap => ({ [SIGIT_RELAY]: { write: true, read: true } }) const isOlderThanOneWeek = (cachedAt: number) => { return Date.now() - cachedAt < ONE_WEEK_IN_MS } const isRelayTag = (tag: string[]): boolean => tag[0] === 'r' const toRelaySet = (obj: RelaySet, tag: string[]): RelaySet => { if (tag.length >= 3) { const marker = tag[2] if (marker === READ_MARKER) { obj.read.push(tag[1]) } else if (marker === WRITE_MARKER) { obj.write.push(tag[1]) } } if (tag.length === 2) { obj.read.push(tag[1]) obj.write.push(tag[1]) } return obj } export { findRelayListAndUpdateCache, findRelayListInCache, getUserRelaySet, getDefaultRelaySet, getDefaultRelayMap, isOlderThanOneWeek }