Add rate limits for every message, fix lobby regex, implement tags into database, reword comments, add channel flags
This commit is contained in:
parent
bb0516b367
commit
71960104eb
|
@ -1,7 +1,6 @@
|
||||||
forceLoad:
|
forceLoad:
|
||||||
- lobby
|
- lobby
|
||||||
- test/awkward
|
- test/awkward
|
||||||
|
|
||||||
lobbySettings:
|
lobbySettings:
|
||||||
lobby: true
|
lobby: true
|
||||||
chat: true
|
chat: true
|
||||||
|
@ -9,17 +8,18 @@ lobbySettings:
|
||||||
visible: true
|
visible: true
|
||||||
color: "#73b3cc"
|
color: "#73b3cc"
|
||||||
color2: "#273546"
|
color2: "#273546"
|
||||||
|
|
||||||
defaultSettings:
|
defaultSettings:
|
||||||
chat: true
|
chat: true
|
||||||
crownsolo: false
|
crownsolo: false
|
||||||
color: "#3b5054"
|
color: "#3b5054"
|
||||||
color2: "#001014"
|
color2: "#001014"
|
||||||
visible: true
|
visible: true
|
||||||
|
|
||||||
lobbyRegexes:
|
lobbyRegexes:
|
||||||
- "^lobby[1-9]?[1-9]?$"
|
- ^lobby[0-9][0-9]$
|
||||||
- "^test/.+$"
|
- ^lobby[0-9]$
|
||||||
|
- ^lobby$
|
||||||
lobbyBackdoor: "lolwutsecretlobbybackdoor"
|
- ^test/.+$
|
||||||
fullChannel: "test/awkward"
|
lobbyBackdoor: lolwutsecretlobbybackdoor
|
||||||
|
fullChannel: test/awkward
|
||||||
|
sendLimit: false
|
||||||
|
sendTags: false
|
||||||
|
|
|
@ -3,28 +3,73 @@ user:
|
||||||
a: 1500
|
a: 1500
|
||||||
m: 50
|
m: 50
|
||||||
ch: 1000
|
ch: 1000
|
||||||
kickban: 250
|
kickban: 125
|
||||||
|
t: 7.8125
|
||||||
|
+ls: 16.666666666666668
|
||||||
|
-ls: 16.666666666666668
|
||||||
|
chown: 2000
|
||||||
|
hi: 50
|
||||||
|
bye: 50
|
||||||
|
devices: 50
|
||||||
|
admin_message: 50
|
||||||
|
admin message: 50
|
||||||
chains:
|
chains:
|
||||||
userset:
|
userset:
|
||||||
interval: 1800000
|
interval: 1800000
|
||||||
num: 1000
|
num: 1000
|
||||||
|
chset:
|
||||||
|
interval: 1800000
|
||||||
|
num: 1024
|
||||||
|
n:
|
||||||
|
interval: 1000
|
||||||
|
num: 512
|
||||||
crown:
|
crown:
|
||||||
normal:
|
normal:
|
||||||
a: 600
|
a: 600
|
||||||
m: 50
|
m: 50
|
||||||
ch: 1000
|
ch: 1000
|
||||||
kickban: 250
|
kickban: 125
|
||||||
|
t: 7.8125
|
||||||
|
+ls: 16.666666666666668
|
||||||
|
-ls: 16.666666666666668
|
||||||
|
chown: 2000
|
||||||
|
hi: 50
|
||||||
|
bye: 50
|
||||||
|
devices: 50
|
||||||
|
admin_message: 50
|
||||||
|
admin message: 50
|
||||||
chains:
|
chains:
|
||||||
userset:
|
userset:
|
||||||
interval: 1800000
|
interval: 1800000
|
||||||
num: 1000
|
num: 1000
|
||||||
|
chset:
|
||||||
|
interval: 1800000
|
||||||
|
num: 1024
|
||||||
|
n:
|
||||||
|
interval: 1000
|
||||||
|
num: 512
|
||||||
admin:
|
admin:
|
||||||
normal:
|
normal:
|
||||||
a: 120
|
a: 120
|
||||||
m: 16.666666666666668
|
m: 16.666666666666668
|
||||||
ch: 100
|
ch: 100
|
||||||
kickban: 31.25
|
kickban: 16.666666666666668
|
||||||
|
t: 3.90625
|
||||||
|
+ls: 16.666666666666668
|
||||||
|
-ls: 16.666666666666668
|
||||||
|
chown: 500
|
||||||
|
hi: 50
|
||||||
|
bye: 50
|
||||||
|
devices: 50
|
||||||
|
admin_message: 16.666666666666668
|
||||||
|
admin message: 16.666666666666668
|
||||||
chains:
|
chains:
|
||||||
userset:
|
userset:
|
||||||
interval: 1800000
|
interval: 500
|
||||||
num: 1000
|
num: 1000
|
||||||
|
chset:
|
||||||
|
interval: 1800000
|
||||||
|
num: 1024
|
||||||
|
n:
|
||||||
|
interval: 50
|
||||||
|
num: 512
|
||||||
|
|
|
@ -16,6 +16,7 @@ model User {
|
||||||
name String @default("Anonymous")
|
name String @default("Anonymous")
|
||||||
color String @default("#ffffff")
|
color String @default("#ffffff")
|
||||||
flags String @default("{}") // JSON flags object
|
flags String @default("{}") // JSON flags object
|
||||||
|
tag String // JSON tag
|
||||||
}
|
}
|
||||||
|
|
||||||
model ChatHistory {
|
model ChatHistory {
|
||||||
|
|
|
@ -7,7 +7,8 @@ import {
|
||||||
Participant,
|
Participant,
|
||||||
ServerEvents,
|
ServerEvents,
|
||||||
IChannelInfo,
|
IChannelInfo,
|
||||||
Notification
|
Notification,
|
||||||
|
UserFlags
|
||||||
} from "../util/types";
|
} from "../util/types";
|
||||||
import type { Socket } from "../ws/Socket";
|
import type { Socket } from "../ws/Socket";
|
||||||
import { validateChannelSettings } from "./settings";
|
import { validateChannelSettings } from "./settings";
|
||||||
|
@ -17,7 +18,7 @@ import { ChannelList } from "./ChannelList";
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
import { saveChatHistory, getChatHistory } from "../data/history";
|
import { saveChatHistory, getChatHistory } from "../data/history";
|
||||||
import { mixin } from "../util/helpers";
|
import { mixin } from "../util/helpers";
|
||||||
import { NoteQuota } from "../ws/ratelimit/NoteQuota";
|
import { readUser } from "../data/user";
|
||||||
|
|
||||||
interface CachedKickban {
|
interface CachedKickban {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -25,9 +26,17 @@ interface CachedKickban {
|
||||||
endTime: number;
|
endTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ExtraPartData {
|
||||||
|
uuids: string[];
|
||||||
|
flags: Partial<UserFlags>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExtraPart = Participant & ExtraPartData;
|
||||||
|
|
||||||
export class Channel extends EventEmitter {
|
export class Channel extends EventEmitter {
|
||||||
private settings: Partial<IChannelSettings>;
|
private settings: Partial<IChannelSettings>;
|
||||||
private ppl = new Array<Participant & { uuids: string[] }>();
|
private ppl = new Array<ExtraPart>();
|
||||||
|
|
||||||
public chatHistory = new Array<ClientEvents["a"]>();
|
public chatHistory = new Array<ClientEvents["a"]>();
|
||||||
|
|
||||||
private async loadChatHistory() {
|
private async loadChatHistory() {
|
||||||
|
@ -39,6 +48,8 @@ export class Channel extends EventEmitter {
|
||||||
|
|
||||||
public crown?: Crown;
|
public crown?: Crown;
|
||||||
|
|
||||||
|
private flags: Record<string, any> = {};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _id: string,
|
private _id: string,
|
||||||
set?: Partial<IChannelSettings>,
|
set?: Partial<IChannelSettings>,
|
||||||
|
@ -55,6 +66,8 @@ export class Channel extends EventEmitter {
|
||||||
// Validate settings in set
|
// Validate settings in set
|
||||||
// Set the verified settings
|
// Set the verified settings
|
||||||
|
|
||||||
|
this.logger.debug("lobby me?", this.isLobby());
|
||||||
|
|
||||||
if (!this.isLobby()) {
|
if (!this.isLobby()) {
|
||||||
if (set) {
|
if (set) {
|
||||||
//this.logger.debug("Passed settings:", set);
|
//this.logger.debug("Passed settings:", set);
|
||||||
|
@ -185,6 +198,15 @@ export class Channel extends EventEmitter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether this channel is a lobby with the name "lobby" in it
|
||||||
|
*/
|
||||||
|
public isTrueLobby() {
|
||||||
|
if (this.getID().match("^lobby[0-9][0-9]$") && this.getID().match("^lobby[1-9]$")) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change this channel's settings
|
* Change this channel's settings
|
||||||
* @param set Channel settings
|
* @param set Channel settings
|
||||||
|
@ -265,7 +287,7 @@ export class Channel extends EventEmitter {
|
||||||
* @param socket Socket that is joining
|
* @param socket Socket that is joining
|
||||||
* @returns undefined
|
* @returns undefined
|
||||||
*/
|
*/
|
||||||
public join(socket: Socket): void {
|
public join(socket: Socket, force: boolean = false): void {
|
||||||
//! /!\ Players are forced to join the same channel on two different tabs!
|
//! /!\ Players are forced to join the same channel on two different tabs!
|
||||||
//? TODO Should this be a bug or a feature?
|
//? TODO Should this be a bug or a feature?
|
||||||
//this.logger.debug("join triggered");
|
//this.logger.debug("join triggered");
|
||||||
|
@ -274,8 +296,8 @@ export class Channel extends EventEmitter {
|
||||||
const part = socket.getParticipant() as Participant;
|
const part = socket.getParticipant() as Participant;
|
||||||
|
|
||||||
let hasChangedChannel = false;
|
let hasChangedChannel = false;
|
||||||
let oldChannelID = socket.currentChannelID;
|
|
||||||
|
|
||||||
|
if (!force) {
|
||||||
// Is user banned?
|
// Is user banned?
|
||||||
if (this.isBanned(part._id)) {
|
if (this.isBanned(part._id)) {
|
||||||
// Send user to ban channel instead
|
// Send user to ban channel instead
|
||||||
|
@ -289,6 +311,17 @@ export class Channel extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is the channel full?
|
||||||
|
if (this.isFull()) {
|
||||||
|
// Is this a genuine lobby (not a test/ room)?
|
||||||
|
if (this.isTrueLobby()) {
|
||||||
|
const nextID = this.getNextIncrementationFromID();
|
||||||
|
this.logger.debug("New ID:", nextID);
|
||||||
|
return socket.setChannel(nextID, undefined, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Is user in this channel?
|
// Is user in this channel?
|
||||||
if (this.hasUser(part._id)) {
|
if (this.hasUser(part._id)) {
|
||||||
// Already in channel, don't add to list, but tell them they're here
|
// Already in channel, don't add to list, but tell them they're here
|
||||||
|
@ -311,7 +344,8 @@ export class Channel extends EventEmitter {
|
||||||
color: part.color,
|
color: part.color,
|
||||||
id: part.id,
|
id: part.id,
|
||||||
tag: part.tag,
|
tag: part.tag,
|
||||||
uuids: [socket.getUUID()]
|
uuids: [socket.getUUID()],
|
||||||
|
flags: socket.getUserFlags() || {}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (socket.currentChannelID !== config.fullChannel) {
|
if (socket.currentChannelID !== config.fullChannel) {
|
||||||
|
@ -331,7 +365,7 @@ export class Channel extends EventEmitter {
|
||||||
if (hasChangedChannel) {
|
if (hasChangedChannel) {
|
||||||
// Were they in a channel before?
|
// Were they in a channel before?
|
||||||
if (socket.currentChannelID) {
|
if (socket.currentChannelID) {
|
||||||
// Find the channel they were in
|
// Find the other channel they were in
|
||||||
const ch = ChannelList.getList().find(
|
const ch = ChannelList.getList().find(
|
||||||
ch => ch._id == socket.currentChannelID
|
ch => ch._id == socket.currentChannelID
|
||||||
);
|
);
|
||||||
|
@ -340,7 +374,7 @@ export class Channel extends EventEmitter {
|
||||||
if (ch) ch.leave(socket);
|
if (ch) ch.leave(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the thing we checked to point to us now
|
// You belong here now
|
||||||
socket.currentChannelID = this.getID();
|
socket.currentChannelID = this.getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,9 +477,9 @@ export class Channel extends EventEmitter {
|
||||||
public isFull() {
|
public isFull() {
|
||||||
// TODO Use limit setting
|
// TODO Use limit setting
|
||||||
|
|
||||||
// if (this.isLobby() && this.ppl.length >= 20) {
|
if (this.isTrueLobby() && this.ppl.length >= 20) {
|
||||||
// return true;
|
return true;
|
||||||
// }
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -472,13 +506,20 @@ export class Channel extends EventEmitter {
|
||||||
* @returns List of people
|
* @returns List of people
|
||||||
*/
|
*/
|
||||||
public getParticipantList() {
|
public getParticipantList() {
|
||||||
return this.ppl.map(p => ({
|
const ppl = [];
|
||||||
id: p.id,
|
|
||||||
|
for (const p of this.ppl) {
|
||||||
|
if (p.flags.vanish) continue;
|
||||||
|
ppl.push({
|
||||||
_id: p._id,
|
_id: p._id,
|
||||||
name: p.name,
|
name: p.name,
|
||||||
color: p.color,
|
color: p.color,
|
||||||
tag: p.tag
|
id: p.id,
|
||||||
}));
|
tag: config.sendTags ? p.tag : undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ppl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getParticipantListUnsanitized() {
|
public getParticipantListUnsanitized() {
|
||||||
|
@ -626,7 +667,7 @@ export class Channel extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drop the crown (remove from user)
|
* Drop the crown (reset timer, and, if applicable, remove from user's head)
|
||||||
*/
|
*/
|
||||||
public dropCrown() {
|
public dropCrown() {
|
||||||
if (this.crown) {
|
if (this.crown) {
|
||||||
|
@ -780,6 +821,11 @@ export class Channel extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a user is banned here right now
|
||||||
|
* @param _id User ID
|
||||||
|
* @returns True if the user is banned, otherwise false
|
||||||
|
**/
|
||||||
public isBanned(_id: string) {
|
public isBanned(_id: string) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
|
@ -799,6 +845,9 @@ export class Channel extends EventEmitter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the chat and chat history
|
||||||
|
**/
|
||||||
public async clearChat() {
|
public async clearChat() {
|
||||||
this.chatHistory = [];
|
this.chatHistory = [];
|
||||||
await saveChatHistory(this.getID(), this.chatHistory);
|
await saveChatHistory(this.getID(), this.chatHistory);
|
||||||
|
@ -826,6 +875,11 @@ export class Channel extends EventEmitter {
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a message in chat
|
||||||
|
* @param msg Chat message event to send
|
||||||
|
* @param p Participant who is "sending the message"
|
||||||
|
**/
|
||||||
public async sendChat(msg: ServerEvents["a"], p: Participant) {
|
public async sendChat(msg: ServerEvents["a"], p: Participant) {
|
||||||
if (!msg.message) return;
|
if (!msg.message) return;
|
||||||
|
|
||||||
|
@ -848,6 +902,38 @@ export class Channel extends EventEmitter {
|
||||||
this.chatHistory.push(outgoing);
|
this.chatHistory.push(outgoing);
|
||||||
await saveChatHistory(this.getID(), this.chatHistory);
|
await saveChatHistory(this.getID(), this.chatHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a flag on this channel
|
||||||
|
* @param key Flag ID
|
||||||
|
* @param val Value of which the flag will be set to
|
||||||
|
**/
|
||||||
|
public setFlag(key: string, val: any) {
|
||||||
|
this.flags[key] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a flag on this channel
|
||||||
|
* @param key Flag ID
|
||||||
|
* @returns Value of flag
|
||||||
|
*/
|
||||||
|
public getFlag(key: string) {
|
||||||
|
return this.flags[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this channel where the number at the end is one higher than this one, given it ends with a number
|
||||||
|
**/
|
||||||
|
public getNextIncrementationFromID() {
|
||||||
|
try {
|
||||||
|
const id = this.getID();
|
||||||
|
const num = parseInt((id.match(/\d+$/) as string[])[0]);
|
||||||
|
return `${id.substring(0, id.length - num.toString().length)}${num + 1}`;
|
||||||
|
} catch (err) {
|
||||||
|
return config.fullChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Channel;
|
export default Channel;
|
||||||
|
|
|
@ -8,6 +8,8 @@ interface ChannelConfig {
|
||||||
lobbyRegexes: string[];
|
lobbyRegexes: string[];
|
||||||
lobbyBackdoor: string;
|
lobbyBackdoor: string;
|
||||||
fullChannel: string;
|
fullChannel: string;
|
||||||
|
sendLimit: boolean;
|
||||||
|
sendTags: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const config = loadConfig<ChannelConfig>("config/channels.yml", {
|
export const config = loadConfig<ChannelConfig>("config/channels.yml", {
|
||||||
|
@ -27,8 +29,10 @@ export const config = loadConfig<ChannelConfig>("config/channels.yml", {
|
||||||
color2: "#001014",
|
color2: "#001014",
|
||||||
visible: true
|
visible: true
|
||||||
},
|
},
|
||||||
// Here's a terrifying fact: Brandon used parseInt to check lobby names in the OG server code
|
// Here's a terrifying fact: Brandon used parseInt to check lobby names
|
||||||
lobbyRegexes: ["^lobby[0-9][0-9]$", "^lobby[1-9]$", "^test/.+$"],
|
lobbyRegexes: ["^lobby[0-9][0-9]$", "^lobby[0-9]$", "^lobby$", "^test/.+$"],
|
||||||
lobbyBackdoor: "lolwutsecretlobbybackdoor",
|
lobbyBackdoor: "lolwutsecretlobbybackdoor",
|
||||||
fullChannel: "test/awkward"
|
fullChannel: "test/awkward",
|
||||||
|
sendLimit: false,
|
||||||
|
sendTags: false,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,41 @@
|
||||||
import { Channel } from "./Channel";
|
import { Channel } from "./Channel";
|
||||||
import { config } from "./config";
|
import { config } from "./config";
|
||||||
|
import { Logger } from "../util/Logger";
|
||||||
// This shit was moved here to try to fix the unit tests segfaulting but it didn't work
|
import { ChannelList } from "./ChannelList";
|
||||||
|
|
||||||
// Channel forceloader (cringe)
|
// Channel forceloader (cringe)
|
||||||
|
|
||||||
|
const logger = new Logger("Channel Forceloader");
|
||||||
|
|
||||||
|
export function forceloadChannel(id: string) {
|
||||||
|
try {
|
||||||
|
logger.info("Forceloading", id);
|
||||||
|
new Channel(id, undefined, undefined, undefined, true);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unforceloadChannel(id: string) {
|
||||||
|
const ch = ChannelList.getList().find(ch => ch.getID() == id);
|
||||||
|
if (!ch) return false;
|
||||||
|
|
||||||
|
logger.info("Unloading", id);
|
||||||
|
ch.destroy();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadDefaultForcedChannels() {
|
||||||
let hasFullChannel = false;
|
let hasFullChannel = false;
|
||||||
|
|
||||||
for (const id of config.forceLoad) {
|
for (const id of config.forceLoad) {
|
||||||
new Channel(id, undefined, undefined, undefined, true);
|
forceloadChannel(id);
|
||||||
if (id == config.fullChannel) hasFullChannel = true;
|
if (id == config.fullChannel) hasFullChannel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasFullChannel) {
|
if (!hasFullChannel) {
|
||||||
new Channel(config.fullChannel, undefined, undefined, undefined, true);
|
new Channel(config.fullChannel, undefined, undefined, undefined, true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
import { User } from "@prisma/client";
|
import { User } from "@prisma/client";
|
||||||
import { prisma } from "./prisma";
|
import { prisma } from "./prisma";
|
||||||
import { UserFlags } from "../util/types";
|
import { Tag, UserFlags } from "../util/types";
|
||||||
|
|
||||||
export async function createUser(
|
export async function createUser(
|
||||||
_id: string,
|
_id: string,
|
||||||
name?: string,
|
name?: string,
|
||||||
color?: string,
|
color?: string,
|
||||||
flags?: UserFlags
|
flags?: UserFlags,
|
||||||
|
tag?: Tag
|
||||||
) {
|
) {
|
||||||
return await prisma.user.create({
|
return await prisma.user.create({
|
||||||
data: { id: _id, name, color, flags: JSON.stringify(flags) }
|
data: {
|
||||||
|
id: _id,
|
||||||
|
name,
|
||||||
|
color,
|
||||||
|
flags: JSON.stringify(flags) || "",
|
||||||
|
tag: JSON.stringify(tag) || ""
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUsers() {
|
export async function getUsers() {
|
||||||
return await {
|
return {
|
||||||
users: await prisma.user.findMany(),
|
users: await prisma.user.findMany(),
|
||||||
count: await prisma.user.count()
|
count: await prisma.user.count()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
|
|
||||||
// If you don't load the server first, bun will literally segfault
|
// If you don't load the server first, bun will literally segfault
|
||||||
import "./ws/server";
|
import "./ws/server";
|
||||||
import "./channel/forceLoad";
|
import { loadDefaultForcedChannels } from "./channel/forceLoad";
|
||||||
import { Logger } from "./util/Logger";
|
import { Logger } from "./util/Logger";
|
||||||
|
|
||||||
const logger = new Logger("Main");
|
const logger = new Logger("Main");
|
||||||
|
logger.info("Loading default channels...");
|
||||||
|
loadDefaultForcedChannels();
|
||||||
|
|
||||||
import "./util/readline";
|
import "./util/readline";
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,5 @@
|
||||||
/**
|
|
||||||
* Typedefs
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Socket } from "../ws/Socket";
|
import { Socket } from "../ws/Socket";
|
||||||
|
|
||||||
/**
|
|
||||||
* Halfway through this file, the same types have appeared again
|
|
||||||
*
|
|
||||||
* I am not a decent enough person to go looking down there, so
|
|
||||||
* good luck when you get there. Somehow I forgot what is even
|
|
||||||
* in this file, so don't come and ask me why something isn't
|
|
||||||
* defined correctly here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||||
|
|
||||||
declare type UserFlags = Partial<{
|
declare type UserFlags = Partial<{
|
||||||
|
@ -27,9 +14,17 @@ declare type UserFlags = Partial<{
|
||||||
cansetcrowns: number;
|
cansetcrowns: number;
|
||||||
|
|
||||||
// new
|
// new
|
||||||
|
"no note quota": number;
|
||||||
"no note rate limit": number;
|
"no note rate limit": number;
|
||||||
"no cursor rate limit": number;
|
"no cursor rate limit": number;
|
||||||
"no userset rate limit": number;
|
"no userset rate limit": number;
|
||||||
|
mod: number;
|
||||||
|
admin: number;
|
||||||
|
vanish: number;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
type ChannelFlags = Partial<{
|
||||||
|
limit: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
declare interface Tag {
|
declare interface Tag {
|
||||||
|
@ -110,7 +105,6 @@ declare interface Crown {
|
||||||
endPos: Vector2;
|
endPos: Vector2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Events copied from Hri7566/mppclone-client typedefs
|
|
||||||
declare interface ServerEvents {
|
declare interface ServerEvents {
|
||||||
a: {
|
a: {
|
||||||
m: "a";
|
m: "a";
|
||||||
|
@ -238,19 +232,40 @@ declare interface ServerEvents {
|
||||||
remove?: true;
|
remove?: true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tag: {
|
||||||
|
m: "tag";
|
||||||
|
_id: string;
|
||||||
|
tag: {
|
||||||
|
text: string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
clear_chat: {
|
clear_chat: {
|
||||||
m: "clear_chat"
|
m: "clear_chat";
|
||||||
};
|
};
|
||||||
|
|
||||||
notification: {
|
notification: {
|
||||||
m: "notification"
|
m: "notification";
|
||||||
targetChannel?: string;
|
targetChannel?: string;
|
||||||
targetUser?: string;
|
targetUser?: string;
|
||||||
} & Notification;
|
} & Notification;
|
||||||
|
|
||||||
restart: {
|
restart: {
|
||||||
m: "restart"
|
m: "restart";
|
||||||
}
|
};
|
||||||
|
|
||||||
|
forceload: {
|
||||||
|
m: "forceload";
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
ch_flag: {
|
||||||
|
m: "ch_flag";
|
||||||
|
_id?: string;
|
||||||
|
key: string;
|
||||||
|
value: any;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
declare interface ClientEvents {
|
declare interface ClientEvents {
|
||||||
|
|
|
@ -123,7 +123,7 @@ export class Socket extends EventEmitter {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setChannel(_id: string, set?: Partial<IChannelSettings>) {
|
public setChannel(_id: string, set?: Partial<IChannelSettings>, force: boolean = false) {
|
||||||
if (this.isDestroyed()) return;
|
if (this.isDestroyed()) return;
|
||||||
if (this.currentChannelID === _id) {
|
if (this.currentChannelID === _id) {
|
||||||
logger.debug("Guy in channel was already in");
|
logger.debug("Guy in channel was already in");
|
||||||
|
@ -155,7 +155,7 @@ export class Socket extends EventEmitter {
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
channel.join(this);
|
channel.join(this, force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,17 +443,25 @@ export class Socket extends EventEmitter {
|
||||||
ch.playNotes(msg, this);
|
ch.playNotes(msg, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private isSubscribedToChannelList = false;
|
||||||
|
|
||||||
public subscribeToChannelList() {
|
public subscribeToChannelList() {
|
||||||
|
if (this.isSubscribedToChannelList) return;
|
||||||
|
|
||||||
ChannelList.subscribe(this.id);
|
ChannelList.subscribe(this.id);
|
||||||
|
|
||||||
const firstList = ChannelList.getPublicList().map(v =>
|
const firstList = ChannelList.getPublicList().map(v =>
|
||||||
v.getInfo(this._id)
|
v.getInfo(this._id)
|
||||||
);
|
);
|
||||||
this.sendChannelList(firstList);
|
this.sendChannelList(firstList);
|
||||||
|
|
||||||
|
this.isSubscribedToChannelList = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsubscribeFromChannelList() {
|
public unsubscribeFromChannelList() {
|
||||||
|
if (!this.isSubscribedToChannelList) return;
|
||||||
ChannelList.unsubscribe(this.id);
|
ChannelList.unsubscribe(this.id);
|
||||||
|
this.isSubscribedToChannelList = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendChannelList(list: IChannelInfo[], complete: boolean = true) {
|
public sendChannelList(list: IChannelInfo[], complete: boolean = true) {
|
||||||
|
@ -476,7 +484,6 @@ export class Socket extends EventEmitter {
|
||||||
const channel = this.getCurrentChannel();
|
const channel = this.getCurrentChannel();
|
||||||
const part = this.getParticipant();
|
const part = this.getParticipant();
|
||||||
|
|
||||||
// this looks cool
|
|
||||||
if (!channel) return false;
|
if (!channel) return false;
|
||||||
if (!channel.crown) return false;
|
if (!channel.crown) return false;
|
||||||
if (!channel.crown.userId) return false;
|
if (!channel.crown.userId) return false;
|
||||||
|
@ -514,6 +521,13 @@ export class Socket extends EventEmitter {
|
||||||
html: notif.html
|
html: notif.html
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setTag(text: string, color: string) {
|
||||||
|
const user = this.getUser();
|
||||||
|
if (!user) return;
|
||||||
|
user.tag = JSON.stringify({ text, color });
|
||||||
|
updateUser(this.getUserID(), user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const socketsBySocketID = new Map<string, Socket>();
|
export const socketsBySocketID = new Map<string, Socket>();
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { ChannelList } from "../../../../channel/ChannelList";
|
||||||
|
import { ServerEventListener } from "../../../../util/types";
|
||||||
|
|
||||||
|
export const ch_flag: ServerEventListener<"ch_flag"> = {
|
||||||
|
id: "ch_flag",
|
||||||
|
callback: async (msg, socket) => {
|
||||||
|
// Edit channel flag
|
||||||
|
let chid = msg._id;
|
||||||
|
|
||||||
|
if (typeof chid !== "string") {
|
||||||
|
const ch = socket.getCurrentChannel();
|
||||||
|
if (!ch) return;
|
||||||
|
|
||||||
|
chid = ch.getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ch = ChannelList.getList().find(c => c.getID() == chid);
|
||||||
|
if (!ch) return;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { forceloadChannel } from "../../../../channel/forceLoad";
|
||||||
|
import { ServerEventListener } from "../../../../util/types";
|
||||||
|
|
||||||
|
export const forceload: ServerEventListener<"forceload"> = {
|
||||||
|
id: "forceload",
|
||||||
|
callback: async (msg, socket) => {
|
||||||
|
// Forceload channel
|
||||||
|
if (typeof msg._id !== "string") return;
|
||||||
|
|
||||||
|
forceloadChannel(msg._id);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { readUser, updateUser } from "../../../../data/user";
|
||||||
|
import { ServerEventListener } from "../../../../util/types";
|
||||||
|
import { findSocketsByUserID } from "../../../Socket";
|
||||||
|
|
||||||
|
export const tag: ServerEventListener<"tag"> = {
|
||||||
|
id: "tag",
|
||||||
|
callback: async (msg, socket) => {
|
||||||
|
// Change someone else's tag
|
||||||
|
const id = msg._id;
|
||||||
|
const tag = msg.tag;
|
||||||
|
|
||||||
|
if (typeof id !== "string") return;
|
||||||
|
if (typeof tag !== "object") return;
|
||||||
|
if (typeof tag["text"] !== "string") return;
|
||||||
|
if (typeof tag.color !== "string") return;
|
||||||
|
if (!tag.color.match(/^#[0-9a-f]{6}$/i)) return;
|
||||||
|
|
||||||
|
const user = await readUser(msg._id);
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
user.tag = JSON.stringify(tag);
|
||||||
|
await updateUser(id, user);
|
||||||
|
|
||||||
|
const toUpdate = findSocketsByUserID(id);
|
||||||
|
toUpdate.forEach(s => {
|
||||||
|
s.setTag(msg.tag.text, msg.tag.color);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -12,6 +12,10 @@ export const plus_ls: ServerEventListener<"+ls"> = {
|
||||||
// and when I see their cursor disappear I'll know
|
// and when I see their cursor disappear I'll know
|
||||||
// precisely where they went to follow them and to
|
// precisely where they went to follow them and to
|
||||||
// annoy them in chat when I see them again.
|
// annoy them in chat when I see them again.
|
||||||
|
if (socket.rateLimits) {
|
||||||
|
if (!socket.rateLimits.normal["+ls"].attempt()) return;
|
||||||
|
}
|
||||||
|
|
||||||
socket.subscribeToChannelList();
|
socket.subscribeToChannelList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,10 @@ export const minus_ls: ServerEventListener<"-ls"> = {
|
||||||
id: "-ls",
|
id: "-ls",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Stop giving us the latest server forecast
|
// Stop giving us the latest server forecast
|
||||||
|
if (socket.rateLimits) {
|
||||||
|
if (!socket.rateLimits.normal["-ls"].attempt()) return;
|
||||||
|
}
|
||||||
|
|
||||||
socket.unsubscribeFromChannelList();
|
socket.unsubscribeFromChannelList();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { Logger } from "../../../../util/Logger";
|
|
||||||
import env from "../../../../util/env";
|
import env from "../../../../util/env";
|
||||||
import { ServerEventListener } from "../../../../util/types";
|
import { ServerEventListener } from "../../../../util/types";
|
||||||
import { config } from "../../../usersConfig";
|
|
||||||
|
|
||||||
const logger = new Logger("Admin Message Handler");
|
|
||||||
|
|
||||||
export const admin_message: ServerEventListener<"admin message"> = {
|
export const admin_message: ServerEventListener<"admin message"> = {
|
||||||
id: "admin message",
|
id: "admin message",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
|
// Administrator control message
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.normal["admin message"].attempt()) return;
|
||||||
|
|
||||||
if (typeof msg.password !== "string") return;
|
if (typeof msg.password !== "string") return;
|
||||||
if (msg.password !== env.ADMIN_PASS) return;
|
if (msg.password !== env.ADMIN_PASS) return;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ export const bye: ServerEventListener<"bye"> = {
|
||||||
id: "bye",
|
id: "bye",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Leave server
|
// Leave server
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.normal.bye.attempt()) return;
|
||||||
|
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,9 @@ export const chown: ServerEventListener<"chown"> = {
|
||||||
id: "chown",
|
id: "chown",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Change channel ownership
|
// Change channel ownership
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.normal["chown"].attempt()) return;
|
||||||
|
|
||||||
const ch = socket.getCurrentChannel();
|
const ch = socket.getCurrentChannel();
|
||||||
if (!ch) return;
|
if (!ch) return;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ export const chset: ServerEventListener<"chset"> = {
|
||||||
id: "chset",
|
id: "chset",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Change channel settings
|
// Change channel settings
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.chains.chset.attempt()) return;
|
||||||
|
|
||||||
if (typeof msg.set == "undefined") return;
|
if (typeof msg.set == "undefined") return;
|
||||||
|
|
||||||
const ch = socket.getCurrentChannel();
|
const ch = socket.getCurrentChannel();
|
||||||
|
|
|
@ -4,6 +4,9 @@ export const devices: ServerEventListener<"devices"> = {
|
||||||
id: "devices",
|
id: "devices",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// List of MIDI Devices (or software ports, because nobody can tell the difference)
|
// List of MIDI Devices (or software ports, because nobody can tell the difference)
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.normal.devices.attempt()) return;
|
||||||
|
|
||||||
if (socket.gateway.hasSentDevices) return;
|
if (socket.gateway.hasSentDevices) return;
|
||||||
socket.gateway.hasSentDevices = true;
|
socket.gateway.hasSentDevices = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@ export const hi: ServerEventListener<"hi"> = {
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Handshake message
|
// Handshake message
|
||||||
// TODO Hi message tokens
|
// TODO Hi message tokens
|
||||||
// I'm not actually sure if I'm up for doing tokens,
|
|
||||||
// but if someone wants to submit a pull request, I
|
if (socket.rateLimits)
|
||||||
// look forward to watching you do all the work
|
if (!socket.rateLimits.normal.hi.attempt()) return;
|
||||||
|
|
||||||
if (socket.gateway.hasProcessedHi) return;
|
if (socket.gateway.hasProcessedHi) return;
|
||||||
let part = socket.getParticipant();
|
let part = socket.getParticipant();
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,10 @@ export const m: ServerEventListener<"m"> = {
|
||||||
id: "m",
|
id: "m",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Cursor movement
|
// Cursor movement
|
||||||
if (!socket.rateLimits) return;
|
if (socket.rateLimits) {
|
||||||
if (!socket.rateLimits.normal.m.attempt()) return;
|
if (!socket.rateLimits.normal.m.attempt()) return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!msg.x || !msg.y) return;
|
if (!msg.x || !msg.y) return;
|
||||||
|
|
||||||
let x = msg.x;
|
let x = msg.x;
|
||||||
|
|
|
@ -5,6 +5,9 @@ export const n: ServerEventListener<"n"> = {
|
||||||
id: "n",
|
id: "n",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Piano note
|
// Piano note
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.chains.n.attempt()) return;
|
||||||
|
|
||||||
if (!Array.isArray(msg.n)) return;
|
if (!Array.isArray(msg.n)) return;
|
||||||
if (typeof msg.t !== "number") return;
|
if (typeof msg.t !== "number") return;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,15 @@ export const t: ServerEventListener<"t"> = {
|
||||||
id: "t",
|
id: "t",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Ping
|
// Ping
|
||||||
|
|
||||||
|
if (socket.rateLimits)
|
||||||
|
if (!socket.rateLimits.normal.t.attempt()) return
|
||||||
|
|
||||||
if (msg.e) {
|
if (msg.e) {
|
||||||
if (typeof msg.e !== "number") return;
|
if (typeof msg.e !== "number") return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pong!
|
// Pong
|
||||||
socket.sendArray([
|
socket.sendArray([
|
||||||
{
|
{
|
||||||
m: "t",
|
m: "t",
|
||||||
|
|
|
@ -7,14 +7,26 @@ export interface RateLimitConfigList<
|
||||||
RLC = { num: number; interval: number }
|
RLC = { num: number; interval: number }
|
||||||
> {
|
> {
|
||||||
normal: {
|
normal: {
|
||||||
m: RL;
|
|
||||||
a: RL;
|
a: RL;
|
||||||
|
m: RL;
|
||||||
ch: RL;
|
ch: RL;
|
||||||
kickban: RL;
|
kickban: RL;
|
||||||
|
t: RL;
|
||||||
|
"+ls": RL;
|
||||||
|
"-ls": RL;
|
||||||
|
chown: RL;
|
||||||
|
|
||||||
|
// weird limits
|
||||||
|
hi: RL;
|
||||||
|
bye: RL;
|
||||||
|
devices: RL;
|
||||||
|
"admin message": RL;
|
||||||
};
|
};
|
||||||
|
|
||||||
chains: {
|
chains: {
|
||||||
userset: RLC;
|
userset: RLC;
|
||||||
|
chset: RLC;
|
||||||
|
n: RLC; // not to be confused with NoteQuota
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,12 +49,29 @@ export const config = loadConfig<RateLimitsConfig>("config/ratelimits.yml", {
|
||||||
a: 6000 / 4,
|
a: 6000 / 4,
|
||||||
m: 1000 / 20,
|
m: 1000 / 20,
|
||||||
ch: 1000 / 1,
|
ch: 1000 / 1,
|
||||||
kickban: 1000 / 4
|
kickban: 1000 / 8,
|
||||||
|
t: 1000 / 128,
|
||||||
|
"+ls": 1000 / 60,
|
||||||
|
"-ls": 1000 / 60,
|
||||||
|
chown: 2000,
|
||||||
|
|
||||||
|
hi: 1000 / 20,
|
||||||
|
bye: 1000 / 20,
|
||||||
|
devices: 1000 / 20,
|
||||||
|
"admin message": 1000 / 20
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: {
|
userset: {
|
||||||
interval: 1000 * 60 * 30,
|
interval: 1000 * 60 * 30,
|
||||||
num: 1000
|
num: 1000
|
||||||
|
},
|
||||||
|
chset: {
|
||||||
|
interval: 1000 * 60 * 30,
|
||||||
|
num: 1024
|
||||||
|
},
|
||||||
|
n: {
|
||||||
|
interval: 1000,
|
||||||
|
num: 512
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -51,12 +80,29 @@ export const config = loadConfig<RateLimitsConfig>("config/ratelimits.yml", {
|
||||||
a: 6000 / 10,
|
a: 6000 / 10,
|
||||||
m: 1000 / 20,
|
m: 1000 / 20,
|
||||||
ch: 1000 / 1,
|
ch: 1000 / 1,
|
||||||
kickban: 1000 / 4
|
kickban: 1000 / 8,
|
||||||
|
t: 1000 / 128,
|
||||||
|
"+ls": 1000 / 60,
|
||||||
|
"-ls": 1000 / 60,
|
||||||
|
chown: 2000,
|
||||||
|
|
||||||
|
hi: 1000 / 20,
|
||||||
|
bye: 1000 / 20,
|
||||||
|
devices: 1000 / 20,
|
||||||
|
"admin message": 1000 / 20
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: {
|
userset: {
|
||||||
interval: 1000 * 60 * 30,
|
interval: 1000 * 60 * 30,
|
||||||
num: 1000
|
num: 1000
|
||||||
|
},
|
||||||
|
chset: {
|
||||||
|
interval: 1000 * 60 * 30,
|
||||||
|
num: 1024
|
||||||
|
},
|
||||||
|
n: {
|
||||||
|
interval: 1000,
|
||||||
|
num: 512
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -65,12 +111,29 @@ export const config = loadConfig<RateLimitsConfig>("config/ratelimits.yml", {
|
||||||
a: 6000 / 50,
|
a: 6000 / 50,
|
||||||
m: 1000 / 60,
|
m: 1000 / 60,
|
||||||
ch: 1000 / 10,
|
ch: 1000 / 10,
|
||||||
kickban: 1000 / 32
|
kickban: 1000 / 60,
|
||||||
|
t: 1000 / 256,
|
||||||
|
"+ls": 1000 / 60,
|
||||||
|
"-ls": 1000 / 60,
|
||||||
|
chown: 500,
|
||||||
|
|
||||||
|
hi: 1000 / 20,
|
||||||
|
bye: 1000 / 20,
|
||||||
|
devices: 1000 / 20,
|
||||||
|
"admin message": 1000 / 60
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: {
|
userset: {
|
||||||
interval: 1000 * 60 * 30,
|
interval: 500,
|
||||||
num: 1000
|
num: 1000
|
||||||
|
},
|
||||||
|
chset: {
|
||||||
|
interval: 1000 * 60 * 30,
|
||||||
|
num: 1024
|
||||||
|
},
|
||||||
|
n: {
|
||||||
|
interval: 50,
|
||||||
|
num: 512
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,32 @@ export const adminLimits: RateLimitConstructorList = {
|
||||||
a: () => new RateLimit(config.admin.normal.a),
|
a: () => new RateLimit(config.admin.normal.a),
|
||||||
m: () => new RateLimit(config.admin.normal.m),
|
m: () => new RateLimit(config.admin.normal.m),
|
||||||
ch: () => new RateLimit(config.admin.normal.ch),
|
ch: () => new RateLimit(config.admin.normal.ch),
|
||||||
kickban: () => new RateLimit(config.admin.normal.kickban)
|
kickban: () => new RateLimit(config.crown.normal.kickban),
|
||||||
|
t: () => new RateLimit(config.crown.normal.t),
|
||||||
|
"+ls": () => new RateLimit(config.crown.normal["+ls"]),
|
||||||
|
"-ls": () => new RateLimit(config.crown.normal["-ls"]),
|
||||||
|
chown: () => new RateLimit(config.crown.normal.chown),
|
||||||
|
|
||||||
|
hi: () => new RateLimit(config.crown.normal.hi),
|
||||||
|
bye: () => new RateLimit(config.crown.normal.bye),
|
||||||
|
devices: () => new RateLimit(config.crown.normal.devices),
|
||||||
|
"admin message": () => new RateLimit(config.crown.normal["admin message"])
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.admin.chains.userset.interval,
|
config.admin.chains.userset.interval,
|
||||||
config.admin.chains.userset.num
|
config.admin.chains.userset.num
|
||||||
|
),
|
||||||
|
chset: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.crown.chains.chset.interval,
|
||||||
|
config.crown.chains.userset.num
|
||||||
|
),
|
||||||
|
n: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.crown.chains.n.interval,
|
||||||
|
config.crown.chains.userset.num
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,13 +6,33 @@ export const crownLimits: RateLimitConstructorList = {
|
||||||
normal: {
|
normal: {
|
||||||
a: () => new RateLimit(config.crown.normal.a),
|
a: () => new RateLimit(config.crown.normal.a),
|
||||||
m: () => new RateLimit(config.crown.normal.m),
|
m: () => new RateLimit(config.crown.normal.m),
|
||||||
ch: () => new RateLimit(config.crown.normal.ch)
|
ch: () => new RateLimit(config.crown.normal.ch),
|
||||||
|
kickban: () => new RateLimit(config.crown.normal.kickban),
|
||||||
|
t: () => new RateLimit(config.crown.normal.t),
|
||||||
|
"+ls": () => new RateLimit(config.crown.normal["+ls"]),
|
||||||
|
"-ls": () => new RateLimit(config.crown.normal["-ls"]),
|
||||||
|
chown: () => new RateLimit(config.crown.normal.chown),
|
||||||
|
|
||||||
|
hi: () => new RateLimit(config.crown.normal.hi),
|
||||||
|
bye: () => new RateLimit(config.crown.normal.bye),
|
||||||
|
devices: () => new RateLimit(config.crown.normal.devices),
|
||||||
|
"admin message": () => new RateLimit(config.crown.normal["admin message"])
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.crown.chains.userset.interval,
|
config.crown.chains.userset.interval,
|
||||||
config.crown.chains.userset.num
|
config.crown.chains.userset.num
|
||||||
|
),
|
||||||
|
chset: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.crown.chains.chset.interval,
|
||||||
|
config.crown.chains.userset.num
|
||||||
|
),
|
||||||
|
n: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.crown.chains.n.interval,
|
||||||
|
config.crown.chains.userset.num
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,19 +2,37 @@ import { RateLimit } from "../RateLimit";
|
||||||
import { RateLimitChain } from "../RateLimitChain";
|
import { RateLimitChain } from "../RateLimitChain";
|
||||||
import { RateLimitConstructorList, config } from "../config";
|
import { RateLimitConstructorList, config } from "../config";
|
||||||
|
|
||||||
// All this does is instantiate rate limits from the config
|
|
||||||
export const userLimits: RateLimitConstructorList = {
|
export const userLimits: RateLimitConstructorList = {
|
||||||
normal: {
|
normal: {
|
||||||
a: () => new RateLimit(config.user.normal.a),
|
a: () => new RateLimit(config.user.normal.a),
|
||||||
m: () => new RateLimit(config.user.normal.m),
|
m: () => new RateLimit(config.user.normal.m),
|
||||||
ch: () => new RateLimit(config.user.normal.ch),
|
ch: () => new RateLimit(config.user.normal.ch),
|
||||||
kickban: () => new RateLimit(config.user.normal.kickban)
|
kickban: () => new RateLimit(config.user.normal.kickban),
|
||||||
|
t: () => new RateLimit(config.user.normal.t),
|
||||||
|
"+ls": () => new RateLimit(config.user.normal["+ls"]),
|
||||||
|
"-ls": () => new RateLimit(config.user.normal["-ls"]),
|
||||||
|
chown: () => new RateLimit(config.user.normal.chown),
|
||||||
|
|
||||||
|
hi: () => new RateLimit(config.user.normal.hi),
|
||||||
|
bye: () => new RateLimit(config.user.normal.bye),
|
||||||
|
devices: () => new RateLimit(config.user.normal.devices),
|
||||||
|
"admin message": () => new RateLimit(config.user.normal["admin message"])
|
||||||
},
|
},
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.user.chains.userset.interval,
|
config.user.chains.userset.interval,
|
||||||
config.user.chains.userset.num
|
config.user.chains.userset.num
|
||||||
|
),
|
||||||
|
chset: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.user.chains.chset.interval,
|
||||||
|
config.user.chains.userset.num
|
||||||
|
),
|
||||||
|
n: () =>
|
||||||
|
new RateLimitChain(
|
||||||
|
config.user.chains.n.interval,
|
||||||
|
config.user.chains.userset.num
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue