Repository: Cog-Creators/Red-DiscordBot

Issue:
[bug] the mod cog/core made bot super slow with making large setting files.
**What Red version are you using?**

3.4.5

**What were you trying to do?**

my bot were super slow my bot is in 4k servers and i unloaded the mod cog like [p]unload mod. then my bot is fast again. i checked whats going on with Process Monitor software and i saw the redbot in mod settings is making so many large files.( i think its bc it check the users changing their name and it save it to the settings or idk for real.)

**What did you expect to happen?**

it shouldnt bug the bot or slow down the bot like this. it use so much cpu too.

**What actually happened?**

please look at screenshot that i send
bot keep writing large files in settings = https://cdn.discordapp.com/attachments/760365719660527627/808880223063375882/unknown.png 
and here  : https://cdn.discordapp.com/attachments/760365719660527627/808880819481215016/unknown.png 



**How can we reproduce this error?**

1. load the mod cog/core
2. it keep making large files. 







Discussion:
There is an open issue suggesting a setting to disable name/nickname tracking, #4514. If you would like a setting such as that one, I recommend you add a comment to that issue.

Resolving patch:
diff --git a/redbot/cogs/mod/events.py b/redbot/cogs/mod/events.py
--- a/redbot/cogs/mod/events.py
+++ b/redbot/cogs/mod/events.py
@@ -161,6 +161,9 @@ async def on_message(self, message):
     @commands.Cog.listener()
     async def on_user_update(self, before: discord.User, after: discord.User):
         if before.name != after.name:
+            track_all_names = await self.config.track_all_names()
+            if not track_all_names:
+                return
             async with self.config.user(before).past_names() as name_list:
                 while None in name_list:  # clean out null entries from a bug
                     name_list.remove(None)
@@ -177,6 +180,10 @@ async def on_member_update(self, before: discord.Member, after: discord.Member):
             guild = after.guild
             if (not guild) or await self.bot.cog_disabled_in_guild(self, guild):
                 return
+            track_all_names = await self.config.track_all_names()
+            track_nicknames = await self.config.guild(guild).track_nicknames()
+            if (not track_all_names) or (not track_nicknames):
+                return
             async with self.config.member(before).past_nicks() as nick_list:
                 while None in nick_list:  # clean out null entries from a bug
                     nick_list.remove(None)
diff --git a/redbot/cogs/mod/mod.py b/redbot/cogs/mod/mod.py
--- a/redbot/cogs/mod/mod.py
+++ b/redbot/cogs/mod/mod.py
@@ -44,7 +44,10 @@ class Mod(
 ):
     """Moderation tools."""
 
-    default_global_settings = {"version": ""}
+    default_global_settings = {
+        "version": "",
+        "track_all_names": True,
+    }
 
     default_guild_settings = {
         "mention_spam": {"ban": None, "kick": None, "warn": None, "strict": False},
@@ -57,6 +60,7 @@ class Mod(
         "dm_on_kickban": False,
         "default_days": 0,
         "default_tempban_duration": 60 * 60 * 24,
+        "track_nicknames": True,
     }
 
     default_channel_settings = {"ignored": False}
diff --git a/redbot/cogs/mod/settings.py b/redbot/cogs/mod/settings.py
--- a/redbot/cogs/mod/settings.py
+++ b/redbot/cogs/mod/settings.py
@@ -18,7 +18,6 @@ class ModSettings(MixinMeta):
     """
 
     @commands.group()
-    @commands.guild_only()
     @checks.guildowner_or_permissions(administrator=True)
     async def modset(self, ctx: commands.Context):
         """Manage server administration settings."""
@@ -26,8 +25,19 @@ async def modset(self, ctx: commands.Context):
     @modset.command(name="showsettings")
     async def modset_showsettings(self, ctx: commands.Context):
         """Show the current server administration settings."""
+        globaldata = await self.config.all()
+        track_all_names = globaldata["track_all_names"]
+        msg = ""
+        msg += _("Track name changes: {yes_or_no}\n").format(
+            yes_or_no=_("Yes") if track_all_names else _("No")
+        )
         guild = ctx.guild
+        if not guild:
+            await ctx.send(box(msg))
+            return
+
         data = await self.config.guild(guild).all()
+        track_nicknames = data["track_nicknames"]
         delete_repeats = data["delete_repeats"]
         warn_mention_spam = data["mention_spam"]["warn"]
         kick_mention_spam = data["mention_spam"]["kick"]
@@ -39,7 +49,11 @@ async def modset_showsettings(self, ctx: commands.Context):
         dm_on_kickban = data["dm_on_kickban"]
         default_days = data["default_days"]
         default_tempban_duration = data["default_tempban_duration"]
-        msg = ""
+        if not track_all_names and track_nicknames:
+            yes_or_no = _("Overridden by another setting")
+        else:
+            yes_or_no = _("Yes") if track_nicknames else _("No")
+        msg += _("Track nickname changes: {yes_or_no}\n").format(yes_or_no=yes_or_no)
         msg += _("Delete repeats: {num_repeats}\n").format(
             num_repeats=_("after {num} repeats").format(num=delete_repeats)
             if delete_repeats != -1
@@ -401,6 +415,58 @@ async def defaultduration(
             )
         )
 
+    @modset.command()
+    @commands.guild_only()
+    async def tracknicknames(self, ctx: commands.Context, enabled: bool = None):
+        """
+        Toggle whether nickname changes should be tracked.
+
+        This setting will be overridden if trackallnames is disabled.
+        """
+        guild = ctx.guild
+        if enabled is None:
+            state = await self.config.guild(guild).track_nicknames()
+            if state:
+                msg = _("Nickname changes are currently being tracked.")
+            else:
+                msg = _("Nickname changes are not currently being tracked.")
+            await ctx.send(msg)
+            return
+
+        if enabled:
+            msg = _("Nickname changes will now be tracked.")
+        else:
+            msg = _("Nickname changes will no longer be tracked.")
+        await self.config.guild(guild).track_nicknames.set(enabled)
+        await ctx.send(msg)
+
+    @modset.command()
+    @commands.is_owner()
+    async def trackallnames(self, ctx: commands.Context, enabled: bool = None):
+        """
+        Toggle whether all name changes should be tracked.
+
+        Toggling this off also overrides the tracknicknames setting.
+        """
+        if enabled is None:
+            state = await self.config.track_all_names()
+            if state:
+                msg = _("Name changes are currently being tracked.")
+            else:
+                msg = _("All name changes are currently not being tracked.")
+            await ctx.send(msg)
+            return
+
+        if enabled:
+            msg = _("Name changes will now be tracked.")
+        else:
+            msg = _(
+                "All name changes will no longer be tracked.\n"
+                "To delete existing name data, use {command}."
+            ).format(command=f"`{ctx.clean_prefix}modset deletenames`")
+        await self.config.track_all_names.set(enabled)
+        await ctx.send(msg)
+
     @modset.command()
     @commands.max_concurrency(1, commands.BucketType.default)
     @commands.is_owner()


Test patch: