1
Fork 0
mirror of https://github.com/allthingslinux/tux.git synced 2024-10-03 00:53:12 +00:00

Merge pull request #52 from allthingslinux/dev

[Feature] Implement Ruff Linting for Enhanced Code Quality
This commit is contained in:
ExploitDemon 2024-01-08 19:26:24 -07:00 committed by GitHub
commit 70757e9f45
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 176 additions and 262 deletions

View file

@ -1,5 +1,5 @@
name: 'Linting'
on: [push, pull_request]
on: [ push, pull_request ]
permissions:
contents: write
@ -8,7 +8,7 @@ permissions:
jobs:
Linting:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
@ -19,26 +19,13 @@ jobs:
with:
python-version: 3.11
# Install Poetry
- name: Poetry Install
uses: snok/install-poetry@v1.3.4
# Cache dependencies
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
# Use Lint Action for linting and formatting
- name: Run linters
uses: wearerequired/lint-action@v2.3.0
with:
github_token: ${{ secrets.github_token }}
auto_fix: true
# Install Ruff
- name: Install Ruff
run: sudo snap install ruff
# Run Ruff linter
- name: Run Ruff format
run: ruff format && ruff check . --fix
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'style fixes by linter'
commit_message: 'style fixes by ruff'

View file

@ -44,32 +44,32 @@ include = '\.pyi?$'
[tool.ruff]
# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
# Same as Black.
@ -87,7 +87,6 @@ target-version = "py311"
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
ignore = []
select = [
# pycodestyle
"E",
@ -102,6 +101,8 @@ select = [
# isort
"I",
]
ignore = ["E501"]
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
@ -147,32 +148,32 @@ docstring-code-line-length = "dynamic"
################################################################
[tool.pyright]
defineConstant = {DEBUG = true}
defineConstant = { DEBUG = true }
exclude = [
".direnv",
".eggs",
".git",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
".direnv",
".eggs",
".git",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
include = ["."]

View file

@ -1,6 +1,8 @@
# on_bulk_message_delete.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_channel_create.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_channel_delete.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,8 +1,10 @@
# on_guild_channel_pins_update.py
from datetime import datetime
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_channel_update.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_role_create.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_role_delete.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_guild_role_update.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_member_ban.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_member_join.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_member_remove.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_member_unban.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,43 +1,84 @@
# Import the necessary modules
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
# Initialize the logger
logger = TuxLogger(__name__)
# Define the OnMemberUpdate class, which is a subclass of commands.Cog
class OnMemberUpdate(commands.Cog):
# Initialize the class with the bot as an argument
def __init__(self, bot):
self.bot = bot
# Define a listener for the 'on_member_update' event
@commands.Cog.listener("on_member_update")
async def on_member_update(self, before: discord.Member, after: discord.Member):
"""
Handles the event when a Discord member updates their profile.
This function is triggered when a member's profile is updated. It
compares the before and after states of the member, logs any changes,
creates an embed for the changes, and sends the embed to a specified
channel.
"""
try:
# Compare the before and after states of the member
changes = self.compare_member_changes(before, after)
if changes:
# Log the changes
self.log_member_changes(changes)
# Create an embed for the changes
embed = self.create_embed_for_changes(changes)
# Send the embed to a specified channel
await self.send_embed(embed)
except Exception as e:
# Log any errors that occur
logger.error(f"Error handling member update: {e}")
This function is triggered when a member's nickname, roles, pending status, timeout status, guild avatar, or flags are modified. It does not react when a member's timeout expires due to a restriction in Discord.
def compare_member_changes(self, before, after):
"""
This function compares the before and after states of a member.
It currently only checks for changes in nickname, but more comparisons can be added as needed.
"""
changes = {}
if before.nick != after.nick:
changes["nickname"] = {"before": before.nick, "after": after.nick}
return changes
Args:
before (discord.Member): The previous state of the member before the update.
after (discord.Member): The updated state of the member after the update.
def log_member_changes(self, changes):
"""
This function logs any changes that have occurred.
"""
for change, values in changes.items():
logger.info(
f"{change} changed from {values['before']} to {values['after']}"
)
Note:
This function requires the `Intents.members` to be enabled.
def create_embed_for_changes(self, changes):
"""
This function creates an embed for the changes that have occurred.
"""
embed = discord.Embed(
title="Member Update", description="A member has updated their profile."
)
for change, values in changes.items():
embed.add_field(name=f"Old {change}", value=values["before"], inline=False)
embed.add_field(name=f"New {change}", value=values["after"], inline=False)
return embed
https://discordpy.readthedocs.io/en/stable/api.html#discord.on_member_update
""" # noqa E501
# TODO: On member update logic goes here.
# You can use the before and after objects to compare the changes.
# We should probably abstract this into multiple functions:
# 1. Comparing changes
# 2. Logging changes
# 3. Creating the embed
# 4. Sending the embed
logger.debug(f"Member {before} updated to {after}.")
async def send_embed(self, embed):
"""
This function sends the embed to a specified channel.
The channel ID needs to be replaced with the actual ID of the channel you want to send the embed to.
"""
some_channel = self.bot.get_channel(
"1191472088695980083"
) # Replace 'channel_id' with the actual ID
await some_channel.send(embed=embed)
# Define an asynchronous setup function that adds the OnMemberUpdate cog to the bot
async def setup(bot):
await bot.add_cog(OnMemberUpdate(bot))

View file

@ -1,6 +1,8 @@
# on_message.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_message_delete.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -1,6 +1,8 @@
# on_message_edit.py
import discord
from discord.ext import commands
from utils._tux_logger import TuxLogger
from tux.utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)

View file

@ -5,14 +5,12 @@ import discord
from cog_loader import CogLoader
from discord.ext import commands
from dotenv import load_dotenv
from utils.error_handler import ErrorHandler
from utils.tux_logger import TuxLogger
logger = TuxLogger(__name__)
load_dotenv()
from discord.ext import commands
from utils.error_handler import ErrorHandler
async def setup(bot: commands.Bot, debug: bool = False):
"""
@ -34,7 +32,7 @@ async def main():
@commands.has_permissions(administrator=True)
async def sync(ctx: commands.Context):
"""Syncs the slash command tree. This command is only available to administrators.
Args:
ctx (commands.Context): The invocation context sent by the Discord API which contains information
about the command and from where it was called.
@ -49,7 +47,7 @@ async def main():
@commands.has_permissions(administrator=True)
async def clear(ctx: commands.Context):
"""Clears the slash command tree. This command is only available to administrators.
Args:
ctx (commands.Context): The invocation context sent by the Discord API which contains information
about the command and from where it was called.
@ -64,11 +62,11 @@ async def main():
@bot.event
async def on_command_error(ctx: commands.Context, error):
"""Handles the event when a command has been invoked but an error has occurred.
Args:
ctx (commands.Context): The invocation context sent by the Discord API which contains information
about the command and from where it was called.
error (Exception): The error that occurred.
""" # noqa E501
if isinstance(error, commands.CommandNotFound):
@ -83,7 +81,7 @@ async def main():
@bot.event
async def on_command_completion(ctx: commands.Context):
"""Handles the event when a command has been completed its invocation. This event is called only if the command succeeded, i.e. all checks have passed and the user input it correctly.
Args:
ctx (commands.Context): The invocation context sent by the Discord API which contains information
about the command and from where it was called.
@ -100,7 +98,7 @@ async def main():
logger.info(f"{bot.user} has connected to Discord!", __name__)
await bot.start(os.getenv("TOKEN") or "", reconnect=True)
except Exception as e:
except Exception:
logger.error("An error occurred:", exc_info=True)

View file

@ -1,143 +0,0 @@
import os
import logging
import colorlog
from discord.ext import commands
# ==================
# Usage Instructions
# ==================
# Hey contributor, Ty here! To use the logger in your cog files, please follow these steps:
#
# 1. Import the logger by adding the following line at the top of your main bot file:
#
# from utils._tux_logger import TuxLogger
#
# logger = TuxLogger(__name__)
#
# 2. Once imported, you can use the logger to log messages in your code. For example:
# logger.info("This is an information message.")
# logger.warning("This is a warning message.")
# logger.error("This is an error message.")
# logger.debug("This is a debug message.")
#
# I love you all and thank you for contributing <3
# =========================
# End of Usage Instructions
# =========================
class TuxLogger(logging.Logger):
def __init__(self,
name,
project_logging_level=logging.INFO):
"""
Constructor for the custom logger class.
Parameters:
- name: The name of the logger.
- project_logging_level: The logging level for the project (default is INFO).
"""
super().__init__(name, level=project_logging_level)
self._setup_logging()
def _setup_logging(self):
"""
Set up the logging configuration for the custom logger.
"""
log_format = '%(asctime)s [%(log_color)s%(levelname)s%(reset)s] [%(name)s]: %(message)s'
log_dir = 'logs'
os.makedirs(log_dir, exist_ok=True)
handler = colorlog.StreamHandler()
handler.setFormatter(colorlog.ColoredFormatter(log_format))
self.addHandler(handler)
file_handler = logging.FileHandler(
os.path.join(log_dir, 'bot.log'),
mode='a'
)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s [%(levelname)s] [%(name)s]: %(message)s'))
self.addHandler(file_handler)
def _log_to_file(self, level, message, caller_module):
"""
Log a message to a specific file.
Parameters:
- level: The logging level (e.g., logging.DEBUG, logging.INFO, etc.).
- message: The log message.
- filename: The name of the file to log to.
"""
file_handler = logging.FileHandler(
os.path.join('logs', f"{caller_module}.log"),
mode='a'
)
file_handler.setFormatter(
logging.Formatter(
f'%(asctime)s [%(levelname)s] [{caller_module}]: %(message)s'
)
)
self.addHandler(file_handler)
self.log(level, message)
self.removeHandler(file_handler)
def exception(self, message, filename="unknown"):
self._log_to_file(logging.ERROR, message, filename, exc_info=True)
def debug(self, message, filename="unknown"):
self._log_to_file(logging.DEBUG, message, filename)
def info(self, message, filename="unknown"):
self._log_to_file(logging.INFO, message, filename)
def warning(self, message, filename="unknown"):
self._log_to_file(logging.WARNING, message, filename)
def error(self, message, filename="unknown"):
self._log_to_file(logging.ERROR, message, filename)
def critical(self, message, filename="unknown"):
self._log_to_file(logging.CRITICAL, message, filename)
class LoggingCog(commands.Cog):
def __init__(self,
bot,
discord_logging_level=logging.WARNING):
"""
Constructor for the LoggingCog class.
Parameters:
- bot: The Discord bot instance.
- discord_logging_level: The logging level for the Discord library (default is WARNING).
"""
self.bot = bot
self.discord_logging_level = discord_logging_level
discord_logger = logging.getLogger('discord')
discord_logger.setLevel(self.discord_logging_level)
logger = TuxLogger(__name__)
async def setup(bot,
project_logging_level=logging.DEBUG,
discord_logging_level=logging.WARNING):
"""
Asynchronous function to set up the LoggingCog and add it to the Discord bot.
Parameters:
- bot: The Discord bot instance.
- project_logging_level: The logging level for the project (default is DEBUG).
- discord_logging_level: The logging level for the Discord library (default is WARNING).
"""
global logger
log_cog = LoggingCog(
bot,
discord_logging_level
)
logger.setLevel(project_logging_level)
await bot.add_cog(log_cog)