Skip to content
This repository was archived by the owner on Feb 7, 2026. It is now read-only.
90 changes: 90 additions & 0 deletions cogs/moderation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Imports
import discord
import time
from framework.isobot.db.warnings import Warnings
from discord import option, ApplicationContext
from discord.ext import commands

# Variables
warningsdb = Warnings()

# Commands
class Moderation(commands.Cog):
def __init__(self, bot):
Expand Down Expand Up @@ -38,5 +43,90 @@ async def ban(self, ctx: ApplicationContext, user, reason=None):
await ctx.respond(embed=discord.Embed(title=f'{user} has been banned.', description=f'Reason: {str(reason)}'))
except Exception: await ctx.respond(embed=discord.Embed(title='Well, something happened...', description='Either I don\'t have permission to do this, or my role isn\'t high enough.', color=discord.Colour.red()))

@commands.slash_command(
name="warn",
description="Warns the specified user, with a specific reason."
)
@option(name="user", description="Who do you want to warn?", type=discord.Member)
@option(name="reason", description="The reason why you are warning the user", type=str)
async def warn(self, ctx: ApplicationContext, user: discord.Member, reason: str):
"""Warns the specified user, with a specific reason."""
if not ctx.author.guild_permissions.manage_messages:
return await ctx.respond(
"""You can't use this command! You need the `Manage Messages` permission to run this.
If you think this is a mistake, contact your server administrator.""",
ephemeral=True
)
warningsdb.add_warning(ctx.guild.id, user.id, ctx.author.id, round(time.time()), reason)
warnembed = discord.Embed(
title=f":warning: You have been warned in **{ctx.guild.name}**",
description=f"Reason: {reason}",
color=discord.Color.red()
)
await user.send(embed=warnembed)
localembed = discord.Embed(
description=f":white_check_mark: **{user.display_name}** has been successfully warned.",
color=discord.Color.green()
)
await ctx.respond(embed=localembed)

@commands.slash_command(
name="clear_all_warnings",
description="Clears all the warnings from the specified user."
)
@option(name="user", description="The user whose warnings you want to clear.", type=discord.Member)
async def clear_all_warning(self, ctx: ApplicationContext, user: discord.Member):
"""Clears all the warnings from the specified user."""
if not ctx.author.guild_permissions.manage_messages:
return await ctx.respond(
"""You can't use this command! You need the `Manage Messages` permission to run this.
If you think this is a mistake, contact your server administrator.""",
ephemeral=True
)
warningsdb.clear_all_warnings(ctx.guild.id, user.id)
localembed = discord.Embed(
description=f":white_check_mark: Successfully cleared all server warnings for **{user.display_name}**.",
color=discord.Color.green()
)
await ctx.respond(embed=localembed)

@commands.slash_command(
name="show_warnings",
description="See all the server warnings for a specific user."
)
@option(name="user", description="The user whose warnings you want to view.", type=discord.Member, default=None)
async def show_warnings(self, ctx: ApplicationContext, user: discord.Member = None):
"""See all the server warnings for a specific user."""
await ctx.defer()
if user == None: user = ctx.author
all_user_warnings = warningsdb.fetch_all_warnings(ctx.guild.id, user.id)
parsed_output = str()
count = int()
for warning in all_user_warnings:
count += 1
mod_ctx = await ctx.bot.fetch_user(warning["moderator_id"])
parsed_output += f"{count}. **Warned by {mod_ctx.display_name}**\n> Reason: {warning['reason']}\n> Time Since Warn: <t:{warning['warning_ts']}:R>\n"
if parsed_output == "":
parsed_output = "*Nothing to see here...*"
localembed = discord.Embed(
title=f"All warnings for **{user.display_name}** in **{ctx.guild.name}**",
description=parsed_output,
color=discord.Color.random()
)
await ctx.respond(embed=localembed)

# User App Commands
@commands.user_command(
name="Clear All Warnings"
)
async def _clear_all_warnings(self, ctx: ApplicationContext, user: discord.Member):
await self.clear_all_warning(ctx, user)

