Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2767fc7
Switched cdn links to `https`
DevSnyco Jul 27, 2024
cc1c81a
Adding Global Chat Sync
DevSnyco Jul 27, 2024
b85fceb
Added database support for global chat
DevSnyco Jul 27, 2024
604d81b
Fixed variable error
DevSnyco Jul 27, 2024
f61a031
Added `internal_error_occured` property
DevSnyco Jul 27, 2024
aeef7ec
Working on `health` command (incomplete)
DevSnyco Jul 27, 2024
61bcb61
Deprecated `files` parameter for webhooks
DevSnyco Jul 27, 2024
2ad33dc
Added `version` property to bot
DevSnyco Aug 28, 2024
4c3bd9f
Converted `/cog health` to `/health`
DevSnyco Aug 28, 2024
33d03cf
Minimised repetitive code
DevSnyco Aug 28, 2024
a3ffd9a
Renamed `admin` cog
DevSnyco Aug 28, 2024
fbc282b
Added error handler cog
DevSnyco Aug 29, 2024
c6b8e64
Fixed `efficiency_description`
DevSnyco Aug 29, 2024
214048e
Create python-app.yml
DevSnyco Oct 5, 2024
80c9434
Update python-app.yml
DevSnyco Oct 5, 2024
a813ccf
Updated Workflow
DevSnyco Oct 14, 2024
e4d87fe
Env setup for workflow
DevSnyco Oct 14, 2024
cbee7cd
Remove Option for Non-TLS Mongo Connection
DevSnyco Oct 14, 2024
27ebd1b
Fixed Env Workflow push
DevSnyco Oct 14, 2024
6411dab
Attempt to fix python3.12 on workflow
DevSnyco Oct 14, 2024
33cd64d
Attempt to fix Python3.12
DevSnyco Oct 14, 2024
d766a6a
Attempt to fix Python3.12
DevSnyco Oct 14, 2024
a46b3d8
Switching to Python3.12.7
DevSnyco Oct 14, 2024
4c4a287
Python Version Range on Workflow
DevSnyco Oct 14, 2024
5ac9d9c
Added new `runs-on` property
DevSnyco Oct 14, 2024
94dd768
Testing different `setup-python` version
DevSnyco Oct 14, 2024
7d7e1f5
Merge branch 'master' into canary
DevSnyco Mar 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 0 additions & 42 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -1,42 +0,0 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

permissions:
contents: read

jobs:
build:

runs-on: prod

steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
- name: Run Bot
run: |
python3 ./index.py
92 changes: 0 additions & 92 deletions cogs/admin.py

This file was deleted.

