Add preliminary nameRequestsController
This commit is contained in:
parent
a14515bbe0
commit
bd6424acf5
|
@ -30,7 +30,7 @@ import { adminAccountsController, adminActionController } from '@/controllers/ap
|
|||
import { appCredentialsController, createAppController } from '@/controllers/api/apps.ts';
|
||||
import { blocksController } from '@/controllers/api/blocks.ts';
|
||||
import { bookmarksController } from '@/controllers/api/bookmarks.ts';
|
||||
import { adminRelaysController, adminSetRelaysController, inviteRequestController } from '@/controllers/api/ditto.ts';
|
||||
import { adminRelaysController, adminSetRelaysController, nameRequestController } from '@/controllers/api/ditto.ts';
|
||||
import { emptyArrayController, emptyObjectController, notImplementedController } from '@/controllers/api/fallback.ts';
|
||||
import { instanceController } from '@/controllers/api/instance.ts';
|
||||
import { markersController, updateMarkersController } from '@/controllers/api/markers.ts';
|
||||
|
@ -243,7 +243,7 @@ app.delete('/api/v1/pleroma/admin/statuses/:id', requireRole('admin'), pleromaAd
|
|||
app.get('/api/v1/admin/ditto/relays', requireRole('admin'), adminRelaysController);
|
||||
app.put('/api/v1/admin/ditto/relays', requireRole('admin'), adminSetRelaysController);
|
||||
|
||||
app.post('/api/v1/ditto/nip05', requireSigner, inviteRequestController);
|
||||
app.post('/api/v1/ditto/names', requireSigner, nameRequestController);
|
||||
app.post('/api/v1/ditto/zap', requireSigner, zapController);
|
||||
|
||||
app.post('/api/v1/reports', requireSigner, reportController);
|
||||
|
|
|
@ -3,9 +3,11 @@ import { z } from 'zod';
|
|||
|
||||
import { AppController } from '@/app.ts';
|
||||
import { Conf } from '@/config.ts';
|
||||
import { Storages } from '@/storages.ts';
|
||||
import { AdminSigner } from '@/signers/AdminSigner.ts';
|
||||
import { Storages } from '@/storages.ts';
|
||||
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||
import { createEvent } from '@/utils/api.ts';
|
||||
import { renderNameRequest } from '@/views/ditto.ts';
|
||||
|
||||
const markerSchema = z.enum(['read', 'write']);
|
||||
|
||||
|
@ -60,15 +62,15 @@ function renderRelays(event: NostrEvent): RelayEntity[] {
|
|||
}, [] as RelayEntity[]);
|
||||
}
|
||||
|
||||
const inviteRequestSchema = z.object({
|
||||
const nameRequestSchema = z.object({
|
||||
nip05: z.string().email(),
|
||||
reason: z.string().max(500).optional(),
|
||||
});
|
||||
|
||||
export const inviteRequestController: AppController = async (c) => {
|
||||
const { nip05, reason } = inviteRequestSchema.parse(await c.req.json());
|
||||
export const nameRequestController: AppController = async (c) => {
|
||||
const { nip05, reason } = nameRequestSchema.parse(await c.req.json());
|
||||
|
||||
await createEvent({
|
||||
const event = await createEvent({
|
||||
kind: 3036,
|
||||
content: reason,
|
||||
tags: [
|
||||
|
@ -79,5 +81,20 @@ export const inviteRequestController: AppController = async (c) => {
|
|||
],
|
||||
}, c);
|
||||
|
||||
return new Response(null, { status: 204 });
|
||||
await hydrateEvents({ events: [event], store: await Storages.db() });
|
||||
|
||||
const nameRequest = await renderNameRequest(event);
|
||||
return c.json(nameRequest);
|
||||
};
|
||||
|
||||
export const nameRequestsController: AppController = async (c) => {
|
||||
const store = await Storages.db();
|
||||
const signer = c.get('signer')!;
|
||||
const pubkey = await signer.getPublicKey();
|
||||
|
||||
const events = await store.query([{ kinds: [3036], authors: [pubkey], limit: 20 }])
|
||||
.then((events) => hydrateEvents({ events, store }));
|
||||
|
||||
const nameRequests = await Promise.all(events.map(renderNameRequest));
|
||||
return c.json(nameRequests);
|
||||
};
|
||||
|
|
|
@ -34,4 +34,6 @@ export interface DittoEvent extends NostrEvent {
|
|||
* https://github.com/nostr-protocol/nips/blob/master/56.md
|
||||
*/
|
||||
reported_notes?: DittoEvent[];
|
||||
/** Admin event relationship. */
|
||||
info?: DittoEvent;
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ async function generateSetEvents(event: NostrEvent): Promise<void> {
|
|||
['d', event.id],
|
||||
['p', event.pubkey],
|
||||
['k', '3036'],
|
||||
['n', 'open'],
|
||||
['n', 'pending'],
|
||||
],
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
});
|
||||
|
|
|
@ -44,6 +44,10 @@ async function hydrateEvents(opts: HydrateOpts): Promise<DittoEvent[]> {
|
|||
cache.push(event);
|
||||
}
|
||||
|
||||
for (const event of await gatherInfo({ events: cache, store, signal })) {
|
||||
cache.push(event);
|
||||
}
|
||||
|
||||
for (const event of await gatherReportedProfiles({ events: cache, store, signal })) {
|
||||
cache.push(event);
|
||||
}
|
||||
|
@ -83,6 +87,7 @@ export function assembleEvents(
|
|||
for (const event of a) {
|
||||
event.author = b.find((e) => matchFilter({ kinds: [0], authors: [event.pubkey] }, e));
|
||||
event.user = b.find((e) => matchFilter({ kinds: [30382], authors: [admin], '#d': [event.pubkey] }, e));
|
||||
event.info = b.find((e) => matchFilter({ kinds: [30383], authors: [admin], '#d': [event.id] }, e));
|
||||
|
||||
if (event.kind === 1) {
|
||||
const id = findQuoteTag(event.tags)?.[1] || findQuoteInContent(event.content);
|
||||
|
@ -106,21 +111,22 @@ export function assembleEvents(
|
|||
}
|
||||
|
||||
if (event.kind === 1984) {
|
||||
const targetAccountId = event.tags.find(([name]) => name === 'p')?.[1];
|
||||
if (targetAccountId) {
|
||||
event.reported_profile = b.find((e) => matchFilter({ kinds: [0], authors: [targetAccountId] }, e));
|
||||
const pubkey = event.tags.find(([name]) => name === 'p')?.[1];
|
||||
if (pubkey) {
|
||||
event.reported_profile = b.find((e) => matchFilter({ kinds: [0], authors: [pubkey] }, e));
|
||||
}
|
||||
const reportedEvents: DittoEvent[] = [];
|
||||
|
||||
const status_ids = event.tags.filter(([name]) => name === 'e').map((tag) => tag[1]);
|
||||
if (status_ids.length > 0) {
|
||||
for (const id of status_ids) {
|
||||
const reportedEvent = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
||||
if (reportedEvent) reportedEvents.push(reportedEvent);
|
||||
const reportedEvents: DittoEvent[] = [];
|
||||
const ids = event.tags.filter(([name]) => name === 'e').map(([_name, value]) => value);
|
||||
|
||||
for (const id of ids) {
|
||||
const reported = b.find((e) => matchFilter({ kinds: [1], ids: [id] }, e));
|
||||
if (reported) {
|
||||
reportedEvents.push(reported);
|
||||
}
|
||||
}
|
||||
event.reported_notes = reportedEvents;
|
||||
}
|
||||
}
|
||||
|
||||
event.author_stats = stats.authors.find((stats) => stats.pubkey === event.pubkey);
|
||||
event.event_stats = eventStats.find((stats) => stats.event_id === event.id);
|
||||
|
@ -206,6 +212,26 @@ function gatherUsers({ events, store, signal }: HydrateOpts): Promise<DittoEvent
|
|||
);
|
||||
}
|
||||
|
||||
/** Collect info events from the events. */
|
||||
function gatherInfo({ events, store, signal }: HydrateOpts): Promise<DittoEvent[]> {
|
||||
const ids = new Set<string>();
|
||||
|
||||
for (const event of events) {
|
||||
if (event.kind === 3036) {
|
||||
ids.add(event.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ids.size) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return store.query(
|
||||
[{ ids: [...ids], limit: ids.size }],
|
||||
{ signal },
|
||||
);
|
||||
}
|
||||
|
||||
/** Collect reported notes from the events. */
|
||||
function gatherReportedNotes({ events, store, signal }: HydrateOpts): Promise<DittoEvent[]> {
|
||||
const ids = new Set<string>();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
|
||||
import { getTagSet } from '@/utils/tags.ts';
|
||||
|
||||
export async function renderNameRequest(event: DittoEvent) {
|
||||
const n = getTagSet(event.info?.tags ?? [], 'n');
|
||||
|
||||
let approvalStatus = 'pending';
|
||||
|
||||
if (n.has('approved')) {
|
||||
approvalStatus = 'approved';
|
||||
}
|
||||
if (n.has('rejected')) {
|
||||
approvalStatus = 'rejected';
|
||||
}
|
||||
|
||||
return {
|
||||
id: event.id,
|
||||
account: event.author ? await renderAccount(event.author) : accountFromPubkey(event.pubkey),
|
||||
name: event.tags.find(([name]) => name === 'r')?.[1] || '',
|
||||
reason: event.content,
|
||||
approval_status: approvalStatus,
|
||||
created_at: new Date(event.created_at * 1000).toISOString(),
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue