Relay operations refactored with NDK for publishing events (+ more. Wrapped up refactoring), pagination scroll up on click, body scroll disable/enable when popups appear/disappear, nsfw tag shown on mod cards if mod post is nsfw #92
@ -4,13 +4,12 @@ import { QRCodeSVG } from 'qrcode.react'
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { UserRelaysType } from '../controllers'
|
|
||||||
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
||||||
import { appRoutes, getProfilePageRoute } from '../routes'
|
import { appRoutes, getProfilePageRoute } from '../routes'
|
||||||
import '../styles/author.css'
|
import '../styles/author.css'
|
||||||
import '../styles/innerPage.css'
|
import '../styles/innerPage.css'
|
||||||
import '../styles/socialPosts.css'
|
import '../styles/socialPosts.css'
|
||||||
import { UserProfile } from '../types'
|
import { UserProfile, UserRelaysType } from '../types'
|
||||||
import {
|
import {
|
||||||
copyTextToClipboard,
|
copyTextToClipboard,
|
||||||
hexToNpub,
|
hexToNpub,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { getRelayListForUser } from '@nostr-dev-kit/ndk'
|
||||||
import { QRCodeSVG } from 'qrcode.react'
|
import { QRCodeSVG } from 'qrcode.react'
|
||||||
import React, {
|
import React, {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
@ -9,7 +10,7 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import Countdown, { CountdownRenderProps } from 'react-countdown'
|
import Countdown, { CountdownRenderProps } from 'react-countdown'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { MetadataController, ZapController } from '../controllers'
|
import { ZapController } from '../controllers'
|
||||||
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
||||||
import '../styles/popup.css'
|
import '../styles/popup.css'
|
||||||
import { PaymentRequest, UserProfile } from '../types'
|
import { PaymentRequest, UserProfile } from '../types'
|
||||||
@ -251,7 +252,7 @@ export const ZapPopUp = ({
|
|||||||
setHasZapped,
|
setHasZapped,
|
||||||
handleClose
|
handleClose
|
||||||
}: ZapPopUpProps) => {
|
}: ZapPopUpProps) => {
|
||||||
const { findMetadata } = useNDKContext()
|
const { ndk, findMetadata } = useNDKContext()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||||
const [amount, setAmount] = useState<number>(0)
|
const [amount, setAmount] = useState<number>(0)
|
||||||
@ -300,6 +301,20 @@ export const ZapPopUp = ({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find the receiver's read relays.
|
||||||
|
const receiverRelays = await getRelayListForUser(receiver, ndk)
|
||||||
|
.then((ndkRelayList) => {
|
||||||
|
if (ndkRelayList) return ndkRelayList.readRelayUrls
|
||||||
|
return [] // Return an empty array if ndkRelayList is undefined
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(
|
||||||
|
`An error occurred in getting zap receiver's read relays`,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
return [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
const zapController = ZapController.getInstance()
|
const zapController = ZapController.getInstance()
|
||||||
|
|
||||||
setLoadingSpinnerDesc('Creating zap request')
|
setLoadingSpinnerDesc('Creating zap request')
|
||||||
@ -308,6 +323,7 @@ export const ZapPopUp = ({
|
|||||||
receiverMetadata.lud16,
|
receiverMetadata.lud16,
|
||||||
amount,
|
amount,
|
||||||
receiverMetadata.pubkey as string,
|
receiverMetadata.pubkey as string,
|
||||||
|
receiverRelays,
|
||||||
userHexKey,
|
userHexKey,
|
||||||
message,
|
message,
|
||||||
eventId,
|
eventId,
|
||||||
@ -482,7 +498,7 @@ export const ZapSplit = ({
|
|||||||
setHasZapped,
|
setHasZapped,
|
||||||
handleClose
|
handleClose
|
||||||
}: ZapSplitProps) => {
|
}: ZapSplitProps) => {
|
||||||
const { findMetadata } = useNDKContext()
|
const { ndk, findMetadata } = useNDKContext()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||||
const [amount, setAmount] = useState<number>(0)
|
const [amount, setAmount] = useState<number>(0)
|
||||||
@ -502,8 +518,8 @@ export const ZapSplit = ({
|
|||||||
setAuthor(res)
|
setAuthor(res)
|
||||||
})
|
})
|
||||||
|
|
||||||
const metadataController = await MetadataController.getInstance()
|
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||||
findMetadata(metadataController.adminNpubs[0]).then((res) => {
|
findMetadata(adminNpubs[0]).then((res) => {
|
||||||
setAdmin(res)
|
setAdmin(res)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -557,12 +573,30 @@ export const ZapSplit = ({
|
|||||||
const invoices = new Map<string, PaymentRequest>()
|
const invoices = new Map<string, PaymentRequest>()
|
||||||
|
|
||||||
if (authorShare > 0 && author?.pubkey && author?.lud16) {
|
if (authorShare > 0 && author?.pubkey && author?.lud16) {
|
||||||
|
// Find the receiver's read relays.
|
||||||
|
const authorRelays = await getRelayListForUser(
|
||||||
|
author.pubkey as string,
|
||||||
|
ndk
|
||||||
|
)
|
||||||
|
.then((ndkRelayList) => {
|
||||||
|
if (ndkRelayList) return ndkRelayList.readRelayUrls
|
||||||
|
return [] // Return an empty array if ndkRelayList is undefined
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(
|
||||||
|
`An error occurred in getting zap receiver's read relays`,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
return [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
setLoadingSpinnerDesc('Generating invoice for author')
|
setLoadingSpinnerDesc('Generating invoice for author')
|
||||||
const invoice = await zapController
|
const invoice = await zapController
|
||||||
.getLightningPaymentRequest(
|
.getLightningPaymentRequest(
|
||||||
author.lud16,
|
author.lud16,
|
||||||
authorShare,
|
authorShare,
|
||||||
author.pubkey as string,
|
author.pubkey as string,
|
||||||
|
authorRelays,
|
||||||
userHexKey,
|
userHexKey,
|
||||||
message,
|
message,
|
||||||
eventId,
|
eventId,
|
||||||
@ -579,12 +613,27 @@ export const ZapSplit = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (adminShare > 0 && admin?.pubkey && admin?.lud16) {
|
if (adminShare > 0 && admin?.pubkey && admin?.lud16) {
|
||||||
|
// Find the receiver's read relays.
|
||||||
|
const adminRelays = await getRelayListForUser(admin.pubkey as string, ndk)
|
||||||
|
.then((ndkRelayList) => {
|
||||||
|
if (ndkRelayList) return ndkRelayList.readRelayUrls
|
||||||
|
return [] // Return an empty array if ndkRelayList is undefined
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(
|
||||||
|
`An error occurred in getting zap receiver's read relays`,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
return [] as string[]
|
||||||
|
})
|
||||||
|
|
||||||
setLoadingSpinnerDesc('Generating invoice for site owner')
|
setLoadingSpinnerDesc('Generating invoice for site owner')
|
||||||
const invoice = await zapController
|
const invoice = await zapController
|
||||||
.getLightningPaymentRequest(
|
.getLightningPaymentRequest(
|
||||||
admin.lud16,
|
admin.lud16,
|
||||||
adminShare,
|
adminShare,
|
||||||
admin.pubkey as string,
|
admin.pubkey as string,
|
||||||
|
adminRelays,
|
||||||
userHexKey,
|
userHexKey,
|
||||||
message,
|
message,
|
||||||
eventId,
|
eventId,
|
||||||
|
@ -3,6 +3,7 @@ import NDK, {
|
|||||||
NDKEvent,
|
NDKEvent,
|
||||||
NDKFilter,
|
NDKFilter,
|
||||||
NDKKind,
|
NDKKind,
|
||||||
|
NDKList,
|
||||||
NDKRelaySet,
|
NDKRelaySet,
|
||||||
NDKSubscriptionCacheUsage,
|
NDKSubscriptionCacheUsage,
|
||||||
NDKUser,
|
NDKUser,
|
||||||
@ -10,11 +11,10 @@ import NDK, {
|
|||||||
} from '@nostr-dev-kit/ndk'
|
} from '@nostr-dev-kit/ndk'
|
||||||
import NDKCacheAdapterDexie from '@nostr-dev-kit/ndk-cache-dexie'
|
import NDKCacheAdapterDexie from '@nostr-dev-kit/ndk-cache-dexie'
|
||||||
import { MOD_FILTER_LIMIT, T_TAG_VALUE } from 'constants.ts'
|
import { MOD_FILTER_LIMIT, T_TAG_VALUE } from 'constants.ts'
|
||||||
import { UserRelaysType } from 'controllers'
|
|
||||||
import { Dexie } from 'dexie'
|
import { Dexie } from 'dexie'
|
||||||
import { createContext, ReactNode, useEffect, useMemo } from 'react'
|
import { createContext, ReactNode, useEffect, useMemo } from 'react'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { ModDetails, UserProfile } from 'types'
|
import { ModDetails, MuteLists, UserProfile, UserRelaysType } from 'types'
|
||||||
import {
|
import {
|
||||||
constructModListFromEvents,
|
constructModListFromEvents,
|
||||||
hexToNpub,
|
hexToNpub,
|
||||||
@ -57,6 +57,11 @@ interface NDKContextType {
|
|||||||
hasZapped: boolean
|
hasZapped: boolean
|
||||||
}>
|
}>
|
||||||
publish: (event: NDKEvent) => Promise<string[]>
|
publish: (event: NDKEvent) => Promise<string[]>
|
||||||
|
getNSFWList: () => Promise<string[]>
|
||||||
|
getMuteLists: (pubkey?: string) => Promise<{
|
||||||
|
admin: MuteLists
|
||||||
|
user: MuteLists
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the context with an initial value of `null`
|
// Create the context with an initial value of `null`
|
||||||
@ -368,6 +373,117 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of NSFW (Not Safe For Work) posts that were not specified as NSFW by post author but marked as NSFW by admin.
|
||||||
|
*
|
||||||
|
* @returns {Promise<string[]>} - A promise that resolves to an array of NSFW post identifiers (e.g., URLs or IDs).
|
||||||
|
*/
|
||||||
|
const getNSFWList = async (): Promise<string[]> => {
|
||||||
|
// Initialize an array to store the NSFW post identifiers
|
||||||
|
const nsfwPosts: string[] = []
|
||||||
|
|
||||||
|
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
||||||
|
|
||||||
|
// Convert the public key (npub) to a hexadecimal format
|
||||||
|
const hexKey = npubToHex(reportingNpub)
|
||||||
|
|
||||||
|
// If the conversion is successful and we have a hexKey
|
||||||
|
if (hexKey) {
|
||||||
|
// Fetch the event that contains the NSFW list
|
||||||
|
const nsfwListEvent = await fetchEvent({
|
||||||
|
kinds: [NDKKind.ArticleCurationSet],
|
||||||
|
authors: [hexKey],
|
||||||
|
'#d': ['nsfw']
|
||||||
|
})
|
||||||
|
|
||||||
|
if (nsfwListEvent) {
|
||||||
|
// Convert the event data to an NDKList, which is a structured list format
|
||||||
|
const list = NDKList.from(nsfwListEvent)
|
||||||
|
|
||||||
|
// Iterate through the items in the list
|
||||||
|
list.items.forEach((item) => {
|
||||||
|
if (item[0] === 'a') {
|
||||||
|
// Add the identifier of the NSFW post to the nsfwPosts array
|
||||||
|
nsfwPosts.push(item[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the array of NSFW post identifiers
|
||||||
|
return nsfwPosts
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMuteLists = async (
|
||||||
|
pubkey?: string
|
||||||
|
): Promise<{
|
||||||
|
admin: MuteLists
|
||||||
|
user: MuteLists
|
||||||
|
}> => {
|
||||||
|
const adminMutedAuthors = new Set<string>()
|
||||||
|
const adminMutedPosts = new Set<string>()
|
||||||
|
|
||||||
|
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
||||||
|
|
||||||
|
const adminHexKey = npubToHex(reportingNpub)
|
||||||
|
|
||||||
|
if (adminHexKey) {
|
||||||
|
const muteListEvent = await fetchEvent({
|
||||||
|
kinds: [NDKKind.MuteList],
|
||||||
|
authors: [adminHexKey]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (muteListEvent) {
|
||||||
|
const list = NDKList.from(muteListEvent)
|
||||||
|
|
||||||
|
list.items.forEach((item) => {
|
||||||
|
if (item[0] === 'p') {
|
||||||
|
adminMutedAuthors.add(item[1])
|
||||||
|
} else if (item[0] === 'a') {
|
||||||
|
adminMutedPosts.add(item[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userMutedAuthors = new Set<string>()
|
||||||
|
const userMutedPosts = new Set<string>()
|
||||||
|
|
||||||
|
if (pubkey) {
|
||||||
|
const userHexKey = npubToHex(pubkey)
|
||||||
|
|
||||||
|
if (userHexKey) {
|
||||||
|
const muteListEvent = await fetchEvent({
|
||||||
|
kinds: [NDKKind.MuteList],
|
||||||
|
authors: [userHexKey]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (muteListEvent) {
|
||||||
|
const list = NDKList.from(muteListEvent)
|
||||||
|
|
||||||
|
list.items.forEach((item) => {
|
||||||
|
if (item[0] === 'p') {
|
||||||
|
userMutedAuthors.add(item[1])
|
||||||
|
} else if (item[0] === 'a') {
|
||||||
|
userMutedPosts.add(item[1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
admin: {
|
||||||
|
authors: Array.from(adminMutedAuthors),
|
||||||
|
replaceableEvents: Array.from(adminMutedPosts)
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
authors: Array.from(userMutedAuthors),
|
||||||
|
replaceableEvents: Array.from(userMutedPosts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NDKContext.Provider
|
<NDKContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@ -379,7 +495,9 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
fetchEventFromUserRelays,
|
fetchEventFromUserRelays,
|
||||||
findMetadata,
|
findMetadata,
|
||||||
getTotalZapAmount,
|
getTotalZapAmount,
|
||||||
publish
|
publish,
|
||||||
|
getNSFWList,
|
||||||
|
getMuteLists
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './metadata'
|
|
||||||
export * from './zap'
|
export * from './zap'
|
||||||
|
@ -1,217 +0,0 @@
|
|||||||
import NDK, { getRelayListForUser, NDKList } from '@nostr-dev-kit/ndk'
|
|
||||||
import { kinds } from 'nostr-tools'
|
|
||||||
import { MuteLists } from '../types'
|
|
||||||
import { log, LogType, npubToHex, timeout } from '../utils'
|
|
||||||
|
|
||||||
export enum UserRelaysType {
|
|
||||||
Read = 'readRelayUrls',
|
|
||||||
Write = 'writeRelayUrls',
|
|
||||||
Both = 'bothRelayUrls'
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton class to manage metadata operations using NDK.
|
|
||||||
*/
|
|
||||||
export class MetadataController {
|
|
||||||
private static instance: MetadataController
|
|
||||||
private ndk: NDK
|
|
||||||
public adminNpubs: string[]
|
|
||||||
public adminRelays = new Set<string>()
|
|
||||||
public reportingNpub: string
|
|
||||||
|
|
||||||
private constructor() {
|
|
||||||
this.ndk = new NDK({
|
|
||||||
explicitRelayUrls: [
|
|
||||||
'wss://user.kindpag.es',
|
|
||||||
'wss://purplepag.es',
|
|
||||||
'wss://relay.damus.io/',
|
|
||||||
import.meta.env.VITE_APP_RELAY
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
this.ndk
|
|
||||||
.connect()
|
|
||||||
.then(() => {
|
|
||||||
console.log('NDK connected')
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log('error in ndk connection', err)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
|
||||||
this.reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
|
||||||
}
|
|
||||||
|
|
||||||
private setAdminRelays = async () => {
|
|
||||||
const promises = this.adminNpubs.map((npub) => {
|
|
||||||
const hexKey = npubToHex(npub)
|
|
||||||
if (!hexKey) return null
|
|
||||||
|
|
||||||
return getRelayListForUser(hexKey, this.ndk)
|
|
||||||
.then((ndkRelayList) => {
|
|
||||||
if (ndkRelayList) {
|
|
||||||
ndkRelayList.writeRelayUrls.forEach((url) =>
|
|
||||||
this.adminRelays.add(url)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
log(
|
|
||||||
true,
|
|
||||||
LogType.Error,
|
|
||||||
`❌ Error occurred in getting the instance of NDKRelayList for npub: ${npub}`,
|
|
||||||
err
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await Promise.allSettled(promises)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides the singleton instance of MetadataController.
|
|
||||||
*
|
|
||||||
* @returns The singleton instance of MetadataController.
|
|
||||||
*/
|
|
||||||
public static async getInstance(): Promise<MetadataController> {
|
|
||||||
if (!MetadataController.instance) {
|
|
||||||
MetadataController.instance = new MetadataController()
|
|
||||||
|
|
||||||
await MetadataController.instance.setAdminRelays()
|
|
||||||
}
|
|
||||||
return MetadataController.instance
|
|
||||||
}
|
|
||||||
|
|
||||||
public findUserRelays = async (
|
|
||||||
hexKey: string,
|
|
||||||
userRelaysType: UserRelaysType = UserRelaysType.Both
|
|
||||||
): Promise<string[]> => {
|
|
||||||
log(true, LogType.Info, `ℹ Finding user's relays`, hexKey, userRelaysType)
|
|
||||||
|
|
||||||
const ndkRelayListPromise = getRelayListForUser(hexKey, this.ndk)
|
|
||||||
|
|
||||||
// Use Promise.race to either get the NDKRelayList instance or handle the timeout
|
|
||||||
return await Promise.race([
|
|
||||||
ndkRelayListPromise,
|
|
||||||
timeout() // Custom timeout function that rejects after a specified time
|
|
||||||
])
|
|
||||||
.then((ndkRelayList) => {
|
|
||||||
if (ndkRelayList) return ndkRelayList[userRelaysType]
|
|
||||||
return [] // Return an empty array if ndkRelayList is undefined
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
log(true, LogType.Error, err)
|
|
||||||
return [] // Return an empty array if an error occurs
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public getNDKRelayList = async (hexKey: string) =>
|
|
||||||
getRelayListForUser(hexKey, this.ndk)
|
|
||||||
|
|
||||||
public getMuteLists = async (
|
|
||||||
pubkey?: string
|
|
||||||
): Promise<{
|
|
||||||
admin: MuteLists
|
|
||||||
user: MuteLists
|
|
||||||
}> => {
|
|
||||||
const adminMutedAuthors = new Set<string>()
|
|
||||||
const adminMutedPosts = new Set<string>()
|
|
||||||
|
|
||||||
const adminHexKey = npubToHex(this.reportingNpub)
|
|
||||||
|
|
||||||
if (adminHexKey) {
|
|
||||||
const muteListEvent = await this.ndk.fetchEvent({
|
|
||||||
kinds: [kinds.Mutelist],
|
|
||||||
authors: [adminHexKey]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (muteListEvent) {
|
|
||||||
const list = NDKList.from(muteListEvent)
|
|
||||||
|
|
||||||
list.items.forEach((item) => {
|
|
||||||
if (item[0] === 'p') {
|
|
||||||
adminMutedAuthors.add(item[1])
|
|
||||||
} else if (item[0] === 'a') {
|
|
||||||
adminMutedPosts.add(item[1])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const userMutedAuthors = new Set<string>()
|
|
||||||
const userMutedPosts = new Set<string>()
|
|
||||||
|
|
||||||
if (pubkey) {
|
|
||||||
const userHexKey = npubToHex(pubkey)
|
|
||||||
|
|
||||||
if (userHexKey) {
|
|
||||||
const muteListEvent = await this.ndk.fetchEvent({
|
|
||||||
kinds: [kinds.Mutelist],
|
|
||||||
authors: [userHexKey]
|
|
||||||
})
|
|
||||||
|
|
||||||
if (muteListEvent) {
|
|
||||||
const list = NDKList.from(muteListEvent)
|
|
||||||
|
|
||||||
list.items.forEach((item) => {
|
|
||||||
if (item[0] === 'p') {
|
|
||||||
userMutedAuthors.add(item[1])
|
|
||||||
} else if (item[0] === 'a') {
|
|
||||||
userMutedPosts.add(item[1])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
admin: {
|
|
||||||
authors: Array.from(adminMutedAuthors),
|
|
||||||
replaceableEvents: Array.from(adminMutedPosts)
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
authors: Array.from(userMutedAuthors),
|
|
||||||
replaceableEvents: Array.from(userMutedPosts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a list of NSFW (Not Safe For Work) posts that were not specified as NSFW by post author but marked as NSFW by admin.
|
|
||||||
*
|
|
||||||
* @returns {Promise<string[]>} - A promise that resolves to an array of NSFW post identifiers (e.g., URLs or IDs).
|
|
||||||
*/
|
|
||||||
public getNSFWList = async (): Promise<string[]> => {
|
|
||||||
// Initialize an array to store the NSFW post identifiers
|
|
||||||
const nsfwPosts: string[] = []
|
|
||||||
|
|
||||||
// Convert the public key (npub) to a hexadecimal format
|
|
||||||
const hexKey = npubToHex(this.reportingNpub)
|
|
||||||
|
|
||||||
// If the conversion is successful and we have a hexKey
|
|
||||||
if (hexKey) {
|
|
||||||
// Fetch the event that contains the NSFW list
|
|
||||||
const nsfwListEvent = await this.ndk.fetchEvent({
|
|
||||||
kinds: [kinds.Curationsets],
|
|
||||||
authors: [hexKey],
|
|
||||||
'#d': ['nsfw']
|
|
||||||
})
|
|
||||||
|
|
||||||
if (nsfwListEvent) {
|
|
||||||
// Convert the event data to an NDKList, which is a structured list format
|
|
||||||
const list = NDKList.from(nsfwListEvent)
|
|
||||||
|
|
||||||
// Iterate through the items in the list
|
|
||||||
list.items.forEach((item) => {
|
|
||||||
if (item[0] === 'a') {
|
|
||||||
// Add the identifier of the NSFW post to the nsfwPosts array
|
|
||||||
nsfwPosts.push(item[1])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the array of NSFW post identifiers
|
|
||||||
return nsfwPosts
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,6 @@ import {
|
|||||||
ZapRequest
|
ZapRequest
|
||||||
} from '../types'
|
} from '../types'
|
||||||
import { log, LogType, npubToHex } from '../utils'
|
import { log, LogType, npubToHex } from '../utils'
|
||||||
import { MetadataController, UserRelaysType } from './metadata'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton class to manage zap related operations.
|
* Singleton class to manage zap related operations.
|
||||||
@ -48,6 +47,7 @@ export class ZapController {
|
|||||||
* @param lud16 - LUD-16 of the recipient.
|
* @param lud16 - LUD-16 of the recipient.
|
||||||
* @param amount - payment amount (will be multiplied by 1000 to represent sats).
|
* @param amount - payment amount (will be multiplied by 1000 to represent sats).
|
||||||
* @param recipientPubKey - pubKey of the recipient.
|
* @param recipientPubKey - pubKey of the recipient.
|
||||||
|
* @param recipientRelays - relays on which zap receipt will be published.
|
||||||
* @param senderPubkey - pubKey of of the sender.
|
* @param senderPubkey - pubKey of of the sender.
|
||||||
* @param content - optional content (comment).
|
* @param content - optional content (comment).
|
||||||
* @param eventId - event id, if zapping an event.
|
* @param eventId - event id, if zapping an event.
|
||||||
@ -59,6 +59,7 @@ export class ZapController {
|
|||||||
lud16: string,
|
lud16: string,
|
||||||
amount: number,
|
amount: number,
|
||||||
recipientPubKey: string,
|
recipientPubKey: string,
|
||||||
|
recipientRelays: string[],
|
||||||
senderPubkey: string,
|
senderPubkey: string,
|
||||||
content?: string,
|
content?: string,
|
||||||
eventId?: string,
|
eventId?: string,
|
||||||
@ -88,6 +89,7 @@ export class ZapController {
|
|||||||
amount,
|
amount,
|
||||||
content,
|
content,
|
||||||
recipientPubKey,
|
recipientPubKey,
|
||||||
|
recipientRelays,
|
||||||
senderPubkey,
|
senderPubkey,
|
||||||
eventId,
|
eventId,
|
||||||
aTag
|
aTag
|
||||||
@ -273,6 +275,7 @@ export class ZapController {
|
|||||||
* @param amount - request amount (sats).
|
* @param amount - request amount (sats).
|
||||||
* @param content - comment.
|
* @param content - comment.
|
||||||
* @param recipientPubKey - pubKey of the recipient.
|
* @param recipientPubKey - pubKey of the recipient.
|
||||||
|
* @param recipientRelays - relays on which zap receipt will be published.
|
||||||
* @param senderPubkey - pubKey of of the sender.
|
* @param senderPubkey - pubKey of of the sender.
|
||||||
* @param eventId - event id, if zapping an event.
|
* @param eventId - event id, if zapping an event.
|
||||||
* @param aTag - value of `a` tag.
|
* @param aTag - value of `a` tag.
|
||||||
@ -282,6 +285,7 @@ export class ZapController {
|
|||||||
amount: number,
|
amount: number,
|
||||||
content = '',
|
content = '',
|
||||||
recipientPubKey: string,
|
recipientPubKey: string,
|
||||||
|
recipientRelays: string[],
|
||||||
senderPubkey: string,
|
senderPubkey: string,
|
||||||
eventId?: string,
|
eventId?: string,
|
||||||
aTag?: string
|
aTag?: string
|
||||||
@ -290,21 +294,15 @@ export class ZapController {
|
|||||||
|
|
||||||
if (!recipientHexKey) throw 'Invalid recipient pubKey.'
|
if (!recipientHexKey) throw 'Invalid recipient pubKey.'
|
||||||
|
|
||||||
const metadataController = await MetadataController.getInstance()
|
if (!recipientRelays.includes(this.appRelay)) {
|
||||||
const receiverReadRelays = await metadataController.findUserRelays(
|
recipientRelays.push(this.appRelay)
|
||||||
recipientHexKey,
|
|
||||||
UserRelaysType.Read
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!receiverReadRelays.includes(this.appRelay)) {
|
|
||||||
receiverReadRelays.push(this.appRelay)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const zapRequest: ZapRequest = {
|
const zapRequest: ZapRequest = {
|
||||||
kind: kinds.ZapRequest,
|
kind: kinds.ZapRequest,
|
||||||
content,
|
content,
|
||||||
tags: [
|
tags: [
|
||||||
['relays', ...receiverReadRelays],
|
['relays', ...recipientRelays],
|
||||||
['amount', `${amount}`],
|
['amount', `${amount}`],
|
||||||
['p', recipientHexKey]
|
['p', recipientHexKey]
|
||||||
],
|
],
|
||||||
|
@ -6,9 +6,8 @@ import {
|
|||||||
NDKSubscription,
|
NDKSubscription,
|
||||||
NDKSubscriptionCacheUsage
|
NDKSubscriptionCacheUsage
|
||||||
} from '@nostr-dev-kit/ndk'
|
} from '@nostr-dev-kit/ndk'
|
||||||
import { UserRelaysType } from 'controllers'
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { CommentEvent, ModDetails } from 'types'
|
import { CommentEvent, ModDetails, UserRelaysType } from 'types'
|
||||||
import { log, LogType } from 'utils'
|
import { log, LogType } from 'utils'
|
||||||
import { useNDKContext } from './useNDKContext'
|
import { useNDKContext } from './useNDKContext'
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { MuteLists } from 'types'
|
import { MuteLists } from 'types'
|
||||||
import { useAppSelector } from './redux'
|
import { useAppSelector } from './redux'
|
||||||
import { MetadataController } from 'controllers'
|
import { useNDKContext } from './useNDKContext'
|
||||||
|
|
||||||
export const useMuteLists = () => {
|
export const useMuteLists = () => {
|
||||||
|
const { getMuteLists } = useNDKContext()
|
||||||
const [muteLists, setMuteLists] = useState<{
|
const [muteLists, setMuteLists] = useState<{
|
||||||
admin: MuteLists
|
admin: MuteLists
|
||||||
user: MuteLists
|
user: MuteLists
|
||||||
@ -21,17 +22,11 @@ export const useMuteLists = () => {
|
|||||||
const userState = useAppSelector((state) => state.user)
|
const userState = useAppSelector((state) => state.user)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getMuteLists = async () => {
|
|
||||||
const pubkey = userState.user?.pubkey as string | undefined
|
const pubkey = userState.user?.pubkey as string | undefined
|
||||||
|
getMuteLists(pubkey).then((lists) => {
|
||||||
const metadataController = await MetadataController.getInstance()
|
|
||||||
metadataController.getMuteLists(pubkey).then((lists) => {
|
|
||||||
setMuteLists(lists)
|
setMuteLists(lists)
|
||||||
})
|
})
|
||||||
}
|
}, [userState, getMuteLists])
|
||||||
|
|
||||||
getMuteLists()
|
|
||||||
}, [userState])
|
|
||||||
|
|
||||||
return muteLists
|
return muteLists
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { MetadataController } from 'controllers'
|
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useDidMount } from './useDidMount'
|
import { useDidMount } from './useDidMount'
|
||||||
|
import { useNDKContext } from './useNDKContext'
|
||||||
|
|
||||||
export const useNSFWList = () => {
|
export const useNSFWList = () => {
|
||||||
|
const { getNSFWList } = useNDKContext()
|
||||||
const [nsfwList, setNSFWList] = useState<string[]>([])
|
const [nsfwList, setNSFWList] = useState<string[]>([])
|
||||||
|
|
||||||
useDidMount(async () => {
|
useDidMount(async () => {
|
||||||
const metadataController = await MetadataController.getInstance()
|
getNSFWList().then((list) => {
|
||||||
|
|
||||||
metadataController.getNSFWList().then((list) => {
|
|
||||||
setNSFWList(list)
|
setNSFWList(list)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk'
|
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk'
|
||||||
import { REACTIONS } from 'constants.ts'
|
import { REACTIONS } from 'constants.ts'
|
||||||
import { UserRelaysType } from 'controllers'
|
|
||||||
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
||||||
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
|
import { UserRelaysType } from 'types'
|
||||||
import { abbreviateNumber, log, LogType, now } from 'utils'
|
import { abbreviateNumber, log, LogType, now } from 'utils'
|
||||||
|
|
||||||
type UseReactionsParams = {
|
type UseReactionsParams = {
|
||||||
|
@ -6,7 +6,6 @@ import React, { useEffect, useState } from 'react'
|
|||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Banner } from '../components/Banner'
|
import { Banner } from '../components/Banner'
|
||||||
import { ZapPopUp } from '../components/Zap'
|
import { ZapPopUp } from '../components/Zap'
|
||||||
import { MetadataController } from '../controllers'
|
|
||||||
import {
|
import {
|
||||||
useAppDispatch,
|
useAppDispatch,
|
||||||
useAppSelector,
|
useAppSelector,
|
||||||
@ -261,8 +260,8 @@ const TipButtonWithDialog = React.memo(() => {
|
|||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
|
||||||
useDidMount(async () => {
|
useDidMount(async () => {
|
||||||
const metadataController = await MetadataController.getInstance()
|
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||||
setAdminNpub(metadataController.adminNpubs[0])
|
setAdminNpub(adminNpubs[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -152,7 +152,7 @@ const SlideContent = ({ naddr }: SlideContentProps) => {
|
|||||||
|
|
||||||
useDidMount(() => {
|
useDidMount(() => {
|
||||||
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
||||||
const { identifier, kind, pubkey, relays = [] } = decoded.data
|
const { identifier, kind, pubkey } = decoded.data
|
||||||
|
|
||||||
const ndkFilter: NDKFilter = {
|
const ndkFilter: NDKFilter = {
|
||||||
'#a': [identifier],
|
'#a': [identifier],
|
||||||
@ -160,7 +160,7 @@ const SlideContent = ({ naddr }: SlideContentProps) => {
|
|||||||
kinds: [kind]
|
kinds: [kind]
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchEvent(ndkFilter, relays)
|
fetchEvent(ndkFilter)
|
||||||
.then((ndkEvent) => {
|
.then((ndkEvent) => {
|
||||||
if (ndkEvent) {
|
if (ndkEvent) {
|
||||||
const extracted = extractModData(ndkEvent)
|
const extracted = extractModData(ndkEvent)
|
||||||
@ -225,7 +225,7 @@ const DisplayMod = ({ naddr }: DisplayModProps) => {
|
|||||||
|
|
||||||
useDidMount(() => {
|
useDidMount(() => {
|
||||||
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
||||||
const { identifier, kind, pubkey, relays = [] } = decoded.data
|
const { identifier, kind, pubkey } = decoded.data
|
||||||
|
|
||||||
const ndkFilter: NDKFilter = {
|
const ndkFilter: NDKFilter = {
|
||||||
'#a': [identifier],
|
'#a': [identifier],
|
||||||
@ -233,7 +233,7 @@ const DisplayMod = ({ naddr }: DisplayModProps) => {
|
|||||||
kinds: [kind]
|
kinds: [kind]
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchEvent(ndkFilter, relays)
|
fetchEvent(ndkFilter)
|
||||||
.then((ndkEvent) => {
|
.then((ndkEvent) => {
|
||||||
if (ndkEvent) {
|
if (ndkEvent) {
|
||||||
const extracted = extractModData(ndkEvent)
|
const extracted = extractModData(ndkEvent)
|
||||||
|
@ -11,7 +11,6 @@ import { toast } from 'react-toastify'
|
|||||||
import { BlogCard } from '../../components/BlogCard'
|
import { BlogCard } from '../../components/BlogCard'
|
||||||
import { LoadingSpinner } from '../../components/LoadingSpinner'
|
import { LoadingSpinner } from '../../components/LoadingSpinner'
|
||||||
import { ProfileSection } from '../../components/ProfileSection'
|
import { ProfileSection } from '../../components/ProfileSection'
|
||||||
import { MetadataController, UserRelaysType } from '../../controllers'
|
|
||||||
import { useAppSelector, useDidMount, useNDKContext } from '../../hooks'
|
import { useAppSelector, useDidMount, useNDKContext } from '../../hooks'
|
||||||
import { getGamePageRoute, getModsEditPageRoute } from '../../routes'
|
import { getGamePageRoute, getModsEditPageRoute } from '../../routes'
|
||||||
import '../../styles/comments.css'
|
import '../../styles/comments.css'
|
||||||
@ -24,7 +23,7 @@ import '../../styles/styles.css'
|
|||||||
import '../../styles/tabs.css'
|
import '../../styles/tabs.css'
|
||||||
import '../../styles/tags.css'
|
import '../../styles/tags.css'
|
||||||
import '../../styles/write.css'
|
import '../../styles/write.css'
|
||||||
import { DownloadUrl, ModDetails } from '../../types'
|
import { DownloadUrl, ModDetails, UserRelaysType } from '../../types'
|
||||||
import {
|
import {
|
||||||
abbreviateNumber,
|
abbreviateNumber,
|
||||||
copyTextToClipboard,
|
copyTextToClipboard,
|
||||||
@ -708,8 +707,8 @@ const ReportPopup = ({ aTag, handleClose }: ReportPopupProps) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadataController = await MetadataController.getInstance()
|
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
||||||
const reportingPubkey = npubToHex(metadataController.reportingNpub)
|
const reportingPubkey = npubToHex(reportingNpub)
|
||||||
|
|
||||||
if (reportingPubkey === hexPubkey) {
|
if (reportingPubkey === hexPubkey) {
|
||||||
setLoadingSpinnerDesc(`Finding user's mute list`)
|
setLoadingSpinnerDesc(`Finding user's mute list`)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { AdminSVG, PreferenceSVG, ProfileSVG, RelaySVG } from 'components/SVGs'
|
import { AdminSVG, PreferenceSVG, ProfileSVG, RelaySVG } from 'components/SVGs'
|
||||||
import { MetadataController } from 'controllers'
|
|
||||||
import { useAppSelector } from 'hooks'
|
import { useAppSelector } from 'hooks'
|
||||||
import { logout } from 'nostr-login'
|
import { logout } from 'nostr-login'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
@ -57,15 +56,12 @@ const SettingTabs = () => {
|
|||||||
const userState = useAppSelector((state) => state.user)
|
const userState = useAppSelector((state) => state.user)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
MetadataController.getInstance().then((controller) => {
|
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||||
if (userState.auth && userState.user?.npub) {
|
if (userState.auth && userState.user?.npub) {
|
||||||
setIsAdmin(
|
setIsAdmin(adminNpubs.includes(userState.user.npub as string))
|
||||||
controller.adminNpubs.includes(userState.user.npub as string)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
setIsAdmin(false)
|
setIsAdmin(false)
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}, [userState])
|
}, [userState])
|
||||||
|
|
||||||
const handleSignOut = () => {
|
const handleSignOut = () => {
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { NDKEvent, NDKRelayList, NDKRelayStatus } from '@nostr-dev-kit/ndk'
|
import {
|
||||||
|
getRelayListForUser,
|
||||||
|
NDKEvent,
|
||||||
|
NDKRelayList,
|
||||||
|
NDKRelayStatus
|
||||||
|
} from '@nostr-dev-kit/ndk'
|
||||||
import { InputField } from 'components/Inputs'
|
import { InputField } from 'components/Inputs'
|
||||||
import { LoadingSpinner } from 'components/LoadingSpinner'
|
import { LoadingSpinner } from 'components/LoadingSpinner'
|
||||||
import { MetadataController, UserRelaysType } from 'controllers'
|
|
||||||
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
||||||
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
|
import { UserRelaysType } from 'types'
|
||||||
import { log, LogType, normalizeWebSocketURL, now } from 'utils'
|
import { log, LogType, normalizeWebSocketURL, now } from 'utils'
|
||||||
|
|
||||||
const READ_MARKER = 'read'
|
const READ_MARKER = 'read'
|
||||||
@ -20,10 +25,8 @@ export const RelaySettings = () => {
|
|||||||
const [inputValue, setInputValue] = useState('')
|
const [inputValue, setInputValue] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchRelayList = async (pubkey: string) => {
|
if (userState.auth && userState.user?.pubkey) {
|
||||||
const metadataController = await MetadataController.getInstance()
|
getRelayListForUser(userState.user.pubkey as string, ndk)
|
||||||
metadataController
|
|
||||||
.getNDKRelayList(pubkey)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setNDKRelayList(res)
|
setNDKRelayList(res)
|
||||||
})
|
})
|
||||||
@ -35,14 +38,10 @@ export const RelaySettings = () => {
|
|||||||
)
|
)
|
||||||
setNDKRelayList(null)
|
setNDKRelayList(null)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if (userState.auth && userState.user?.pubkey) {
|
|
||||||
fetchRelayList(userState.user.pubkey as string)
|
|
||||||
} else {
|
} else {
|
||||||
setNDKRelayList(null)
|
setNDKRelayList(null)
|
||||||
}
|
}
|
||||||
}, [userState])
|
}, [userState, ndk])
|
||||||
|
|
||||||
const handleAdd = async (relayUrl: string) => {
|
const handleAdd = async (relayUrl: string) => {
|
||||||
if (!ndkRelayList) return
|
if (!ndkRelayList) return
|
||||||
|
@ -29,7 +29,7 @@ export const SubmitModPage = () => {
|
|||||||
useDidMount(async () => {
|
useDidMount(async () => {
|
||||||
if (naddr) {
|
if (naddr) {
|
||||||
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
||||||
const { identifier, kind, pubkey, relays = [] } = decoded.data
|
const { identifier, kind, pubkey } = decoded.data
|
||||||
|
|
||||||
const filter: NDKFilter = {
|
const filter: NDKFilter = {
|
||||||
'#a': [identifier],
|
'#a': [identifier],
|
||||||
@ -39,7 +39,7 @@ export const SubmitModPage = () => {
|
|||||||
|
|
||||||
setIsFetching(true)
|
setIsFetching(true)
|
||||||
|
|
||||||
fetchEvent(filter, relays)
|
fetchEvent(filter)
|
||||||
.then((event) => {
|
.then((event) => {
|
||||||
if (event) {
|
if (event) {
|
||||||
const extracted = extractModData(event)
|
const extracted = extractModData(event)
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
import { NDKUserProfile } from '@nostr-dev-kit/ndk'
|
import { NDKUserProfile } from '@nostr-dev-kit/ndk'
|
||||||
|
|
||||||
export type UserProfile = NDKUserProfile | null
|
export type UserProfile = NDKUserProfile | null
|
||||||
|
|
||||||
|
export enum UserRelaysType {
|
||||||
|
Read = 'readRelayUrls',
|
||||||
|
Write = 'writeRelayUrls',
|
||||||
|
Both = 'bothRelayUrls'
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user