diff --git a/lib/articleEncryption.ts b/lib/articleEncryption.ts index 0c56ec5..5652797 100644 --- a/lib/articleEncryption.ts +++ b/lib/articleEncryption.ts @@ -81,7 +81,7 @@ export async function encryptArticleContent(content: string): Promise<{ const ivBuffer = iv.buffer instanceof ArrayBuffer ? iv.buffer : new ArrayBuffer(iv.byteLength) const ivView = new Uint8Array(ivBuffer, 0, iv.byteLength) ivView.set(iv) - + const encryptedBuffer = await crypto.subtle.encrypt( { name: 'AES-GCM', diff --git a/lib/nostrEventParsing.ts b/lib/nostrEventParsing.ts deleted file mode 100644 index f45feba..0000000 --- a/lib/nostrEventParsing.ts +++ /dev/null @@ -1,163 +0,0 @@ -import type { Event } from 'nostr-tools' -import type { Article, KindType, MediaRef, Review, Series } from '@/types/nostr' -import { extractTagsFromEvent } from './nostrTagSystem' - -/** - * Parse article metadata from Nostr event - * Uses new tag system: #publication, #sciencefiction|research, #id_, #paywall, #payment - */ -export function parseArticleFromEvent(event: Event): Article | null { - try { - const tags = extractTagsFromEvent(event) - // Check if it's a publication type - if (tags.type !== 'publication') { - return null - } - const { previewContent } = getPreviewContent(event.content, tags.preview as string | undefined) - return buildArticle(event, tags, previewContent) - } catch (e) { - console.error('Error parsing article:', e) - return null - } -} - -export function parseSeriesFromEvent(event: Event): Series | null { - try { - const tags = extractTagsFromEvent(event) - // Check if it's a series type (tag is 'series' in English) - if (tags.type !== 'series') { - return null - } - if (!tags.title || !tags.description) { - return null - } - // Map category from new system to old system - const category = tags.category === 'sciencefiction' ? 'science-fiction' : tags.category === 'research' ? 'scientific-research' : 'science-fiction' - const series: Series = { - id: tags.id ?? event.id, - pubkey: event.pubkey, - title: tags.title as string, - description: tags.description as string, - preview: (tags.preview as string | undefined) ?? event.content.substring(0, 200), - category, - ...(tags.coverUrl ? { coverUrl: tags.coverUrl as string } : {}), - } - series.kindType = 'series' - return series - } catch (e) { - console.error('Error parsing series:', e) - return null - } -} - -export function parseReviewFromEvent(event: Event): Review | null { - try { - const tags = extractTagsFromEvent(event) - // Check if it's a quote type (reviews are quotes, tag is 'quote' in English) - if (tags.type !== 'quote') { - return null - } - const articleId = tags.articleId as string | undefined - const reviewer = tags.reviewerPubkey as string | undefined - if (!articleId || !reviewer) { - return null - } - const rewardedTag = event.tags.find((tag) => tag[0] === 'rewarded' && tag[1] === 'true') - const rewardAmountTag = event.tags.find((tag) => tag[0] === 'reward_amount') - - const review: Review = { - id: tags.id ?? event.id, - articleId, - authorPubkey: event.pubkey, - reviewerPubkey: reviewer, - content: event.content, - createdAt: event.created_at, - ...(tags.title ? { title: tags.title as string } : {}), - ...(rewardedTag ? { rewarded: true } : {}), - ...(rewardAmountTag ? { rewardAmount: parseInt(rewardAmountTag[1] ?? '0', 10) } : {}), - } - review.kindType = 'review' - return review - } catch (e) { - console.error('Error parsing review:', e) - return null - } -} - -// extractTags is now replaced by extractTagsFromEvent from nostrTagSystem -// This function is kept for backward compatibility but should be migrated -// Currently unused - kept for potential future migration -// @ts-expect-error - Unused function kept for backward compatibility -function _unusedExtractTags(event: Event) { - const tags = extractTagsFromEvent(event) - const mediaTags = event.tags.filter((tag: string[]) => tag[0] === 'media') - const media: MediaRef[] = - mediaTags - .map((tag: string[]) => { - const url = tag[1] - const type = tag[2] === 'video' ? 'video' : 'image' - if (!url) { - return null - } - return { url, type } - }) - .filter(Boolean) as MediaRef[] - - // Map category from new system to old system - const category = tags.category === 'sciencefiction' ? 'science-fiction' : tags.category === 'research' ? 'scientific-research' : undefined - const isPresentation = tags.type === 'author' - - return { - title: (tags.title as string | undefined) ?? 'Untitled', - preview: tags.preview as string | undefined, - description: tags.description as string | undefined, - zapAmount: (tags.zapAmount as number | undefined) ?? 800, - invoice: tags.invoice as string | undefined, - paymentHash: tags.paymentHash as string | undefined, - category, - isPresentation, - mainnetAddress: tags.mainnetAddress as string | undefined, - totalSponsoring: (tags.totalSponsoring as number | undefined) ?? 0, - authorPresentationId: undefined, // Not used in new system - seriesId: tags.seriesId as string | undefined, - bannerUrl: tags.bannerUrl as string | undefined, - coverUrl: tags.coverUrl as string | undefined, - media, - kindType: tags.type === 'author' ? 'article' : tags.type === 'series' ? 'series' : tags.type === 'publication' ? 'article' : tags.type === 'quote' ? 'review' : undefined, - articleId: tags.articleId as string | undefined, - reviewerPubkey: tags.reviewerPubkey as string | undefined, - author: undefined, // Not used in new system - } -} - -function getPreviewContent(content: string, previewTag?: string) { - const lines = content.split('\n') - const previewContent = previewTag ?? lines[0] ?? content.substring(0, 200) - return { previewContent } -} - -function buildArticle(event: Event, tags: ReturnType, preview: string): Article { - // Map category from new system to old system - const category = tags.category === 'sciencefiction' ? 'science-fiction' : tags.category === 'research' ? 'scientific-research' : undefined - const isPresentation = tags.type === 'author' - - return { - id: tags.id ?? event.id, - pubkey: event.pubkey, - title: (tags.title as string | undefined) ?? 'Untitled', - preview, - content: '', - createdAt: event.created_at, - zapAmount: (tags.zapAmount as number | undefined) ?? 800, - paid: false, - ...(tags.invoice ? { invoice: tags.invoice as string } : {}), - ...(tags.paymentHash ? { paymentHash: tags.paymentHash as string } : {}), - ...(category ? { category } : {}), - ...(isPresentation ? { isPresentation: true } : {}), - ...(tags.mainnetAddress ? { mainnetAddress: tags.mainnetAddress as string } : {}), - ...(tags.totalSponsoring ? { totalSponsoring: tags.totalSponsoring as number } : {}), - ...(tags.seriesId ? { seriesId: tags.seriesId as string } : {}), - ...(tags.bannerUrl ? { bannerUrl: tags.bannerUrl as string } : {}), - ...(tags.type === 'publication' ? { kindType: 'article' as KindType } : tags.type === 'author' ? { kindType: 'article' as KindType } : {}), - } -} diff --git a/lib/nostrPrivateMessages.ts b/lib/nostrPrivateMessages.ts index c1b72ec..e9b6594 100644 --- a/lib/nostrPrivateMessages.ts +++ b/lib/nostrPrivateMessages.ts @@ -1,6 +1,6 @@ import { Event, nip04 } from 'nostr-tools' import { SimplePool } from 'nostr-tools' -import { decryptDecryptionKey, decryptArticleContent, type DecryptionKey } from './articleEncryption' +import { decryptArticleContent, type DecryptionKey } from './articleEncryption' const RELAY_URL = process.env.NEXT_PUBLIC_NOSTR_RELAY_URL ?? 'wss://relay.damus.io' diff --git a/lib/nostrTagSystem.ts b/lib/nostrTagSystem.ts index eeda4a8..af432a1 100644 --- a/lib/nostrTagSystem.ts +++ b/lib/nostrTagSystem.ts @@ -143,11 +143,24 @@ export function buildTags(tags: AuthorTags | SeriesTags | PublicationTags | Quot * Extract tags from event */ export function extractTagsFromEvent(event: { tags: string[][] }): { - type?: TagType - category?: TagCategory - id?: string + type?: TagType | undefined + category?: TagCategory | undefined + id?: string | undefined paywall: boolean payment: boolean + title?: string | undefined + preview?: string | undefined + description?: string | undefined + mainnetAddress?: string | undefined + totalSponsoring?: number | undefined + seriesId?: string | undefined + coverUrl?: string | undefined + bannerUrl?: string | undefined + zapAmount?: number | undefined + invoice?: string | undefined + paymentHash?: string | undefined + articleId?: string | undefined + reviewerPubkey?: string | undefined [key: string]: unknown } { const findTag = (key: string) => event.tags.find((tag) => tag[0] === key)?.[1] diff --git a/lib/zapAggregation.ts b/lib/zapAggregation.ts index 83be29d..84669a9 100644 --- a/lib/zapAggregation.ts +++ b/lib/zapAggregation.ts @@ -85,7 +85,6 @@ function collectZap( sub.on('eose', () => done()) setTimeout(() => done(), timeout).unref?.() if (typeof (sub as unknown as { on?: unknown }).on === 'function') { - // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(sub as any).on('error', onError) } })