Re-add v11 parser for chat messages
This commit is contained in:
parent
0aacd8e7f7
commit
5c3104153c
17 changed files with 1137 additions and 21 deletions
25
README.md
25
README.md
|
@ -1,13 +1,13 @@
|
|||
# owobot
|
||||
# botv12
|
||||
|
||||
owobot is a Minecraft bot originally designed for [Kaboom](https://kaboom.pw/) and its clones. It has many of the features that you would expect in a modern Kaboom bot:
|
||||
botv12 is a Minecraft bot originally designed for [Kaboom](https://kaboom.pw/) and its clones. It has many of the features that you would expect in a modern Kaboom bot:
|
||||
|
||||
- commands (obviously)
|
||||
- a self care system
|
||||
- a command core, to run commands quickly
|
||||
- a hashing system, to enable trusted users to securely run certain commands in chat
|
||||
|
||||
It supports all Minecraft versions from 1.13 to 1.20.4 that are supported by node-minecraft-protocol.
|
||||
It supports all Minecraft versions from 1.13 to 1.20.4 that are supported by node-minecraft-protocol. It may work on other versions, however, support will not be provided for them.
|
||||
|
||||
If you are not sure if this code is safe to run, you can read through every line of code. You can also see the commit history by clicking on the (n) commits button, to make sure nobody has added any exploits or introduced vulnerabilities to the code.
|
||||
|
||||
|
@ -24,22 +24,5 @@ If you find any exploits, security issues, etc in the code, please send me an is
|
|||
|
||||
## Command list
|
||||
|
||||
| Name | Usage | Description |
|
||||
|-|-|-|
|
||||
| about | [serverlist \| servers \| server] | About the bot. May also show system information or a list of connected servers. |
|
||||
| cb | \<command\> | Run a command in a command block |
|
||||
| cloop | add <rate> <command>, remove <index>, list, clear | Manage command loops |
|
||||
| eval | \<code\> | Run JavaScript code (must run through console)|
|
||||
| help | [cmd] | Shows command help |
|
||||
| logoff | | Disconnect and reconnect the bot from a server |
|
||||
| netmsg | \<message\> | Send a message to all servers the bot is connected to |
|
||||
| refill | | Refill core |
|
||||
| restart | | Restart bot, closes when launched directly |
|
||||
| say | \<message\> | Sends a message to chat |
|
||||
| settings | get, set <key> <value> | Set your user preferences |
|
||||
| stop | | Close bot |
|
||||
| template | | Used in development, does nothing |
|
||||
| test | | Debug command for the chat parser |
|
||||
| tpr | | Teleport to a random location |
|
||||
| validate | | Check the hashing system |
|
||||
None yet...
|
||||
|
||||
|
|
47
chatParsers/chat_cmm.js
Executable file
47
chatParsers/chat_cmm.js
Executable file
|
@ -0,0 +1,47 @@
|
|||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
|
||||
const priority = 0
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'system' || data.type === 'legacy') {
|
||||
if (data.json.translate === '%s %s › %s' || data.json.translate === '[%s] %s › %s') {
|
||||
let subtype = 'chipmunkmod_'
|
||||
if (data.json.translate === '%s %s › %s') {
|
||||
subtype += 'name3'
|
||||
} else if (data.json.translate === '[%s] %s › %s') {
|
||||
subtype += 'chomens'
|
||||
}
|
||||
if (data.json.with && data.json.with[1] && data.json.with[2]) {
|
||||
const username = parsePlain(data.json.with[1])
|
||||
const uuid = b.findUUID(username)
|
||||
const nickname = b.findDisplayName(uuid)
|
||||
const message = parsePlain(data.json.with[2])
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype,
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username
|
||||
}
|
||||
} else {
|
||||
subtype += '_invalid'
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype,
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
message: '',
|
||||
nickname: '',
|
||||
username: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
27
chatParsers/chat_cmm_mcp.js
Executable file
27
chatParsers/chat_cmm_mcp.js
Executable file
|
@ -0,0 +1,27 @@
|
|||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
|
||||
const priority = 0
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'system' || data.type === 'legacy') {
|
||||
if (data.json.extra && data.json.extra[4] && data.json.extra[3] && data.json.extra[5] && data.json.extra[4].text === ' » ') { // ChipmunkMod format - m_c_player
|
||||
const username = parsePlain(data.json.extra[3])
|
||||
const uuid = b.findUUID(username)
|
||||
const nickname = b.findDisplayName(uuid)
|
||||
const message = parsePlain(data.json.extra[5])
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype: 'chipmunkmod_mcp',
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
31
chatParsers/chat_extras_profileless.js
Executable file
31
chatParsers/chat_extras_profileless.js
Executable file
|
@ -0,0 +1,31 @@
|
|||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
|
||||
const priority = 1
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'profileless') {
|
||||
if (data.playerChatType.translation_key === '%s') {
|
||||
const parsed = parsePlain(data.json)
|
||||
const split = parsed.split(': ')
|
||||
const chatName = split.splice(0, 1)[0]
|
||||
const chatNameSplit = chatName.split(' ')
|
||||
const nickname = chatNameSplit[chatNameSplit.length - 1]
|
||||
const username = b.findRealName(chatName)
|
||||
const uuid = b.findUUID(username)
|
||||
const message = split.join(': ')
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype: 'extras_profileless',
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
19
chatParsers/chat_player.js
Executable file
19
chatParsers/chat_player.js
Executable file
|
@ -0,0 +1,19 @@
|
|||
const priority = 2
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'player' || data.type === 'profileless') {
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype: 'generic_player',
|
||||
uuid: data.uuid,
|
||||
message: data.message,
|
||||
nickname: data.nickname,
|
||||
username: data.username
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
40
chatParsers/chat_system.js
Executable file
40
chatParsers/chat_system.js
Executable file
|
@ -0,0 +1,40 @@
|
|||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
|
||||
const priority = 2
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'system' || data.type === 'legacy') {
|
||||
let subtype = 'generic_system'
|
||||
if (data.type === 'legacy' && data.uuid) subtype += '_withuuid'
|
||||
const parsed = parsePlain(data.json)
|
||||
const split = parsed.split(': ')
|
||||
const chatName = split.splice(0, 1)[0]
|
||||
const chatNameSplit = chatName.split(' ')
|
||||
|
||||
let uuid
|
||||
let username
|
||||
let nickname
|
||||
if (data.uuid) {
|
||||
uuid = data.uuid
|
||||
username = b.findRealNameFromUUID(uuid)
|
||||
nickname = b.findDisplayName(uuid)
|
||||
} else {
|
||||
nickname = chatNameSplit[chatNameSplit.length - 1]
|
||||
username = b.findRealName(chatName)
|
||||
uuid = b.findUUID(username)
|
||||
}
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype,
|
||||
uuid,
|
||||
message: split.join(': '),
|
||||
nickname,
|
||||
username
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
33
chatParsers/chat_vanilla_legacy.js
Executable file
33
chatParsers/chat_vanilla_legacy.js
Executable file
|
@ -0,0 +1,33 @@
|
|||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
|
||||
const priority = 1
|
||||
const parse = (data, b) => {
|
||||
if (data.type === 'legacy') {
|
||||
let subtype = 'vanilla_legacy'
|
||||
if (data.type === 'legacy' && data.uuid) subtype += '_withuuid'
|
||||
if (data.json.translate === 'chat.type.text') { // Servers without Extras chat
|
||||
let message
|
||||
let username
|
||||
if (data.json.with && data.json.with.length >= 2) {
|
||||
message = parsePlain(data.json.with[1])
|
||||
username = parsePlain(data.json.with[0])
|
||||
}
|
||||
const uuid = b.findUUID(username)
|
||||
const nickname = b.findDisplayName(uuid)
|
||||
return {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype,
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
parsed: false
|
||||
}
|
||||
}
|
||||
export { priority, parse }
|
76
plugins/player.js
Executable file
76
plugins/player.js
Executable file
|
@ -0,0 +1,76 @@
|
|||
import { parse2 as parse } from '../util/chatparse_plain.js'
|
||||
import { parse as parseNBT } from '../util/parseNBT.js'
|
||||
|
||||
const load = (b) => {
|
||||
b.players = {}
|
||||
b._client.on('player_info', (data) => {
|
||||
const buffer2 = {}
|
||||
for (const player of data.data) {
|
||||
let uuid
|
||||
if (player.uuid) {
|
||||
uuid = player.uuid
|
||||
} else if (player.UUID) {
|
||||
uuid = player.UUID
|
||||
}
|
||||
let displayName
|
||||
if (player.displayName !== undefined) {
|
||||
displayName = player.displayName
|
||||
} else {
|
||||
displayName = '{"text":"[[[[ No display name ]]]]"}'
|
||||
}
|
||||
if (player.player && player.player.name !== undefined) {
|
||||
buffer2[uuid] = { realName: player.player.name, displayName: parse(parseNBT(displayName)) }
|
||||
} else if (player.name !== undefined) {
|
||||
buffer2[uuid] = { realName: player.name, displayName: parse(parseNBT(displayName)) }
|
||||
} else if (player.displayName !== undefined) {
|
||||
buffer2[uuid] = { displayName: parse(parseNBT(displayName)) }
|
||||
}
|
||||
}
|
||||
for (const uuid in buffer2) {
|
||||
if (!b.players[uuid]) b.players[uuid] = { displayName: '', realName: '' }
|
||||
let displayName = ''
|
||||
let realName = ''
|
||||
if (buffer2[uuid].displayName) {
|
||||
displayName = buffer2[uuid].displayName
|
||||
b.players[uuid].displayName = buffer2[uuid].displayName
|
||||
}
|
||||
if (buffer2[uuid].realName) {
|
||||
realName = buffer2[uuid].realName
|
||||
b.players[uuid].realName = buffer2[uuid].realName
|
||||
}
|
||||
b.emit('playerdata', uuid, displayName, realName)
|
||||
}
|
||||
})
|
||||
b.findUUID = (name) => {
|
||||
for (const i in b.players) {
|
||||
if (b.players[i].realName === name) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return '00000000-0000-0000-0000-000000000000'
|
||||
}
|
||||
b.findRealName = (name) => {
|
||||
for (const i in b.players) {
|
||||
if (b.players[i].displayName === name) {
|
||||
return b.players[i].realName
|
||||
}
|
||||
}
|
||||
return '[[[[ no name ]]]]'
|
||||
}
|
||||
b.findRealNameFromUUID = (uuid) => {
|
||||
if (b.players[uuid]) {
|
||||
return b.players[uuid].realName
|
||||
} else {
|
||||
return '[[[[ no name ]]]]'
|
||||
}
|
||||
}
|
||||
b.findDisplayName = (uuid) => {
|
||||
if (b.players[uuid]) {
|
||||
const displayName = b.players[uuid].displayName.split(' ')
|
||||
return displayName[displayName.length - 1]
|
||||
} else {
|
||||
return '[[[[ No display name ]]]]'
|
||||
}
|
||||
}
|
||||
}
|
||||
export { load }
|
209
plugins/serverChat.js
Executable file
209
plugins/serverChat.js
Executable file
|
@ -0,0 +1,209 @@
|
|||
import { default as settings } from '../settings.json' with {type: "json"}
|
||||
import { parse2 as parsePlain } from '../util/chatparse_plain.js'
|
||||
import { parse2 as parseConsole } from '../util/chatparse_console.js'
|
||||
import { parse as parse1204 } from '../util/parseNBT.js'
|
||||
import { getMessage } from '../util/lang.js'
|
||||
import { readdirSync } from "node:fs"
|
||||
const convertChatStyleItem = (item) => {
|
||||
const output = {}
|
||||
for (const i in item) {
|
||||
output[i] = item[i].value
|
||||
}
|
||||
return output
|
||||
}
|
||||
const convertChatTypeItem = (item) => {
|
||||
if (item.style) {
|
||||
return {
|
||||
translation_key: item.translation_key.value,
|
||||
parameters: item.parameters.value.value,
|
||||
style: convertChatStyleItem(item.style.value)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
translation_key: item.translation_key.value,
|
||||
parameters: item.parameters.value.value,
|
||||
style: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Level 0: highly specific parsers for certain players
|
||||
// Level 1: server chat format parsers
|
||||
// Level 2: generic parsers
|
||||
|
||||
if(false){
|
||||
for (const plugin of bpl) {
|
||||
if (!plugin.endsWith('.js')) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
const parser = require(`./chatParsers/${plugin}`)
|
||||
parsers[parser.priority].push(parser.parse)
|
||||
} catch (e) { console.log(e) }
|
||||
}
|
||||
}
|
||||
|
||||
const parsers = [[], [], []]
|
||||
const bpl = readdirSync('chatParsers')
|
||||
for (const plugin of bpl) {
|
||||
if (!plugin.endsWith('.js')) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
import(`../chatParsers/${plugin}`).then((pluginItem)=>{
|
||||
parsers[pluginItem.priority].push(pluginItem.parse)
|
||||
})
|
||||
} catch (e) { console.log(e) }
|
||||
}
|
||||
|
||||
|
||||
const load = (b) => {
|
||||
b.messageCount = 0
|
||||
b.chatDisabledUntil = 0
|
||||
b.interval.antiSpam = setInterval(() => {
|
||||
b.messageCount = 0
|
||||
}, 4000)
|
||||
b.messageTypes = []
|
||||
b._client.on('registry_data', (data) => {
|
||||
if (data.codec.value['minecraft:chat_type']) {
|
||||
b.messageTypes = data.codec.value['minecraft:chat_type']
|
||||
const nbtItems = data.codec.value['minecraft:chat_type'].value.value.value.value
|
||||
nbtItems.forEach((item, i) => {
|
||||
b.messageTypes[i] = convertChatTypeItem(item.element.value.chat.value)
|
||||
})
|
||||
}
|
||||
})
|
||||
b._client.on('profileless_chat', (data) => {
|
||||
let messageType = b.messageTypes[data.type]
|
||||
if (messageType === undefined) messageType = { translation_key: '%s', parameters: ['content'] }
|
||||
const json = { translate: messageType.translation_key, with: [] }
|
||||
messageType.parameters.forEach((item, i) => {
|
||||
if (item === 'content') {
|
||||
json.with[i] = parse1204(data.message)
|
||||
} else if (item === 'sender') {
|
||||
json.with[i] = parse1204(data.name)
|
||||
} else if (item === 'target') {
|
||||
json.with[i] = parse1204(data.target)
|
||||
}
|
||||
})
|
||||
for (const i in messageType.style) {
|
||||
json[i] = messageType.style[i]
|
||||
}
|
||||
const message = parsePlain(parse1204(data.message))
|
||||
const uuid = b.findUUID(parsePlain(parse1204(data.name)))
|
||||
const nickname = b.findDisplayName(uuid)
|
||||
const username = parsePlain(parse1204(data.name))
|
||||
b.emit('chat_unparsed', {
|
||||
json,
|
||||
type: 'profileless',
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username,
|
||||
playerChatType: messageType
|
||||
})
|
||||
})
|
||||
|
||||
b._client.on('player_chat', (data) => {
|
||||
let messageType = b.messageTypes[data.type]
|
||||
if (messageType === undefined) messageType = { translation_key: '%s', parameters: ['content'] }
|
||||
const json = { translate: messageType.translation_key, with: [] }
|
||||
messageType.parameters.forEach((item, i) => {
|
||||
if (item === 'content') {
|
||||
if (messageType.translation_key === '%s') {
|
||||
json.with[i] = parse1204(data.unsignedChatContent)
|
||||
} else {
|
||||
json.with[i] = data.plainMessage
|
||||
}
|
||||
} else if (item === 'sender') {
|
||||
json.with[i] = parse1204(data.networkName)
|
||||
} else if (item === 'target') {
|
||||
json.with[i] = parse1204(data.networkTargetName)
|
||||
}
|
||||
})
|
||||
for (const i in messageType.style) {
|
||||
json[i] = messageType.style[i]
|
||||
}
|
||||
b.emit('chat_unparsed', {
|
||||
json,
|
||||
type: 'player',
|
||||
uuid: data.senderUuid,
|
||||
message: data.plainMessage,
|
||||
nickname: parsePlain(parse1204(data.networkName)),
|
||||
username: b.findRealNameFromUUID(data.senderUuid),
|
||||
playerChatType: messageType
|
||||
})
|
||||
})
|
||||
|
||||
b._client.on('system_chat', (data) => {
|
||||
const json = parse1204(data.content)
|
||||
b.emit('chat_unparsed', {
|
||||
json,
|
||||
type: 'system',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
message: '',
|
||||
nickname: '',
|
||||
username: '',
|
||||
playerChatType: {}
|
||||
})
|
||||
})
|
||||
|
||||
b._client.on('chat', (data) => { // Legacy chat for versions <1.19
|
||||
const json = parse1204(data.message)
|
||||
let nickname
|
||||
let username
|
||||
let message
|
||||
let uuid
|
||||
if (data.uuid) uuid = data.uuid
|
||||
b.emit('chat_unparsed', {
|
||||
json,
|
||||
type: 'legacy',
|
||||
uuid,
|
||||
message,
|
||||
nickname,
|
||||
username,
|
||||
playerChatType: {}
|
||||
})
|
||||
})
|
||||
|
||||
b.on('chat_unparsed', (data) => {
|
||||
for (const lvl of parsers) {
|
||||
for (const item of lvl) {
|
||||
const output = item(data, b)
|
||||
if (output.parsed) {
|
||||
b.emit('chat', output)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
b.emit('chat', {
|
||||
parsed: true,
|
||||
json: data.json,
|
||||
type: data.type,
|
||||
subtype: 'fallback',
|
||||
uuid: '00000000-0000-0000-0000-000000000000',
|
||||
message: '',
|
||||
nickname: '',
|
||||
username: ''
|
||||
})
|
||||
})
|
||||
|
||||
b.on('chat', (data) => {
|
||||
b.messageCount++
|
||||
if (Date.now() < b.chatDisabledUntil) return
|
||||
if (b.messageCount >= 100) {
|
||||
b.info(getMessage(settings.defaultLang, 'chat.antiSpamTriggered'))
|
||||
b.chatDisabledUntil = Date.now() + 30000
|
||||
return
|
||||
}
|
||||
const msgConsole = parseConsole(data.json)
|
||||
const msgPlain = parsePlain(data.json)
|
||||
if (settings.logJSONmessages) console.log(data.json)
|
||||
if (msgPlain.endsWith('\n\n\n\n\nThe chat has been cleared')) return
|
||||
if (msgPlain.startsWith('Command set: ')) return
|
||||
b.emit('plainchat', msgPlain, data.type, data.subtype)
|
||||
b.displayChat(data.type, data.subtype, `${msgConsole}\x1b[0m`)
|
||||
})
|
||||
}
|
||||
|
||||
export { load }
|
130
util/chatparse_console.js
Executable file
130
util/chatparse_console.js
Executable file
|
@ -0,0 +1,130 @@
|
|||
import { default as settings } from '../settings.json' with {type: "json"}
|
||||
import { lang } from './mc_lang.js'
|
||||
import { default as _consoleColors } from './consolecolors.json' with {type: "json"}
|
||||
|
||||
let consoleColors
|
||||
let consoleColors24
|
||||
if (_consoleColors[settings.terminalMode]) {
|
||||
consoleColors = _consoleColors[settings.terminalMode].fourBit
|
||||
consoleColors24 = _consoleColors[settings.terminalMode].twentyFourBit
|
||||
} else {
|
||||
consoleColors = _consoleColors.none.fourBit
|
||||
consoleColors24 = _consoleColors.none.twentyFourBit
|
||||
}
|
||||
const process8bitColorChannel = (value) => {
|
||||
if (value < 65) return 0
|
||||
if (value < 115) return 1
|
||||
if (value < 155) return 2
|
||||
if (value < 195) return 3
|
||||
if (value < 235) return 4
|
||||
return 5
|
||||
}
|
||||
const hexColorParser = (color) => {
|
||||
if (!consoleColors24.enabled || consoleColors24.bit === 4) { // Hex color parsing to the 4 bit mode has not been implemented yet
|
||||
return ''
|
||||
}
|
||||
if (consoleColors24.bit === 24) {
|
||||
let out = '\x1B[0;'
|
||||
const redChannel = Number(`0x${color.slice(1, 3)}`)
|
||||
const greenChannel = Number(`0x${color.slice(3, 5)}`)
|
||||
const blueChannel = Number(`0x${color.slice(5, 7)}`)
|
||||
if (!consoleColors24.lightMode && redChannel < 64 && greenChannel < 64 && blueChannel < 64) {
|
||||
out += '48;2;220;220;220;'
|
||||
} else if (consoleColors24.lightMode && ((redChannel > 192 && greenChannel > 192 && blueChannel > 192) || greenChannel > 160)) {
|
||||
out += '48;2;0;0;0;'
|
||||
}
|
||||
return out + `38;2;${redChannel};${greenChannel};${blueChannel}m`
|
||||
} else if (consoleColors24.bit === 8) {
|
||||
let out = '\x1B[0;'
|
||||
const redChannel = Number(`0x${color.slice(1, 3)}`)
|
||||
const greenChannel = Number(`0x${color.slice(3, 5)}`)
|
||||
const blueChannel = Number(`0x${color.slice(5, 7)}`)
|
||||
if (!consoleColors24.lightMode && redChannel < 65 && greenChannel < 65 && blueChannel < 65) {
|
||||
out += '48;5;253;'
|
||||
} else if (consoleColors24.lightMode && ((redChannel > 194 && greenChannel > 194 && blueChannel > 194) || greenChannel > 154)) {
|
||||
out += '48;5;16;'
|
||||
}
|
||||
const redOut = process8bitColorChannel(redChannel)
|
||||
const greenOut = process8bitColorChannel(greenChannel)
|
||||
const blueOut = process8bitColorChannel(blueChannel)
|
||||
const colorValue = 16 + 36 * redOut + 6 * greenOut + blueOut
|
||||
return out + `38;5;${colorValue}m`
|
||||
}
|
||||
}
|
||||
|
||||
const processColor = (col, rcol) => {
|
||||
let out
|
||||
if (col === 'reset') {
|
||||
out = rcol
|
||||
} else if (col.startsWith('#')) {
|
||||
out = hexColorParser(col)
|
||||
} else {
|
||||
out = consoleColors[col]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
const parse = function (_data, l = 0, resetColor = consoleColors.reset) {
|
||||
if (l >= 4) {
|
||||
return ''
|
||||
}
|
||||
let data
|
||||
if (typeof _data === 'string') {
|
||||
data = { text: _data, color: 'reset' }
|
||||
} else if (typeof _data === 'number') {
|
||||
data = { text: _data + '', color: 'reset' }
|
||||
} else if (_data.constructor === Array) {
|
||||
data = { extra: _data, color: 'reset' }
|
||||
} else {
|
||||
data = _data
|
||||
}
|
||||
if (data['']) {
|
||||
data.text = data['']
|
||||
if (!data.color) data.color = 'reset'
|
||||
}
|
||||
|
||||
let out = ''
|
||||
if (data.color) {
|
||||
out += processColor(data.color, resetColor)
|
||||
} else {
|
||||
out += resetColor
|
||||
}
|
||||
if (data.text) {
|
||||
let _text = data.text
|
||||
if (typeof _text === 'number') {
|
||||
_text = _text.toString()
|
||||
}
|
||||
out += _text.replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
}
|
||||
if (data.translate) {
|
||||
let trans = data.translate.replaceAll('%%', '\ud900\ud801').replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
if (lang[trans] !== undefined) {
|
||||
trans = lang[trans].replace(/%%/g, '\ue123')
|
||||
}
|
||||
if (data.with) {
|
||||
data.with.forEach((item, i) => {
|
||||
const j2 = parse(item, l + 1, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
trans = trans.replace(/%s/, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
trans = trans.replaceAll(`%${+i + 1}$s`, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
})
|
||||
}
|
||||
out += trans.replaceAll('\ud900\ud801', '%').replaceAll('\ud900\ud804', '%s').replaceAll('\ud900\ud805', '$s')
|
||||
}
|
||||
if (data.extra) {
|
||||
for (const item of data.extra) {
|
||||
const parsed = parse(item, l, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
out += parsed
|
||||
}
|
||||
}
|
||||
out += resetColor
|
||||
return out
|
||||
}
|
||||
const parse2 = function (_data, l, resetColor) {
|
||||
try {
|
||||
return parse(_data)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return `\x1B[0m\x1B[38;2;255;85;85mAn error occured while parsing a message. See console for more information.\nJSON that caused the error: ${JSON.stringify(_data)}`
|
||||
}
|
||||
}
|
||||
export { parse2 }
|
96
util/chatparse_mc.js
Executable file
96
util/chatparse_mc.js
Executable file
|
@ -0,0 +1,96 @@
|
|||
import { lang } from './mc_lang.js'
|
||||
|
||||
const consoleColors = {
|
||||
dark_red: '§4',
|
||||
red: '§c',
|
||||
dark_green: '§2',
|
||||
green: '§a',
|
||||
gold: '§6',
|
||||
yellow: '§e',
|
||||
dark_blue: '§1',
|
||||
blue: '§9',
|
||||
dark_purple: '§5',
|
||||
light_purple: '§d',
|
||||
dark_aqua: '§3',
|
||||
aqua: '§b',
|
||||
black: '§0',
|
||||
gray: '§7',
|
||||
dark_gray: '§8',
|
||||
white: '§f',
|
||||
reset: '§r§f'
|
||||
}
|
||||
|
||||
const processColor = (col, rcol) => {
|
||||
let out
|
||||
if (col === 'reset') {
|
||||
out = rcol
|
||||
} else {
|
||||
out = consoleColors[col]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
const parse = function (_data, l = 0, resetColor = consoleColors.reset) {
|
||||
if (l >= 4) {
|
||||
return ''
|
||||
}
|
||||
let data
|
||||
if (typeof _data === 'string') {
|
||||
data = { text: _data, color: 'reset' }
|
||||
} else if (typeof _data === 'number') {
|
||||
data = { text: _data + '', color: 'reset' }
|
||||
} else if (_data.constructor === Array) {
|
||||
data = { extra: _data, color: 'reset' }
|
||||
} else {
|
||||
data = _data
|
||||
}
|
||||
if (data['']) {
|
||||
data.text = data['']
|
||||
if (!data.color) data.color = 'reset'
|
||||
}
|
||||
|
||||
let out = ''
|
||||
if (data.color) {
|
||||
out += processColor(data.color, resetColor)
|
||||
} else {
|
||||
out += resetColor
|
||||
}
|
||||
if (data.text) {
|
||||
let _text = data.text
|
||||
if (typeof _text === 'number') {
|
||||
_text = _text.toString()
|
||||
}
|
||||
out += _text.replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
}
|
||||
if (data.translate) {
|
||||
let trans = data.translate.replaceAll('%%', '\ud900\ud801').replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
if (lang[trans] !== undefined) {
|
||||
trans = lang[trans].replace(/%%/g, '\ue123')
|
||||
}
|
||||
if (data.with) {
|
||||
data.with.forEach((item, i) => {
|
||||
const j2 = parse(item, l + 1, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
trans = trans.replace(/%s/, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
trans = trans.replaceAll(`%${+i + 1}$s`, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
})
|
||||
}
|
||||
out += trans.replaceAll('\ud900\ud801', '%').replaceAll('\ud900\ud804', '%s').replaceAll('\ud900\ud805', '$s')
|
||||
}
|
||||
if (data.extra) {
|
||||
for (const item of data.extra) {
|
||||
const parsed = parse(item, l, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
out += parsed
|
||||
}
|
||||
}
|
||||
out += resetColor
|
||||
return out
|
||||
}
|
||||
const parse2 = function (_data, l, resetColor) {
|
||||
try {
|
||||
return parse(_data)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return `\x1B[0m\x1B[38;2;255;85;85mAn error occured while parsing a message. See console for more information.\nJSON that caused the error: ${JSON.stringify(_data)}`
|
||||
}
|
||||
}
|
||||
export { parse2 }
|
98
util/chatparse_mc_withHex.js
Executable file
98
util/chatparse_mc_withHex.js
Executable file
|
@ -0,0 +1,98 @@
|
|||
import { lang } from './mc_lang.js'
|
||||
|
||||
const consoleColors = {
|
||||
dark_red: '§4',
|
||||
red: '§c',
|
||||
dark_green: '§2',
|
||||
green: '§a',
|
||||
gold: '§6',
|
||||
yellow: '§e',
|
||||
dark_blue: '§1',
|
||||
blue: '§9',
|
||||
dark_purple: '§5',
|
||||
light_purple: '§d',
|
||||
dark_aqua: '§3',
|
||||
aqua: '§b',
|
||||
black: '§0',
|
||||
gray: '§7',
|
||||
dark_gray: '§8',
|
||||
white: '§f',
|
||||
reset: '§r§f'
|
||||
}
|
||||
|
||||
const processColor = (col, rcol) => {
|
||||
let out
|
||||
if (col === 'reset') {
|
||||
out = rcol
|
||||
} else if (col.startsWith('#')) {
|
||||
out = `§${col}`
|
||||
} else {
|
||||
out = consoleColors[col]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
const parse = function (_data, l = 0, resetColor = consoleColors.reset) {
|
||||
if (l >= 4) {
|
||||
return ''
|
||||
}
|
||||
let data
|
||||
if (typeof _data === 'string') {
|
||||
data = { text: _data, color: 'reset' }
|
||||
} else if (typeof _data === 'number') {
|
||||
data = { text: _data + '', color: 'reset' }
|
||||
} else if (_data.constructor === Array) {
|
||||
data = { extra: _data, color: 'reset' }
|
||||
} else {
|
||||
data = _data
|
||||
}
|
||||
if (data['']) {
|
||||
data.text = data['']
|
||||
if (!data.color) data.color = 'reset'
|
||||
}
|
||||
|
||||
let out = ''
|
||||
if (data.color) {
|
||||
out += processColor(data.color, resetColor)
|
||||
} else {
|
||||
out += resetColor
|
||||
}
|
||||
if (data.text) {
|
||||
let _text = data.text
|
||||
if (typeof _text === 'number') {
|
||||
_text = _text.toString()
|
||||
}
|
||||
out += _text.replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
}
|
||||
if (data.translate) {
|
||||
let trans = data.translate.replaceAll('%%', '\ud900\ud801').replaceAll('\x1b', '').replaceAll('\x0e', '')
|
||||
if (lang[trans] !== undefined) {
|
||||
trans = lang[trans].replace(/%%/g, '\ue123')
|
||||
}
|
||||
if (data.with) {
|
||||
data.with.forEach((item, i) => {
|
||||
const j2 = parse(item, l + 1, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
trans = trans.replace(/%s/, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
trans = trans.replaceAll(`%${+i + 1}$s`, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
})
|
||||
}
|
||||
out += trans.replaceAll('\ud900\ud801', '%').replaceAll('\ud900\ud804', '%s').replaceAll('\ud900\ud805', '$s')
|
||||
}
|
||||
if (data.extra) {
|
||||
for (const item of data.extra) {
|
||||
const parsed = parse(item, l, data.color ? processColor(data.color, resetColor) : resetColor)
|
||||
out += parsed
|
||||
}
|
||||
}
|
||||
out += resetColor
|
||||
return out
|
||||
}
|
||||
const parse2 = function (_data, l, resetColor) {
|
||||
try {
|
||||
return parse(_data)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return `\x1B[0m\x1B[38;2;255;85;85mAn error occured while parsing a message. See console for more information.\nJSON that caused the error: ${JSON.stringify(_data)}`
|
||||
}
|
||||
}
|
||||
export { parse2 }
|
57
util/chatparse_plain.js
Executable file
57
util/chatparse_plain.js
Executable file
|
@ -0,0 +1,57 @@
|
|||
import { lang } from './mc_lang.js'
|
||||
const parse = function (_data, l = 0) {
|
||||
if (l >= 4) {
|
||||
return ''
|
||||
}
|
||||
let data
|
||||
if (typeof _data === 'string') {
|
||||
data = { text: _data }
|
||||
} else if (typeof _data === 'number') {
|
||||
data = { text: _data + '' }
|
||||
} else if (_data.constructor === Array) {
|
||||
data = { extra: _data }
|
||||
} else {
|
||||
data = _data
|
||||
}
|
||||
let out = ''
|
||||
if (data['']) {
|
||||
data.text = data['']
|
||||
}
|
||||
if (data.text) {
|
||||
let _text = data.text
|
||||
if (typeof _text === 'number') {
|
||||
_text = _text.toString()
|
||||
}
|
||||
out += _text
|
||||
}
|
||||
if (data.translate) {
|
||||
let trans = data.translate.replace(/%%/g, '\ue123')
|
||||
if (lang[trans] !== undefined) {
|
||||
trans = lang[trans].replace(/%%/g, '\ue123')
|
||||
}
|
||||
if (data.with) {
|
||||
data.with.forEach((item, i) => {
|
||||
const j2 = parse(item, l + 1)
|
||||
trans = trans.replace(/%s/, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
trans = trans.replaceAll(`%${+i + 1}$s`, j2.replaceAll('%s', '\ud900\ud804').replaceAll('$s', '\ud900\ud805'))
|
||||
})
|
||||
}
|
||||
out += trans.replaceAll('\ud900\ud801', '%').replaceAll('\ud900\ud804', '%s').replaceAll('\ud900\ud805', '$s')
|
||||
}
|
||||
if (data.extra) {
|
||||
for (const item of data.extra) {
|
||||
const parsed = parse(item, l)
|
||||
out += parsed
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
const parse2 = function (_data, l) {
|
||||
try {
|
||||
return parse(_data)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return `An error occured while parsing a message. See console for more information. JSON that caused the error: ${JSON.stringify(_data)}`
|
||||
}
|
||||
}
|
||||
export { parse2 }
|
182
util/consolecolors.json
Executable file
182
util/consolecolors.json
Executable file
|
@ -0,0 +1,182 @@
|
|||
{
|
||||
"blackTerminal_24bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;38;2;170;0;0m",
|
||||
"red": "\u001B[0;38;2;255;85;85m",
|
||||
"dark_green": "\u001B[0;38;2;0;170;0m",
|
||||
"green": "\u001B[0;38;2;85;255;85m",
|
||||
"gold": "\u001B[0;38;2;255;170;0m",
|
||||
"yellow": "\u001B[0;38;2;255;255;85m",
|
||||
"dark_blue": "\u001B[0;38;2;0;0;170m",
|
||||
"blue": "\u001B[0;38;2;85;85;255m",
|
||||
"dark_purple": "\u001B[0;38;2;170;0;170m",
|
||||
"light_purple": "\u001B[0;38;2;255;85;255m",
|
||||
"dark_aqua": "\u001B[0;38;2;0;170;170m",
|
||||
"aqua": "\u001B[0;38;2;85;255;255m",
|
||||
"black": "\u001B[0;48;2;220;220;220;38;2;0;0;0m",
|
||||
"gray": "\u001B[0;38;2;170;170;170m",
|
||||
"dark_gray": "\u001B[0;38;2;85;85;85m",
|
||||
"white": "\u001B[0;38;2;255;255;255m",
|
||||
"reset": "\u001B[0;38;2;255;255;255m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 24,
|
||||
"lightMode": false
|
||||
}
|
||||
},
|
||||
"whiteTerminal_24bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;38;2;170;0;0m",
|
||||
"red": "\u001B[0;38;2;255;85;85m",
|
||||
"dark_green": "\u001B[0;38;2;0;170;0m",
|
||||
"green": "\u001B[0;48;2;20;20;20;38;2;85;255;85m",
|
||||
"gold": "\u001B[0;38;2;255;170;0m",
|
||||
"yellow": "\u001B[0;48;2;20;20;20;38;2;255;255;85m",
|
||||
"dark_blue": "\u001B[0;38;2;0;0;170m",
|
||||
"blue": "\u001B[0;38;2;85;85;255m",
|
||||
"dark_purple": "\u001B[0;38;2;170;0;170m",
|
||||
"light_purple": "\u001B[0;38;2;255;85;255m",
|
||||
"dark_aqua": "\u001B[0;38;2;0;170;170m",
|
||||
"aqua": "\u001B[0;48;2;20;20;20;38;2;85;255;255m",
|
||||
"black": "\u001B[0;38;2;0;0;0m",
|
||||
"gray": "\u001B[0;38;2;170;170;170m",
|
||||
"dark_gray": "\u001B[0;38;2;85;85;85m",
|
||||
"white": "\u001B[0;48;2;20;20;20;38;2;255;255;255m",
|
||||
"reset": "\u001B[0;48;2;20;20;20;38;2;255;255;255m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 24,
|
||||
"lightMode": true
|
||||
}
|
||||
},
|
||||
"blackTerminal_8bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;38;5;124m",
|
||||
"red": "\u001B[0;38;5;203m",
|
||||
"dark_green": "\u001B[0;38;5;34m",
|
||||
"green": "\u001B[0;38;5;83m",
|
||||
"gold": "\u001B[0;38;5;214m",
|
||||
"yellow": "\u001B[0;38;5;227m",
|
||||
"dark_blue": "\u001B[0;38;5;19m",
|
||||
"blue": "\u001B[0;38;5;63m",
|
||||
"dark_purple": "\u001B[0;38;5;127m",
|
||||
"light_purple": "\u001B[0;38;5;207m",
|
||||
"dark_aqua": "\u001B[0;38;5;37m",
|
||||
"aqua": "\u001B[0;38;5;87m",
|
||||
"black": "\u001B[0;48;5;253;38;5;16m",
|
||||
"gray": "\u001B[0;38;5;145m",
|
||||
"dark_gray": "\u001B[0;38;5;59m",
|
||||
"white": "\u001B[0;38;5;231m",
|
||||
"reset": "\u001B[0;38;5;231m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 8,
|
||||
"lightMode": false
|
||||
}
|
||||
},
|
||||
"whiteTerminal_8bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;38;5;124m",
|
||||
"red": "\u001B[0;38;5;203m",
|
||||
"dark_green": "\u001B[0;38;5;34m",
|
||||
"green": "\u001B[0;48;5;16;38;5;83m",
|
||||
"gold": "\u001B[0;38;5;214m",
|
||||
"yellow": "\u001B[0;48;5;16;38;5;227m",
|
||||
"dark_blue": "\u001B[0;38;5;19m",
|
||||
"blue": "\u001B[0;38;5;63m",
|
||||
"dark_purple": "\u001B[0;38;5;127m",
|
||||
"light_purple": "\u001B[0;38;5;207m",
|
||||
"dark_aqua": "\u001B[0;38;5;37m",
|
||||
"aqua": "\u001B[0;48;5;16;38;5;87m",
|
||||
"black": "\u001B[0;38;5;16m",
|
||||
"gray": "\u001B[0;38;5;145m",
|
||||
"dark_gray": "\u001B[0;38;5;59m",
|
||||
"white": "\u001B[0;48;5;16;38;5;231m",
|
||||
"reset": "\u001B[0;48;5;16;38;5;231m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 8,
|
||||
"lightMode": true
|
||||
}
|
||||
},
|
||||
"blackTerminal_4bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;31m",
|
||||
"red": "\u001B[0;1;31m",
|
||||
"dark_green": "\u001B[0;32m",
|
||||
"green": "\u001B[0;1;32m",
|
||||
"gold": "\u001B[0;33m",
|
||||
"yellow": "\u001B[0;1;33m",
|
||||
"dark_blue": "\u001B[0;34m",
|
||||
"blue": "\u001B[0;1;34m",
|
||||
"dark_purple": "\u001B[0;35m",
|
||||
"light_purple": "\u001B[0;1;35m",
|
||||
"dark_aqua": "\u001B[0;36m",
|
||||
"aqua": "\u001B[0;1;36m",
|
||||
"black": "\u001B[0;1;47;30m",
|
||||
"gray": "\u001B[0;37m",
|
||||
"dark_gray": "\u001B[0;1;30m",
|
||||
"white": "\u001B[0;1;37m",
|
||||
"reset": "\u001B[0;1;37m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 4,
|
||||
"lightMode": false
|
||||
}
|
||||
},
|
||||
"whiteTerminal_4bit":{
|
||||
"fourBit":{
|
||||
"dark_red": "\u001B[0;31m",
|
||||
"red": "\u001B[0;1;31m",
|
||||
"dark_green": "\u001B[0;32m",
|
||||
"green": "\u001B[0;40;1;32m",
|
||||
"gold": "\u001B[0;33m",
|
||||
"yellow": "\u001B[0;40;1;33m",
|
||||
"dark_blue": "\u001B[0;34m",
|
||||
"blue": "\u001B[0;1;34m",
|
||||
"dark_purple": "\u001B[0;35m",
|
||||
"light_purple": "\u001B[0;1;35m",
|
||||
"dark_aqua": "\u001B[0;36m",
|
||||
"aqua": "\u001B[0;40;1;36m",
|
||||
"black": "\u001B[0;30m",
|
||||
"gray": "\u001B[0;37m",
|
||||
"dark_gray": "\u001B[0;1;30m",
|
||||
"white": "\u001B[0;40;1;37m",
|
||||
"reset": "\u001B[0;40;1;37m"
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": true,
|
||||
"bit": 4,
|
||||
"lightMode": true
|
||||
}
|
||||
},
|
||||
"none":{
|
||||
"fourBit":{
|
||||
"dark_red": "",
|
||||
"red": "",
|
||||
"dark_green": "",
|
||||
"green": "",
|
||||
"gold": "",
|
||||
"yellow": "",
|
||||
"dark_blue": "",
|
||||
"blue": "",
|
||||
"dark_purple": "",
|
||||
"light_purple": "",
|
||||
"dark_aqua": "",
|
||||
"aqua": "",
|
||||
"black": "",
|
||||
"gray": "",
|
||||
"dark_gray": "",
|
||||
"white": "",
|
||||
"reset": ""
|
||||
},
|
||||
"twentyFourBit":{
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
70
util/lang.js
Executable file
70
util/lang.js
Executable file
|
@ -0,0 +1,70 @@
|
|||
//const fs = require('fs')
|
||||
const languages = {}
|
||||
import { default as settings } from '../settings.json' with {type: "json"}
|
||||
const fallbackLocale = settings.fallbackLocale ? settings.fallbackLocale : 'en-US'
|
||||
|
||||
const loadplug = (botno) => {
|
||||
const bpl = fs.readdirSync('lang')
|
||||
for (const plugin of bpl) {
|
||||
if (!plugin.endsWith('.json')) {
|
||||
continue
|
||||
}
|
||||
try {
|
||||
languages[plugin.split('.')[0]] = require(`../lang/${plugin}`)
|
||||
} catch (e) { console.log(e) }
|
||||
}
|
||||
}
|
||||
//loadplug()
|
||||
|
||||
const getMessage = function (l, msg, with2) {
|
||||
let message = msg.replace(/%%/g, '\ue123')
|
||||
if (languages[l] && languages[l][message] !== undefined) {
|
||||
message = languages[l][message].replace(/%%/g, '\ue123')
|
||||
} else if (languages[fallbackLocale] && languages['en-US'][message] !== undefined) {
|
||||
message = languages[fallbackLocale][message].replace(/%%/g, '\ue123')
|
||||
}fs
|
||||
if (with2) {
|
||||
with2.forEach((withItem, i) => {
|
||||
message = message.replace(/%s/, withItem.replace(/%s/g, '\ue124').replace(/\$s/g, '\ue125'))
|
||||
message = message.replaceAll(`%${+i + 1}$s`, withItem.replace(/%s/g, '\ue124').replace(/\$s/g, '\ue125'))
|
||||
})
|
||||
}
|
||||
return message.replace(/\ue123/g, '%').replace(/\ue124/g, '%s').replace(/\ue125/g, '$s')
|
||||
}
|
||||
|
||||
const languages_keys = Object.keys(languages)
|
||||
const formatTime = function (time, language) {
|
||||
let finalString = ''
|
||||
const seconds = Math.floor(time / 1000) % 60
|
||||
const minutes = Math.floor(time / 60000) % 60
|
||||
const hours = Math.floor(time / 3600000) % 24
|
||||
const days = Math.floor(time / 86400000) % 7
|
||||
const weeks = Math.floor(time / 604800000)
|
||||
if (weeks !== 0) {
|
||||
finalString += weeks
|
||||
finalString += `${weeks === 1 ? getMessage(language, 'time.week') : getMessage(language, 'time.weekPlural')}`
|
||||
}
|
||||
if (days !== 0) {
|
||||
finalString += days
|
||||
finalString += `${days === 1 ? getMessage(language, 'time.day') : getMessage(language, 'time.dayPlural')}`
|
||||
}
|
||||
if (hours !== 0) {
|
||||
finalString += hours
|
||||
finalString += `${hours === 1 ? getMessage(language, 'time.hour') : getMessage(language, 'time.hourPlural')}`
|
||||
}
|
||||
if (minutes !== 0) {
|
||||
finalString += minutes
|
||||
finalString += `${minutes === 1 ? getMessage(language, 'time.minute') : getMessage(language, 'time.minutePlural')}`
|
||||
}
|
||||
if (seconds !== 0) {
|
||||
finalString += seconds
|
||||
finalString += `${seconds === 1 ? getMessage(language, 'time.second') : getMessage(language, 'time.secondPlural')}`
|
||||
}
|
||||
return finalString
|
||||
}
|
||||
|
||||
export {
|
||||
languages_keys as languages,
|
||||
formatTime,
|
||||
getMessage
|
||||
}
|
7
util/mc_lang.js
Executable file
7
util/mc_lang.js
Executable file
|
@ -0,0 +1,7 @@
|
|||
import MinecraftData from 'minecraft-data'
|
||||
const _lang = MinecraftData('1.20.6').language
|
||||
const lang = Object.create(null) // Without constructor function
|
||||
for (const i in _lang) {
|
||||
lang[i] = _lang[i]
|
||||
}
|
||||
export { lang }
|
11
util/parseNBT.js
Executable file
11
util/parseNBT.js
Executable file
|
@ -0,0 +1,11 @@
|
|||
import { processNbtMessage } from 'prismarine-chat'
|
||||
const parse = function (data) {
|
||||
if (typeof data.type === 'string') {
|
||||
return JSON.parse(processNbtMessage(data))
|
||||
} else if (typeof data === 'string') {
|
||||
return JSON.parse(data)
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
||||
export { parse }
|
Loading…
Reference in a new issue