Merge branch 'markers' into 'main'
Implement Markers API See merge request soapbox-pub/ditto!215
This commit is contained in:
commit
ad3a1ef137
|
@ -31,6 +31,7 @@ import { blocksController } from '@/controllers/api/blocks.ts';
|
|||
import { bookmarksController } from '@/controllers/api/bookmarks.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';
|
||||
import { mediaController } from '@/controllers/api/media.ts';
|
||||
import { mutesController } from '@/controllers/api/mutes.ts';
|
||||
import { notificationsController } from '@/controllers/api/notifications.ts';
|
||||
|
@ -191,6 +192,9 @@ app.get('/api/v1/bookmarks', requirePubkey, bookmarksController);
|
|||
app.get('/api/v1/blocks', requirePubkey, blocksController);
|
||||
app.get('/api/v1/mutes', requirePubkey, mutesController);
|
||||
|
||||
app.get('/api/v1/markers', requireProof(), markersController);
|
||||
app.post('/api/v1/markers', requireProof(), updateMarkersController);
|
||||
|
||||
app.get('/api/v1/admin/accounts', requireRole('admin'), adminAccountsController);
|
||||
app.get('/api/v1/pleroma/admin/config', requireRole('admin'), configController);
|
||||
app.post('/api/v1/pleroma/admin/config', requireRole('admin'), updateConfigController);
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
import { AppController } from '@/app.ts';
|
||||
import { parseBody } from '@/utils/api.ts';
|
||||
|
||||
const kv = await Deno.openKv();
|
||||
|
||||
type Timeline = 'home' | 'notifications';
|
||||
|
||||
interface Marker {
|
||||
last_read_id: string;
|
||||
version: number;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export const markersController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const timelines = c.req.queries('timeline[]') ?? [];
|
||||
|
||||
const results = await kv.getMany<Marker[]>(
|
||||
timelines.map((timeline) => ['markers', pubkey, timeline]),
|
||||
);
|
||||
|
||||
const marker = results.reduce<Record<string, Marker>>((acc, { key, value }) => {
|
||||
if (value) {
|
||||
const timeline = key[key.length - 1] as string;
|
||||
acc[timeline] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return c.json(marker);
|
||||
};
|
||||
|
||||
const markerDataSchema = z.object({
|
||||
last_read_id: z.string(),
|
||||
});
|
||||
|
||||
export const updateMarkersController: AppController = async (c) => {
|
||||
const pubkey = c.get('pubkey')!;
|
||||
const record = z.record(z.enum(['home', 'notifications']), markerDataSchema).parse(await parseBody(c.req.raw));
|
||||
const timelines = Object.keys(record) as Timeline[];
|
||||
|
||||
const markers: Record<string, Marker> = {};
|
||||
|
||||
const entries = await kv.getMany<Marker[]>(
|
||||
timelines.map((timeline) => ['markers', pubkey, timeline]),
|
||||
);
|
||||
|
||||
for (const timeline of timelines) {
|
||||
const last = entries.find(({ key }) => key[key.length - 1] === timeline);
|
||||
|
||||
const marker: Marker = {
|
||||
last_read_id: record[timeline]!.last_read_id,
|
||||
version: last?.value ? last.value.version + 1 : 1,
|
||||
updated_at: new Date().toISOString(),
|
||||
};
|
||||
|
||||
await kv.set(['markers', pubkey, timeline], marker);
|
||||
markers[timeline] = marker;
|
||||
}
|
||||
|
||||
return c.json(markers);
|
||||
};
|
Loading…
Reference in New Issue