@commands.user_command(
name="Show Warnings"
)
async def _show_warnings(self, ctx: ApplicationContext, user: discord.Member):
await self.show_warnings(ctx, user)

# Initialization
def setup(bot): bot.add_cog(Moderation(bot))
55 changes: 55 additions & 0 deletions framework/isobot/db/warnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""The framework module library used for managing isobot's warnings database."""

# Imports
import json
from framework.isobot.colors import Colors as colors

# Functions
class Warnings:
"""Used to initialize the warnings database."""
def __init__(self):
print(f"[framework/db/Warnings] {colors.green}Warnings db library initialized.{colors.end}")

def load(self) -> dict:
"""Fetches and returns the latest data from the warnings database."""
with open("database/warnings.json", 'r', encoding="utf8") as f: db = json.load(f)
return db

def save(self, data: dict) -> int:
"""Dumps all cached data to your local machine."""
with open("database/warnings.json", 'w+', encoding="utf8") as f: json.dump(data, f)
return 0

def generate(self, guild_id: int, user_id: int) -> int:
"""Generates a new database key for the user in the specified guild.\n\nReturns `0` if generation is successful."""
data = self.load()
if str(guild_id) not in data:
data[str(guild_id)] = {}
if str(user_id) not in data[str(guild_id)]:
data[str(guild_id)][str(user_id)] = []
self.save(data)
return 0

def add_warning(self, guild_id: int, user_id: int, moderator_id: int, warning_ts: int, reason: str) -> dict:
"""Adds a new warning entry to the user of the specified guild, in the database.\n\nReturns the warning data as a `dict`."""
data = self.load()
warning_data = {
"moderator_id": moderator_id,
"warning_ts": warning_ts,
"reason": reason
}
data[str(guild_id)][str(user_id)].append(warning_data)
self.save(data)
return warning_data

def clear_all_warnings(self, guild_id: int, user_id: int) -> int:
"""Clears all the warnings for the user in the specified guild."""
data = self.load()
data[str(guild_id)][str(user_id)] = []
self.save(data)
return 0

def fetch_all_warnings(self, guild_id: int, user_id: int) -> list:
"""Returns a `list` of all the warnings of the user in a specific guild."""
data = self.load()
return data[str(guild_id)][str(user_id)]
21 changes: 18 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from random import randint
from framework.isobot import currency, colors, settings, commands as _commands
from framework.isobot.shop import ShopData
from framework.isobot.db import levelling, items, userdata, automod, weather, presence as _presence
from framework.isobot.db import levelling, items, userdata, automod, weather, warnings, presence as _presence
from discord import ApplicationContext, option
from discord.ext import commands
from cogs.isocoin import create_isocoin_key
Expand All @@ -40,7 +40,19 @@ def initial_setup():

# Generating database files
try:
databases = ["automod", "currency", "isocard", "items", "levels", "presence", "user_data", "weather", "isobank/accounts", "isobank/auth"]
databases = [
"automod",
"currency",
"isocard",
"items",
"levels",
"warnings",
"presence",
"user_data",
"weather",
"isobank/accounts",
"isobank/auth"
]
for f in databases:
if not os.path.isfile(f"database/{f}.json"):
logger.warn(f"[main/Setup] '{f}.json' was not found in database directory. Creating new database...", module="main/Setup", nolog=True)
Expand Down Expand Up @@ -91,6 +103,7 @@ def initial_setup():
settings = settings.Configurator()
levelling = levelling.Levelling()
items = items.Items()
warningsdb = warnings.Warnings()
userdata = userdata.UserData()
automod = automod.Automod()
_presence = _presence.Presence()
Expand Down Expand Up @@ -173,7 +186,9 @@ async def on_message(ctx):
settings.generate(ctx.author.id)
items.generate(ctx.author.id)
levelling.generate(ctx.author.id)
try: automod.generate(ctx.guild.id)
try:
automod.generate(ctx.guild.id)
warningsdb.generate(ctx.guild.id, ctx.author.id)
except AttributeError: pass

try:
Expand Down