mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 22:51:30 -07:00
[api] msg delete
This commit is contained in:
@@ -213,6 +213,15 @@ export const SendMultipleMessagesRequest = z.object({
|
|||||||
Data: z.string().optional().describe('The message payload; often empty'),
|
Data: z.string().optional().describe('The message payload; often empty'),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `POST /api/messages/v3/delete` JSON body — the messages the client is dropping from
|
||||||
|
* its inbox. Ids are the `Id` of a stored message, which this server has never issued:
|
||||||
|
* with no message store the list is only ever echoed back as accepted.
|
||||||
|
*/
|
||||||
|
export const DeleteMessagesRequest = z.object({
|
||||||
|
MessageIds: z.array(z.int()).describe('Ids of the messages to delete'),
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `POST /api/messages/v1/friendOnlineStatus` — how many of the caller's friends are
|
* `POST /api/messages/v1/friendOnlineStatus` — how many of the caller's friends are
|
||||||
* online, wrapped in the client's `{ success, value }` envelope.
|
* online, wrapped in the client's `{ success, value }` envelope.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { authedId, unauthorized } from '../http'
|
|||||||
import {
|
import {
|
||||||
AckResponse,
|
AckResponse,
|
||||||
AUTHED,
|
AUTHED,
|
||||||
|
DeleteMessagesRequest,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
form,
|
form,
|
||||||
FriendOnlineCountResponse,
|
FriendOnlineCountResponse,
|
||||||
@@ -624,6 +625,28 @@ export const socialRoutes = new Hono<App>({ strict: false })
|
|||||||
}),
|
}),
|
||||||
(c) => c.json([])
|
(c) => c.json([])
|
||||||
)
|
)
|
||||||
|
// The inbox's delete button. A POST rather than a DELETE because the ids arrive as
|
||||||
|
// a JSON array body — the client batches a multi-select into one call, and its HTTP
|
||||||
|
// layer only ever sends a body on POST/PUT.
|
||||||
|
.post(
|
||||||
|
'/api/messages/v3/delete',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['Social'],
|
||||||
|
summary: 'Delete messages',
|
||||||
|
description:
|
||||||
|
'Drops the given messages from the caller’s inbox. Nothing happens: there is no ' +
|
||||||
|
'message store behind `GET /api/messages/v2/get` (the `MessageReceived` ' +
|
||||||
|
'notification is the whole delivery — see `POST /api/messages/v2/send`), so ' +
|
||||||
|
'there are no ids to match and nothing to remove.\n\n' +
|
||||||
|
'Accepted unconditionally and answered 200 with an empty body, which is what the ' +
|
||||||
|
'client wants: it removes the rows locally and re-reads the empty list either ' +
|
||||||
|
'way. Not auth-gated, for the same reason `GET /api/messages/v2/get` isn’t — ' +
|
||||||
|
'the call reaches no state to protect.',
|
||||||
|
requestBody: jsonBody(DeleteMessagesRequest, 'The messages to delete'),
|
||||||
|
responses: { 200: { description: 'Accepted (empty body)' } },
|
||||||
|
}),
|
||||||
|
(c) => c.body(null, 200)
|
||||||
|
)
|
||||||
// How many of the caller's friends are online — the friends panel's header count.
|
// How many of the caller's friends are online — the friends panel's header count.
|
||||||
// Answered from the friend graph joined to live presence, so it agrees with the
|
// Answered from the friend graph joined to live presence, so it agrees with the
|
||||||
// friends the panel then lists. Auth-gated: the count is the CALLER's own.
|
// friends the panel then lists. Auth-gated: the count is the CALLER's own.
|
||||||
|
|||||||
@@ -3418,6 +3418,20 @@ describe('messages', () => {
|
|||||||
expect(res.status).toBe(401)
|
expect(res.status).toBe(401)
|
||||||
expect(await pushed()).toEqual([])
|
expect(await pushed()).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('POST /api/messages/v3/delete accepts anything with an empty 200', async () => {
|
||||||
|
// No message store, so no id can be real and nothing is gated — an unknown id, an
|
||||||
|
// empty list and a missing body all land the same way.
|
||||||
|
for (const body of [{ MessageIds: [1787377235629] }, { MessageIds: [] }, {}]) {
|
||||||
|
const res = await exports.default.fetch(`${ORIGIN}/api/messages/v3/delete`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
})
|
||||||
|
expect(res.status).toBe(200)
|
||||||
|
expect(await res.text()).toBe('')
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('mutual friends', () => {
|
describe('mutual friends', () => {
|
||||||
@@ -4837,6 +4851,7 @@ describe('openapi', () => {
|
|||||||
'POST /api/messages/v1/friendOnlineStatus',
|
'POST /api/messages/v1/friendOnlineStatus',
|
||||||
'POST /api/messages/v1/sendMultiple',
|
'POST /api/messages/v1/sendMultiple',
|
||||||
'POST /api/messages/v2/send',
|
'POST /api/messages/v2/send',
|
||||||
|
'POST /api/messages/v3/delete',
|
||||||
'POST /api/playerReputation/v1/bulk',
|
'POST /api/playerReputation/v1/bulk',
|
||||||
'POST /api/playerReputation/v2/bulk',
|
'POST /api/playerReputation/v2/bulk',
|
||||||
'POST /api/playerevents/v1/bulkInvite',
|
'POST /api/playerevents/v1/bulkInvite',
|
||||||
|
|||||||
Reference in New Issue
Block a user