mirror of
https://github.com/elder-plinius/P4RS3LT0NGV3.git
synced 2026-04-22 03:36:19 +02:00
218 lines
6.7 KiB
JavaScript
218 lines
6.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const vm = require('vm');
|
|
|
|
const projectRoot = path.join(__dirname, '..');
|
|
const transformsRoot = path.join(projectRoot, 'src', 'transformers');
|
|
const transforms = require(path.join(projectRoot, 'src', 'transformers', 'loader-node.js'));
|
|
|
|
function buildRegistry() {
|
|
const skipFiles = new Set(['BaseTransformer.js', 'index.js', 'loader-node.js', 'README.md']);
|
|
const categories = fs.readdirSync(transformsRoot, { withFileTypes: true })
|
|
.filter((entry) => entry.isDirectory())
|
|
.map((entry) => entry.name)
|
|
.sort();
|
|
|
|
const registry = [];
|
|
for (const category of categories) {
|
|
const categoryPath = path.join(transformsRoot, category);
|
|
const files = fs.readdirSync(categoryPath)
|
|
.filter((file) => file.endsWith('.js') && !skipFiles.has(file))
|
|
.sort();
|
|
|
|
for (const file of files) {
|
|
const key = file.replace('.js', '').replace(/-/g, '_');
|
|
const transform = transforms[key];
|
|
if (!transform) {
|
|
continue;
|
|
}
|
|
|
|
registry.push({
|
|
key,
|
|
category,
|
|
name: transform.name,
|
|
priority: transform.priority ?? 0,
|
|
canDecode: Boolean(transform.reverse),
|
|
description: transform.description || '',
|
|
inputKind: transform.inputKind || 'textarea',
|
|
configurableOptions: (transform.configurableOptions || []).map((opt) => ({
|
|
id: opt.id,
|
|
label: opt.label,
|
|
type: opt.type,
|
|
default: opt.default,
|
|
min: opt.min,
|
|
max: opt.max,
|
|
step: opt.step,
|
|
options: opt.options || undefined
|
|
}))
|
|
});
|
|
}
|
|
}
|
|
|
|
return registry;
|
|
}
|
|
|
|
function getDefaultOptions(transform) {
|
|
if (!transform || !transform.configurableOptions || !transform.configurableOptions.length) {
|
|
return {};
|
|
}
|
|
|
|
const defaults = {};
|
|
for (const opt of transform.configurableOptions) {
|
|
let value = opt.default;
|
|
if (value === undefined || value === null) {
|
|
if (opt.type === 'boolean') {
|
|
value = false;
|
|
} else if (opt.type === 'select' && opt.options && opt.options.length) {
|
|
value = opt.options[0].value;
|
|
} else if (opt.type === 'number') {
|
|
value = 0;
|
|
} else {
|
|
value = '';
|
|
}
|
|
}
|
|
defaults[opt.id] = value;
|
|
}
|
|
|
|
return defaults;
|
|
}
|
|
|
|
function loadUniversalDecoder() {
|
|
const transformOptionsCode = fs.readFileSync(path.join(projectRoot, 'js', 'core', 'transformOptions.js'), 'utf8');
|
|
const decoderCode = fs.readFileSync(path.join(projectRoot, 'js', 'core', 'decoder.js'), 'utf8');
|
|
const emojiWordMapCode = fs.readFileSync(path.join(projectRoot, 'src', 'emojiWordMap.js'), 'utf8');
|
|
const emojiUtilsCode = fs.readFileSync(path.join(projectRoot, 'js', 'utils', 'emoji.js'), 'utf8');
|
|
|
|
const mockSteganography = {
|
|
hasEmojiInText: () => false,
|
|
decodeEmoji: () => null,
|
|
decodeInvisible: () => null
|
|
};
|
|
|
|
const sandbox = {
|
|
window: {
|
|
transforms,
|
|
steganography: mockSteganography,
|
|
emojiLibrary: {},
|
|
emojiKeywords: {},
|
|
emojiData: {}
|
|
},
|
|
console,
|
|
TextEncoder,
|
|
TextDecoder,
|
|
Intl,
|
|
btoa: (str) => Buffer.from(str, 'binary').toString('base64'),
|
|
atob: (str) => Buffer.from(str, 'base64').toString('binary')
|
|
};
|
|
|
|
vm.createContext(sandbox);
|
|
vm.runInContext(emojiUtilsCode, sandbox);
|
|
vm.runInContext(emojiWordMapCode, sandbox);
|
|
vm.runInContext(transformOptionsCode, sandbox);
|
|
vm.runInContext(decoderCode, sandbox);
|
|
|
|
return sandbox.universalDecode;
|
|
}
|
|
|
|
function normalizeError(error) {
|
|
if (error && typeof error.message === 'string') {
|
|
return error.message;
|
|
}
|
|
return String(error);
|
|
}
|
|
|
|
function readPayload() {
|
|
const raw = fs.readFileSync(0, 'utf8');
|
|
return raw ? JSON.parse(raw) : {};
|
|
}
|
|
|
|
function writeResult(result, exitCode = 0) {
|
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
process.exit(exitCode);
|
|
}
|
|
|
|
function main() {
|
|
const payload = readPayload();
|
|
const command = payload.command;
|
|
const registry = buildRegistry();
|
|
|
|
if (command === 'list') {
|
|
writeResult({ ok: true, transforms: registry });
|
|
}
|
|
|
|
const transformKey = payload.transform;
|
|
const transform = transformKey ? transforms[transformKey] : null;
|
|
|
|
if (command === 'inspect') {
|
|
if (!transform || !transformKey) {
|
|
writeResult({ ok: false, error: `Unknown transform: ${transformKey}` }, 1);
|
|
}
|
|
|
|
const meta = registry.find((entry) => entry.key === transformKey);
|
|
writeResult({
|
|
ok: true,
|
|
transform: {
|
|
...meta,
|
|
defaultOptions: getDefaultOptions(transform)
|
|
}
|
|
});
|
|
}
|
|
|
|
if (command === 'run') {
|
|
if (!transform || !transformKey) {
|
|
writeResult({ ok: false, error: `Unknown transform: ${transformKey}` }, 1);
|
|
}
|
|
|
|
const action = payload.action || 'encode';
|
|
const text = payload.text || '';
|
|
const options = {
|
|
...getDefaultOptions(transform),
|
|
...(payload.options || {})
|
|
};
|
|
|
|
try {
|
|
let output;
|
|
if (action === 'encode') {
|
|
output = transform.func(text, options);
|
|
} else if (action === 'decode') {
|
|
if (!transform.reverse) {
|
|
throw new Error(`${transform.name} does not support decode`);
|
|
}
|
|
output = transform.reverse(text, options);
|
|
} else if (action === 'preview') {
|
|
output = transform.preview(text, options);
|
|
} else {
|
|
throw new Error(`Unsupported action: ${action}`);
|
|
}
|
|
|
|
writeResult({
|
|
ok: true,
|
|
action,
|
|
transform: transformKey,
|
|
name: transform.name,
|
|
options,
|
|
output
|
|
});
|
|
} catch (error) {
|
|
writeResult({ ok: false, error: normalizeError(error) }, 1);
|
|
}
|
|
}
|
|
|
|
if (command === 'auto-decode') {
|
|
const decode = loadUniversalDecoder();
|
|
try {
|
|
const result = decode(payload.text || '', {});
|
|
writeResult({ ok: true, result });
|
|
} catch (error) {
|
|
writeResult({ ok: false, error: normalizeError(error) }, 1);
|
|
}
|
|
}
|
|
|
|
writeResult({ ok: false, error: `Unknown command: ${command}` }, 1);
|
|
}
|
|
|
|
main();
|
|
|