25 lines
1.2 KiB
TypeScript
25 lines
1.2 KiB
TypeScript
/**
|
|
* The single chokepoint for viewer display names crossing from Twitch into the feed.
|
|
*
|
|
* See `docs/design/stage-bridge.md` section C, "How viewer names reach the ticker": Twitch ->
|
|
* flybridge -> `POST /stimulate` on flysim -> flysim emits a `viewer`/`sugar` event in the next
|
|
* snapshot's `events[]` -> flystage renders it. `validateDisplayName` runs in flybridge before
|
|
* the sim call, and flystage re-validates on render as defence in depth. Only login/display
|
|
* names ever cross this boundary, never message bodies.
|
|
*/
|
|
|
|
/** Letters, digits and underscore only, 1 to 25 characters. Anything else falls back to the literal `"a viewer"`. */
|
|
const DISPLAY_NAME_PATTERN = /^[\p{L}\p{N}_]{1,25}$/u;
|
|
|
|
/** Fallback for a name that fails validation, or is missing entirely. */
|
|
export const FALLBACK_DISPLAY_NAME = 'a viewer';
|
|
|
|
/**
|
|
* Validate a Twitch display name for use in templates, feed events and anything rendered on
|
|
* screen. Returns the name unchanged when it matches `^[\p{L}\p{N}_]{1,25}$`, else the literal
|
|
* `"a viewer"`. Never throws.
|
|
*/
|
|
export function validateDisplayName(name: string | null | undefined): string {
|
|
if (typeof name !== 'string') return FALLBACK_DISPLAY_NAME;
|
|
return DISPLAY_NAME_PATTERN.test(name) ? name : FALLBACK_DISPLAY_NAME;
|
|
}
|