mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-08-29 00:01:09 +00:00
a0b3968d33
Reorganize the panel around product capabilities and integrate the remote i18n feature from origin/master into the new structure. - Restructure src into capability features (app, trainer, library, remote-session, appearance, shared); move the bridge to bridge/src. - Add lingui-based UI localization and wrap remaining user-facing strings (Trans / msg macros); fix the 'END В·' mojibake. - Port WeMod cheat-metadata i18n: capture the access token from the snapshot's renderer in the bridge and fetch localized trainer_meta in remote-session.i18n; guarantee snapshot sync on token failure. - Wire vitest to the app's lingui/preact pipeline (mergeConfig).
79 lines
2.9 KiB
TypeScript
79 lines
2.9 KiB
TypeScript
import webContract from '../../protocol/web-contract.json';
|
|
|
|
const BRIDGE_PROTOCOL_VERSION = webContract.protocolVersion;
|
|
|
|
export function validateClientMessage(message, handshaken) {
|
|
if (!isRecord(message) || typeof message.type !== 'string' || !isRecord(message.payload)) {
|
|
return invalid('invalid_message', 'Expected a protocol envelope with an object payload.');
|
|
}
|
|
|
|
if (message.version !== BRIDGE_PROTOCOL_VERSION) {
|
|
return invalid('protocol_mismatch', `Unsupported protocol version ${String(message.version)}.`);
|
|
}
|
|
|
|
if (message.requestId !== null && typeof message.requestId !== 'string') {
|
|
return invalid('invalid_request_id', 'requestId must be a string or null.');
|
|
}
|
|
|
|
if (message.type === 'hello') {
|
|
if (message.payload.client !== 'mobile-web' || typeof message.payload.clientVersion !== 'string' || !isRecord(message.payload.capabilities)) {
|
|
return invalid('invalid_hello', 'The hello payload is incomplete.');
|
|
}
|
|
return { ok: true };
|
|
}
|
|
|
|
if (!handshaken) {
|
|
return invalid('handshake_required', 'Send a compatible hello message before commands.');
|
|
}
|
|
|
|
if (message.type === 'set_value') {
|
|
if (!safeString(message.payload.trainerId) || !safeString(message.payload.target) || !('value' in message.payload)) {
|
|
return invalid('invalid_set_value', 'trainerId, target and value are required.');
|
|
}
|
|
return { ok: true };
|
|
}
|
|
|
|
if (message.type === 'remote_command') {
|
|
if (message.payload.action !== 'launch' && message.payload.action !== 'stop') {
|
|
return invalid('invalid_command', 'Unknown remote command.');
|
|
}
|
|
return { ok: true };
|
|
}
|
|
|
|
return invalid('unknown_message', 'Unknown protocol message type.');
|
|
}
|
|
|
|
export function validateSetValueTarget(message, snapshot) {
|
|
const target = safeString(message.payload?.target);
|
|
const requestedTrainerId = safeString(message.payload?.trainerId);
|
|
const activeTrainerId = snapshot?.trainerMeta?.trainer?.trainerId || '';
|
|
if (!snapshot || requestedTrainerId !== activeTrainerId) {
|
|
return invalid('trainer_mismatch', 'The requested trainer is not active.');
|
|
}
|
|
|
|
const cheat = snapshot.trainerMeta.schema.cheats.find((entry) => entry.target === target);
|
|
if (!target || !cheat || !(target in snapshot.trainerValues.values)) {
|
|
return invalid('invalid_target', 'Unknown cheat target.');
|
|
}
|
|
|
|
return {
|
|
ok: true,
|
|
trainerId: activeTrainerId,
|
|
target,
|
|
cheat,
|
|
value: cheat.type === 'toggle' ? Boolean(message.payload.value) : message.payload.value,
|
|
};
|
|
}
|
|
|
|
function invalid(code, message) {
|
|
return { ok: false, error: { code, message } };
|
|
}
|
|
|
|
function isRecord(value) {
|
|
return typeof value === 'object' && value !== null;
|
|
}
|
|
|
|
function safeString(value) {
|
|
return typeof value === 'string' && value.length > 0 ? value : '';
|
|
}
|