Minecraft-STC-Modpack/showdown/server/roomlogs.js
2023-08-14 21:45:09 -04:00

285 lines
9.0 KiB
JavaScript

"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var roomlogs_exports = {};
__export(roomlogs_exports, {
Roomlog: () => Roomlog,
Roomlogs: () => Roomlogs
});
module.exports = __toCommonJS(roomlogs_exports);
var import_lib = require("../lib");
/**
* Roomlogs
* Pokemon Showdown - http://pokemonshowdown.com/
*
* This handles data storage for rooms.
*
* @license MIT
*/
class Roomlog {
constructor(room, options = {}) {
this.visibleMessageCount = 0;
this.roomid = room.roomid;
this.isMultichannel = !!options.isMultichannel;
this.noAutoTruncate = !!options.noAutoTruncate;
this.noLogTimes = !!options.noLogTimes;
this.log = [];
this.broadcastBuffer = [];
this.roomlogStream = void 0;
this.roomlogFilename = "";
this.numTruncatedLines = 0;
void this.setupRoomlogStream(true);
}
getScrollback(channel = 0) {
let log = this.log;
if (!this.noLogTimes)
log = [`|:|${~~(Date.now() / 1e3)}`].concat(log);
if (!this.isMultichannel) {
return log.join("\n") + "\n";
}
log = [];
for (let i = 0; i < this.log.length; ++i) {
const line = this.log[i];
const split = /\|split\|p(\d)/g.exec(line);
if (split) {
const canSeePrivileged = channel === Number(split[1]) || channel === -1;
const ownLine = this.log[i + (canSeePrivileged ? 1 : 2)];
if (ownLine)
log.push(ownLine);
i += 2;
} else {
log.push(line);
}
}
return log.join("\n") + "\n";
}
async setupRoomlogStream(sync = false) {
if (this.roomlogStream === null)
return;
if (!Config.logchat) {
this.roomlogStream = null;
return;
}
if (this.roomid.startsWith("battle-")) {
this.roomlogStream = null;
return;
}
const date = new Date();
const dateString = Chat.toTimestamp(date).split(" ")[0];
const monthString = dateString.split("-", 2).join("-");
const basepath = `logs/chat/${this.roomid}/`;
const relpath = `${monthString}/${dateString}.txt`;
if (relpath === this.roomlogFilename)
return;
if (sync) {
(0, import_lib.FS)(basepath + monthString).mkdirpSync();
} else {
await (0, import_lib.FS)(basepath + monthString).mkdirp();
if (this.roomlogStream === null)
return;
}
this.roomlogFilename = relpath;
if (this.roomlogStream)
void this.roomlogStream.writeEnd();
this.roomlogStream = (0, import_lib.FS)(basepath + relpath).createAppendStream();
const link0 = basepath + "today.txt.0";
(0, import_lib.FS)(link0).unlinkIfExistsSync();
try {
(0, import_lib.FS)(link0).symlinkToSync(relpath);
(0, import_lib.FS)(link0).renameSync(basepath + "today.txt");
} catch {
}
if (!Roomlogs.rollLogTimer)
void Roomlogs.rollLogs();
}
add(message) {
this.roomlog(message);
if (["|c|", "|c:|", "|raw|", "|html|", "|uhtml"].some((k) => message.startsWith(k))) {
this.visibleMessageCount++;
}
message = this.withTimestamp(message);
this.log.push(message);
this.broadcastBuffer.push(message);
return this;
}
withTimestamp(message) {
if (!this.noLogTimes && message.startsWith("|c|")) {
return `|c:|${Math.trunc(Date.now() / 1e3)}|${message.slice(3)}`;
} else {
return message;
}
}
hasUsername(username) {
const userid = toID(username);
for (const line of this.log) {
if (line.startsWith("|c:|")) {
const curUserid = toID(line.split("|", 4)[3]);
if (curUserid === userid)
return true;
} else if (line.startsWith("|c|")) {
const curUserid = toID(line.split("|", 3)[2]);
if (curUserid === userid)
return true;
}
}
return false;
}
clearText(userids, lineCount = 0) {
const cleared = [];
const clearAll = lineCount === 0;
this.log = this.log.reverse().filter((line) => {
const parsed = this.parseChatLine(line);
if (parsed) {
const userid = toID(parsed.user);
if (userids.includes(userid)) {
if (!cleared.includes(userid))
cleared.push(userid);
if (this.roomid.startsWith("battle-"))
return true;
if (clearAll)
return false;
if (lineCount > 0) {
lineCount--;
return false;
}
return true;
}
}
return true;
}).reverse();
return cleared;
}
uhtmlchange(name, message) {
const originalStart = "|uhtml|" + name + "|";
const fullMessage = originalStart + message;
for (const [i, line] of this.log.entries()) {
if (line.startsWith(originalStart)) {
this.log[i] = fullMessage;
break;
}
}
this.broadcastBuffer.push(fullMessage);
}
attributedUhtmlchange(user, name, message) {
const start = `/uhtmlchange ${name},`;
const fullMessage = this.withTimestamp(`|c|${user.getIdentity()}|${start}${message}`);
for (const [i, line] of this.log.entries()) {
if (this.parseChatLine(line)?.message.startsWith(start)) {
this.log[i] = fullMessage;
break;
}
}
this.broadcastBuffer.push(fullMessage);
}
parseChatLine(line) {
const messageStart = !this.noLogTimes ? "|c:|" : "|c|";
const section = !this.noLogTimes ? 4 : 3;
if (line.startsWith(messageStart)) {
const parts = import_lib.Utils.splitFirst(line, "|", section);
return { user: parts[section - 1], message: parts[section] };
}
}
roomlog(message, date = new Date()) {
if (!this.roomlogStream)
return;
const timestamp = Chat.toTimestamp(date).split(" ")[1] + " ";
message = message.replace(/<img[^>]* src="data:image\/png;base64,[^">]+"[^>]*>/g, "");
void this.roomlogStream.write(timestamp + message + "\n");
}
modlog(entry, overrideID) {
void Rooms.Modlog.write(this.roomid, entry, overrideID);
}
async rename(newID) {
const roomlogPath = `logs/chat`;
const roomlogStreamExisted = this.roomlogStream !== null;
await this.destroy();
const [roomlogExists, newRoomlogExists] = await Promise.all([
(0, import_lib.FS)(roomlogPath + `/${this.roomid}`).exists(),
(0, import_lib.FS)(roomlogPath + `/${newID}`).exists()
]);
if (roomlogExists && !newRoomlogExists) {
await (0, import_lib.FS)(roomlogPath + `/${this.roomid}`).rename(roomlogPath + `/${newID}`);
}
await Rooms.Modlog.rename(this.roomid, newID);
this.roomid = newID;
Roomlogs.roomlogs.set(newID, this);
if (roomlogStreamExisted) {
this.roomlogStream = void 0;
this.roomlogFilename = "";
await this.setupRoomlogStream(true);
}
return true;
}
static async rollLogs() {
if (Roomlogs.rollLogTimer === true)
return;
if (Roomlogs.rollLogTimer) {
clearTimeout(Roomlogs.rollLogTimer);
}
Roomlogs.rollLogTimer = true;
for (const log of Roomlogs.roomlogs.values()) {
await log.setupRoomlogStream();
}
const time = Date.now();
const nextMidnight = new Date(time + 24 * 60 * 60 * 1e3);
nextMidnight.setHours(0, 0, 1);
Roomlogs.rollLogTimer = setTimeout(() => void Roomlog.rollLogs(), nextMidnight.getTime() - time);
}
truncate() {
if (this.noAutoTruncate)
return;
if (this.log.length > 100) {
const truncationLength = this.log.length - 100;
this.log.splice(0, truncationLength);
this.numTruncatedLines += truncationLength;
}
}
/**
* Returns the total number of lines in the roomlog, including truncated lines.
*/
getLineCount(onlyVisible = true) {
return (onlyVisible ? this.visibleMessageCount : this.log.length) + this.numTruncatedLines;
}
destroy() {
const promises = [];
if (this.roomlogStream) {
promises.push(this.roomlogStream.writeEnd());
this.roomlogStream = null;
}
Roomlogs.roomlogs.delete(this.roomid);
return Promise.all(promises);
}
}
const roomlogs = /* @__PURE__ */ new Map();
function createRoomlog(room, options = {}) {
let roomlog = Roomlogs.roomlogs.get(room.roomid);
if (roomlog)
throw new Error(`Roomlog ${room.roomid} already exists`);
roomlog = new Roomlog(room, options);
Roomlogs.roomlogs.set(room.roomid, roomlog);
return roomlog;
}
const Roomlogs = {
create: createRoomlog,
Roomlog,
roomlogs,
rollLogs: Roomlog.rollLogs,
rollLogTimer: null
};
//# sourceMappingURL=roomlogs.js.map