From 2ee29bf1e26c87fd2672bb0b60fa593dabdea436 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 29 Aug 2023 14:44:59 -0500 Subject: [PATCH] Make favourites stick, refactor some async logic in threads --- src/controllers/api/accounts.ts | 2 +- src/controllers/api/statuses.ts | 25 +++++++++++++---------- src/controllers/api/timelines.ts | 2 +- src/deps.ts | 1 - src/transformers/nostr-to-mastoapi.ts | 29 +++++++++++++++++---------- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/controllers/api/accounts.ts b/src/controllers/api/accounts.ts index d84382a..0f10b9d 100644 --- a/src/controllers/api/accounts.ts +++ b/src/controllers/api/accounts.ts @@ -109,7 +109,7 @@ const accountStatusesController: AppController = async (c) => { events = events.filter((event) => !findReplyTag(event)); } - const statuses = await Promise.all(events.map(toStatus)); + const statuses = await Promise.all(events.map((event) => toStatus(event, c.get('pubkey')))); return paginated(c, events, statuses); }; diff --git a/src/controllers/api/statuses.ts b/src/controllers/api/statuses.ts index bb8e9d5..4544373 100644 --- a/src/controllers/api/statuses.ts +++ b/src/controllers/api/statuses.ts @@ -1,5 +1,5 @@ import { type AppController } from '@/app.ts'; -import { ISO6391, Kind, z } from '@/deps.ts'; +import { type Event, ISO6391, z } from '@/deps.ts'; import { getAncestors, getDescendants, getEvent } from '@/queries.ts'; import { toStatus } from '@/transformers/nostr-to-mastoapi.ts'; import { createEvent, parseBody } from '@/utils/web.ts'; @@ -69,7 +69,7 @@ const createStatusController: AppController = async (c) => { } const event = await createEvent({ - kind: Kind.Text, + kind: 1, content: data.status ?? '', tags, }, c); @@ -82,17 +82,20 @@ const createStatusController: AppController = async (c) => { const contextController: AppController = async (c) => { const id = c.req.param('id'); - const event = await getEvent(id, { kind: 1 }); - if (event) { - const ancestorEvents = await getAncestors(event); - const descendantEvents = await getDescendants(event.id); + async function renderStatuses(events: Event<1>[]) { + const statuses = await Promise.all(events.map((event) => toStatus(event, c.get('pubkey')))); + return statuses.filter(Boolean); + } - return c.json({ - ancestors: (await Promise.all(ancestorEvents.map(toStatus))).filter(Boolean), - descendants: (await Promise.all(descendantEvents.map(toStatus))).filter(Boolean), - }); + if (event) { + const [ancestors, descendants] = await Promise.all([ + getAncestors(event).then(renderStatuses), + getDescendants(event.id).then(renderStatuses), + ]); + + return c.json({ ancestors, descendants }); } return c.json({ error: 'Event not found.' }, 404); @@ -104,7 +107,7 @@ const favouriteController: AppController = async (c) => { if (target) { await createEvent({ - kind: Kind.Reaction, + kind: 7, content: '+', tags: [ ['e', target.id], diff --git a/src/controllers/api/timelines.ts b/src/controllers/api/timelines.ts index d5833ca..a97b747 100644 --- a/src/controllers/api/timelines.ts +++ b/src/controllers/api/timelines.ts @@ -40,7 +40,7 @@ async function renderStatuses(c: AppContext, filters: DittoFilter<1>[]) { return c.json([]); } - const statuses = await Promise.all(events.map(toStatus)); + const statuses = await Promise.all(events.map((event) => toStatus(event, c.get('pubkey')))); return paginated(c, events, statuses); } diff --git a/src/deps.ts b/src/deps.ts index b361c5b..dcef225 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -18,7 +18,6 @@ export { getEventHash, getPublicKey, getSignature, - Kind, matchFilters, nip04, nip05, diff --git a/src/transformers/nostr-to-mastoapi.ts b/src/transformers/nostr-to-mastoapi.ts index 7849665..50bbee1 100644 --- a/src/transformers/nostr-to-mastoapi.ts +++ b/src/transformers/nostr-to-mastoapi.ts @@ -1,7 +1,7 @@ import { isCWTag } from 'https://gitlab.com/soapbox-pub/mostr/-/raw/c67064aee5ade5e01597c6d23e22e53c628ef0e2/src/nostr/tags.ts'; import { Conf } from '@/config.ts'; -import { countFilters } from '@/db/events.ts'; +import * as eventsDB from '@/db/events.ts'; import { type Event, findReplyTag, lodash, nip19, sanitizeHtml, TTLCache, unfurl, z } from '@/deps.ts'; import { verifyNip05Cached } from '@/nip05.ts'; import { getMediaLinks, type MediaLink, parseNoteContent } from '@/note.ts'; @@ -92,7 +92,7 @@ async function toMention(pubkey: string) { } } -async function toStatus(event: Event<1>) { +async function toStatus(event: Event<1>, viewerPubkey?: string) { const profile = await getAuthor(event.pubkey); const account = profile ? await toAccount(profile) : undefined; if (!account) return; @@ -110,13 +110,20 @@ async function toStatus(event: Event<1>) { const { html, links, firstUrl } = parseNoteContent(event.content); const mediaLinks = getMediaLinks(links); - const [mentions, card, repliesCount, reblogsCount, favouritesCount] = await Promise.all([ - Promise.all(mentionedPubkeys.map(toMention)), - firstUrl ? unfurlCardCached(firstUrl) : null, - countFilters([{ kinds: [1], '#e': [event.id] }]), - countFilters([{ kinds: [6], '#e': [event.id] }]), - countFilters([{ kinds: [7], '#e': [event.id] }]), - ]); + const [mentions, card, repliesCount, reblogsCount, favouritesCount, [repostEvent], [reactionEvent]] = await Promise + .all([ + Promise.all(mentionedPubkeys.map(toMention)), + firstUrl ? unfurlCardCached(firstUrl) : null, + eventsDB.countFilters([{ kinds: [1], '#e': [event.id] }]), + eventsDB.countFilters([{ kinds: [6], '#e': [event.id] }]), + eventsDB.countFilters([{ kinds: [7], '#e': [event.id] }]), + viewerPubkey + ? eventsDB.getFilters([{ kinds: [6], '#e': [event.id], authors: [viewerPubkey] }], { limit: 1 }) + : [], + viewerPubkey + ? eventsDB.getFilters([{ kinds: [7], '#e': [event.id], authors: [viewerPubkey] }], { limit: 1 }) + : [], + ]); const content = buildInlineRecipients(mentions) + html; @@ -138,8 +145,8 @@ async function toStatus(event: Event<1>) { replies_count: repliesCount, reblogs_count: reblogsCount, favourites_count: favouritesCount, - favourited: false, - reblogged: false, + favourited: reactionEvent?.content === '+', + reblogged: Boolean(repostEvent), muted: false, bookmarked: false, reblog: null,