Add Charades word lists management, profanity filter, and matchmaking routes (#41)

* feat: add 3D Charades word lists management and profanity filter toggle

- Implemented Charades word lists management in the admin UI, allowing for unlimited named word lists with difficulty settings.
- Added functionality to bind live card slots to specific word lists, with automatic fallback to built-in lists.
- Introduced a profanity filter toggle in server settings, enabling or disabling the server-side profanity filter.
- Updated database schema to support new features, including additional columns for profanity filter status and charades slot bindings.
- Enhanced documentation to reflect new features and their usage.

* feat: add identityserver-signing.pfx to .gitignore

* feat: add new matchmake routes for player, event, club, and code
This commit is contained in:
Alexa
2026-07-02 10:11:18 +03:00
committed by GitHub
parent 28c1755d99
commit 6bd9034194
20 changed files with 1567 additions and 25 deletions
@@ -0,0 +1,46 @@
namespace DorkNet.Server.Data.Entities;
/// <summary>
/// One admin-authored 3D Charades word list. The March 2023 client
/// pulls a deck at card-box spawn time from
/// <c>api/activities/charades/v1/words/{source}</c>, where
/// <c>{source}</c> is one of three baked <c>CardBox.cardSource</c>
/// slots — <c>Charades</c>, <c>CharadesAprilFoolsDay</c>, or
/// <c>Icebreakers</c> (verified in the 2023.03.21 il2cpp dump:
/// <c>GEFMIBEPMKJ.EODJJDILECA</c>). The game itself only ever requests
/// those three ids.
///
/// To let admins keep an unlimited library and freely switch which list
/// each slot serves, every list is a row here (name + words), and the
/// live slot→list binding lives in
/// <see cref="ServerSettingsEntity.CharadesSlotBindingsJson"/>. This is
/// the same admin-editable-collection shape as
/// <see cref="LoadingScreenTipEntity"/>: a plain entity CRUD'd from the
/// SPA, created on existing DBs via the idempotent bootstrap (it
/// post-dates the consolidated Initial migration).
/// </summary>
public class CharadesWordListEntity
{
public long Id { get; set; }
/// <summary>Admin-facing display name, e.g. "Default", "Movie night",
/// "April Fools". Not sent to the client.</summary>
public string Name { get; set; } = string.Empty;
/// <summary>Serialized <c>List&lt;CharadesWord&gt;</c> — each entry is
/// <c>{ Text, Difficulty }</c>. <c>Text</c> becomes the wire
/// <c>EN_US</c> field; <c>Difficulty</c> is the client
/// <c>CNMMMNJJDMM</c> enum (0 easy, 1 hard, 10 very hard, 20
/// icebreaker). Stored as JSON so a list can grow to hundreds of
/// cards without a child table.</summary>
public string WordsJson { get; set; } = "[]";
/// <summary>True for the lists seeded on first boot (Default /
/// April Fools / Icebreakers). Purely informational — admins may
/// still rename, edit, or delete them; it only gates the one-time
/// seed so we don't duplicate them every startup.</summary>
public bool IsBuiltIn { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
@@ -64,5 +64,23 @@ public class ServerSettingsEntity
/// migration each time.</summary>
public string DiscoveredGameConfigsJson { get; set; } = string.Empty;
/// <summary>When true, the server-side profanity filter behind
/// <c>api/sanitize/*</c> is bypassed — every string is treated as
/// clean and returned unmodified. Built for private friend servers
/// that don't want room/invention names or chat censored. Off by
/// default (filter active). See <see cref="Services.ProfanityFilter"/>
/// and <c>SanitizeController</c>.</summary>
public bool ProfanityFilterDisabled { get; set; }
/// <summary>Which charades word list (row id in
/// <see cref="CharadesWordListEntity"/>) is live for each of the
/// client's three baked card-source slots. JSON object keyed by the
/// client enum name — <c>{"Charades":id,"CharadesAprilFoolsDay":id,
/// "Icebreakers":id}</c>. Empty/0 or a dangling id falls back to the
/// list the seeder created for that slot. Lets admins keep an
/// unlimited library and switch which list a slot serves without a
/// redeploy.</summary>
public string CharadesSlotBindingsJson { get; set; } = string.Empty;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}