From 3fce21922cdc1d4bf6266b521910cc1b73939adb Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 28 Feb 2025 23:12:22 +0200 Subject: [PATCH] use rconts --- advancementAPI.ts | 112 +++++++++------------- bun.lockb | Bin 18588 -> 52292 bytes index.ts | 19 +++- package.json | 2 + rcon.ts | 235 ---------------------------------------------- 5 files changed, 64 insertions(+), 304 deletions(-) delete mode 100644 rcon.ts diff --git a/advancementAPI.ts b/advancementAPI.ts index 2e9a666..7c9f8be 100644 --- a/advancementAPI.ts +++ b/advancementAPI.ts @@ -1,85 +1,65 @@ -import {Rcon, PacketType} from "./rcon"; - +import { Rcon } from "rconts"; +import { EventEmitter } from "tseep" import config from "./config.json" assert { type: "json" }; +export const apiEvents = new EventEmitter<{ + state: (currentUser: string, amount: number, done: number) => void +}>(); -const advancements = new Map(); -let advancementsRequired = 0; +let lastUpdated = 0; let authenicated = false; +const advancements = new Map(); -const advancementRegex = /^([^ ]*) has (\d*) \[Advancements\]$/gm; -const playerRegex = /There are \d* whitelisted player\(s\): /gm; -const noAdvancements = - /^Can't get value of bac_advancements for ([^;]*); none is set$/gm; - -const client = new Rcon( - config.rcon.host, - config.rcon.port, - config.rcon.password +const client = new Rcon({ + host: config.rcon.host, + port: config.rcon.port, + password: config.rcon.password +} ); -let rconReconnectTimeout: Timer | null | undefined; -client.on("connect", () => { +client.on("connected", () => { console.log("RCON connected."); }); -client.on("auth", () => { - console.log("RCON authenicated."); +client.on("authenicated", () => { authenicated = true; }); -client.on("end", () => { - console.log("RCON ended. Reconnecting in 2000ms.") - if(rconReconnectTimeout) { - clearTimeout(rconReconnectTimeout); - } - rconReconnectTimeout = setTimeout(() => { - client.connect() - }, 2000) -}) -client.on("response", (a: string) => { - if (playerRegex.test(a)) { - const whitelistedPlayers = a.replace(playerRegex, "").split(", "); - advancementsRequired = whitelistedPlayers.length; - - for (let i = 0; i < whitelistedPlayers.length; i++) { - setTimeout(() => { - const name = whitelistedPlayers[i]; - client.send(`scoreboard players get ${name} bac_advancements`, PacketType.COMMAND); - }, i * 20); - } - } - - if (advancementRegex.test(a)) { - advancements.set( - a.replace(advancementRegex, "$1"), - +a.replace(advancementRegex, "$2") - ); - } - if (noAdvancements.test(a)) { - advancements.set(a.replace(noAdvancements, "$1"), 0); - } - if (advancements.size == advancementsRequired) { - client.emit("done"); - } -}); export function getAdvancements(): Promise> { + if (Date.now() - lastUpdated < 60000) { + return Promise.resolve(advancements); + } + + lastUpdated = Date.now(); + advancements.clear(); return new Promise(async (res, rej) => { if (!authenicated) { - await new Promise((res2, rej2) => { - client.once("auth", () => { - res2(""); - }); - client.once("error", () => { - rej2(); - }); - }); + rej("Not authenicated."); + return; } - advancementsRequired = 0; - advancements.clear(); - client.send("whitelist list", PacketType.COMMAND); - client.once("done", () => { - res(advancements); - }); + + const list = await client.exec("whitelist list"); + const whitelistedPlayers = list.replace(/There are \d* whitelisted player\(s\): /gm, "").split(", "); + let amount = 0; + apiEvents.emit("state", "-", whitelistedPlayers.length, amount) + + for await(const name of whitelistedPlayers) { + const data = await client.exec(`scoreboard players get ${name} bac_advancements`); + const advancementRegex = /^([^ ]*) has (\d*) \[Advancements\]$/gm; + const noAdvancements = + /^Can't get value of bac_advancements for ([^;]*); none is set$/gm; + + if (advancementRegex.test(data)) { + advancements.set( + data.replace(advancementRegex, "$1"), + +data.replace(advancementRegex, "$2") + ); + } else if (noAdvancements.test(data)) { + advancements.set(data.replace(noAdvancements, "$1"), 0); + } + amount++; + apiEvents.emit("state", name, whitelistedPlayers.length, amount) + } + res(advancements); }); } diff --git a/bun.lockb b/bun.lockb index 07d1635efd048484bf70c7a75aaa0f2e044950ca..d83f563b5a49efa259bfb26c1cb4dec352cf444c 100755 GIT binary patch literal 52292 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 UZpZBlOxUncaKAwOzwh7w2ma*LRR910 delta 3220 zcmcguYiv}<6`mQd@!qx9um+P|d+}q9Uw{|CcO9GS2Prr#aj9gu#=)))b{ng#A=qsk z8nCHKgv~44lPHkd*f>amrco0aO06mhsqzD?;FP{X)kjn$szfDH+aKi7g!Vgk_d+U+ z#GiInXTCWzXV09+oip?HvAEHQe8yi`mvVD<_s<{S-eNT@KlVC09oJO7_PJlu?Tz<`1!!?JGwgi1|JimHZ}pp;hur+UHyIAd$vM( z8|D{4usF89VV)3~;H!bWp|w#FcsB6cy_z%n+Ow z4tm{IHgz!}DDC69Lo1f=@80?Ytx@*U!&@afv=I3XUwS{%820d*seMtr(jZKD~i4I{*BqHFly zyEa;vqigZ;LR4c?Qp6F6uLBpP%UZP>h$qKVUHcIx8nJ96S7Jc>XG~bpm6U+C1CedT znqoV&OW;^ik}Er)xe}r_V$BgyEeSM|tE;gDn#t9*Utui}l}rq%6g#cU)797PGy-_u zPBVb3c5>wFDqf>?fO?Ha^7Z(`2zViAk@uEQLSW7KYrzQAaUIogbT ze#0ESiBYRL@*wxk<|vGjDW_e+s3GczBcLTBQN`dA$OY4@lWAm`uAWS$nPru9L9?q1 z$>hkcqy?I75c%Ys3Vi$gv73#Nd01h#FC(lF4}f^xZLZFZ2oQf-0*MycF}XQ#&|I2h z!8B@F?2q?@>_i!e4J(gf1&|vf8-kRX>p>vP*PH(^2k7n>DR)KwAa8@O)KrTv@^^vu?RsjP5P99`&nXlg`InySDl1v!{z2Zv8vjSYQQ+BaLcdHjC%Oftq2qBJ?aX5mVK&l0F;B zqaPnwRFC>7_+aCnF)x>TAfKfw(1RdUVNnBG1=2yapgItrJ1!zgR5H9==Oe;L=PMvS z*(IP-5N;mf0paE`PcWAcR56hcIC4*@EwIq z*z`07$R@K1T-(?H%MJby?%><9EXOsD*Eu2_DN8TcJ=V!GtY*)LfBCKzxa9t{W`hoGJ ziu12s-}F-MtBH^(@#BXCC>k1dt6D`D#@$})Y2&#V(f+jm)t8klgBX|HHbt|L3oE)Y z=Jr}oqJf|O@wZps_qCY%f_`KuGZ?rTp+)*WX^OWQo7RR5Yz``Zn z5s#>sF((vE{riczOl>cP(+Gd{JW8H$s}1u=A78IDI~^K#tN#j^6_2~!olA$?YrW(m zD_aleom*98ZV4Hdzc?E0Ccvjs860 zuC$(ZhyI$`cBUfh_#FZ3@waRD^Zm24X}&uvA8WMYq}yw~7B{Xv)3mzh-OwF@atC!l z;P&(K)Y+%kZ0xPPBe2s!&z@ZGwH}b)z46V<2U7m#HKv1)F*G8O`_-CXe3wo*na@L@=f6Y diff --git a/index.ts b/index.ts index 921df02..83118bf 100644 --- a/index.ts +++ b/index.ts @@ -1,10 +1,13 @@ -import { getAdvancements } from "./advancementAPI"; -import { Client, Events, GatewayIntentBits } from "discord.js"; +import { apiEvents, getAdvancements } from "./advancementAPI"; +import { Client, Events, GatewayIntentBits, Message } from "discord.js"; import { createCanvas, GlobalFonts } from "@napi-rs/canvas"; import config from "./config.json" assert { type: "json" }; GlobalFonts.registerFromPath("minecraft.otf", "Minecraft"); +let lastUpdate = Date.now(); +let waiting: Message|undefined; + const client = new Client({ intents: [ GatewayIntentBits.Guilds, @@ -47,15 +50,25 @@ async function makeCanvas(): Promise { return canvas.toBuffer("image/png"); } +apiEvents.on("state", (currentUser, amount, done) => { + if (Date.now() - lastUpdate > 500) { + lastUpdate = Date.now(); + waiting?.edit(`Please wait.. (D/A: ${done}/${amount}, ${currentUser})`) + } +}) + client.once(Events.ClientReady, async (readyClient) => { console.log(`DISCORD connected. ${readyClient.user.tag}`); }); client.on("messageCreate", async (message) => { if (message.content == ".lb") { - message.channel.send({ + waiting = await message.channel.send("Please wait...") + waiting.edit({ + content: "", files: [await makeCanvas()], }); + } }); diff --git a/package.json b/package.json index 57e440e..1cce744 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "@napi-rs/canvas": "^0.1.53", "bufferutil": "^4.0.8", "discord.js": "^14.15.3", + "node-gyp": "^11.1.0", + "rconts": "git+https://git.sad.ovh/sophie/rconts.git#8f6d5a48330a35f7e4e288b5a3f0104e249aa575", "ts-rcon": "^1.2.1", "utf-8-validate": "^6.0.4", "zlib-sync": "^0.1.9" diff --git a/rcon.ts b/rcon.ts deleted file mode 100644 index e30dfb3..0000000 --- a/rcon.ts +++ /dev/null @@ -1,235 +0,0 @@ -import EventEmitter from "events"; -import * as net from "net"; -import * as dgram from "dgram"; -import { Buffer } from "buffer"; -import type TypedEmitter from "typed-emitter"; - -type Events = { - error: (error: Error) => void; - auth: () => void; - response: (response: string) => void; - connect: () => void; - end: () => void; - done: () => void; -}; - -export const PacketType = { - COMMAND: 0x02, - AUTH: 0x03, - RESPONSE_VALUE: 0x00, - RESPONSE_AUTH: 0x02, -}; - -interface Options { - tcp?: boolean; - challenge?: boolean; - id?: number; -} -export class Rcon extends (EventEmitter as new () => TypedEmitter) { - private host: string; - private port: number; - private password: string; - private rconId: number; - private hasAuthed: boolean; - private outstandingData: Uint8Array | null; - private tcp: boolean; - private challenge: boolean; - private _challengeToken: string; - private _tcpSocket!: net.Socket; - private _udpSocket!: dgram.Socket; - - constructor(host: string, port: number, password: string, options?: Options) { - super(); - options = options || {}; - this.host = host; - this.port = port; - this.password = password; - this.rconId = options.id || 0x0012d4a6; // This is arbitrary in most cases - this.hasAuthed = false; - this.outstandingData = null; - this.tcp = options.tcp ? options.tcp : true; - this.challenge = options.challenge ? options.challenge : true; - this._challengeToken = ""; - } - - public send = (data: string, cmd?: number, id?: number): void => { - let sendBuf: Buffer; - if (this.tcp) { - cmd = cmd || PacketType.COMMAND; - id = id || this.rconId; - - const length = Buffer.byteLength(data); - sendBuf = Buffer.alloc(length + 14); - sendBuf.writeInt32LE(length + 10, 0); - sendBuf.writeInt32LE(id, 4); - sendBuf.writeInt32LE(cmd, 8); - sendBuf.write(data, 12); - sendBuf.writeInt16LE(0, length + 12); - } else { - if (this.challenge && !this._challengeToken) { - this.emit("error", new Error("Not authenticated")); - return; - } - let str = "rcon "; - if (this._challengeToken) str += this._challengeToken + " "; - if (this.password) str += this.password + " "; - str += data + "\n"; - sendBuf = Buffer.alloc(4 + Buffer.byteLength(str)); - sendBuf.writeInt32LE(-1, 0); - sendBuf.write(str, 4); - } - this._sendSocket(sendBuf); - }; - - private _sendSocket = (buf: Buffer) => { - if (this._tcpSocket) { - this._tcpSocket.write(buf.toString("binary"), "binary"); - } else if (this._udpSocket) { - this._udpSocket.send(buf, 0, buf.length, this.port, this.host); - } - }; - - public connect = (): void => { - if (this.tcp) { - this._tcpSocket = net.createConnection(this.port, this.host); - this._tcpSocket.on("data", (data) => { - this._tcpSocketOnData(data); - }); - this._tcpSocket.on("connect", () => { - this.socketOnConnect(); - }); - this._tcpSocket.on("error", (err) => { - //this.emit("error", err); - this.socketOnEnd() - }); - this._tcpSocket.on("end", () => { - this.socketOnEnd(); - }); - } else { - this._udpSocket = dgram.createSocket("udp4"); - this._udpSocket - .on("message", (data) => { - this._udpSocketOnData(data); - }) - .on("listening", () => { - this.socketOnConnect(); - }) - .on("error", (err) => { - this.emit("error", err); - }) - .on("close", () => { - this.socketOnEnd(); - }); - this._udpSocket.bind(0); - } - }; - - public disconnect = (): void => { - if (this._tcpSocket) this._tcpSocket.end(); - if (this._udpSocket) this._udpSocket.close(); - }; - - public setTimeout = (timeout: number, callback: () => void): void => { - if (!this._tcpSocket) return; - this._tcpSocket.setTimeout(timeout, () => { - this._tcpSocket.end(); - if (callback) callback(); - }); - }; - - private _udpSocketOnData = (data: Buffer) => { - const a = data.readUInt32LE(0); - if (a === 0xffffffff) { - const str = data.toString("utf-8", 4); - const tokens = str.split(" "); - if ( - tokens.length === 3 && - tokens[0] === "challenge" && - tokens[1] === "rcon" - ) { - this._challengeToken = tokens[2] - .substring(0, tokens[2].length - 1) - .trim(); - this.hasAuthed = true; - this.emit("auth"); - } else { - this.emit("response", str.substring(1, str.length - 2)); - } - } else { - this.emit("error", new Error("Received malformed packet")); - } - }; - - private _tcpSocketOnData = (data: Buffer) => { - if (this.outstandingData != null) { - data = Buffer.concat( - [this.outstandingData, data], - this.outstandingData.length + data.length - ); - this.outstandingData = null; - } - - while (data.length) { - const len = data.readInt32LE(0); - if (!len) return; - - const id = data.readInt32LE(4); - const type = data.readInt32LE(8); - - if (len >= 10 && data.length >= len + 4) { - if (id === this.rconId) { - if (!this.hasAuthed && type === PacketType.RESPONSE_AUTH) { - this.hasAuthed = true; - this.emit("auth"); - } else if (type === PacketType.RESPONSE_VALUE) { - // Read just the body of the packet (truncate the last null byte) - // See https://developer.valvesoftware.com/wiki/Source_RCON_Protocol for details - let str = data.toString("utf8", 12, 12 + len - 10); - - if (str.charAt(str.length - 1) === "\n") { - // Emit the response without the newline. - str = str.substring(0, str.length - 1); - } - - this.emit("response", str); - } - } else { - this.emit("error", new Error("Authentication failed")); - } - - data = data.slice(12 + len - 8); - } else { - // Keep a reference to the chunk if it doesn't represent a full packet - this.outstandingData = data; - break; - } - } - }; - - public socketOnConnect = (): void => { - this.emit("connect"); - - if (this.tcp) { - this.send(this.password, PacketType.AUTH); - } else if (this.challenge) { - const str = "challenge rcon\n"; - const sendBuf = Buffer.alloc(str.length + 4); - sendBuf.writeInt32LE(-1, 0); - sendBuf.write(str, 4); - this._sendSocket(sendBuf); - } else { - const sendBuf = Buffer.alloc(5); - sendBuf.writeInt32LE(-1, 0); - sendBuf.writeUInt8(0, 4); - this._sendSocket(sendBuf); - - this.hasAuthed = true; - this.emit("auth"); - } - }; - - public socketOnEnd = (): void => { - this.emit("end"); - this.hasAuthed = false; - }; -}