4 changes: 2 additions & 2 deletions cogs/copyright.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ async def copyright(self, interaction: Interaction):
colour = 0x2B2D31
).set_author(
name = "Copyright Notice",
icon_url = "http://cdn.uwitz.org/r/justice.png"
icon_url = "https://cdn.uwitz.org/r/justice.png"
).set_footer(
text = "Uwitz Federation",
icon_url = "http://cdn.uwitz.org/r/shield-logo.png"
icon_url = "https://cdn.uwitz.org/r/shield-logo.png"
)
await interaction.response.send_message(
embed = embed,
Expand Down
135 changes: 135 additions & 0 deletions cogs/developer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import os

from typing import List

from discord import Embed, Interaction, Object
from discord.app_commands import Choice, Group, autocomplete, command
from discord.ext.commands import Bot, Cog

class Developer(Cog):
def __init__(self, bot: Bot):
self.bot = bot

async def unloaded_extension_list(
self,
interaction: Interaction,
current: str
) -> List[Choice[str]]:
return [
Choice(
name = extension,
value = extension
)
for extension in [
extension[:-3]
for extension in os.listdir("./cogs") if extension.endswith(".py")
] if (current.lower() in extension.lower()) and (extension not in self.bot.loaded_extension_list)
]

async def loaded_extension_list(
self,
interaction: Interaction,
current: str
) -> List[Choice[str]]:
return [
Choice(
name = extension,
value = extension
)
for extension in [
extension[:-3]
for extension in os.listdir("./cogs") if extension.endswith(".py")
] if (current.lower() in extension.lower()) and (extension in self.bot.loaded_extension_list)
]

cog = Group(name="cog", description = "Group of commands to manage cogs.")

@cog.command(name = "enable", description = "Load a cog to the bot's runtime")
@autocomplete(extension = unloaded_extension_list)
async def enable(self, interaction: Interaction, extension: str):
try:
await self.bot.load_extension(f"cogs.{extension}")
await interaction.response.send_message(
f"{os.getenv('EMOJI_SUCCESS')} Loaded `cogs.{extension}` extension"
)
except Exception as error:
await interaction.response.send_message(
f"{os.getenv('EMOJI_FAIL')} Unable to load `cogs.{extension}`\n```python\n{error}\n```",
ephemeral = True
)

@cog.command(name = "disable", description = "Unload a cog from the bot's runtime")
@autocomplete(extension = loaded_extension_list)
async def disable(self, interaction: Interaction, extension: str):
if extension == "developer":
return await interaction.response.send_message(f"{os.getenv('EMOJI_FAIL')} Unloading `cogs.{extension}` is disallowed")
try:
await self.bot.unload_extension(f"cogs.{extension}")
self.bot.loaded_extension_list.remove(extension)
await interaction.response.send_message(
f"{os.getenv('EMOJI_SUCCESS')} Unloaded `cogs.{extension}` extension"
)
except Exception as error:
await interaction.response.send_message(
f"{os.getenv('EMOJI_FAIL')} Unable to unload `cogs.{extension}`\n```python\n{error}\n```",
ephemeral = True
)

@cog.command(name = "restart", description = "Unload a cog from bots runtime to load updated code")
@autocomplete(extension = loaded_extension_list)
async def restart(self, interaction: Interaction, extension: str):
try:
await self.bot.reload_extension(f"cogs.{extension}")
await interaction.response.send_message(
f"{os.getenv('EMOJI_SUCCESS')} Reloaded `cogs.{extension}` extension"
)
except Exception as error:
await interaction.response.send_message(
f"{os.getenv('EMOJI_FAIL')} Unable to reload `cogs.{extension}`\n```python\n{error}\n```",
ephemeral = True
)

@command(name = "health", description = "Check the bot's developer information.")
async def health(self, interaction: Interaction):
unloaded_extensions = [
extension
for extension in [
extension[:-3]
for extension in os.listdir("./cogs") if extension.endswith(".py")
] if extension not in self.bot.loaded_extension_list
]
unloaded_extensions = ["null"] if len(unloaded_extensions) == 0 else unloaded_extensions

ping = round(self.bot.latency * 1000)
efficiency_description = "peak" if ping <= 50 and len(unloaded_extensions) == 0 else ("critical" if self.bot.internal_error_occured else "degraded")
status = "critical-health" if self.bot.internal_error_occured else ("degraded-health" if len(unloaded_extensions) > 0 or ping >= 125 else "good-health")
ping_emoji = os.getenv('EMOJI_GOODPING') if ping <= 50 else (os.getenv('EMOJI_MODERATEPING') if ping <= 125 else os.getenv('EMOJI_BADPING'))

embed = Embed(
description = f"Running `v{self.bot.version}` with `{efficiency_description}` performance",
colour = 0x2B2D31
).add_field(
name = "> Ping",
value = f"{ping_emoji} `{ping}ms`",
inline = True
).add_field(
name = "> Servers",
value = f"`{len(self.bot.guilds)}` *(`{len(self.bot.users)}` members)*",
inline = True
).add_field(
name = "> Loaded",
value = f"```diff\n+ {'\n+ '.join(self.bot.loaded_extension_list)}\n```",
inline = False
).add_field(
name = "> Unloaded",
value = f"```diff\n- {'\n- '.join(unloaded_extensions)}\n```",
inline = True
).set_author(
name = "Health Status",
icon_url = f"https://cdn.uwitz.org/r/{status}.png"
)

await interaction.response.send_message(embed = embed)

async def setup(bot: Bot):
await bot.add_cog(Developer(bot), guild = Object(os.getenv("GUILD")))
13 changes: 13 additions & 0 deletions cogs/error_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from discord.ext.commands import Bot, Cog

class ErrorHandler(Cog):
def __init__(self, bot: Bot):
self.bot = bot

@Cog.listener("on_error")
async def error_event(self, exception):
print(f"ERROR:\n{exception}")
self.bot.internal_error_occured = True

async def setup(bot: Bot):
await bot.add_cog(ErrorHandler(bot))
68 changes: 68 additions & 0 deletions cogs/mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,74 @@ class Mod(Cog):
def __init__(self, bot):
self.bot = bot

# @command(
# name = "ban",
# description = "Banish a member with a valid reason.",
# )
# @describe(member = "The member you'd like banned.")
# @describe(reason = "Why should the member be banned?")
# async def ban(self, interaction: Interaction, member: Member, reason: str):
# guild_config = await self.bot.database["config"].find_one(
# {
# "_id": interaction.guild.id
# }
# )
# report_channel = self.bot.get_channel(os.getenv("ENFORCEMENT"))
# if interaction.user.id in

# report_channel = self.bot.get_channel(os.getenv("ENFORCEMENT"))
# if not interaction.user.id == int(os.getenv("OWNER_ID")):
# guild_config = await self.bot.database["config"].find_one(
# {
# "_id": interaction.guild.id
# }
# )
# for role in guild_config.get("ADMINISTRATOR_ROLES"):
# if (interaction.guild.get_role(role) in interaction.user.roles) or (interaction.user.guild_permissions.administrator):
# if interaction.user.guild_permissions.administrator or (
# (os.getenv("ADMINISTRATOR_ROLE"), os.getenv("MODERATOR_ROLE")) in [role.id for role in interaction.user.roles]
# ):
# await interaction.response.send(f"{os.getenv("EMOJI_FAIL")} You are not authorised to moderate another person in authority.")
# break
# report = Embed(
# description = f"Sudo Banned by <@!{interaction.user.id}>\n\n**Reason:**\n```diff\n - {reason}```",
# timestamp = datetime.now(),
# color = 0xFF7A7A
# ).set_author(
# name = member.display_name,
# icon_url = member.display_avatar.url
# )

# try:
# await member.ban(
# reason = reason,
# delete_message_seconds = 60
# )
# except:
# return await interaction.response.send_message(f"{os.getenv("EMOJI_FAIL")} The Royal Defence is not authorised to ban this user.")

# await report_channel.send(embed = report)
# return await interaction.response.send_message(f"{os.getenv("EMOJI_SUCCESS")} Successfully Sudo Banished User.", ephemeral = True)

# confirmation_embed = Embed(
# description = f"Would you like to confirm that you want to send a ban report about <@!{member.id}> for:\n```diff\n- {reason}\n```",
# timestamp = datetime.now(),
# colour = 0xFF7A7A
# ).set_author(
# name = member.display_name,
# icon_url = member.display_avatar.url
# )

# await interaction.response.send_message(
# embed = confirmation_embed,
# view = Prompt(
# target_user = member,
# reason = reason,
# report_channel = report_channel
# )
# )
# break

@command(
name = "mute",
description = "Mute a member with a valid reason."
Expand Down
Loading
Loading