summary refs log tree commit diff
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-11 23:19:55 +1000
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-12 00:12:45 +1000
commit255aaccf20eca46040fd0b0a3797cfe4bb8ec373 (patch)
tree717506dfc7832104c17c2a1f78635029e6b66ac4
parentTrash ip logging for rate limits (diff)
downloadserver-255aaccf20eca46040fd0b0a3797cfe4bb8ec373.tar.xz
Primitive banned words blocking
-rw-r--r--bundle/bannedWords0
-rw-r--r--bundle/src/Server.ts3
-rw-r--r--util/src/entities/Member.ts11
-rw-r--r--util/src/entities/Message.ts10
-rw-r--r--util/src/entities/User.ts22
-rw-r--r--util/src/entities/index.ts2
-rw-r--r--util/src/util/BannedWords.ts23
-rw-r--r--util/src/util/index.ts3
8 files changed, 56 insertions, 18 deletions
diff --git a/bundle/bannedWords b/bundle/bannedWords
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/bundle/bannedWords
diff --git a/bundle/src/Server.ts b/bundle/src/Server.ts
index 9cef9ed1..df29266d 100644
--- a/bundle/src/Server.ts
+++ b/bundle/src/Server.ts
@@ -7,7 +7,7 @@ import * as Gateway from "@fosscord/gateway";
 import { CDNServer } from "@fosscord/cdn";
 import express from "express";
 import { green, bold, yellow } from "picocolors";
-import { Config, initDatabase } from "@fosscord/util";
+import { Config, initDatabase, BannedWords } from "@fosscord/util";
 import * as Sentry from "@sentry/node";
 import * as Tracing from "@sentry/tracing";
 
