Merge branch 'reactions' into 'main'
Add reactionsController See merge request soapbox-pub/ditto!303
This commit is contained in:
commit
c2562a3ed1
|
@ -43,7 +43,7 @@ import {
|
||||||
updateConfigController,
|
updateConfigController,
|
||||||
} from '@/controllers/api/pleroma.ts';
|
} from '@/controllers/api/pleroma.ts';
|
||||||
import { preferencesController } from '@/controllers/api/preferences.ts';
|
import { preferencesController } from '@/controllers/api/preferences.ts';
|
||||||
import { deleteReactionController, reactionController } from '@/controllers/api/reactions.ts';
|
import { deleteReactionController, reactionController, reactionsController } from '@/controllers/api/reactions.ts';
|
||||||
import { relayController } from '@/controllers/nostr/relay.ts';
|
import { relayController } from '@/controllers/nostr/relay.ts';
|
||||||
import {
|
import {
|
||||||
adminReportController,
|
adminReportController,
|
||||||
|
@ -211,6 +211,8 @@ app.get('/api/v1/mutes', requireSigner, mutesController);
|
||||||
app.get('/api/v1/markers', requireProof(), markersController);
|
app.get('/api/v1/markers', requireProof(), markersController);
|
||||||
app.post('/api/v1/markers', requireProof(), updateMarkersController);
|
app.post('/api/v1/markers', requireProof(), updateMarkersController);
|
||||||
|
|
||||||
|
app.get('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions', reactionsController);
|
||||||
|
app.get('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions/:emoji', reactionsController);
|
||||||
app.put('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions/:emoji', requireSigner, reactionController);
|
app.put('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions/:emoji', requireSigner, reactionController);
|
||||||
app.delete('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions/:emoji', requireSigner, deleteReactionController);
|
app.delete('/api/v1/pleroma/statuses/:id{[0-9a-f]{64}}/reactions/:emoji', requireSigner, deleteReactionController);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { AppController } from '@/app.ts';
|
import { AppController } from '@/app.ts';
|
||||||
|
import { DittoEvent } from '@/interfaces/DittoEvent.ts';
|
||||||
|
import { hydrateEvents } from '@/storages/hydrate.ts';
|
||||||
import { Storages } from '@/storages.ts';
|
import { Storages } from '@/storages.ts';
|
||||||
import { createEvent } from '@/utils/api.ts';
|
import { createEvent } from '@/utils/api.ts';
|
||||||
|
import { accountFromPubkey, renderAccount } from '@/views/mastodon/accounts.ts';
|
||||||
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
import { renderStatus } from '@/views/mastodon/statuses.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,4 +81,46 @@ const deleteReactionController: AppController = async (c) => {
|
||||||
return c.json(status);
|
return c.json(status);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { deleteReactionController, reactionController };
|
/**
|
||||||
|
* Get an object of emoji to account mappings with accounts that reacted to the post.
|
||||||
|
* https://docs.pleroma.social/backend/development/API/pleroma_api/#get-apiv1pleromastatusesidreactions
|
||||||
|
*/
|
||||||
|
const reactionsController: AppController = async (c) => {
|
||||||
|
const id = c.req.param('id');
|
||||||
|
const store = await Storages.db();
|
||||||
|
const pubkey = await c.get('signer')?.getPublicKey();
|
||||||
|
const emoji = c.req.param('emoji') as string | undefined;
|
||||||
|
|
||||||
|
if (typeof emoji === 'string' && !/^\p{RGI_Emoji}$/v.test(emoji)) {
|
||||||
|
return c.json({ error: 'Invalid emoji' }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
const events = await store.query([{ kinds: [7], '#e': [id], limit: 100 }])
|
||||||
|
.then((events) => hydrateEvents({ events, store }))
|
||||||
|
.then((events) => events.filter((event) => !emoji || event.content === emoji));
|
||||||
|
|
||||||
|
/** Events grouped by emoji. */
|
||||||
|
const byEmoji = events.reduce((acc, event) => {
|
||||||
|
const emoji = event.content;
|
||||||
|
acc[emoji] = acc[emoji] || [];
|
||||||
|
acc[emoji].push(event);
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, DittoEvent[]>);
|
||||||
|
|
||||||
|
const results = await Promise.all(
|
||||||
|
Object.entries(byEmoji).map(async ([name, events]) => {
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
count: events.length,
|
||||||
|
me: pubkey && events.some((event) => event.pubkey === pubkey),
|
||||||
|
accounts: await Promise.all(
|
||||||
|
events.map((event) => event.author ? renderAccount(event.author) : accountFromPubkey(event.pubkey)),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
return c.json(results);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { deleteReactionController, reactionController, reactionsController };
|
||||||
|
|
Loading…
Reference in New Issue