matterbridge-roborock-vacuum-plugin
Version:
Matterbridge Roborock Vacuum Plugin
79 lines (63 loc) • 1.89 kB
text/typescript
const token = '%[a-f0-9]{2}';
const singleMatcher = new RegExp('(' + token + ')|([^%]+?)', 'gi');
const multiMatcher = new RegExp('(' + token + ')+', 'gi');
function decodeComponents(components: RegExpMatchArray | string[] | [], split: number | undefined = undefined): string[] {
try {
return [decodeURIComponent(components.join(''))];
} catch {
// Do nothing
}
if (components.length === 1) {
return components;
}
split = split || 1;
const left = components.slice(0, split);
const right = components.slice(split);
return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
}
function decode(input: string) {
try {
return decodeURIComponent(input);
} catch {
let tokens = input.match(singleMatcher) || [];
for (let i = 1; i < tokens.length; i++) {
input = decodeComponents(tokens, i).join('');
tokens = input.match(singleMatcher) || [];
}
return input;
}
}
function customDecodeURIComponent(input: string): string {
const replaceMap: Record<string, string> = {
'%FE%FF': '\uFFFD\uFFFD',
'%FF%FE': '\uFFFD\uFFFD',
};
let match = multiMatcher.exec(input);
while (match) {
try {
replaceMap[match[0]] = decodeURIComponent(match[0]);
} catch {
const result = decode(match[0]);
if (result !== match[0]) {
replaceMap[match[0]] = result;
}
}
match = multiMatcher.exec(input);
}
replaceMap['%C2'] = '\uFFFD';
const entries = Object.keys(replaceMap);
for (const key of entries) {
input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
}
return input;
}
export default function decodeComponent(encodedURI: string | undefined) {
if (encodedURI === undefined) {
return undefined;
}
try {
return decodeURIComponent(encodedURI);
} catch {
return customDecodeURIComponent(encodedURI);
}
}