@@ -35,6 +35,7 @@ process.on('SIGTERM', () => {
 async function main() {
 	await initDatabase();
 	await Config.init();
+	await BannedWords.init();
 	// only set endpointPublic, if not already set
 	await Config.set({
 		cdn: {
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts
index a6798a7c..387181df 100644
--- a/util/src/entities/Member.ts
+++ b/util/src/entities/Member.ts
@@ -1,6 +1,5 @@
 import { PublicUser, User } from "./User";
 import { Message } from "./Message";
-import { BaseClass } from "./BaseClass";
 import {
 	Column,
 	Entity,
@@ -13,7 +12,7 @@ import {
 	RelationId,
 } from "typeorm";
 import { Guild } from "./Guild";
-import { Config, emitEvent } from "../util";
+import { Config, emitEvent, BannedWords, FieldErrors } from "../util";
 import {
 	GuildCreateEvent,
 	GuildDeleteEvent,
@@ -21,6 +20,7 @@ import {
 	GuildMemberRemoveEvent,
 	GuildMemberUpdateEvent,
 	MessageCreateEvent,
+
 } from "../interfaces";
 import { HTTPError } from "lambert-server";
 import { Role } from "./Role";
@@ -73,6 +73,11 @@ export class Member extends BaseClassWithoutId {
 	@Column({ nullable: true })
 	nick?: string;
 
+	setNick(val: string) {
+		if (BannedWords.find(val)) throw FieldErrors({ nick: { message: "Bad nickname", code: "INVALID_NICKNAME" } });
+		this.nick = val;
+	}
+
 	@JoinTable({
 		name: "member_roles",
 		joinColumn: { name: "index", referencedColumnName: "index" },
@@ -244,7 +249,7 @@ export class Member extends BaseClassWithoutId {
 			where: {
 				id: guild_id,
 			},
-			relations: [ ...PublicGuildRelations, "system_channel" ],
+			relations: [...PublicGuildRelations, "system_channel"],
 		});
 
 		if (await Member.count({ id: user.id, guild: { id: guild_id } }))
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index 38242152..78888e17 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -8,7 +8,6 @@ import {
 	Column,
 	CreateDateColumn,
 	Entity,
-	FindConditions,
 	Index,
 	JoinColumn,
 	JoinTable,
@@ -16,14 +15,14 @@ import {
 	ManyToOne,
 	OneToMany,
 	RelationId,
-	RemoveOptions,
-	UpdateDateColumn,
 } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { Guild } from "./Guild";
 import { Webhook } from "./Webhook";
 import { Sticker } from "./Sticker";
 import { Attachment } from "./Attachment";
+import { BannedWords } from "../util";
+import { HTTPError } from "lambert-server";
 
 export enum MessageType {
 	DEFAULT = 0,
@@ -117,6 +116,11 @@ export class Message extends BaseClass {
 	@Column({ nullable: true, type: process.env.PRODUCTION ? "longtext" : undefined })
 	content?: string;
 
+	setContent(val: string) {
+		if (BannedWords.find(val)) throw new HTTPError("Message was blocked by automatic moderation", 200000);
+		this.content = val;
+	}
+
 	@Column()
 	@CreateDateColumn()
 	timestamp: Date;
diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts
index cac2784a..230d6d82 100644
--- a/util/src/entities/User.ts
+++ b/util/src/entities/User.ts
@@ -3,9 +3,8 @@ import { BaseClass } from "./BaseClass";
 import { BitField } from "../util/BitField";
 import { Relationship } from "./Relationship";
 import { ConnectedAccount } from "./ConnectedAccount";
-import { Config, FieldErrors, Snowflake, trimSpecial } from "..";
+import { Config, FieldErrors, Snowflake, trimSpecial, BannedWords } from "..";
 import { Member, Session } from ".";
-import { Note } from "./Note";
 
 export enum PublicUserEnum {
 	username,
@@ -49,7 +48,7 @@ export const PrivateUserProjection = [
 // Private user data that should never get sent to the client
 export type PublicUser = Pick<User, PublicUserKeys>;
 
-export interface UserPublic extends Pick<User, PublicUserKeys> {}
+export interface UserPublic extends Pick<User, PublicUserKeys> { }
 
 export interface UserPrivate extends Pick<User, PrivateUserKeys> {
 	locale: string;
@@ -60,6 +59,11 @@ export class User extends BaseClass {
 	@Column()
 	username: string; // username max length 32, min 2 (should be configurable)
 
+	setUsername(val: string) {
+		if (BannedWords.find(val)) throw FieldErrors({ username: { message: "Bad username", code: "INVALID_USERNAME" } });
+		this.username = val;
+	}
+
 	@Column()
 	discriminator: string; // opaque string: 4 digits on discord.com
 
@@ -90,7 +94,7 @@ export class User extends BaseClass {
 
 	@Column()
 	premium: boolean; // if user bought individual premium
-	
+
 	@Column()
 	premium_type: number; // individual premium level
 
@@ -105,7 +109,7 @@ export class User extends BaseClass {
 
 	@Column({ select: false })
 	nsfw_allowed: boolean; // if the user can do age-restricted actions (NSFW channels/guilds/commands)
-	
+
 	@Column({ select: false })
 	mfa_enabled: boolean; // if multi factor authentication is enabled
 
@@ -176,7 +180,7 @@ export class User extends BaseClass {
 
 	@Column({ type: "simple-json", select: false })
 	settings: UserSettings;
-		
+
 	// workaround to prevent fossord-unaware clients from deleting settings not used by them
 	@Column({ type: "simple-json", select: false })
 	extended_settings: string;
@@ -202,7 +206,7 @@ export class User extends BaseClass {
 	private static async generateDiscriminator(username: string): Promise<string | undefined> {
 		if (Config.get().register.incrementingDiscriminators) {
 			// discriminator will be incrementally generated
-			
+
 			// First we need to figure out the currently highest discrimnator for the given username and then increment it
 			const users = await User.find({ where: { username }, select: ["discriminator"] });
 			const highestDiscriminator = Math.max(0, ...users.map((u) => Number(u.discriminator)));
@@ -299,7 +303,7 @@ export class User extends BaseClass {
 		setImmediate(async () => {
 			if (Config.get().guild.autoJoin.enabled) {
 				for (const guild of Config.get().guild.autoJoin.guilds || []) {
-					await Member.addToGuild(user.id, guild).catch((e) => {});
+					await Member.addToGuild(user.id, guild).catch((e) => { });
 				}
 			}
 		});
@@ -366,7 +370,7 @@ export interface UserSettings {
 	disable_games_tab: boolean;
 	enable_tts_command: boolean;
 	explicit_content_filter: number;
-	friend_source_flags: { all: boolean };
+	friend_source_flags: { all: boolean; };
 	gateway_connected: boolean;
 	gif_auto_play: boolean;
 	// every top guild is displayed as a "folder"
diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts
index c439a4b7..49793810 100644
--- a/util/src/entities/index.ts
+++ b/util/src/entities/index.ts
@@ -29,4 +29,4 @@ export * from "./VoiceState";
 export * from "./Webhook";
 export * from "./ClientRelease";
 export * from "./BackupCodes";
-export * from "./Note";
+export * from "./Note";
\ No newline at end of file
diff --git a/util/src/util/BannedWords.ts b/util/src/util/BannedWords.ts
new file mode 100644
index 00000000..891a5980
--- /dev/null
+++ b/util/src/util/BannedWords.ts
@@ -0,0 +1,23 @@
+import fs from "fs/promises";
+import path from "path";
+
+var words: string[];
+
+export const BannedWords = {
+	init: async function init() {
+		if (words) return words;
+		const file = (await fs.readFile(path.join(process.cwd(), "bannedWords"))).toString();
+		if (!file) {
+			words = [];
+			return [];
+		}
+		words = file.trim().split("\n");
+		return words;
+	},
+
+	get: () => words,
+
+	find: (val: string) => {
+		return words.some(x => val.indexOf(x) != -1);
+	}
+};
\ No newline at end of file
diff --git a/util/src/util/index.ts b/util/src/util/index.ts
index f7a273cb..b2bd6489 100644
--- a/util/src/util/index.ts
+++ b/util/src/util/index.ts
@@ -19,4 +19,5 @@ export * from "./Snowflake";
 export * from "./String";
 export * from "./Array";
 export * from "./TraverseDirectory";
-export * from "./InvisibleCharacters";
\ No newline at end of file
+export * from "./InvisibleCharacters";
+export * from "./BannedWords";
\ No newline at end of file