67 lines
2.2 KiB
TypeScript
67 lines
2.2 KiB
TypeScript
// Parse the URL params the host appends when loading experience.url.
|
|
// Source of truth on the host side:
|
|
// src/app/features/bots/BotWidgetEmbed.ts (getBotWidgetUrl).
|
|
// Keep this in sync if the host adds params.
|
|
|
|
export type WidgetBootstrap = {
|
|
widgetId: string;
|
|
parentUrl: string;
|
|
parentOrigin: string;
|
|
roomId: string;
|
|
userId: string;
|
|
botId: string;
|
|
botMxid: string;
|
|
/** Bridge command prefix (e.g. `!wa`). Always non-empty — the host
|
|
* validator (catalog.ts) defaults missing values to `!tg` and rejects
|
|
* malformed overrides. The widget prepends `<commandPrefix> ` to every
|
|
* outbound command and form-field value (bridgev2/queue.go:118 strips
|
|
* exactly `prefix+" "`). For mautrix-whatsapp the operator must set
|
|
* `commandPrefix: "!wa"` in /config.json — connector.go ships
|
|
* `DefaultCommandPrefix: "!wa"`. */
|
|
commandPrefix: string;
|
|
theme: 'light' | 'dark';
|
|
clientLanguage: string;
|
|
};
|
|
|
|
export type BootstrapResult =
|
|
| { ok: true; bootstrap: WidgetBootstrap }
|
|
| { ok: false; missing: string[] };
|
|
|
|
const REQUIRED = ['widgetId', 'parentUrl', 'roomId', 'userId', 'botMxid', 'commandPrefix'] as const;
|
|
|
|
export const readBootstrap = (search: string): BootstrapResult => {
|
|
const params = new URLSearchParams(search);
|
|
const get = (k: string) => params.get(k) ?? '';
|
|
|
|
const missing = REQUIRED.filter((k) => !params.get(k));
|
|
if (missing.length > 0) return { ok: false, missing: [...missing] };
|
|
|
|
// Origin is what the widget validates against on incoming postMessage —
|
|
// see widget-api.ts. Falling back to '*' would defeat the security
|
|
// boundary, so a malformed parentUrl bails out as a missing-param error.
|
|
let parentOrigin: string;
|
|
try {
|
|
parentOrigin = new URL(get('parentUrl')).origin;
|
|
} catch {
|
|
return { ok: false, missing: ['parentUrl'] };
|
|
}
|
|
|
|
const themeRaw = get('theme');
|
|
const theme: 'light' | 'dark' = themeRaw === 'dark' ? 'dark' : 'light';
|
|
|
|
return {
|
|
ok: true,
|
|
bootstrap: {
|
|
widgetId: get('widgetId'),
|
|
parentUrl: get('parentUrl'),
|
|
parentOrigin,
|
|
roomId: get('roomId'),
|
|
userId: get('userId'),
|
|
botId: get('botId'),
|
|
botMxid: get('botMxid'),
|
|
commandPrefix: get('commandPrefix'),
|
|
theme,
|
|
clientLanguage: get('clientLanguage'),
|
|
},
|
|
};
|
|
};
|