Можете предложить рекомендации по улучшению кода?

У меня есть событие `on_message` в системе, написанной на Python, и я не совсем уверен, как сделать его более читабельным. Ранее я программировал на C и C#, но с Python я не так опытен. Я пытался разбить код на функции, но у меня это не удалось. Не могли бы вы показать пример того, как я могу улучшить свой код, или посоветовать ресурсы, которые помогут мне разобраться в этом сложном вопросе? <br/> <br/> <pre><code class="python">import database
import db_levels
import time
from disnake import Embed, Colour
from disnake.ext import commands

class XpController(commands.Cog):
    def __init__(self,bot: commands.Bot, guilds, xp_delay):
        self.bot = bot
        self.guilds = guilds
        self.xp_delay = xp_delay
        self.last_xp_update = {}
        
    @commands.Cog.listener()
    async def on_message(self, message):
        
        if message.author == self.bot.user:
            return
        
        user_id = message.author.id
        user_name = message.author.name
        xp_amount = 0
        current_time = time.time()
        if message.channel.id == 1233498806881095824:

            if message.attachments:
                xp_amount = 150
            else:
                xp_amount = 100

            if user_id in self.last_xp_update:
                time_since_last_update = current_time - self.last_xp_update[user_id]
                if time_since_last_update < self.xp_delay:
                    return

            self.last_xp_update[user_id] = current_time
            database.increase_xp(user_id, user_name, xp_amount)
        
            guild_id = message.guild.id
            guild = self.bot.get_guild(guild_id)
            member = guild.get_member(user_id)
        
            if db_levels.get_id_add_role(database.get_lvl...
  • 14 сентября 2024 г. 15:53
Ответы на вопрос 2
Чтобы улучшить читабельность и структуру вашего кода, можно разбить `on_message` на несколько более мелких функций. Это не только сделает ваш код более понятным и легким для сопровождения, но и упростит тестирование. Вот пример того, как можно реорганизовать ваш код:

```python
import database
import db_levels
import time
from disnake import Embed, Colour
from disnake.ext import commands

class XpController(commands.Cog):
    def __init__(self, bot: commands.Bot, guilds, xp_delay):
        self.bot = bot
        self.guilds = guilds
        self.xp_delay = xp_delay
        self.last_xp_update = {}

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.author == self.bot.user:
            return

        user_id = message.author.id
        
        if message.channel.id == 1233498806881095824:
            await self.handle_xp_update(message, user_id)

    async def handle_xp_update(self, message, user_id):
        current_time = time.time()

        # Determine XP amount
        xp_amount = self.calculate_xp_amount(message)

        # Check for update delay
        if not self.can_update_xp(user_id, current_time):
            return

        self.last_xp_update[user_id] = current_time
        user_name = message.author.name
        database.increase_xp(user_id, user_name, xp_amount)
        
        await self.check_and_assign_roles(message.guild.id, user_id)

    def calculate_xp_amount(self, message):
        if message.attachments:
            return 150
        return 100

    def can_update_xp(self, user_id, current_time):
        if user_id in self.last_xp_update:
            time_since_last_update = current_time - self.last_xp_update[user_id]
            return time_since_last_update >= self.xp_delay
        return True
    
    async def check_and_assign_roles(self, guild_id, user_id):
        guild = self.bot.get_guild(guild_id)
        member = guild.get_member(user_id)

        # Получаем уровень пользователя и назначаем роль, если необходимо
        level_id = db_levels.get_id_add_role(database.get_lvl(user_id))
        if level_id:
            role = discord.utils.get(guild.roles, id=level_id)
            if role and role not in member.roles:
                await member.add_roles(role)

```

### Комментарии по улучшениям:
1. **Разделение на функции**: Основная логика кода разделена на несколько построенных функций:
   - `handle_xp_update`: обрабатывает обновление XP.
   - `calculate_xp_amount`: вычисляет количество XP в зависимости от наличия вложений.
   - `can_update_xp`: проверяет, можно ли обновить XP для пользователя.
   - `check_and_assign_roles`: проверяет и назначает роли пользователю.

2. **Переименование функций**: Функции имеют понятные названия, которые указывают на их назначение.

3. **Асинхронность**: Если функция выполняет асинхронные действия (например, `member.add_roles`), важно, чтобы она была помечена как `async`.

4. **Использование `discord.utils.get`**: Это более безопасный и удобный способ получения ролей.

Эти изменения сделают ваш код более структурированным и дружелюбным для чтения. Также следите за тем, чтобы использовать комментарии и документацию, чтобы другим разработчикам было легче понимать ваш код (в том числе вам в будущем!).

### Ресурсы для изучения Python:
- [Официальная документация Python](https://docs.python.org/3/)
- [PEP 8 - Рекомендации по стилю кода Python](https://www.python.org/dev/peps/pep-0008/)
- Книги, такие как "Automate the Boring Stuff with Python" и "Python Crash Course".
- Видео-лекции на YouTube по Python и разработке на Discord с использованием библиотеки Disnake.
Ну вообще советую закидывать ивенты в основной файл, а не в ког(так будет читабельнее изза меньшего количества отступов) 

Также стоит добавить комментарии
Похожие вопросы