mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 14:41:28 -07:00
update moderationblockdetails to work on both clients for now
This commit is contained in:
@@ -391,10 +391,11 @@ export const SubscriptionResponse = z.object({
|
|||||||
// ---- Moderation ------------------------------------------------------------
|
// ---- Moderation ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `GET /api/PlayerReporting/v1/moderationBlockDetails` — always the "not blocked"
|
* `GET|POST /api/PlayerReporting/v1/moderationBlockDetails` — always the "not blocked"
|
||||||
* answer (no ban storage yet), mirroring the reference server's stub
|
* answer (no ban storage yet), mirroring the reference server's stub
|
||||||
* `ReturnModerationBlockDetails()`. `ReportCategory` is `Unknown` (-1) rather than 0,
|
* `ReturnModerationBlockDetails()`. `ReportCategory` is `Unknown` (-1) rather than 0,
|
||||||
* which is a real category, and `Message` is the empty string the reference sends.
|
* which is a real category, and `Message` is null — the client distinguishes "no
|
||||||
|
* message" from a blank one, so we send null where the reference sends an empty string.
|
||||||
* `IsVoiceModAutoban`/`TimeoutStartedAt` are on the DTO but unset by that stub, so
|
* `IsVoiceModAutoban`/`TimeoutStartedAt` are on the DTO but unset by that stub, so
|
||||||
* they carry their C# defaults (false / null).
|
* they carry their C# defaults (false / null).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,22 +16,27 @@ import type { App } from '../context'
|
|||||||
export const moderationRoutes = new Hono<App>({ strict: false })
|
export const moderationRoutes = new Hono<App>({ strict: false })
|
||||||
// Whether the caller is currently blocked (banned / timed out / host-kicked). No ban
|
// Whether the caller is currently blocked (banned / timed out / host-kicked). No ban
|
||||||
// storage yet, so this is always the "not blocked" answer — the reference server's
|
// storage yet, so this is always the "not blocked" answer — the reference server's
|
||||||
// stub `ReturnModerationBlockDetails()` verbatim. `ReportCategory` is `Unknown` (-1),
|
// stub `ReturnModerationBlockDetails()`. `ReportCategory` is `Unknown` (-1), not 0,
|
||||||
// not 0, which is a real category, and `Message` is the empty string that stub sends.
|
// which is a real category. `Message` is null rather than the empty string that stub
|
||||||
|
// sends: the client distinguishes "no message" from a blank one.
|
||||||
// `IsVoiceModAutoban`/`TimeoutStartedAt` are on the DTO but left unset there, so they
|
// `IsVoiceModAutoban`/`TimeoutStartedAt` are on the DTO but left unset there, so they
|
||||||
// go out with their C# defaults.
|
// go out with their C# defaults.
|
||||||
// POST with no body — the client's actual call, despite this being a pure read.
|
// POST with no body is the client's actual call, despite this being a pure read; it
|
||||||
.post(
|
// answers GET too, so the path is reachable either way.
|
||||||
|
.on(
|
||||||
|
['GET', 'POST'],
|
||||||
'/api/PlayerReporting/v1/moderationBlockDetails',
|
'/api/PlayerReporting/v1/moderationBlockDetails',
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Moderation'],
|
tags: ['Moderation'],
|
||||||
summary: 'Whether the caller is blocked',
|
summary: 'Whether the caller is blocked',
|
||||||
description:
|
description:
|
||||||
'Ban / timeout / host-kick state for the caller. There is no ban storage yet, so ' +
|
'Ban / timeout / host-kick state for the caller. There is no ban storage yet, so ' +
|
||||||
'this is always the “not blocked” answer, matching the reference server’s stub: ' +
|
'this is always the “not blocked” answer, following the reference server’s stub: ' +
|
||||||
'`ReportCategory` is `Unknown` (-1) rather than 0, which is a real category, and ' +
|
'`ReportCategory` is `Unknown` (-1) rather than 0, which is a real category. ' +
|
||||||
'`Message` is an empty string. `IsVoiceModAutoban` and `TimeoutStartedAt` are on ' +
|
'`Message` is null rather than the empty string that stub sends — the client ' +
|
||||||
'the DTO but unset by that stub, so they carry their defaults.',
|
'distinguishes “no message” from a blank one. `IsVoiceModAutoban` and ' +
|
||||||
|
'`TimeoutStartedAt` are on the DTO but unset by that stub, so they carry their ' +
|
||||||
|
'defaults.',
|
||||||
responses: { 200: json(ModerationBlockDetails, 'Always “not blocked”') },
|
responses: { 200: json(ModerationBlockDetails, 'Always “not blocked”') },
|
||||||
}),
|
}),
|
||||||
(c) =>
|
(c) =>
|
||||||
@@ -42,7 +47,7 @@ export const moderationRoutes = new Hono<App>({ strict: false })
|
|||||||
IsBan: false,
|
IsBan: false,
|
||||||
IsHostKick: false,
|
IsHostKick: false,
|
||||||
IsVoiceModAutoban: false,
|
IsVoiceModAutoban: false,
|
||||||
Message: '',
|
Message: null,
|
||||||
PlayerIdReporter: null,
|
PlayerIdReporter: null,
|
||||||
TimeoutStartedAt: null,
|
TimeoutStartedAt: null,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -233,27 +233,31 @@ describe('public endpoints', () => {
|
|||||||
expect(await res.json()).toEqual([])
|
expect(await res.json()).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
test('POST /api/PlayerReporting/v1/moderationBlockDetails reports "not blocked"', async () => {
|
// The client POSTs this with no body, despite it being a pure read; the route answers
|
||||||
// The client POSTs this with no body, despite it being a pure read.
|
// GET as well, and both methods serve the same body.
|
||||||
const res = await exports.default.fetch(
|
test.each(['GET', 'POST'])(
|
||||||
`${ORIGIN}/api/PlayerReporting/v1/moderationBlockDetails`,
|
'%s /api/PlayerReporting/v1/moderationBlockDetails reports "not blocked"',
|
||||||
{ method: 'POST' }
|
async (method) => {
|
||||||
)
|
const res = await exports.default.fetch(
|
||||||
expect(res.status).toBe(200)
|
`${ORIGIN}/api/PlayerReporting/v1/moderationBlockDetails`,
|
||||||
// The reference server's stub verbatim: ReportCategory -1 = Unknown (0 is a real
|
{ method }
|
||||||
// category) and an empty-string Message.
|
)
|
||||||
expect(await res.json()).toEqual({
|
expect(res.status).toBe(200)
|
||||||
ReportCategory: -1,
|
// ReportCategory -1 = Unknown (0 is a real category). Message is null, not the
|
||||||
Duration: 0,
|
// reference stub's empty string — the client tells "no message" from a blank one.
|
||||||
GameSessionId: 0,
|
expect(await res.json()).toEqual({
|
||||||
IsBan: false,
|
ReportCategory: -1,
|
||||||
IsHostKick: false,
|
Duration: 0,
|
||||||
IsVoiceModAutoban: false,
|
GameSessionId: 0,
|
||||||
Message: '',
|
IsBan: false,
|
||||||
PlayerIdReporter: null,
|
IsHostKick: false,
|
||||||
TimeoutStartedAt: null,
|
IsVoiceModAutoban: false,
|
||||||
})
|
Message: null,
|
||||||
})
|
PlayerIdReporter: null,
|
||||||
|
TimeoutStartedAt: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Unauthenticated by design — the client posts this before it has an account, so
|
// Unauthenticated by design — the client posts this before it has an account, so
|
||||||
// there's no bearer token to check and nothing to attribute the id to.
|
// there's no bearer token to check and nothing to attribute the id to.
|
||||||
@@ -1899,6 +1903,7 @@ describe('openapi', () => {
|
|||||||
)
|
)
|
||||||
expect([...documented].sort()).toEqual([
|
expect([...documented].sort()).toEqual([
|
||||||
'DELETE /api/images/v1/deletesaved',
|
'DELETE /api/images/v1/deletesaved',
|
||||||
|
'GET /api/PlayerReporting/v1/moderationBlockDetails',
|
||||||
'GET /api/PlayerReporting/v1/voteToKickReasons',
|
'GET /api/PlayerReporting/v1/voteToKickReasons',
|
||||||
'GET /api/activities/charades/v1/words/{activity}',
|
'GET /api/activities/charades/v1/words/{activity}',
|
||||||
'GET /api/announcement/v1/get',
|
'GET /api/announcement/v1/get',
|
||||||
|
|||||||
Reference in New Issue
Block a user