diff --git a/api/bun.lockb b/api/bun.lockb
index c329b0f..10b8a5b 100755
Binary files a/api/bun.lockb and b/api/bun.lockb differ
diff --git a/api/index.ts b/api/index.ts
index a94bcc6..ee61a2a 100644
--- a/api/index.ts
+++ b/api/index.ts
@@ -12,7 +12,7 @@
 
 import express, { type Request, type Response, type NextFunction } from 'express';
 import { InstantVector, PrometheusDriver, ResponseType, SampleValue } from 'prometheus-query';
-import { PacketType, Rcon } from "./rcon";
+import { Rcon } from 'rconts';
 
 if(!process.env.prometheusHost) {
     throw new Error("missing prometheus host")
@@ -28,36 +28,19 @@ if(process.env.prometheusUsername || process.env.prometheusPassword) {
 if(!process.env.rconHost || !process.env.rconPassword) {
     throw new Error("missing rcon host or rcon password")
 }
-const rcon = new Rcon(process.env.rconHost.split(":")[0], +process.env.rconHost.split(":")[1], process.env.rconPassword);
-let rconReconnectTimeout: Timer | null | undefined;
-let whitelistedPlayers: string[] = [];
+
+const rcon = new Rcon({
+    host: process.env.rconHost,
+    password: process.env.rconPassword
+});
+
 let lastRequested = 0;
+let whitelistedPlayers: string[] = [];
 
-const playerRegex = /There are \d* whitelisted player\(s\): /gm;
-
-rcon.on("connect", () => {
+rcon.on("connected", () => {
     console.log("RCON connected.");
 });
 
-rcon.on("auth", () => {
-    console.log("RCON authenicated.");
-});
-
-rcon.on("response", (a: string) => {
-    if (playerRegex.test(a)) {
-        whitelistedPlayers = a.replace(playerRegex, "").split(", ");
-    }
-})
-
-rcon.on("end", () => {
-    console.log("RCON ended. Reconnecting in 2000ms.")
-    if(rconReconnectTimeout) {
-        clearTimeout(rconReconnectTimeout);
-    }
-    rconReconnectTimeout = setTimeout(() => {
-        rcon.connect()
-    }, 2000)
-})
 const app = express();
 
 //@ts-expect-error
@@ -103,13 +86,12 @@ app.get("/api/uptime", async (req, res) => {
 app.get("/api/whitelist", async (req, res) => {
     if ( Date.now() - lastRequested > 60000) {
         lastRequested =  Date.now();
-        rcon.send("whitelist list", PacketType.COMMAND);
-        rcon.once("response", () => {
-            res.json(whitelistedPlayers);
-        });
-    } else {
-        res.json(whitelistedPlayers);
+
+        const list = await rcon.exec("whitelist list");
+        whitelistedPlayers = list.replace(/There are \d* whitelisted player\(s\): /gm, "").split(", ");
     }
+    res.json(whitelistedPlayers);
+
 })
 app.listen(port, host, () => {
     rcon.connect() 
diff --git a/api/package.json b/api/package.json
index 2912ac0..6f44ca8 100644
--- a/api/package.json
+++ b/api/package.json
@@ -12,6 +12,7 @@
     "@types/express": "^5.0.0",
     "express": "^4.21.2",
     "prometheus-query": "^3.4.1",
+    "rconts": "git+https://git.sad.ovh/sophie/rconts.git#8f6d5a48330a35f7e4e288b5a3f0104e249aa575",
     "typed-emitter": "^2.1.0"
   }
 }
\ No newline at end of file
diff --git a/api/rcon.ts b/api/rcon.ts
deleted file mode 100644
index bbe39a0..0000000
--- a/api/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<Events>) {
-  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;
-  };
-}
\ No newline at end of file