2024-11-06 13:17:13 +01:00
|
|
|
import { filterForEventsTaggingId, NDKFilter } from '@nostr-dev-kit/ndk'
|
2024-10-31 20:14:29 +01:00
|
|
|
import { NDKContextType } from 'contexts/NDKContext'
|
2024-11-06 13:17:13 +01:00
|
|
|
import { kinds, nip19 } from 'nostr-tools'
|
2024-10-31 20:14:29 +01:00
|
|
|
import { LoaderFunctionArgs, redirect } from 'react-router-dom'
|
|
|
|
import { toast } from 'react-toastify'
|
|
|
|
import { appRoutes } from 'routes'
|
2024-11-06 13:17:13 +01:00
|
|
|
import { BlogPageLoaderResult, FilterOptions, NSFWFilter } from 'types'
|
|
|
|
import {
|
|
|
|
DEFAULT_FILTER_OPTIONS,
|
|
|
|
getLocalStorageItem,
|
|
|
|
log,
|
|
|
|
LogType
|
|
|
|
} from 'utils'
|
|
|
|
import { extractBlogCardDetails, extractBlogDetails } from 'utils/blog'
|
2024-10-31 20:14:29 +01:00
|
|
|
|
|
|
|
export const blogRouteLoader =
|
|
|
|
(ndkContext: NDKContextType) =>
|
|
|
|
async ({ params }: LoaderFunctionArgs) => {
|
|
|
|
const { naddr } = params
|
|
|
|
if (!naddr) {
|
|
|
|
log(true, LogType.Error, 'Required naddr.')
|
|
|
|
return redirect(appRoutes.blogs)
|
|
|
|
}
|
|
|
|
|
2024-11-06 13:17:13 +01:00
|
|
|
// Decode author from naddr
|
|
|
|
const decoded = nip19.decode<'naddr'>(naddr as `naddr1${string}`)
|
|
|
|
const { pubkey } = decoded.data
|
|
|
|
|
2024-10-31 20:14:29 +01:00
|
|
|
try {
|
2024-11-06 13:17:13 +01:00
|
|
|
// Get the filter with #a from naddr for the main blog content
|
2024-10-31 20:14:29 +01:00
|
|
|
const filter = filterForEventsTaggingId(naddr)
|
|
|
|
if (!filter) {
|
|
|
|
log(true, LogType.Error, 'Unable to create filter from blog naddr.')
|
|
|
|
return redirect(appRoutes.blogs)
|
|
|
|
}
|
2024-11-05 16:22:08 +01:00
|
|
|
|
2024-11-06 13:17:13 +01:00
|
|
|
// Get the blog filter options for latest blogs
|
|
|
|
const filterOptions = JSON.parse(
|
|
|
|
getLocalStorageItem('filter-blog', DEFAULT_FILTER_OPTIONS)
|
|
|
|
) as FilterOptions
|
|
|
|
|
|
|
|
// Fetch 4 in case the current blog is included in the latest
|
|
|
|
const latestModsFilter: NDKFilter = {
|
|
|
|
authors: [pubkey],
|
|
|
|
kinds: [kinds.LongFormArticle],
|
|
|
|
limit: 4
|
|
|
|
}
|
|
|
|
// Add source filter
|
|
|
|
if (filterOptions.source === window.location.host) {
|
|
|
|
latestModsFilter['#r'] = [filterOptions.source]
|
|
|
|
}
|
|
|
|
// Filter by NSFW tag
|
|
|
|
// NSFWFilter.Show_NSFW -> filter not needed
|
|
|
|
// NSFWFilter.Only_NSFW -> true
|
|
|
|
// NSFWFilter.Hide_NSFW -> false
|
|
|
|
if (filterOptions.nsfw !== NSFWFilter.Show_NSFW) {
|
|
|
|
latestModsFilter['#nsfw'] = [
|
|
|
|
(filterOptions.nsfw === NSFWFilter.Only_NSFW).toString()
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parallel fetch blog event and latest events
|
|
|
|
const settled = await Promise.allSettled([
|
|
|
|
ndkContext.fetchEvent(filter),
|
|
|
|
ndkContext.fetchEvents(latestModsFilter)
|
|
|
|
])
|
|
|
|
|
|
|
|
const result: BlogPageLoaderResult = {
|
|
|
|
blog: undefined,
|
|
|
|
latest: []
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the blog event result
|
|
|
|
const fetchEventResult = settled[0]
|
|
|
|
if (fetchEventResult.status === 'fulfilled' && fetchEventResult.value) {
|
|
|
|
// Extract the blog details from the event
|
|
|
|
result.blog = extractBlogDetails(fetchEventResult.value)
|
|
|
|
} else if (fetchEventResult.status === 'rejected') {
|
|
|
|
log(
|
|
|
|
true,
|
|
|
|
LogType.Error,
|
|
|
|
'Unable to fetch the blog event.',
|
|
|
|
fetchEventResult.reason
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the lateast blog events
|
|
|
|
const fetchEventsResult = settled[1]
|
|
|
|
if (fetchEventsResult.status === 'fulfilled' && fetchEventsResult.value) {
|
|
|
|
// Extract the blog card details from the events
|
|
|
|
result.latest = fetchEventsResult.value
|
|
|
|
.map(extractBlogCardDetails)
|
|
|
|
.filter((b) => b.id !== result.blog?.id) // Filter out current blog if present
|
|
|
|
.slice(0, 3) // Take only three
|
|
|
|
} else if (fetchEventsResult.status === 'rejected') {
|
|
|
|
log(
|
|
|
|
true,
|
|
|
|
LogType.Error,
|
|
|
|
'Unable to fetch the latest blog events.',
|
|
|
|
fetchEventsResult.reason
|
|
|
|
)
|
2024-10-31 20:14:29 +01:00
|
|
|
}
|
|
|
|
|
2024-11-06 13:17:13 +01:00
|
|
|
return result
|
2024-10-31 20:14:29 +01:00
|
|
|
} catch (error) {
|
|
|
|
log(
|
|
|
|
true,
|
|
|
|
LogType.Error,
|
|
|
|
'An error occurred in fetching blog details from relays',
|
|
|
|
error
|
|
|
|
)
|
2024-11-05 13:57:39 +01:00
|
|
|
toast.error('An error occurred in fetching blog details from relays')
|
2024-10-31 20:14:29 +01:00
|
|
|
return redirect(appRoutes.blogs)
|
|
|
|
}
|
|
|
|
}
|