Please look over - not for production
diff --git a/src/reflex/scanners.ts b/src/reflex/scanners.ts
index 450a4af..f00e82c 100644
--- a/src/reflex/scanners.ts
+++ b/src/reflex/scanners.ts
@@ -8,6 +8,9 @@
 import * as nsfwjs from 'nsfwjs';
 import * as clamscan from 'clamscan'
 import * as tf from "@tensorflow/tfjs-node";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../utils/getEmojiByName.js";
+import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
 
 interface NSFWSchema {
     nsfw: boolean;
@@ -164,7 +167,8 @@
     }
 }
 
-export function TestString(string: string, soft: string[], strict: string[]): object | null {
+export function TestString(string: string, soft: string[], strict: string[], enabled?: boolean): {word: string, type: string} | null {
+    if (!enabled) return null;
     for (const word of strict) {
         if (string.toLowerCase().includes(word)) {
             return { word: word, type: "strict" };
@@ -173,7 +177,7 @@
     for (const word of soft) {
         for (const word2 of string.match(/[a-z]+/gi) ?? []) {
             if (word2 === word) {
-                return { word: word, type: "strict" };
+                return { word: word, type: "soft" };
             }
         }
     }
@@ -188,3 +192,76 @@
     });
     return text;
 }
+
+export async function doMemberChecks(member: Discord.GuildMember, guild: Discord.Guild): Promise<void> {
+    if (member.user.bot) return;
+    const guildData = await client.database.guilds.read(guild.id);
+    if (!guildData.logging.staff.channel) return;
+    const [ loose, strict ] = [guildData.filters.wordFilter.words.loose, guildData.filters.wordFilter.words.strict];
+    // Does the username contain filtered words
+    const usernameCheck = TestString(member.user.username, loose, strict, guildData.filters.wordFilter.enabled);
+    // Does the nickname contain filtered words
+    const nicknameCheck = TestString(member.nickname ?? "", loose, strict, guildData.filters.wordFilter.enabled);
+    // Does the profile picture contain filtered words
+    const avatarTextCheck = TestString(await TestImage(member.user.displayAvatarURL({ forceStatic: true })) ?? "", loose, strict, guildData.filters.wordFilter.enabled);
+    // Is the profile picture NSFW
+    const avatarCheck = guildData.filters.images.NSFW && await NSFWCheck(member.user.displayAvatarURL({ forceStatic: true }));
+    // Does the username contain an invite
+    const inviteCheck = guildData.filters.invite.enabled && member.user.username.match(/discord\.gg\/[a-zA-Z0-9]+/gi) !== null;
+    // Does the nickname contain an invite
+    const nicknameInviteCheck = guildData.filters.invite.enabled && member.nickname?.match(/discord\.gg\/[a-zA-Z0-9]+/gi) !== null;
+
+    if (usernameCheck !== null || nicknameCheck !== null || avatarCheck || inviteCheck || nicknameInviteCheck || avatarTextCheck !== null) {
+        const infractions = [];
+        if (usernameCheck !== null) {
+            infractions.push(`Username contains a ${usernameCheck.type}ly filtered word (${usernameCheck.word})`);
+        } if (nicknameCheck !== null) {
+            infractions.push(`Nickname contains a ${nicknameCheck.type}ly filtered word (${nicknameCheck.word})`);
+        } if (avatarCheck) {
+            infractions.push("Profile picture is NSFW");
+        } if (inviteCheck) {
+            infractions.push("Username contains an invite");
+        } if (nicknameInviteCheck) {
+            infractions.push("Nickname contains an invite");
+        } if (avatarTextCheck !== null) {
+            infractions.push(`Profile picture contains a ${avatarTextCheck.type}ly filtered word: ${avatarTextCheck.word}`);
+        }
+        if (infractions.length === 0) return;
+        // This is bad - Warn in the staff notifications channel
+        const filter = getEmojiByName("ICONS.FILTER");
+        const channel = guild.channels.cache.get(guildData.logging.staff.channel) as Discord.TextChannel;
+        const embed = new EmojiEmbed()
+            .setTitle("Member Flagged")
+            .setEmoji("ICONS.FLAGS.RED")
+            .setStatus("Danger")
+            .setDescription(`**Member:** ${member.user.username} (<@${member.user.id}>)\n\n` +
+                infractions.map((element) => `${filter} ${element}`).join("\n")
+            )
+        await channel.send({
+            embeds: [embed],
+            components: [new ActionRowBuilder<ButtonBuilder>().addComponents(...[
+                new ButtonBuilder()
+                    .setCustomId(`mod:warn:${member.user.id}`)
+                    .setLabel("Warn")
+                    .setStyle(ButtonStyle.Primary),
+                new ButtonBuilder()
+                    .setCustomId(`mod:mute:${member.user.id}`)
+                    .setLabel("Mute")
+                    .setStyle(ButtonStyle.Primary),
+                new ButtonBuilder()
+                    .setCustomId(`mod:kick:${member.user.id}`)
+                    .setLabel("Kick")
+                    .setStyle(ButtonStyle.Danger),
+                new ButtonBuilder()
+                    .setCustomId(`mod:ban:${member.user.id}`)
+                    .setLabel("Ban")
+                    .setStyle(ButtonStyle.Danger),
+            ].concat((usernameCheck !== null || nicknameCheck !== null || avatarTextCheck !== null) ? [
+                new ButtonBuilder()
+                    .setCustomId(`mod:nickname:${member.user.id}`)
+                    .setLabel("Change Name")
+                    .setStyle(ButtonStyle.Primary)
+            ] : []))]
+        });
+    }
+}
\ No newline at end of file
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index 6c601f7..e3c7a2a 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -1,7 +1,6 @@
 import { getCommandMentionByName } from "../utils/getCommandDataByName.js";
 import type { Guild, User } from "discord.js";
-import type { NucleusClient } from "../utils/client.js";
-import type { GuildMember } from "discord.js";
+import client from "../utils/client.js";
 import convertCurlyBracketString from "../utils/convertCurlyBracketString.js";
 import singleNotify from "../utils/singleNotify.js";
 
@@ -10,10 +9,8 @@
     name: string;
 }
 
