mirror of
https://github.com/aljazceru/ditto.git
synced 2026-01-09 08:34:20 +01:00
Merge branch 'main' into fix-blocked-users-in-streaming
(((updating local branch)))
This commit is contained in:
@@ -29,7 +29,7 @@ const createAccountSchema = z.object({
|
||||
});
|
||||
|
||||
const createAccountController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const result = createAccountSchema.safeParse(await c.req.json());
|
||||
|
||||
if (!result.success) {
|
||||
@@ -45,7 +45,7 @@ const createAccountController: AppController = async (c) => {
|
||||
};
|
||||
|
||||
const verifyCredentialsController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
|
||||
const event = await getAuthor(pubkey, { relations: ['author_stats'] });
|
||||
if (event) {
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -122,7 +123,7 @@ const accountSearchController: AppController = async (c) => {
|
||||
};
|
||||
|
||||
const relationshipsController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const ids = z.array(z.string()).safeParse(c.req.queries('id[]'));
|
||||
|
||||
if (!ids.success) {
|
||||
@@ -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));
|
||||
@@ -178,7 +181,11 @@ const accountStatusesController: AppController = async (c) => {
|
||||
return events;
|
||||
});
|
||||
|
||||
const statuses = await Promise.all(events.map((event) => renderStatus(event, { viewerPubkey: c.get('pubkey') })));
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const statuses = await Promise.all(
|
||||
events.map((event) => renderStatus(event, { viewerPubkey })),
|
||||
);
|
||||
return paginated(c, events, statuses);
|
||||
};
|
||||
|
||||
@@ -194,7 +201,7 @@ const updateCredentialsSchema = z.object({
|
||||
});
|
||||
|
||||
const updateCredentialsController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const body = await parseBody(c.req.raw);
|
||||
const result = updateCredentialsSchema.safeParse(body);
|
||||
|
||||
@@ -236,11 +243,11 @@ const updateCredentialsController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/accounts/#follow */
|
||||
const followController: AppController = async (c) => {
|
||||
const sourcePubkey = c.get('pubkey')!;
|
||||
const sourcePubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const targetPubkey = c.req.param('pubkey');
|
||||
|
||||
await updateListEvent(
|
||||
{ kinds: [3], authors: [sourcePubkey] },
|
||||
{ kinds: [3], authors: [sourcePubkey], limit: 1 },
|
||||
(tags) => addTag(tags, ['p', targetPubkey]),
|
||||
c,
|
||||
);
|
||||
@@ -253,11 +260,11 @@ const followController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/accounts/#unfollow */
|
||||
const unfollowController: AppController = async (c) => {
|
||||
const sourcePubkey = c.get('pubkey')!;
|
||||
const sourcePubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const targetPubkey = c.req.param('pubkey');
|
||||
|
||||
await updateListEvent(
|
||||
{ kinds: [3], authors: [sourcePubkey] },
|
||||
{ kinds: [3], authors: [sourcePubkey], limit: 1 },
|
||||
(tags) => deleteTag(tags, ['p', targetPubkey]),
|
||||
c,
|
||||
);
|
||||
@@ -290,11 +297,11 @@ const unblockController: AppController = (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/accounts/#mute */
|
||||
const muteController: AppController = async (c) => {
|
||||
const sourcePubkey = c.get('pubkey')!;
|
||||
const sourcePubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const targetPubkey = c.req.param('pubkey');
|
||||
|
||||
await updateListEvent(
|
||||
{ kinds: [10000], authors: [sourcePubkey] },
|
||||
{ kinds: [10000], authors: [sourcePubkey], limit: 1 },
|
||||
(tags) => addTag(tags, ['p', targetPubkey]),
|
||||
c,
|
||||
);
|
||||
@@ -305,11 +312,11 @@ const muteController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/accounts/#unmute */
|
||||
const unmuteController: AppController = async (c) => {
|
||||
const sourcePubkey = c.get('pubkey')!;
|
||||
const sourcePubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const targetPubkey = c.req.param('pubkey');
|
||||
|
||||
await updateListEvent(
|
||||
{ kinds: [10000], authors: [sourcePubkey] },
|
||||
{ kinds: [10000], authors: [sourcePubkey], limit: 1 },
|
||||
(tags) => deleteTag(tags, ['p', targetPubkey]),
|
||||
c,
|
||||
);
|
||||
@@ -319,11 +326,13 @@ const unmuteController: AppController = async (c) => {
|
||||
};
|
||||
|
||||
const favouritesController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
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 },
|
||||
);
|
||||
@@ -332,10 +341,14 @@ 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 statuses = await Promise.all(events1.map((event) => renderStatus(event, { viewerPubkey: c.get('pubkey') })));
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const statuses = await Promise.all(
|
||||
events1.map((event) => renderStatus(event, { viewerPubkey })),
|
||||
);
|
||||
return paginated(c, events1, statuses);
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -5,10 +5,11 @@ import { renderStatuses } from '@/views.ts';
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/bookmarks/#get */
|
||||
const bookmarksController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
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 },
|
||||
);
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
@@ -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:';
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Marker {
|
||||
}
|
||||
|
||||
export const markersController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const timelines = c.req.queries('timeline[]') ?? [];
|
||||
|
||||
const results = await kv.getMany<Marker[]>(
|
||||
@@ -37,7 +37,7 @@ const markerDataSchema = z.object({
|
||||
});
|
||||
|
||||
export const updateMarkersController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const record = z.record(z.enum(['home', 'notifications']), markerDataSchema).parse(await parseBody(c.req.raw));
|
||||
const timelines = Object.keys(record) as Timeline[];
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const mediaBodySchema = z.object({
|
||||
});
|
||||
|
||||
const mediaController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const result = mediaBodySchema.safeParse(await parseBody(c.req.raw));
|
||||
const { signal } = c.req.raw;
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@ import { renderAccounts } from '@/views.ts';
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/mutes/#get */
|
||||
const mutesController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
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 },
|
||||
);
|
||||
|
||||
@@ -5,8 +5,8 @@ import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||
import { paginated, paginationSchema } from '@/utils/api.ts';
|
||||
import { renderNotification } from '@/views/mastodon/notifications.ts';
|
||||
|
||||
const notificationsController: AppController = (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const notificationsController: AppController = async (c) => {
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const { since, until } = paginationSchema.parse(c.req.query());
|
||||
|
||||
return renderNotifications(c, [{ kinds: [1, 6, 7], '#p': [pubkey], since, until }]);
|
||||
@@ -14,13 +14,13 @@ const notificationsController: AppController = (c) => {
|
||||
|
||||
async function renderNotifications(c: AppContext, filters: NostrFilter[]) {
|
||||
const store = c.get('store');
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const { signal } = c.req.raw;
|
||||
|
||||
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([]);
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -48,16 +48,22 @@ const reportController: AppController = async (c) => {
|
||||
tags,
|
||||
}, c);
|
||||
|
||||
await hydrateEvents({ events: [event], storage: store });
|
||||
await hydrateEvents({ events: [event], store });
|
||||
return c.json(await renderReport(event));
|
||||
};
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/admin/reports/#get */
|
||||
const adminReportsController: AppController = async (c) => {
|
||||
const store = c.get('store');
|
||||
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) => Promise.all(events.map((event) => renderAdminReport(event, { viewerPubkey: c.get('pubkey') }))));
|
||||
.then((events) => hydrateEvents({ store, events: events, signal: c.req.raw.signal }))
|
||||
.then((events) =>
|
||||
Promise.all(
|
||||
events.map((event) => renderAdminReport(event, { viewerPubkey })),
|
||||
)
|
||||
);
|
||||
|
||||
return c.json(reports);
|
||||
};
|
||||
@@ -67,7 +73,7 @@ const adminReportController: AppController = async (c) => {
|
||||
const eventId = c.req.param('id');
|
||||
const { signal } = c.req.raw;
|
||||
const store = c.get('store');
|
||||
const pubkey = c.get('pubkey');
|
||||
const pubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const [event] = await store.query([{
|
||||
kinds: [1984],
|
||||
@@ -79,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 }));
|
||||
};
|
||||
@@ -89,7 +95,7 @@ const adminReportResolveController: AppController = async (c) => {
|
||||
const eventId = c.req.param('id');
|
||||
const { signal } = c.req.raw;
|
||||
const store = c.get('store');
|
||||
const pubkey = c.get('pubkey');
|
||||
const pubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const [event] = await store.query([{
|
||||
kinds: [1984],
|
||||
@@ -101,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,
|
||||
|
||||
@@ -43,6 +43,7 @@ const searchController: AppController = async (c) => {
|
||||
}
|
||||
|
||||
const results = dedupeEvents(events);
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const [accounts, statuses] = await Promise.all([
|
||||
Promise.all(
|
||||
@@ -54,7 +55,7 @@ const searchController: AppController = async (c) => {
|
||||
Promise.all(
|
||||
results
|
||||
.filter((event) => event.kind === 1)
|
||||
.map((event) => renderStatus(event, { viewerPubkey: c.get('pubkey') }))
|
||||
.map((event) => renderStatus(event, { viewerPubkey }))
|
||||
.filter(Boolean),
|
||||
),
|
||||
]);
|
||||
@@ -77,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 = {
|
||||
@@ -90,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. */
|
||||
@@ -109,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NostrEvent, NostrFilter, NSchema as n } from '@nostrify/nostrify';
|
||||
import { NostrEvent, NSchema as n } from '@nostrify/nostrify';
|
||||
import ISO6391 from 'iso-639-1';
|
||||
import { z } from 'zod';
|
||||
|
||||
@@ -47,7 +47,7 @@ const statusController: AppController = async (c) => {
|
||||
});
|
||||
|
||||
if (event) {
|
||||
return c.json(await renderStatus(event, { viewerPubkey: c.get('pubkey') }));
|
||||
return c.json(await renderStatus(event, { viewerPubkey: await c.get('signer')?.getPublicKey() }));
|
||||
}
|
||||
|
||||
return c.json({ error: 'Event not found.' }, 404);
|
||||
@@ -89,9 +89,11 @@ const createStatusController: AppController = async (c) => {
|
||||
tags.push(['subject', data.spoiler_text]);
|
||||
}
|
||||
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
if (data.media_ids?.length) {
|
||||
const media = await getUnattachedMediaByIds(data.media_ids)
|
||||
.then((media) => media.filter(({ pubkey }) => pubkey === c.get('pubkey')))
|
||||
.then((media) => media.filter(({ pubkey }) => pubkey === viewerPubkey))
|
||||
.then((media) => media.map(({ url, data }) => ['media', url, data]));
|
||||
|
||||
tags.push(...media);
|
||||
@@ -138,17 +140,17 @@ 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,
|
||||
});
|
||||
}
|
||||
|
||||
return c.json(await renderStatus({ ...event, author }, { viewerPubkey: c.get('pubkey') }));
|
||||
return c.json(await renderStatus({ ...event, author }, { viewerPubkey: await c.get('signer')?.getPublicKey() }));
|
||||
};
|
||||
|
||||
const deleteStatusController: AppController = async (c) => {
|
||||
const id = c.req.param('id');
|
||||
const pubkey = c.get('pubkey');
|
||||
const pubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const event = await getEvent(id, { signal: c.req.raw.signal });
|
||||
|
||||
@@ -172,9 +174,12 @@ const deleteStatusController: AppController = async (c) => {
|
||||
const contextController: AppController = async (c) => {
|
||||
const id = c.req.param('id');
|
||||
const event = await getEvent(id, { kind: 1, relations: ['author', 'event_stats', 'author_stats'] });
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
async function renderStatuses(events: NostrEvent[]) {
|
||||
const statuses = await Promise.all(events.map((event) => renderStatus(event, { viewerPubkey: c.get('pubkey') })));
|
||||
const statuses = await Promise.all(
|
||||
events.map((event) => renderStatus(event, { viewerPubkey })),
|
||||
);
|
||||
return statuses.filter(Boolean);
|
||||
}
|
||||
|
||||
@@ -204,7 +209,7 @@ const favouriteController: AppController = async (c) => {
|
||||
],
|
||||
}, c);
|
||||
|
||||
const status = await renderStatus(target, { viewerPubkey: c.get('pubkey') });
|
||||
const status = await renderStatus(target, { viewerPubkey: await c.get('signer')?.getPublicKey() });
|
||||
|
||||
if (status) {
|
||||
status.favourited = true;
|
||||
@@ -243,11 +248,11 @@ const reblogStatusController: AppController = async (c) => {
|
||||
|
||||
await hydrateEvents({
|
||||
events: [reblogEvent],
|
||||
storage: Storages.db,
|
||||
store: await Storages.db(),
|
||||
signal: signal,
|
||||
});
|
||||
|
||||
const status = await renderReblog(reblogEvent, { viewerPubkey: c.get('pubkey') });
|
||||
const status = await renderReblog(reblogEvent, { viewerPubkey: await c.get('signer')?.getPublicKey() });
|
||||
|
||||
return c.json(status);
|
||||
};
|
||||
@@ -255,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 = c.get('pubkey') 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) => {
|
||||
@@ -282,7 +294,7 @@ const rebloggedByController: AppController = (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/statuses/#bookmark */
|
||||
const bookmarkController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const eventId = c.req.param('id');
|
||||
|
||||
const event = await getEvent(eventId, {
|
||||
@@ -292,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,
|
||||
);
|
||||
@@ -309,7 +321,7 @@ const bookmarkController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/statuses/#unbookmark */
|
||||
const unbookmarkController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const eventId = c.req.param('id');
|
||||
|
||||
const event = await getEvent(eventId, {
|
||||
@@ -319,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,
|
||||
);
|
||||
@@ -336,7 +348,7 @@ const unbookmarkController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/statuses/#pin */
|
||||
const pinController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const eventId = c.req.param('id');
|
||||
|
||||
const event = await getEvent(eventId, {
|
||||
@@ -346,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,
|
||||
);
|
||||
@@ -363,7 +375,7 @@ const pinController: AppController = async (c) => {
|
||||
|
||||
/** https://docs.joinmastodon.org/methods/statuses/#unpin */
|
||||
const unpinController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const eventId = c.req.param('id');
|
||||
const { signal } = c.req.raw;
|
||||
|
||||
@@ -375,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,
|
||||
);
|
||||
@@ -423,7 +435,7 @@ const zapController: AppController = async (c) => {
|
||||
],
|
||||
}, c);
|
||||
|
||||
const status = await renderStatus(target, { viewerPubkey: c.get('pubkey') });
|
||||
const status = await renderStatus(target, { viewerPubkey: await c.get('signer')?.getPublicKey() });
|
||||
status.zapped = true;
|
||||
|
||||
return c.json(status);
|
||||
|
||||
@@ -69,7 +69,10 @@ const streamingController: AppController = (c) => {
|
||||
if (!filter) return;
|
||||
|
||||
try {
|
||||
for await (const msg of Storages.pubsub.req([filter], { signal: controller.signal })) {
|
||||
const pubsub = await Storages.pubsub();
|
||||
const optimizer = await Storages.optimizer();
|
||||
|
||||
for await (const msg of pubsub.req([filter], { signal: controller.signal })) {
|
||||
if (msg[0] === 'EVENT') {
|
||||
const event = msg[2];
|
||||
|
||||
@@ -83,7 +86,7 @@ const streamingController: AppController = (c) => {
|
||||
|
||||
await hydrateEvents({
|
||||
events: [event],
|
||||
storage: Storages.admin,
|
||||
store: optimizer,
|
||||
signal: AbortSignal.timeout(1000),
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { renderReblog, renderStatus } from '@/views/mastodon/statuses.ts';
|
||||
|
||||
const homeTimelineController: AppController = async (c) => {
|
||||
const params = paginationSchema.parse(c.req.query());
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const pubkey = await c.get('signer')?.getPublicKey()!;
|
||||
const authors = await getFeedPubkeys(pubkey);
|
||||
return renderStatuses(c, [{ authors, kinds: [1, 6], ...params }]);
|
||||
};
|
||||
@@ -49,24 +49,20 @@ 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([]);
|
||||
}
|
||||
|
||||
const viewerPubkey = await c.get('signer')?.getPublicKey();
|
||||
|
||||
const statuses = (await Promise.all(events.map((event) => {
|
||||
if (event.kind === 6) {
|
||||
return renderReblog(event, { viewerPubkey: c.get('pubkey') });
|
||||
return renderReblog(event, { viewerPubkey });
|
||||
}
|
||||
return renderStatus(event, { viewerPubkey: c.get('pubkey') });
|
||||
}))).filter((boolean) => boolean);
|
||||
return renderStatus(event, { viewerPubkey });
|
||||
}))).filter(Boolean);
|
||||
|
||||
if (!statuses.length) {
|
||||
return c.json([]);
|
||||
|
||||
Reference in New Issue
Block a user