feat: add hint to e tags
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { COMMENT_EVENT_KIND, PICTURE_EVENT_KIND } from '@/constants'
|
import { COMMENT_EVENT_KIND, PICTURE_EVENT_KIND } from '@/constants'
|
||||||
|
import client from '@/services/client.service'
|
||||||
import { TDraftEvent, TMailboxRelay, TRelaySet } from '@/types'
|
import { TDraftEvent, TMailboxRelay, TRelaySet } from '@/types'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { Event, kinds } from 'nostr-tools'
|
import { Event, kinds } from 'nostr-tools'
|
||||||
@@ -14,12 +15,14 @@ import {
|
|||||||
// https://github.com/nostr-protocol/nips/blob/master/25.md
|
// https://github.com/nostr-protocol/nips/blob/master/25.md
|
||||||
export function createReactionDraftEvent(event: Event): TDraftEvent {
|
export function createReactionDraftEvent(event: Event): TDraftEvent {
|
||||||
const tags = event.tags.filter((tag) => tag.length >= 2 && ['e', 'p'].includes(tag[0]))
|
const tags = event.tags.filter((tag) => tag.length >= 2 && ['e', 'p'].includes(tag[0]))
|
||||||
tags.push(['e', event.id])
|
|
||||||
|
const hint = client.getEventHint(event.id)
|
||||||
|
tags.push(['e', event.id, hint, event.pubkey])
|
||||||
tags.push(['p', event.pubkey])
|
tags.push(['p', event.pubkey])
|
||||||
tags.push(['k', event.kind.toString()])
|
tags.push(['k', event.kind.toString()])
|
||||||
|
|
||||||
if (isReplaceable(event.kind)) {
|
if (isReplaceable(event.kind)) {
|
||||||
tags.push(['a', getEventCoordinate(event)])
|
tags.push(hint ? ['a', getEventCoordinate(event), hint] : ['a', getEventCoordinate(event)])
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -33,7 +36,7 @@ export function createReactionDraftEvent(event: Event): TDraftEvent {
|
|||||||
// https://github.com/nostr-protocol/nips/blob/master/18.md
|
// https://github.com/nostr-protocol/nips/blob/master/18.md
|
||||||
export function createRepostDraftEvent(event: Event): TDraftEvent {
|
export function createRepostDraftEvent(event: Event): TDraftEvent {
|
||||||
const tags = [
|
const tags = [
|
||||||
['e', event.id], // TODO: url
|
['e', event.id, client.getEventHint(event.id), event.pubkey],
|
||||||
['p', event.pubkey]
|
['p', event.pubkey]
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -60,16 +63,16 @@ export async function createShortTextNoteDraftEvent(
|
|||||||
|
|
||||||
const tags = pubkeys
|
const tags = pubkeys
|
||||||
.map((pubkey) => ['p', pubkey])
|
.map((pubkey) => ['p', pubkey])
|
||||||
.concat(otherRelatedEventIds.map((eventId) => ['e', eventId]))
|
.concat(otherRelatedEventIds.map((eventId) => ['e', eventId, client.getEventHint(eventId)]))
|
||||||
.concat(quoteEventIds.map((eventId) => ['q', eventId, '', 'mention']))
|
.concat(quoteEventIds.map((eventId) => ['q', eventId, client.getEventHint(eventId)]))
|
||||||
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
||||||
|
|
||||||
if (rootEventId) {
|
if (rootEventId) {
|
||||||
tags.push(['e', rootEventId, '', 'root'])
|
tags.push(['e', rootEventId, client.getEventHint(rootEventId), 'root'])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentEventId) {
|
if (parentEventId) {
|
||||||
tags.push(['e', parentEventId, '', 'reply'])
|
tags.push(['e', parentEventId, client.getEventHint(parentEventId), 'reply'])
|
||||||
}
|
}
|
||||||
|
|
||||||
const { images } = extractImagesFromContent(content)
|
const { images } = extractImagesFromContent(content)
|
||||||
@@ -124,7 +127,7 @@ export async function createPictureNoteDraftEvent(
|
|||||||
const tags = pictureInfos
|
const tags = pictureInfos
|
||||||
.map((info) => ['imeta', ...info.tags.map(([n, v]) => `${n} ${v}`)])
|
.map((info) => ['imeta', ...info.tags.map(([n, v]) => `${n} ${v}`)])
|
||||||
.concat(pubkeys.map((pubkey) => ['p', pubkey]))
|
.concat(pubkeys.map((pubkey) => ['p', pubkey]))
|
||||||
.concat(quoteEventIds.map((eventId) => ['q', eventId]))
|
.concat(quoteEventIds.map((eventId) => ['q', eventId, client.getEventHint(eventId)]))
|
||||||
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
||||||
|
|
||||||
if (options.addClientTag) {
|
if (options.addClientTag) {
|
||||||
@@ -165,15 +168,15 @@ export async function createCommentDraftEvent(
|
|||||||
const hashtags = extractHashtags(content)
|
const hashtags = extractHashtags(content)
|
||||||
|
|
||||||
const tags = [
|
const tags = [
|
||||||
['E', rootEventId],
|
['E', rootEventId, client.getEventHint(rootEventId), rootEventPubkey],
|
||||||
['K', rootEventKind.toString()],
|
['K', rootEventKind.toString()],
|
||||||
['P', rootEventPubkey],
|
['P', rootEventPubkey],
|
||||||
['e', parentEventId],
|
['e', parentEventId, client.getEventHint(parentEventId), parentEventPubkey],
|
||||||
['k', parentEventKind.toString()],
|
['k', parentEventKind.toString()],
|
||||||
['p', parentEventPubkey]
|
['p', parentEventPubkey]
|
||||||
]
|
]
|
||||||
.concat(pubkeys.map((pubkey) => ['p', pubkey]))
|
.concat(pubkeys.map((pubkey) => ['p', pubkey]))
|
||||||
.concat(quoteEventIds.map((eventId) => ['q', eventId]))
|
.concat(quoteEventIds.map((eventId) => ['q', eventId, client.getEventHint(eventId)]))
|
||||||
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
.concat(hashtags.map((hashtag) => ['t', hashtag]))
|
||||||
|
|
||||||
const { images } = extractImagesFromContent(content)
|
const { images } = extractImagesFromContent(content)
|
||||||
|
|||||||
@@ -31,6 +31,47 @@ export function simplifyUrl(url: string): string {
|
|||||||
return url.replace('wss://', '').replace('ws://', '').replace(/\/$/, '')
|
return url.replace('wss://', '').replace('ws://', '').replace(/\/$/, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isLocalNetworkUrl(urlString: string): boolean {
|
||||||
|
try {
|
||||||
|
const url = new URL(urlString)
|
||||||
|
const hostname = url.hostname
|
||||||
|
|
||||||
|
// Check if it's localhost
|
||||||
|
if (hostname === 'localhost' || hostname === '::1') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's an IPv4 local network address
|
||||||
|
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/)
|
||||||
|
if (ipv4Match) {
|
||||||
|
const [, a, b, c, d] = ipv4Match.map(Number)
|
||||||
|
return (
|
||||||
|
a === 10 ||
|
||||||
|
(a === 172 && b >= 16 && b <= 31) ||
|
||||||
|
(a === 192 && b === 168) ||
|
||||||
|
(a === 127 && b === 0 && c === 0 && d === 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's an IPv6 address
|
||||||
|
if (hostname.includes(':')) {
|
||||||
|
if (hostname === '::1') {
|
||||||
|
return true // IPv6 loopback address
|
||||||
|
}
|
||||||
|
if (hostname.startsWith('fe80:')) {
|
||||||
|
return true // Link-local address
|
||||||
|
}
|
||||||
|
if (hostname.startsWith('fc') || hostname.startsWith('fd')) {
|
||||||
|
return true // Unique local address (ULA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
} catch {
|
||||||
|
return false // Return false for invalid URLs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function isImage(url: string) {
|
export function isImage(url: string) {
|
||||||
try {
|
try {
|
||||||
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.heic', '.svg']
|
const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.heic', '.svg']
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { BIG_RELAY_URLS } from '@/constants'
|
|||||||
import { getProfileFromProfileEvent, getRelayListFromRelayListEvent } from '@/lib/event'
|
import { getProfileFromProfileEvent, getRelayListFromRelayListEvent } from '@/lib/event'
|
||||||
import { formatPubkey, userIdToPubkey } from '@/lib/pubkey'
|
import { formatPubkey, userIdToPubkey } from '@/lib/pubkey'
|
||||||
import { extractPubkeysFromEventTags } from '@/lib/tag'
|
import { extractPubkeysFromEventTags } from '@/lib/tag'
|
||||||
|
import { isLocalNetworkUrl } from '@/lib/url'
|
||||||
import { TDraftEvent, TProfile, TRelayInfo, TRelayList } from '@/types'
|
import { TDraftEvent, TProfile, TRelayInfo, TRelayList } from '@/types'
|
||||||
import { sha256 } from '@noble/hashes/sha2'
|
import { sha256 } from '@noble/hashes/sha2'
|
||||||
import DataLoader from 'dataloader'
|
import DataLoader from 'dataloader'
|
||||||
@@ -559,6 +560,11 @@ class ClientService extends EventTarget {
|
|||||||
return this.getSeenEventRelays(eventId).map((relay) => relay.url)
|
return this.getSeenEventRelays(eventId).map((relay) => relay.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEventHint(eventId: string) {
|
||||||
|
const relayUrls = this.getSeenEventRelayUrls(eventId)
|
||||||
|
return relayUrls.find((url) => !isLocalNetworkUrl(url)) ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
trackEventSeenOn(eventId: string, relay: AbstractRelay) {
|
trackEventSeenOn(eventId: string, relay: AbstractRelay) {
|
||||||
let set = this.pool.seenOn.get(eventId)
|
let set = this.pool.seenOn.get(eventId)
|
||||||
if (!set) {
|
if (!set) {
|
||||||
|
|||||||
Reference in New Issue
Block a user