Don't let your memes be dreams

This commit is contained in:
Alex Gleason
2024-05-14 18:23:41 -05:00
parent 08c9ee0670
commit 68b5887ed0
38 changed files with 260 additions and 174 deletions

View File

@@ -94,15 +94,16 @@ const accountSearchController: AppController = async (c) => {
}
const query = decodeURIComponent(q);
const store = await Storages.search();
const [event, events] = await Promise.all([
lookupAccount(query),
Storages.search.query([{ kinds: [0], search: query, limit: 20 }], { signal: c.req.raw.signal }),
store.query([{ kinds: [0], search: query, limit: 20 }], { signal: c.req.raw.signal }),
]);
const results = await hydrateEvents({
events: event ? [event, ...events] : events,
storage: Storages.db,
store,
signal: c.req.raw.signal,
});
@@ -147,8 +148,10 @@ const accountStatusesController: AppController = async (c) => {
const { pinned, limit, exclude_replies, tagged } = accountStatusesQuerySchema.parse(c.req.query());
const { signal } = c.req.raw;
const store = await Storages.db();
if (pinned) {
const [pinEvent] = await Storages.db.query([{ kinds: [10001], authors: [pubkey], limit: 1 }], { signal });
const [pinEvent] = await store.query([{ kinds: [10001], authors: [pubkey], limit: 1 }], { signal });
if (pinEvent) {
const pinnedEventIds = getTagSet(pinEvent.tags, 'e');
return renderStatuses(c, [...pinnedEventIds].reverse());
@@ -169,8 +172,8 @@ const accountStatusesController: AppController = async (c) => {
filter['#t'] = [tagged];
}
const events = await Storages.db.query([filter], { signal })
.then((events) => hydrateEvents({ events, storage: Storages.db, signal }))
const events = await store.query([filter], { signal })
.then((events) => hydrateEvents({ events, store, signal }))
.then((events) => {
if (exclude_replies) {
return events.filter((event) => !findReplyTag(event.tags));
@@ -244,7 +247,7 @@ const followController: AppController = async (c) => {
const targetPubkey = c.req.param('pubkey');
await updateListEvent(
{ kinds: [3], authors: [sourcePubkey] },
{ kinds: [3], authors: [sourcePubkey], limit: 1 },
(tags) => addTag(tags, ['p', targetPubkey]),
c,
);
@@ -261,7 +264,7 @@ const unfollowController: AppController = async (c) => {
const targetPubkey = c.req.param('pubkey');
await updateListEvent(
{ kinds: [3], authors: [sourcePubkey] },
{ kinds: [3], authors: [sourcePubkey], limit: 1 },
(tags) => deleteTag(tags, ['p', targetPubkey]),
c,
);
@@ -298,7 +301,7 @@ const muteController: AppController = async (c) => {
const targetPubkey = c.req.param('pubkey');
await updateListEvent(
{ kinds: [10000], authors: [sourcePubkey] },
{ kinds: [10000], authors: [sourcePubkey], limit: 1 },
(tags) => addTag(tags, ['p', targetPubkey]),
c,
);
@@ -313,7 +316,7 @@ const unmuteController: AppController = async (c) => {
const targetPubkey = c.req.param('pubkey');
await updateListEvent(
{ kinds: [10000], authors: [sourcePubkey] },
{ kinds: [10000], authors: [sourcePubkey], limit: 1 },
(tags) => deleteTag(tags, ['p', targetPubkey]),
c,
);
@@ -327,7 +330,9 @@ const favouritesController: AppController = async (c) => {
const params = paginationSchema.parse(c.req.query());
const { signal } = c.req.raw;
const events7 = await Storages.db.query(
const store = await Storages.db();
const events7 = await store.query(
[{ kinds: [7], authors: [pubkey], ...params }],
{ signal },
);
@@ -336,8 +341,8 @@ const favouritesController: AppController = async (c) => {
.map((event) => event.tags.find((tag) => tag[0] === 'e')?.[1])
.filter((id): id is string => !!id);
const events1 = await Storages.db.query([{ kinds: [1], ids }], { signal })
.then((events) => hydrateEvents({ events, storage: Storages.db, signal }));
const events1 = await store.query([{ kinds: [1], ids }], { signal })
.then((events) => hydrateEvents({ events, store, signal }));
const viewerPubkey = await c.get('signer')?.getPublicKey();

View File

@@ -39,12 +39,13 @@ const adminAccountsController: AppController = async (c) => {
return c.json([]);
}
const store = await Storages.db();
const { since, until, limit } = paginationSchema.parse(c.req.query());
const { signal } = c.req.raw;
const events = await Storages.db.query([{ kinds: [30361], authors: [Conf.pubkey], since, until, limit }], { signal });
const events = await store.query([{ kinds: [30361], authors: [Conf.pubkey], since, until, limit }], { signal });
const pubkeys = events.map((event) => event.tags.find(([name]) => name === 'd')?.[1]!);
const authors = await Storages.db.query([{ kinds: [0], authors: pubkeys }], { signal });
const authors = await store.query([{ kinds: [0], authors: pubkeys }], { signal });
for (const event of events) {
const d = event.tags.find(([name]) => name === 'd')?.[1];
@@ -78,7 +79,7 @@ const adminAccountAction: AppController = async (c) => {
}
await updateListAdminEvent(
{ kinds: [10000], authors: [Conf.pubkey] },
{ kinds: [10000], authors: [Conf.pubkey], limit: 1 },
(tags) => addTag(tags, ['p', authorId]),
c,
);

View File

@@ -5,10 +5,11 @@ import { renderStatuses } from '@/views.ts';
/** https://docs.joinmastodon.org/methods/bookmarks/#get */
const bookmarksController: AppController = async (c) => {
const store = await Storages.db();
const pubkey = await c.get('signer')?.getPublicKey()!;
const { signal } = c.req.raw;
const [event10003] = await Storages.db.query(
const [event10003] = await store.query(
[{ kinds: [10003], authors: [pubkey], limit: 1 }],
{ signal },
);

View File

@@ -16,7 +16,9 @@ const relaySchema = z.object({
type RelayEntity = z.infer<typeof relaySchema>;
export const adminRelaysController: AppController = async (c) => {
const [event] = await Storages.db.query([
const store = await Storages.db();
const [event] = await store.query([
{ kinds: [10002], authors: [Conf.pubkey], limit: 1 },
]);
@@ -28,6 +30,7 @@ export const adminRelaysController: AppController = async (c) => {
};
export const adminSetRelaysController: AppController = async (c) => {
const store = await Storages.db();
const relays = relaySchema.array().parse(await c.req.json());
const event = await new AdminSigner().signEvent({
@@ -37,7 +40,7 @@ export const adminSetRelaysController: AppController = async (c) => {
created_at: Math.floor(Date.now() / 1000),
});
await Storages.db.event(event);
await store.event(event);
return c.json(renderRelays(event));
};

View File

@@ -1,10 +1,11 @@
import { AppController } from '@/app.ts';
import { Conf } from '@/config.ts';
import { Storages } from '@/storages.ts';
import { getInstanceMetadata } from '@/utils/instance.ts';
const instanceController: AppController = async (c) => {
const { host, protocol } = Conf.url;
const meta = await getInstanceMetadata(c.req.raw.signal);
const meta = await getInstanceMetadata(await Storages.db(), c.req.raw.signal);
/** Protocol to use for WebSocket URLs, depending on the protocol of the `LOCAL_DOMAIN`. */
const wsProtocol = protocol === 'http:' ? 'ws:' : 'wss:';

View File

@@ -5,10 +5,11 @@ import { renderAccounts } from '@/views.ts';
/** https://docs.joinmastodon.org/methods/mutes/#get */
const mutesController: AppController = async (c) => {
const store = await Storages.db();
const pubkey = await c.get('signer')?.getPublicKey()!;
const { signal } = c.req.raw;
const [event10000] = await Storages.db.query(
const [event10000] = await store.query(
[{ kinds: [10000], authors: [pubkey], limit: 1 }],
{ signal },
);

View File

@@ -20,7 +20,7 @@ async function renderNotifications(c: AppContext, filters: NostrFilter[]) {
const events = await store
.query(filters, { signal })
.then((events) => events.filter((event) => event.pubkey !== pubkey))
.then((events) => hydrateEvents({ events, storage: store, signal }));
.then((events) => hydrateEvents({ events, store, signal }));
if (!events.length) {
return c.json([]);

View File

@@ -1,4 +1,4 @@
import { NSchema as n } from '@nostrify/nostrify';
import { NSchema as n, NStore } from '@nostrify/nostrify';
import { z } from 'zod';
import { type AppController } from '@/app.ts';
@@ -9,7 +9,8 @@ import { Storages } from '@/storages.ts';
import { createAdminEvent } from '@/utils/api.ts';
const frontendConfigController: AppController = async (c) => {
const configs = await getConfigs(c.req.raw.signal);
const store = await Storages.db();
const configs = await getConfigs(store, c.req.raw.signal);
const frontendConfig = configs.find(({ group, key }) => group === ':pleroma' && key === ':frontend_configurations');
if (frontendConfig) {
@@ -25,7 +26,8 @@ const frontendConfigController: AppController = async (c) => {
};
const configController: AppController = async (c) => {
const configs = await getConfigs(c.req.raw.signal);
const store = await Storages.db();
const configs = await getConfigs(store, c.req.raw.signal);
return c.json({ configs, need_reboot: false });
};
@@ -33,7 +35,8 @@ const configController: AppController = async (c) => {
const updateConfigController: AppController = async (c) => {
const { pubkey } = Conf;
const configs = await getConfigs(c.req.raw.signal);
const store = await Storages.db();
const configs = await getConfigs(store, c.req.raw.signal);
const { configs: newConfigs } = z.object({ configs: z.array(configSchema) }).parse(await c.req.json());
for (const { group, key, value } of newConfigs) {
@@ -63,10 +66,10 @@ const pleromaAdminDeleteStatusController: AppController = async (c) => {
return c.json({});
};
async function getConfigs(signal: AbortSignal): Promise<PleromaConfig[]> {
async function getConfigs(store: NStore, signal: AbortSignal): Promise<PleromaConfig[]> {
const { pubkey } = Conf;
const [event] = await Storages.db.query([{
const [event] = await store.query([{
kinds: [30078],
authors: [pubkey],
'#d': ['pub.ditto.pleroma.config'],

View File

@@ -48,7 +48,7 @@ const reportController: AppController = async (c) => {
tags,
}, c);
await hydrateEvents({ events: [event], storage: store });
await hydrateEvents({ events: [event], store });
return c.json(await renderReport(event));
};
@@ -58,7 +58,7 @@ const adminReportsController: AppController = async (c) => {
const viewerPubkey = await c.get('signer')?.getPublicKey();
const reports = await store.query([{ kinds: [1984], '#P': [Conf.pubkey] }])
.then((events) => hydrateEvents({ storage: store, events: events, signal: c.req.raw.signal }))
.then((events) => hydrateEvents({ store, events: events, signal: c.req.raw.signal }))
.then((events) =>
Promise.all(
events.map((event) => renderAdminReport(event, { viewerPubkey })),
@@ -85,7 +85,7 @@ const adminReportController: AppController = async (c) => {
return c.json({ error: 'This action is not allowed' }, 403);
}
await hydrateEvents({ events: [event], storage: store, signal });
await hydrateEvents({ events: [event], store, signal });
return c.json(await renderAdminReport(event, { viewerPubkey: pubkey }));
};
@@ -107,7 +107,7 @@ const adminReportResolveController: AppController = async (c) => {
return c.json({ error: 'This action is not allowed' }, 403);
}
await hydrateEvents({ events: [event], storage: store, signal });
await hydrateEvents({ events: [event], store, signal });
await createAdminEvent({
kind: 5,

View File

@@ -78,7 +78,7 @@ const searchController: AppController = async (c) => {
};
/** Get events for the search params. */
function searchEvents({ q, type, limit, account_id }: SearchQuery, signal: AbortSignal): Promise<NostrEvent[]> {
async function searchEvents({ q, type, limit, account_id }: SearchQuery, signal: AbortSignal): Promise<NostrEvent[]> {
if (type === 'hashtags') return Promise.resolve([]);
const filter: NostrFilter = {
@@ -91,8 +91,10 @@ function searchEvents({ q, type, limit, account_id }: SearchQuery, signal: Abort
filter.authors = [account_id];
}
return Storages.search.query([filter], { signal })
.then((events) => hydrateEvents({ events, storage: Storages.search, signal }));
const store = await Storages.search();
return store.query([filter], { signal })
.then((events) => hydrateEvents({ events, store, signal }));
}
/** Get event kinds to search from `type` query param. */
@@ -110,9 +112,10 @@ function typeToKinds(type: SearchQuery['type']): number[] {
/** Resolve a searched value into an event, if applicable. */
async function lookupEvent(query: SearchQuery, signal: AbortSignal): Promise<NostrEvent | undefined> {
const filters = await getLookupFilters(query, signal);
const store = await Storages.search();
return Storages.search.query(filters, { limit: 1, signal })
.then((events) => hydrateEvents({ events, storage: Storages.search, signal }))
return store.query(filters, { limit: 1, signal })
.then((events) => hydrateEvents({ events, store, signal }))
.then(([event]) => event);
}

View File

@@ -140,7 +140,7 @@ const createStatusController: AppController = async (c) => {
if (data.quote_id) {
await hydrateEvents({
events: [event],
storage: Storages.db,
store: await Storages.db(),
signal: c.req.raw.signal,
});
}
@@ -248,7 +248,7 @@ const reblogStatusController: AppController = async (c) => {
await hydrateEvents({
events: [reblogEvent],
storage: Storages.db,
store: await Storages.db(),
signal: signal,
});
@@ -260,23 +260,30 @@ const reblogStatusController: AppController = async (c) => {
/** https://docs.joinmastodon.org/methods/statuses/#unreblog */
const unreblogStatusController: AppController = async (c) => {
const eventId = c.req.param('id');
const pubkey = await c.get('signer')?.getPublicKey() as string;
const pubkey = await c.get('signer')?.getPublicKey()!;
const event = await getEvent(eventId, {
kind: 1,
});
if (!event) return c.json({ error: 'Event not found.' }, 404);
const event = await getEvent(eventId, { kind: 1 });
const filters: NostrFilter[] = [{ kinds: [6], authors: [pubkey], '#e': [event.id] }];
const [repostedEvent] = await Storages.db.query(filters, { limit: 1 });
if (!repostedEvent) return c.json({ error: 'Event not found.' }, 404);
if (!event) {
return c.json({ error: 'Event not found.' }, 404);
}
const store = await Storages.db();
const [repostedEvent] = await store.query(
[{ kinds: [6], authors: [pubkey], '#e': [event.id], limit: 1 }],
);
if (!repostedEvent) {
return c.json({ error: 'Event not found.' }, 404);
}
await createEvent({
kind: 5,
tags: [['e', repostedEvent.id]],
}, c);
return c.json(await renderStatus(event, {}));
return c.json(await renderStatus(event, { viewerPubkey: pubkey }));
};
const rebloggedByController: AppController = (c) => {
@@ -297,7 +304,7 @@ const bookmarkController: AppController = async (c) => {
if (event) {
await updateListEvent(
{ kinds: [10003], authors: [pubkey] },
{ kinds: [10003], authors: [pubkey], limit: 1 },
(tags) => addTag(tags, ['e', eventId]),
c,
);
@@ -324,7 +331,7 @@ const unbookmarkController: AppController = async (c) => {
if (event) {
await updateListEvent(
{ kinds: [10003], authors: [pubkey] },
{ kinds: [10003], authors: [pubkey], limit: 1 },
(tags) => deleteTag(tags, ['e', eventId]),
c,
);
@@ -351,7 +358,7 @@ const pinController: AppController = async (c) => {
if (event) {
await updateListEvent(
{ kinds: [10001], authors: [pubkey] },
{ kinds: [10001], authors: [pubkey], limit: 1 },
(tags) => addTag(tags, ['e', eventId]),
c,
);
@@ -380,7 +387,7 @@ const unpinController: AppController = async (c) => {
if (event) {
await updateListEvent(
{ kinds: [10001], authors: [pubkey] },
{ kinds: [10001], authors: [pubkey], limit: 1 },
(tags) => deleteTag(tags, ['e', eventId]),
c,
);

View File

@@ -68,13 +68,15 @@ const streamingController: AppController = (c) => {
if (!filter) return;
try {
for await (const msg of Storages.pubsub.req([filter], { signal: controller.signal })) {
const store = await Storages.pubsub();
for await (const msg of store.req([filter], { signal: controller.signal })) {
if (msg[0] === 'EVENT') {
const event = msg[2];
await hydrateEvents({
events: [event],
storage: Storages.admin,
store,
signal: AbortSignal.timeout(1000),
});

View File

@@ -40,7 +40,7 @@ async function renderSuggestedAccounts(store: NStore, signal?: AbortSignal) {
[{ kinds: [0], authors: pubkeys, limit: pubkeys.length }],
{ signal },
)
.then((events) => hydrateEvents({ events, storage: store, signal }));
.then((events) => hydrateEvents({ events, store, signal }));
const accounts = await Promise.all(pubkeys.map((pubkey) => {
const profile = profiles.find((event) => event.pubkey === pubkey);

View File

@@ -49,13 +49,7 @@ async function renderStatuses(c: AppContext, filters: NostrFilter[]) {
const events = await store
.query(filters, { signal })
.then((events) =>
hydrateEvents({
events,
storage: store,
signal,
})
);
.then((events) => hydrateEvents({ events, store, signal }));
if (!events.length) {
return c.json([]);