import { NDKContextType } from 'contexts/NDKContext' import { nip19 } from 'nostr-tools' import { LoaderFunctionArgs, redirect } from 'react-router-dom' import { appRoutes, getProfilePageRoute } from 'routes' import { store } from 'store' import { MuteLists, UserProfile } from 'types' import { log, LogType } from 'utils' export interface ProfilePageLoaderResult { profile: UserProfile isBlocked: boolean isOwnProfile: boolean muteLists: { admin: MuteLists user: MuteLists } nsfwList: string[] } export const profileRouteLoader = (ndkContext: NDKContextType) => async ({ params }: LoaderFunctionArgs) => { // Try to decode nprofile parameter const { nprofile } = params let profilePubkey: string | undefined try { const value = nprofile ? nip19.decode(nprofile as `nprofile1${string}`) : undefined profilePubkey = value?.data.pubkey } catch (error) { // Silently ignore and redirect to home or logged in user log(true, LogType.Error, 'Failed to decode nprofile.', error) } // Get the current state const userState = store.getState().user // Check if current user is logged in let userPubkey: string | undefined if (userState.auth && userState.user?.pubkey) { userPubkey = userState.user.pubkey as string } // Redirect if profile naddr is missing // - home if user is not logged let profileRoute = appRoutes.home if (!profilePubkey && userPubkey) { // - own profile profileRoute = getProfilePageRoute( nip19.nprofileEncode({ pubkey: userPubkey }) ) } if (!profilePubkey) return redirect(profileRoute) // Empty result const result: ProfilePageLoaderResult = { profile: {}, isBlocked: false, isOwnProfile: false, muteLists: { admin: { authors: [], replaceableEvents: [] }, user: { authors: [], replaceableEvents: [] } }, nsfwList: [] } // Check if user the user is logged in if (userState.auth && userState.user?.pubkey) { result.isOwnProfile = userState.user.pubkey === profilePubkey } const settled = await Promise.allSettled([ ndkContext.findMetadata(profilePubkey), ndkContext.getMuteLists(userPubkey), ndkContext.getNSFWList() ]) // Check the profile event result const profileEventResult = settled[0] if (profileEventResult.status === 'fulfilled' && profileEventResult.value) { result.profile = profileEventResult.value } else if (profileEventResult.status === 'rejected') { log( true, LogType.Error, 'Failed to fetch profile.', profileEventResult.reason ) } // Check the profile event result const muteListResult = settled[1] if (muteListResult.status === 'fulfilled' && muteListResult.value) { result.muteLists = muteListResult.value // Check if user has blocked this profile result.isBlocked = result.muteLists.user.authors.includes(profilePubkey) } else if (muteListResult.status === 'rejected') { log( true, LogType.Error, 'Failed to fetch mutelist.', muteListResult.reason ) } // Check the profile event result const nsfwListResult = settled[2] if (nsfwListResult.status === 'fulfilled' && nsfwListResult.value) { result.nsfwList = nsfwListResult.value } else if (nsfwListResult.status === 'rejected') { log( true, LogType.Error, 'Failed to fetch mutelist.', nsfwListResult.reason ) } return result }