-export async function callback(client: NucleusClient, member?: GuildMember, guild?: Guild, user?: User) {
-    if (!member && !guild) return;
-    guild = await client.guilds.fetch(member ? member.guild.id : guild!.id);
-    user = user ?? member!.user;
+export async function callback(user: User, guild: Guild) {
+    guild = await client.guilds.fetch(guild.id);
     const config = await client.database.guilds.read(guild.id);
     Object.entries(config.stats).forEach(async ([channel, props]) => {
         if ((props as PropSchema).enabled) {
@@ -22,16 +19,16 @@
             string = await convertCurlyBracketString(string, user!.id, user!.username, guild!.name, guild!.members);
             let fetchedChannel;
             try {
-                fetchedChannel = await guild!.channels.fetch(channel);
+                fetchedChannel = await guild.channels.fetch(channel);
             } catch (e) {
                 fetchedChannel = null;
             }
             if (!fetchedChannel) {
                 const deleted = config.stats[channel];
-                await client.database.guilds.write(guild!.id, null, `stats.${channel}`);
+                await client.database.guilds.write(guild.id, null, `stats.${channel}`);
                 return singleNotify(
                     "statsChannelDeleted",
-                    guild!.id,
+                    guild.id,
                     `One or more of your stats channels have been deleted. You can use ${getCommandMentionByName(
                         "settings/stats"
                     )}.\n` + `The channels name was: ${deleted!.name}`,
diff --git a/src/reflex/welcome.ts b/src/reflex/welcome.ts
index 5597b81..8e471c6 100644
--- a/src/reflex/welcome.ts
+++ b/src/reflex/welcome.ts
@@ -1,12 +1,11 @@
 import { getCommandMentionByName } from "./../utils/getCommandDataByName.js";
-import type { NucleusClient } from "../utils/client.js";
 import convertCurlyBracketString from "../utils/convertCurlyBracketString.js";
 import client from "../utils/client.js";
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import { GuildChannel, GuildMember, BaseGuildTextChannel } from "discord.js";
 import singleNotify from "../utils/singleNotify.js";
 
-export async function callback(_client: NucleusClient, member: GuildMember) {
+export async function callback(member: GuildMember) {
     if (member.user.bot) return;
     const config = await client.database.guilds.read(member.guild.id);
     if (!config.welcome.enabled) return;