Refactor to use NDK instead of custom relay and metadata controllers #89
@ -4,13 +4,12 @@ import { QRCodeSVG } from 'qrcode.react'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { toast } from 'react-toastify'
|
||||
import { UserRelaysType } from '../controllers'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
||||
import { appRoutes, getProfilePageRoute } from '../routes'
|
||||
import '../styles/author.css'
|
||||
import '../styles/innerPage.css'
|
||||
import '../styles/socialPosts.css'
|
||||
import { UserProfile } from '../types'
|
||||
import { UserProfile, UserRelaysType } from '../types'
|
||||
import {
|
||||
copyTextToClipboard,
|
||||
hexToNpub,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { getRelayListForUser } from '@nostr-dev-kit/ndk'
|
||||
import { QRCodeSVG } from 'qrcode.react'
|
||||
import React, {
|
||||
Dispatch,
|
||||
@ -9,7 +10,7 @@ import React, {
|
||||
} from 'react'
|
||||
import Countdown, { CountdownRenderProps } from 'react-countdown'
|
||||
import { toast } from 'react-toastify'
|
||||
import { MetadataController, ZapController } from '../controllers'
|
||||
import { ZapController } from '../controllers'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from '../hooks'
|
||||
import '../styles/popup.css'
|
||||
import { PaymentRequest, UserProfile } from '../types'
|
||||
@ -251,7 +252,7 @@ export const ZapPopUp = ({
|
||||
setHasZapped,
|
||||
handleClose
|
||||
}: ZapPopUpProps) => {
|
||||
const { findMetadata } = useNDKContext()
|
||||
const { ndk, findMetadata } = useNDKContext()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||
const [amount, setAmount] = useState<number>(0)
|
||||
@ -300,6 +301,20 @@ export const ZapPopUp = ({
|
||||
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()
|
||||
|
||||
setLoadingSpinnerDesc('Creating zap request')
|
||||
@ -308,6 +323,7 @@ export const ZapPopUp = ({
|
||||
receiverMetadata.lud16,
|
||||
amount,
|
||||
receiverMetadata.pubkey as string,
|
||||
receiverRelays,
|
||||
userHexKey,
|
||||
message,
|
||||
eventId,
|
||||
@ -482,7 +498,7 @@ export const ZapSplit = ({
|
||||
setHasZapped,
|
||||
handleClose
|
||||
}: ZapSplitProps) => {
|
||||
const { findMetadata } = useNDKContext()
|
||||
const { ndk, findMetadata } = useNDKContext()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||
const [amount, setAmount] = useState<number>(0)
|
||||
@ -502,8 +518,8 @@ export const ZapSplit = ({
|
||||
setAuthor(res)
|
||||
})
|
||||
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
findMetadata(metadataController.adminNpubs[0]).then((res) => {
|
||||
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||
findMetadata(adminNpubs[0]).then((res) => {
|
||||
setAdmin(res)
|
||||
})
|
||||
})
|
||||
@ -557,12 +573,30 @@ export const ZapSplit = ({
|
||||
const invoices = new Map<string, PaymentRequest>()
|
||||
|
||||
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')
|
||||
const invoice = await zapController
|
||||
.getLightningPaymentRequest(
|
||||
author.lud16,
|
||||
authorShare,
|
||||
author.pubkey as string,
|
||||
authorRelays,
|
||||
userHexKey,
|
||||
message,
|
||||
eventId,
|
||||
@ -579,12 +613,27 @@ export const ZapSplit = ({
|
||||
}
|
||||
|
||||
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')
|
||||
const invoice = await zapController
|
||||
.getLightningPaymentRequest(
|
||||
admin.lud16,
|
||||
adminShare,
|
||||
admin.pubkey as string,
|
||||
adminRelays,
|
||||
userHexKey,
|
||||
message,
|
||||
eventId,
|
||||
|
@ -3,6 +3,7 @@ import NDK, {
|
||||
NDKEvent,
|
||||
NDKFilter,
|
||||
NDKKind,
|
||||
NDKList,
|
||||
NDKRelaySet,
|
||||
NDKSubscriptionCacheUsage,
|
||||
NDKUser,
|
||||
@ -10,11 +11,10 @@ import NDK, {
|
||||
} from '@nostr-dev-kit/ndk'
|
||||
import NDKCacheAdapterDexie from '@nostr-dev-kit/ndk-cache-dexie'
|
||||
import { MOD_FILTER_LIMIT, T_TAG_VALUE } from 'constants.ts'
|
||||
import { UserRelaysType } from 'controllers'
|
||||
import { Dexie } from 'dexie'
|
||||
import { createContext, ReactNode, useEffect, useMemo } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ModDetails, UserProfile } from 'types'
|
||||
import { ModDetails, MuteLists, UserProfile, UserRelaysType } from 'types'
|
||||
import {
|
||||
constructModListFromEvents,
|
||||
hexToNpub,
|
||||
@ -57,6 +57,11 @@ interface NDKContextType {
|
||||
hasZapped: boolean
|
||||
}>
|
||||
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`
|
||||
@ -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 (
|
||||
<NDKContext.Provider
|
||||
value={{
|
||||
@ -379,7 +495,9 @@ export const NDKContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
fetchEventFromUserRelays,
|
||||
findMetadata,
|
||||
getTotalZapAmount,
|
||||
publish
|
||||
publish,
|
||||
getNSFWList,
|
||||
getMuteLists
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
@ -1,2 +1 @@
|
||||
export * from './metadata'
|
||||
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
|
||||
} from '../types'
|
||||
import { log, LogType, npubToHex } from '../utils'
|
||||
import { MetadataController, UserRelaysType } from './metadata'
|
||||
|
||||
/**
|
||||
* Singleton class to manage zap related operations.
|
||||
@ -48,6 +47,7 @@ export class ZapController {
|
||||
* @param lud16 - LUD-16 of the recipient.
|
||||
* @param amount - payment amount (will be multiplied by 1000 to represent sats).
|
||||
* @param recipientPubKey - pubKey of the recipient.
|
||||
* @param recipientRelays - relays on which zap receipt will be published.
|
||||
* @param senderPubkey - pubKey of of the sender.
|
||||
* @param content - optional content (comment).
|
||||
* @param eventId - event id, if zapping an event.
|
||||
@ -59,6 +59,7 @@ export class ZapController {
|
||||
lud16: string,
|
||||
amount: number,
|
||||
recipientPubKey: string,
|
||||
recipientRelays: string[],
|
||||
senderPubkey: string,
|
||||
content?: string,
|
||||
eventId?: string,
|
||||
@ -88,6 +89,7 @@ export class ZapController {
|
||||
amount,
|
||||
content,
|
||||
recipientPubKey,
|
||||
recipientRelays,
|
||||
senderPubkey,
|
||||
eventId,
|
||||
aTag
|
||||
@ -273,6 +275,7 @@ export class ZapController {
|
||||
* @param amount - request amount (sats).
|
||||
* @param content - comment.
|
||||
* @param recipientPubKey - pubKey of the recipient.
|
||||
* @param recipientRelays - relays on which zap receipt will be published.
|
||||
* @param senderPubkey - pubKey of of the sender.
|
||||
* @param eventId - event id, if zapping an event.
|
||||
* @param aTag - value of `a` tag.
|
||||
@ -282,6 +285,7 @@ export class ZapController {
|
||||
amount: number,
|
||||
content = '',
|
||||
recipientPubKey: string,
|
||||
recipientRelays: string[],
|
||||
senderPubkey: string,
|
||||
eventId?: string,
|
||||
aTag?: string
|
||||
@ -290,21 +294,15 @@ export class ZapController {
|
||||
|
||||
if (!recipientHexKey) throw 'Invalid recipient pubKey.'
|
||||
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
const receiverReadRelays = await metadataController.findUserRelays(
|
||||
recipientHexKey,
|
||||
UserRelaysType.Read
|
||||
)
|
||||
|
||||
if (!receiverReadRelays.includes(this.appRelay)) {
|
||||
receiverReadRelays.push(this.appRelay)
|
||||
if (!recipientRelays.includes(this.appRelay)) {
|
||||
recipientRelays.push(this.appRelay)
|
||||
}
|
||||
|
||||
const zapRequest: ZapRequest = {
|
||||
kind: kinds.ZapRequest,
|
||||
content,
|
||||
tags: [
|
||||
['relays', ...receiverReadRelays],
|
||||
['relays', ...recipientRelays],
|
||||
['amount', `${amount}`],
|
||||
['p', recipientHexKey]
|
||||
],
|
||||
|
@ -6,9 +6,8 @@ import {
|
||||
NDKSubscription,
|
||||
NDKSubscriptionCacheUsage
|
||||
} from '@nostr-dev-kit/ndk'
|
||||
import { UserRelaysType } from 'controllers'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { CommentEvent, ModDetails } from 'types'
|
||||
import { CommentEvent, ModDetails, UserRelaysType } from 'types'
|
||||
import { log, LogType } from 'utils'
|
||||
import { useNDKContext } from './useNDKContext'
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MuteLists } from 'types'
|
||||
import { useAppSelector } from './redux'
|
||||
import { MetadataController } from 'controllers'
|
||||
import { useNDKContext } from './useNDKContext'
|
||||
|
||||
export const useMuteLists = () => {
|
||||
const { getMuteLists } = useNDKContext()
|
||||
const [muteLists, setMuteLists] = useState<{
|
||||
admin: MuteLists
|
||||
user: MuteLists
|
||||
@ -21,17 +22,11 @@ export const useMuteLists = () => {
|
||||
const userState = useAppSelector((state) => state.user)
|
||||
|
||||
useEffect(() => {
|
||||
const getMuteLists = async () => {
|
||||
const pubkey = userState.user?.pubkey as string | undefined
|
||||
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
metadataController.getMuteLists(pubkey).then((lists) => {
|
||||
setMuteLists(lists)
|
||||
})
|
||||
}
|
||||
|
||||
getMuteLists()
|
||||
}, [userState])
|
||||
const pubkey = userState.user?.pubkey as string | undefined
|
||||
getMuteLists(pubkey).then((lists) => {
|
||||
setMuteLists(lists)
|
||||
})
|
||||
}, [userState, getMuteLists])
|
||||
|
||||
return muteLists
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { MetadataController } from 'controllers'
|
||||
import { useState } from 'react'
|
||||
import { useDidMount } from './useDidMount'
|
||||
import { useNDKContext } from './useNDKContext'
|
||||
|
||||
export const useNSFWList = () => {
|
||||
const { getNSFWList } = useNDKContext()
|
||||
const [nsfwList, setNSFWList] = useState<string[]>([])
|
||||
|
||||
useDidMount(async () => {
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
|
||||
metadataController.getNSFWList().then((list) => {
|
||||
getNSFWList().then((list) => {
|
||||
setNSFWList(list)
|
||||
})
|
||||
})
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { NDKEvent, NDKFilter } from '@nostr-dev-kit/ndk'
|
||||
import { REACTIONS } from 'constants.ts'
|
||||
import { UserRelaysType } from 'controllers'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
||||
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
import { UserRelaysType } from 'types'
|
||||
import { abbreviateNumber, log, LogType, now } from 'utils'
|
||||
|
||||
type UseReactionsParams = {
|
||||
|
@ -6,7 +6,6 @@ import React, { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { Banner } from '../components/Banner'
|
||||
import { ZapPopUp } from '../components/Zap'
|
||||
import { MetadataController } from '../controllers'
|
||||
import {
|
||||
useAppDispatch,
|
||||
useAppSelector,
|
||||
@ -261,8 +260,8 @@ const TipButtonWithDialog = React.memo(() => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
useDidMount(async () => {
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
setAdminNpub(metadataController.adminNpubs[0])
|
||||
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||
setAdminNpub(adminNpubs[0])
|
||||
})
|
||||
|
||||
return (
|
||||
|
@ -152,7 +152,7 @@ const SlideContent = ({ naddr }: SlideContentProps) => {
|
||||
|
||||
useDidMount(() => {
|
||||
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 = {
|
||||
'#a': [identifier],
|
||||
@ -160,7 +160,7 @@ const SlideContent = ({ naddr }: SlideContentProps) => {
|
||||
kinds: [kind]
|
||||
}
|
||||
|
||||
fetchEvent(ndkFilter, relays)
|
||||
fetchEvent(ndkFilter)
|
||||
.then((ndkEvent) => {
|
||||
if (ndkEvent) {
|
||||
const extracted = extractModData(ndkEvent)
|
||||
@ -225,7 +225,7 @@ const DisplayMod = ({ naddr }: DisplayModProps) => {
|
||||
|
||||
useDidMount(() => {
|
||||
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 = {
|
||||
'#a': [identifier],
|
||||
@ -233,7 +233,7 @@ const DisplayMod = ({ naddr }: DisplayModProps) => {
|
||||
kinds: [kind]
|
||||
}
|
||||
|
||||
fetchEvent(ndkFilter, relays)
|
||||
fetchEvent(ndkFilter)
|
||||
.then((ndkEvent) => {
|
||||
if (ndkEvent) {
|
||||
const extracted = extractModData(ndkEvent)
|
||||
|
@ -11,7 +11,6 @@ import { toast } from 'react-toastify'
|
||||
import { BlogCard } from '../../components/BlogCard'
|
||||
import { LoadingSpinner } from '../../components/LoadingSpinner'
|
||||
import { ProfileSection } from '../../components/ProfileSection'
|
||||
import { MetadataController, UserRelaysType } from '../../controllers'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from '../../hooks'
|
||||
import { getGamePageRoute, getModsEditPageRoute } from '../../routes'
|
||||
import '../../styles/comments.css'
|
||||
@ -24,7 +23,7 @@ import '../../styles/styles.css'
|
||||
import '../../styles/tabs.css'
|
||||
import '../../styles/tags.css'
|
||||
import '../../styles/write.css'
|
||||
import { DownloadUrl, ModDetails } from '../../types'
|
||||
import { DownloadUrl, ModDetails, UserRelaysType } from '../../types'
|
||||
import {
|
||||
abbreviateNumber,
|
||||
copyTextToClipboard,
|
||||
@ -708,8 +707,8 @@ const ReportPopup = ({ aTag, handleClose }: ReportPopupProps) => {
|
||||
return
|
||||
}
|
||||
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
const reportingPubkey = npubToHex(metadataController.reportingNpub)
|
||||
const reportingNpub = import.meta.env.VITE_REPORTING_NPUB
|
||||
const reportingPubkey = npubToHex(reportingNpub)
|
||||
|
||||
if (reportingPubkey === hexPubkey) {
|
||||
setLoadingSpinnerDesc(`Finding user's mute list`)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { AdminSVG, PreferenceSVG, ProfileSVG, RelaySVG } from 'components/SVGs'
|
||||
import { MetadataController } from 'controllers'
|
||||
import { useAppSelector } from 'hooks'
|
||||
import { logout } from 'nostr-login'
|
||||
import { useEffect, useState } from 'react'
|
||||
@ -57,15 +56,12 @@ const SettingTabs = () => {
|
||||
const userState = useAppSelector((state) => state.user)
|
||||
|
||||
useEffect(() => {
|
||||
MetadataController.getInstance().then((controller) => {
|
||||
if (userState.auth && userState.user?.npub) {
|
||||
setIsAdmin(
|
||||
controller.adminNpubs.includes(userState.user.npub as string)
|
||||
)
|
||||
} else {
|
||||
setIsAdmin(false)
|
||||
}
|
||||
})
|
||||
const adminNpubs = import.meta.env.VITE_ADMIN_NPUBS.split(',')
|
||||
if (userState.auth && userState.user?.npub) {
|
||||
setIsAdmin(adminNpubs.includes(userState.user.npub as string))
|
||||
} else {
|
||||
setIsAdmin(false)
|
||||
}
|
||||
}, [userState])
|
||||
|
||||
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 { LoadingSpinner } from 'components/LoadingSpinner'
|
||||
import { MetadataController, UserRelaysType } from 'controllers'
|
||||
import { useAppSelector, useDidMount, useNDKContext } from 'hooks'
|
||||
import { Event, kinds, UnsignedEvent } from 'nostr-tools'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { toast } from 'react-toastify'
|
||||
import { UserRelaysType } from 'types'
|
||||
import { log, LogType, normalizeWebSocketURL, now } from 'utils'
|
||||
|
||||
const READ_MARKER = 'read'
|
||||
@ -20,10 +25,8 @@ export const RelaySettings = () => {
|
||||
const [inputValue, setInputValue] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
const fetchRelayList = async (pubkey: string) => {
|
||||
const metadataController = await MetadataController.getInstance()
|
||||
metadataController
|
||||
.getNDKRelayList(pubkey)
|
||||
if (userState.auth && userState.user?.pubkey) {
|
||||
getRelayListForUser(userState.user.pubkey as string, ndk)
|
||||
.then((res) => {
|
||||
setNDKRelayList(res)
|
||||
})
|
||||
@ -35,14 +38,10 @@ export const RelaySettings = () => {
|
||||
)
|
||||
setNDKRelayList(null)
|
||||
})
|
||||
}
|
||||
|
||||
if (userState.auth && userState.user?.pubkey) {
|
||||
fetchRelayList(userState.user.pubkey as string)
|
||||
} else {
|
||||
setNDKRelayList(null)
|
||||
}
|
||||
}, [userState])
|
||||
}, [userState, ndk])
|
||||
|
||||
const handleAdd = async (relayUrl: string) => {
|
||||
if (!ndkRelayList) return
|
||||
|
@ -29,7 +29,7 @@ export const SubmitModPage = () => {
|
||||
useDidMount(async () => {
|
||||
if (naddr) {
|
||||
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 = {
|
||||
'#a': [identifier],
|
||||
@ -39,7 +39,7 @@ export const SubmitModPage = () => {
|
||||
|
||||
setIsFetching(true)
|
||||
|
||||
fetchEvent(filter, relays)
|
||||
fetchEvent(filter)
|
||||
.then((event) => {
|
||||
if (event) {
|
||||
const extracted = extractModData(event)
|
||||
|
@ -1,3 +1,9 @@
|
||||
import { NDKUserProfile } from '@nostr-dev-kit/ndk'
|
||||
|
||||
export type UserProfile = NDKUserProfile | null
|
||||
|
||||
export enum UserRelaysType {
|
||||
Read = 'readRelayUrls',
|
||||
Write = 'writeRelayUrls',
|
||||
Both = 'bothRelayUrls'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user