From cacadafd59e21e719faa18141ba82d60c80ccbb9 Mon Sep 17 00:00:00 2001 From: Yaode_owo Date: Sat, 12 Oct 2024 09:27:44 -0400 Subject: [PATCH] Update main/chatparser.js --- main/chatparser.js | 553 +++++++++++++++++++++++---------------------- 1 file changed, 281 insertions(+), 272 deletions(-) diff --git a/main/chatparser.js b/main/chatparser.js index 7f73e09..fd4145f 100644 --- a/main/chatparser.js +++ b/main/chatparser.js @@ -1,273 +1,282 @@ -const lang = require("./en_us.json"); // translate message -const nbt = require('prismarine-nbt'); - -function uuidFromIntArray (arr) { - const buf = Buffer.alloc(16) - arr.forEach((num, index) => { buf.writeInt32BE(num, index * 4) }) - return buf.toString('hex') -} - -function processNbtMessage(msg) { - try { // RangeError: Maximum call stack size exceeded - if (!msg || msg.type === 'end' || msg === undefined) return undefined - const simplified = nbt.simplify(msg) - const json = JSON.stringify(simplified, (key, val) => { - if (key === 'id' && Array.isArray(val)) return uuidFromIntArray(val) - return val - }) - return json - } catch (e) { - return '{"text":""}'; - } -} - -function inject(bot) { - -bot.on('system_chat', (packet) => { // system - if (packet.isActionBar) return; - let systemchat = {}; - systemchat.jsonMsg = packet.content; - systemchat.message = parseMinecraftMessage(processNbtMessage(packet.content)); - systemchat.nocolor_message = parseMinecraftMessageNoColor(processNbtMessage(packet.content)); - bot.emit('Custom_SystemChat', systemchat.message, systemchat); - bot.emit('Custom_AllChat', systemchat.message, systemchat); -}); - - -bot.on('profileless_chat', (packet) => { // sudo and vanish - let profilelesschat = {}; - - profilelesschat.type = packet.type - - profilelesschat.formattedMessage = parseMinecraftMessage(processNbtMessage(packet.message)) - profilelesschat.senderName = parseMinecraftMessage(processNbtMessage(packet.name)) - profilelesschat.targetName = parseMinecraftMessage(processNbtMessage(packet.target)) - - profilelesschat.nocolor_formattedMessage = parseMinecraftMessageNoColor(processNbtMessage(packet.message)) - profilelesschat.nocolor_senderName = parseMinecraftMessageNoColor(processNbtMessage(packet.name)) - profilelesschat.nocolor_targetName = parseMinecraftMessageNoColor(processNbtMessage(packet.target)) - - bot.emit('Custom_ProfilelessChat', profilelesschat.formattedMessage, profilelesschat) - bot.emit('Custom_AllChat', profilelesschat.formattedMessage, profilelesschat) -}) - -bot.on('player_chat', (packet) => { // player - let playerchat = {}; - - playerchat.plainMessage = packet.plainMessage; - playerchat.type = packet.type; - playerchat.sender = packet.senderUuid; - - playerchat.unsignedContent = parseMinecraftMessage(processNbtMessage(packet.unsignedChatContent)); - playerchat.formattedMessage = parseMinecraftMessage(processNbtMessage(packet.formattedMessage)); - playerchat.senderName = parseMinecraftMessage(processNbtMessage(packet.networkName)); - playerchat.targetName = parseMinecraftMessage(processNbtMessage(packet.networkTargetName)); - - playerchat.nocolor_unsignedContent = parseMinecraftMessageNoColor(processNbtMessage(packet.unsignedChatContent)); - playerchat.nocolor_formattedMessage = parseMinecraftMessageNoColor(processNbtMessage(packet.formattedMessage)); - playerchat.nocolor_senderName = parseMinecraftMessageNoColor(processNbtMessage(packet.networkName)); - playerchat.nocolor_targetName = parseMinecraftMessageNoColor(processNbtMessage(packet.networkTargetName)); - - switch (playerchat.type) { - case 1: // /me text - msg = `* ${playerchat.senderName} ${playerchat.formattedMessage}`; - playerchat.nocolor_msg = `* ${playerchat.nocolor_senderName} ${playerchat.nocolor_formattedMessage}`; - break; - case 2: // someone /tell you text - msg = `${playerchat.senderName} whispers to you: ${playerchat.plainMessage || playerchat.formattedMessage}`; - playerchat.nocolor_msg = `${playerchat.nocolor_senderName} whispers to you: ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; - break; - case 3: // you /tell someone text - msg = `You whisper to ${playerchat.targetName}: ${playerchat.plainMessage || playerchat.formattedMessage}`; - playerchat.nocolor_msg = `You whisper to ${NoColorTargetName}: ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; - break; - case 4: // player chat - msg = playerchat.unsignedContent; - playerchat.nocolor_msg = playerchat.nocolor_unsignedContent; - break; - case 5: // /say text - msg = `[${playerchat.senderName}] ${playerchat.plainMessage || playerchat.formattedMessage}`; - playerchat.nocolor_msg = `[${playerchat.nocolor_senderName}] ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; - break; - case 6: // /minecraft:teammsg text - msg = `${playerchat.targetName} <${playerchat.senderName}> ${playerchat.plainMessage}`; - playerchat.nocolor_msg = `${playerchat.nocolor_targetName} <${playerchat.nocolor_senderName}> ${playerchat.plainMessage}`; - break; - default: - console.log(`Unknown player_chat packet. Type: ${playerchat.type}`); - console.log(packet); - break; - } - bot.emit('custom_PlayerChat', msg, playerchat); - bot.emit('Custom_AllChat', msg, playerchat) -}); - -const ansiColorCodes = { - '§0': '\x1B[30m', '§1': '\x1B[34m', '§2': '\x1B[32m', '§3': '\x1B[36m', - '§4': '\x1B[31m', '§5': '\x1B[35m', '§6': '\x1B[33m', '§7': '\x1B[37m', - '§8': '\x1B[90m', '§9': '\x1B[94m', '§a': '\x1B[92m', '§b': '\x1B[96m', - '§c': '\x1B[91m', '§d': '\x1B[95m', '§e': '\x1B[93m', '§f': '\x1B[97m', - 'black': '\x1B[30m', 'dark_blue': '\x1B[34m', 'dark_green': '\x1B[32m', - 'dark_aqua': '\x1B[36m', 'dark_red': '\x1B[31m', 'dark_purple': '\x1B[35m', - 'gold': '\x1B[33m', 'gray': '\x1B[37m', 'dark_gray': '\x1B[90m', 'blue': '\x1B[94m', - 'green': '\x1B[92m', 'aqua': '\x1B[96m', 'red': '\x1B[91m', 'light_purple': '\x1B[95m', - 'yellow': '\x1B[93m', 'white': '\x1B[97m' -}; - -const ansiFormatCodes = { - '§l': '\x1B[1m', '§o': '\x1B[3m', '§n': '\x1B[4m', '§m': '\x1B[9m', '§k': '\x1B[5m', '§r': '\x1B[0m', - 'bold': '\x1B[1m', 'italic': '\x1B[3m', 'underlined': '\x1B[4m', 'strikethrough': '\x1B[9m', 'obfuscated': '\x1B[5m', 'reset': '\x1B[0m', -}; - -function parseMinecraftMessage(component) { - if (component === undefined) return; - - let jsonComponent; - try { - jsonComponent = JSON.parse(component); - } catch (e) { - console.error("Invalid JSON format:", component); - return ''; - } - - function extractText(comp) { - let text = ''; - if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number' && comp.text !== undefined && comp.text !== null) { - text += comp.text; - } - if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number' && comp[""] !== undefined && comp[""] !== null) { - text += comp[""]; - } - if (comp && typeof comp === 'string' || typeof comp === 'number' && comp !== undefined && comp !== null) { - return comp; - } - - if (comp.extra) { - if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] - comp.extra.forEach(subComp => { - text += formatfunction(comp, extractText(subComp)); - }); - } - - if (comp.translate) { - let translateString = lang[comp.translate] || comp.translate; - if (comp.with) { - const withArgs = comp.with.map(arg => { return parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + extractText(arg) }); - - let usedReplacements = 0; - translateString = translateString.replace(/%s/g, () => { - if (usedReplacements < withArgs.length) { - return formatfunction(comp, withArgs[usedReplacements++]); - } - return "%s"; - }); - - withArgs.forEach((arg, index) => { - const regex = new RegExp(`%${index + 1}\\$s`, 'g'); - translateString = translateString.replace(regex, formatfunction(comp, arg)); - }); - } - text += formatfunction(comp, translateString); - } - - text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + ansiFormatCodes['reset']; - return text; - } - return extractText(jsonComponent) + ansiFormatCodes['reset']; -} - -function formatfunction(comp, text) { - if (text === undefined) return ''; - return text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + parseMinecraftColor(comp.color) + parseMinecraftFormat(comp); -} - -function parseMinecraftColor(color) { - if (color && ansiColorCodes[color] && !color.startsWith('#')) { - return ansiColorCodes[color]; - } else if (color && color.startsWith('#')) { - const hexRegex = /#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})/; - const hexCodes = hexRegex.exec(color); - if (hexCodes) { - const red = parseInt(hexCodes[1], 16); - const green = parseInt(hexCodes[2], 16); - const blue = parseInt(hexCodes[3], 16); - const ansiColor = `\u001b[38;2;${red};${green};${blue}m`; - return ansiColor; - } - } else { - return ''; - } -} - -function parseMinecraftFormat(format) { - let result = ''; - if (format.bold && format.bold === 1) result += ansiFormatCodes['bold']; - if (format.italic && format.italic === 1) result += ansiFormatCodes['italic']; - if (format.underlined && format.underlined === 1) result += ansiFormatCodes['underlined']; - if (format.strikethrough && format.strikethrough === 1) result += ansiFormatCodes['strikethrough']; - if (format.obfuscated && format.obfuscated === 1) result += ansiFormatCodes['obfuscated']; - return result; -} - - -function parseMinecraftMessageNoColor(component) { - if (component === undefined) return; - let jsonComponent; - try { - jsonComponent = JSON.parse(component); - } catch (e) { - console.error("Invalid JSON format:", component); - } - - function extractText(comp) { - let text = ''; - - if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number' && comp.text !== undefined && comp.text !== null) { - text += comp.text; - } - if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number' && comp[""] !== undefined && comp[""] !== null) { - text += comp[""]; - } - if (comp && typeof comp === 'string' || typeof comp === 'number' && comp !== undefined && comp !== null) { - return comp; - } - if (comp.extra) { - if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] - comp.extra.forEach(subComp => { - text += extractText(subComp); - }); - } - - if (comp.translate) { - let translateString = lang[comp.translate] || comp.translate; - if (comp.with) { - const withArgs = comp.with.map(arg => extractText(arg)); - - let usedReplacements = 0; - translateString = translateString.replace(/%s/g, () => { - if (usedReplacements < withArgs.length) { - return formatfunction(comp, withArgs[usedReplacements++]); - } - return "%s"; - }); - - withArgs.forEach((arg, index) => { - const regex = new RegExp(`%${index + 1}\\$s`, 'g'); - translateString = translateString.replace(regex, arg); - }); - } - text += translateString; - } - - - return text; - } - msgText = extractText(jsonComponent) - // msgText = msgText.replace('§', '&') - return msgText; -} - - -} - +const lang = require("./en_us.json"); // translate message +const nbt = require('prismarine-nbt'); + +function uuidFromIntArray (arr) { + const buf = Buffer.alloc(16) + arr.forEach((num, index) => { buf.writeInt32BE(num, index * 4) }) + return buf.toString('hex') +} + +function processNbtMessage(msg) { + try { + if (typeof msg === 'string') { // just create simple nbt structure + msg = { + id: 'string', + value: msg + }; + } + + if (!msg || msg.type === 'end') return msg; + + const simplified = nbt.simplify(msg); // Ensure nbt is defined elsewhere + const json = JSON.stringify(simplified, (key, val) => { + if (key === 'id' && Array.isArray(val)) return uuidFromIntArray(val); + return val; + }); + + return json; + } catch (e) { + return '{"text":""}'; + } +} + +function inject(bot) { + +bot.on('system_chat', (packet) => { // system + if (packet.isActionBar) return; + let systemchat = {}; + systemchat.jsonMsg = packet.content; + systemchat.message = parseMinecraftMessage(processNbtMessage(packet.content)); + systemchat.nocolor_message = parseMinecraftMessageNoColor(processNbtMessage(packet.content)); + bot.emit('Custom_SystemChat', systemchat.message, systemchat); + bot.emit('Custom_AllChat', systemchat.message, systemchat); +}); + + +bot.on('profileless_chat', (packet) => { // sudo and vanish + let profilelesschat = {}; + + profilelesschat.type = packet.type + + profilelesschat.formattedMessage = parseMinecraftMessage(processNbtMessage(packet.message)) + profilelesschat.senderName = parseMinecraftMessage(processNbtMessage(packet.name)) + profilelesschat.targetName = parseMinecraftMessage(processNbtMessage(packet.target)) + + profilelesschat.nocolor_formattedMessage = parseMinecraftMessageNoColor(processNbtMessage(packet.message)) + profilelesschat.nocolor_senderName = parseMinecraftMessageNoColor(processNbtMessage(packet.name)) + profilelesschat.nocolor_targetName = parseMinecraftMessageNoColor(processNbtMessage(packet.target)) + + bot.emit('Custom_ProfilelessChat', profilelesschat.formattedMessage, profilelesschat) + bot.emit('Custom_AllChat', profilelesschat.formattedMessage, profilelesschat) +}) + +bot.on('player_chat', (packet) => { // player + let playerchat = {}; + + playerchat.plainMessage = packet.plainMessage; + playerchat.type = packet.type; + playerchat.sender = packet.senderUuid; + + playerchat.unsignedContent = parseMinecraftMessage(processNbtMessage(packet.unsignedChatContent)); + playerchat.formattedMessage = parseMinecraftMessage(processNbtMessage(packet.formattedMessage)); + playerchat.senderName = parseMinecraftMessage(processNbtMessage(packet.networkName)); + playerchat.targetName = parseMinecraftMessage(processNbtMessage(packet.networkTargetName)); + + playerchat.nocolor_unsignedContent = parseMinecraftMessageNoColor(processNbtMessage(packet.unsignedChatContent)); + playerchat.nocolor_formattedMessage = parseMinecraftMessageNoColor(processNbtMessage(packet.formattedMessage)); + playerchat.nocolor_senderName = parseMinecraftMessageNoColor(processNbtMessage(packet.networkName)); + playerchat.nocolor_targetName = parseMinecraftMessageNoColor(processNbtMessage(packet.networkTargetName)); + + switch (playerchat.type) { + case 1: // /me text + msg = `* ${playerchat.senderName} ${playerchat.formattedMessage}`; + playerchat.nocolor_msg = `* ${playerchat.nocolor_senderName} ${playerchat.nocolor_formattedMessage}`; + break; + case 2: // someone /tell you text + msg = `${playerchat.senderName} whispers to you: ${playerchat.plainMessage || playerchat.formattedMessage}`; + playerchat.nocolor_msg = `${playerchat.nocolor_senderName} whispers to you: ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; + break; + case 3: // you /tell someone text + msg = `You whisper to ${playerchat.targetName}: ${playerchat.plainMessage || playerchat.formattedMessage}`; + playerchat.nocolor_msg = `You whisper to ${NoColorTargetName}: ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; + break; + case 4: // player chat + msg = playerchat.unsignedContent; + playerchat.nocolor_msg = playerchat.nocolor_unsignedContent; + break; + case 5: // /say text + msg = `[${playerchat.senderName}] ${playerchat.plainMessage || playerchat.formattedMessage}`; + playerchat.nocolor_msg = `[${playerchat.nocolor_senderName}] ${playerchat.plainMessage || playerchat.nocolor_formattedMessage}`; + break; + case 6: // /minecraft:teammsg text + msg = `${playerchat.targetName} <${playerchat.senderName}> ${playerchat.plainMessage}`; + playerchat.nocolor_msg = `${playerchat.nocolor_targetName} <${playerchat.nocolor_senderName}> ${playerchat.plainMessage}`; + break; + default: + console.log(`Unknown player_chat packet. Type: ${playerchat.type}`); + console.log(packet); + break; + } + bot.emit('custom_PlayerChat', msg, playerchat); + bot.emit('Custom_AllChat', msg, playerchat) +}); + +const ansiColorCodes = { + '§0': '\x1B[30m', '§1': '\x1B[34m', '§2': '\x1B[32m', '§3': '\x1B[36m', + '§4': '\x1B[31m', '§5': '\x1B[35m', '§6': '\x1B[33m', '§7': '\x1B[37m', + '§8': '\x1B[90m', '§9': '\x1B[94m', '§a': '\x1B[92m', '§b': '\x1B[96m', + '§c': '\x1B[91m', '§d': '\x1B[95m', '§e': '\x1B[93m', '§f': '\x1B[97m', + 'black': '\x1B[30m', 'dark_blue': '\x1B[34m', 'dark_green': '\x1B[32m', + 'dark_aqua': '\x1B[36m', 'dark_red': '\x1B[31m', 'dark_purple': '\x1B[35m', + 'gold': '\x1B[33m', 'gray': '\x1B[37m', 'dark_gray': '\x1B[90m', 'blue': '\x1B[94m', + 'green': '\x1B[92m', 'aqua': '\x1B[96m', 'red': '\x1B[91m', 'light_purple': '\x1B[95m', + 'yellow': '\x1B[93m', 'white': '\x1B[97m' +}; + +const ansiFormatCodes = { + '§l': '\x1B[1m', '§o': '\x1B[3m', '§n': '\x1B[4m', '§m': '\x1B[9m', '§k': '\x1B[5m', '§r': '\x1B[0m', + 'bold': '\x1B[1m', 'italic': '\x1B[3m', 'underlined': '\x1B[4m', 'strikethrough': '\x1B[9m', 'obfuscated': '\x1B[5m', 'reset': '\x1B[0m', +}; + +function parseMinecraftMessage(component) { + if (component === undefined) return; + + let jsonComponent; + try { + jsonComponent = JSON.parse(component); + } catch (e) { + console.error("Invalid JSON format:", component); + return ''; + } + + function extractText(comp) { + let text = ''; + if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number' && comp.text !== undefined && comp.text !== null) { + text += comp.text; + } + if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number' && comp[""] !== undefined && comp[""] !== null) { + text += comp[""]; + } + if (comp && typeof comp === 'string' || typeof comp === 'number' && comp !== undefined && comp !== null) { + return comp; + } + + if (comp.extra) { + if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] + comp.extra.forEach(subComp => { + text += formatfunction(comp, extractText(subComp)); + }); + } + + if (comp.translate) { + let translateString = lang[comp.translate] || comp.translate; + if (comp.with) { + const withArgs = comp.with.map(arg => { return parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + extractText(arg) }); + + let usedReplacements = 0; + translateString = translateString.replace(/%s/g, () => { + if (usedReplacements < withArgs.length) { + return formatfunction(comp, withArgs[usedReplacements++]); + } + return "%s"; + }); + + withArgs.forEach((arg, index) => { + const regex = new RegExp(`%${index + 1}\\$s`, 'g'); + translateString = translateString.replace(regex, formatfunction(comp, arg)); + }); + } + text += formatfunction(comp, translateString); + } + + text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + ansiFormatCodes['reset']; + return text; + } + return extractText(jsonComponent) + ansiFormatCodes['reset']; +} + +function formatfunction(comp, text) { + if (text === undefined) return ''; + return text = parseMinecraftColor(comp.color) + parseMinecraftFormat(comp) + text + parseMinecraftColor(comp.color) + parseMinecraftFormat(comp); +} + +function parseMinecraftColor(color) { + if (color && ansiColorCodes[color] && !color.startsWith('#')) { + return ansiColorCodes[color]; + } else if (color && color.startsWith('#')) { + const hexRegex = /#?([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})/; + const hexCodes = hexRegex.exec(color); + if (hexCodes) { + const red = parseInt(hexCodes[1], 16); + const green = parseInt(hexCodes[2], 16); + const blue = parseInt(hexCodes[3], 16); + const ansiColor = `\u001b[38;2;${red};${green};${blue}m`; + return ansiColor; + } + } else { + return ''; + } +} + +function parseMinecraftFormat(format) { + let result = ''; + if (format.bold && format.bold === 1) result += ansiFormatCodes['bold']; + if (format.italic && format.italic === 1) result += ansiFormatCodes['italic']; + if (format.underlined && format.underlined === 1) result += ansiFormatCodes['underlined']; + if (format.strikethrough && format.strikethrough === 1) result += ansiFormatCodes['strikethrough']; + if (format.obfuscated && format.obfuscated === 1) result += ansiFormatCodes['obfuscated']; + return result; +} + + +function parseMinecraftMessageNoColor(component) { + if (component === undefined) return; + let jsonComponent; + try { + jsonComponent = JSON.parse(component); + } catch (e) { + console.error("Invalid JSON format:", component); + } + + function extractText(comp) { + let text = ''; + + if (comp.text && typeof comp.text === 'string' || typeof comp.text === 'number' && comp.text !== undefined && comp.text !== null) { + text += comp.text; + } + if (comp[""] && typeof comp[""] === 'string' || typeof comp[""] === 'number' && comp[""] !== undefined && comp[""] !== null) { + text += comp[""]; + } + if (comp && typeof comp === 'string' || typeof comp === 'number' && comp !== undefined && comp !== null) { + return comp; + } + if (comp.extra) { + if (!Array.isArray(comp.extra)) comp.extra = [comp.extra] + comp.extra.forEach(subComp => { + text += extractText(subComp); + }); + } + + if (comp.translate) { + let translateString = lang[comp.translate] || comp.translate; + if (comp.with) { + const withArgs = comp.with.map(arg => extractText(arg)); + + let usedReplacements = 0; + translateString = translateString.replace(/%s/g, () => { + if (usedReplacements < withArgs.length) { + return formatfunction(comp, withArgs[usedReplacements++]); + } + return "%s"; + }); + + withArgs.forEach((arg, index) => { + const regex = new RegExp(`%${index + 1}\\$s`, 'g'); + translateString = translateString.replace(regex, arg); + }); + } + text += translateString; + } + + + return text; + } + msgText = extractText(jsonComponent) + // msgText = msgText.replace('§', '&') + return msgText; +} + + +} + module.exports = { inject }; \ No newline at end of file