Теперь, добавим команду /blacklist (add|remove) (Пинг игрока, или его юзернейм). Данную команду смогут писать только игроки с ролью 1302341076157468802 и 1300437358063259658. Данная команда позволяет заблокировать или наоборот разблокировать игрока. Когда игрок заблокирован, он не может создавать заявки, даже если он нажмет на создание, канал не создасться и роль тоже, а ему будет сказано что он в черном списке. Как понять что игрок заблокирован? У него будет роль 1302348539271188511. Так-же, игрок не может блокировать сам себя, и добавлять в черный список игрока с ролью 1302341076157468802 и 1300437358063259658. Так-же если эту команду пишет не человек с разрешенной ролью, бот просто будет удалять сообщение с командой, а не отвечать на него.

import discord
from discord.ext import commands
from discord.ui import View, Select, Button, Modal, TextInput
from discord import SelectOption, ButtonStyle, Permissions
import asyncio  # Импорт для асинхронных задержек
from tokens import TOKENE
import datetime
from datetime import datetime
import pytz

TOKEN = TOKENE
CATEGORY_ID = 1300442089334636596
ADMIN_MENTION_ROLE_ID = 1300437358063259658
WELCOME_ROLE_ID = 1300388576722423828
WELCOME_CHANNEL_ID = 1300387074603618307
WEBHOOK_CHANNEL_ID = 1300390174496129044
LOG_CHANNEL_ID = 1302343284697337876  # ID канала для логирования заяво


intents = discord.Intents.default()
intents.members = True

bot = commands.Bot(command_prefix='!', intents=intents)

app_counter = 0

category_display_names = {
    "helper": "🧡 Хелпера",
    "builder": "💛 Билдера",
    "tech_admin": "❤️ Технического Администратора",
    "curator": "🖤 Куратора"
}

class ApplicationSelect(Select):
    def __init__(self):
        options = [
            SelectOption(label="🧡 Хелпер", value="helper"),
            SelectOption(label="💛 Билдер", value="builder"),
            SelectOption(label="❤️ Технический Администратор", value="tech_admin"),
            SelectOption(label="🖤 Куратор", value="curator"),
        ]
        super().__init__(placeholder="Выберите категорию", options=options)

    async def callback(self, interaction):
        selected_value = [option.label for option in self.options if option.value == self.values[0]][0]
        await interaction.response.send_message(f"Вы выбрали: {selected_value}", ephemeral=True)

class SubmitApplication(Button):
    def __init__(self):
        super().__init__(label="💛 | Подать заявку", style=ButtonStyle.primary)

    async def callback(self, interaction):
        try:
            selected_label = self.view.select.values[0]
        except IndexError:
            await interaction.response.send_message("Вы не выбрали категорию, либо произошла ошибка. Попробуйте снова.", ephemeral=True)
            return

        if selected_label not in category_display_names:
            await interaction.response.send_message("Вы выбрали неизвестную категорию. Попробуйте снова.", ephemeral=True)
            return

        global app_counter
        app_counter += 1

        guild = interaction.guild
        category = guild.get_channel(CATEGORY_ID)
        
        role_name = f"заявка-{app_counter}"
        channel_name = f"заявка-{app_counter}"

        # Настройка прав доступа в зависимости от выбранной категории
        if selected_label in ["helper", "builder"]:
            allowed_roles = [1300437358063259658, 1302341076157468802]
        else:  # "tech_admin", "curator"
            allowed_roles = [1300437358063259658, 1300387258893074435]

        # Создаем роль и канал с соответствующими правами доступа
        role = await guild.create_role(name=role_name)
        overwrites = {
            guild.default_role: discord.PermissionOverwrite(read_messages=False),
            role: discord.PermissionOverwrite(read_messages=True),
            guild.me: discord.PermissionOverwrite(read_messages=True)
        }

        # Добавляем права для ролей, которым нужно разрешить просмотр канала
        for allowed_role in allowed_roles:
            overwrites[guild.get_role(allowed_role)] = discord.PermissionOverwrite(read_messages=True)
        
        channel = await guild.create_text_channel(
            name=channel_name, 
            category=category,
            overwrites=overwrites
        )

        await interaction.user.add_roles(role)

        display_name = category_display_names.get(selected_label, "Unknown")

        embed = discord.Embed(
            title=f"Заявка на {display_name}",
            description=f"{interaction.user.mention} подал заявку. Напиши заявку в чат, чтобы ее рассмотрели. Просмотр заявки занимает максимально один день.\n\n1. Имя\n2. Еще что-то\n3. f\n\nДля закрытия заявки, нажмите кнопку закрыть внизу. Все остальные кнопки нажимать могут только администраторы/кураторы."
        )
        component_view = ChannelManageView(role, channel, interaction.user, selected_label)
        await channel.send(embed=embed, view=component_view)

        await interaction.response.send_message("Заявка была создана и назначена соответствующим пользователям.", ephemeral=True)


class CloseApplication(Button):
    def __init__(self, role, channel):
        super().__init__(label="❌ | Закрыть", style=ButtonStyle.danger)
        self.role = role
        self.channel = channel

    async def callback(self, interaction):
        if self.role in interaction.user.roles or len(self.view.children) <= 1:
            await interaction.response.send_message("✅ | Заявка закрыта. Она будет удалена через 5 секунд.", ephemeral=True)
            await asyncio.sleep(5)
            await self.channel.delete()
            await self.role.delete()
            

class AdminDecisionButton(Button):
    def __init__(self, label, style, role, channel, applicant, selected_label):
        super().__init__(label=label, style=style)
        self.role = role
        self.channel = channel
        self.applicant = applicant
        self.selected_label = selected_label

    async def callback(self, interaction):
        # Определяем роли, имеющие право рассматривать каждую категорию заявок
        allowed_roles = {
            "helper": [1300437358063259658, 1302341076157468802],
            "builder": [1300437358063259658, 1302341076157468802],
            "tech_admin": [1300437358063259658, 1300387258893074435],
            "curator": [1300437358063259658, 1300387258893074435]
        }
        # Получаем роли пользователя
        user_roles = [role.id for role in interaction.user.roles]
        # Проверяем, может ли пользователь рассматривать данную категорию заявок
        if any(role in user_roles for role in allowed_roles.get(self.selected_label, [])):
            if self.label == "⛔ | Отклонить":
                await interaction.response.send_modal(RejectModal(self.role, self.channel, self.applicant, interaction.user, self.selected_label))
            elif self.label == "✅ | Одобрить":
                await interaction.response.send_modal(AcceptModal(self.role, self.channel, self.applicant, interaction.user, self.selected_label))
        else:
            await interaction.response.send_message("У вас нет прав для этого действия.", ephemeral=True)

class RejectModal(Modal):
    def __init__(self, role, channel, applicant, actor, selected_label):
        super().__init__(title="Отклонение заявки")
        self.role = role
        self.channel = channel
        self.applicant = applicant
        self.actor = actor
        self.selected_label = selected_label

    reason = TextInput(label="Напишите причину отклонения", placeholder="Если причины нет, напишите '-'")

    async def on_submit(self, interaction):
        await interaction.response.send_message(f"Заявка отклонена: {self.reason.value}. Она будет удалена через 5 секунд.", ephemeral=True)
        await self.notify_applicant_and_actor(False)
        await self.log_decision(False)
        await asyncio.sleep(5)
        await self.channel.delete()
        await self.role.delete()  # Удаление роли заявки

    async def notify_applicant_and_actor(self, approved):
        verdict = "Отклонена" if not approved else "Одобрена"
        comment_text = f"Комментария не было предоставлено." if self.reason.value == "-" else f"Он также приложил комментарий: {self.reason.value}"
        msk_timezone = pytz.timezone('Europe/Moscow')
        now = datetime.now(msk_timezone)

        applicant_embed = discord.Embed(
            title=f"Вашу заявку на {category_display_names.get(self.selected_label, 'Unknown')} рассмотрели.",
            description=f"Ваша заявка была рассмотрена. Вердикт вынес {self.actor.name}. Ваша заявка была {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}"
        )

        actor_embed = discord.Embed(
            title=f"Вы рассмотрели заявку на {category_display_names.get(self.selected_label, 'Unknown')} от {self.applicant.name}.",
            description=f"Вы рассмотрели заявку. Вердикт: {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}"
        )

        await self.applicant.send(embed=applicant_embed)
        await self.actor.send(embed=actor_embed)

    async def log_decision(self, approved):
        log_channel = discord.utils.get(self.channel.guild.channels, id=LOG_CHANNEL_ID)
        if log_channel:
            verdict = "Отклонена" if not approved else "Одобрена"
            comment_text = f"Комментария не было предоставлено." if self.reason.value == "-" else f"Он также приложил комментарий: {self.reason.value}"
            msk_timezone = pytz.timezone('Europe/Moscow')
            now = datetime.now(msk_timezone)

            embed = discord.Embed(
                title=f"Заявка {category_display_names.get(self.selected_label, 'Unknown')} от {self.applicant.name} рассмотрена.",
                description=f"Была рассмотрена заявка. Вердикт: {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}. Закрыл: {self.actor.mention}. Кто подал заявку: {self.applicant.mention}"
            )
            await log_channel.send(embed=embed)

class AcceptModal(Modal):
    def __init__(self, role, channel, applicant, actor, selected_label):
        super().__init__(title="Одобрение заявки")
        self.role = role
        self.channel = channel
        self.applicant = applicant
        self.actor = actor
        self.selected_label = selected_label

    comment = TextInput(label="Комментарий к одобрению", placeholder="Если его нет, напишите '-'")

    async def on_submit(self, interaction):
        await interaction.response.send_message(f"Заявка одобрена: {self.comment.value}. Она будет удалена через 5 секунд.", ephemeral=True)
        await self.notify_applicant_and_actor(True)
        await self.log_decision(True)
        await asyncio.sleep(5)
        await self.channel.delete()
        await self.role.delete()  # Удаление роли заявки

    async def notify_applicant_and_actor(self, approved):
        verdict = "Отклонена" if not approved else "Одобрена"
        comment_text = f"Комментария не было предоставлено." if self.comment.value == "-" else f"Он также приложил комментарий: {self.comment.value}"
        msk_timezone = pytz.timezone('Europe/Moscow')
        now = datetime.now(msk_timezone)

        applicant_embed = discord.Embed(
            title=f"Вашу заявку на {category_display_names.get(self.selected_label, 'Unknown')} рассмотрели.",
            description=f"Ваша заявка была рассмотрена. Вердикт вынес {self.actor.name}. Ваша заявка была {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}"
        )

        actor_embed = discord.Embed(
            title=f"Вы рассмотрели заявку на {category_display_names.get(self.selected_label, 'Unknown')} от {self.applicant.name}.",
            description=f"Вы рассмотрели заявку. Вердикт: {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}"
        )

        await self.applicant.send(embed=applicant_embed)
        await self.actor.send(embed=actor_embed)

    async def log_decision(self, approved):
        log_channel = discord.utils.get(self.channel.guild.channels, id=LOG_CHANNEL_ID)
        if log_channel:
            verdict = "Отклонена" if not approved else "Одобрена"
            comment_text = f"Комментария не было предоставлено." if self.comment.value == "-" else f"Он также приложил комментарий: {self.comment.value}"
            msk_timezone = pytz.timezone('Europe/Moscow')
            now = datetime.now(msk_timezone)

            embed = discord.Embed(
                title=f"Заявка {category_display_names.get(self.selected_label, 'Unknown')} от {self.applicant.name} рассмотрена.",
                description=f"Была рассмотрена заявка. Вердикт: {verdict}. {comment_text}. Дата и время закрытия заявки: {now.strftime('%Y-%m-%d %H:%M:%S МСК')}. Закрыл: {self.actor.mention}. Кто подал заявку: {self.applicant.mention}"
            )
            await log_channel.send(embed=embed)
class ChannelManageView(View):
    def __init__(self, role, channel, applicant, selected_label):
        super().__init__()
        self.add_item(CloseApplication(role, channel))
        self.add_item(AdminDecisionButton("⛔ | Отклонить", ButtonStyle.danger, role, channel, applicant, selected_label))
        self.add_item(AdminDecisionButton("✅ | Одобрить", ButtonStyle.success, role, channel, applicant, selected_label))

class SelectApplicationView(View):
    def __init__(self):
        super().__init__()
        self.select = ApplicationSelect()
        self.add_item(self.select)
        self.add_item(SubmitApplication())

@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}')

    channel = bot.get_channel(WEBHOOK_CHANNEL_ID)
    for guild in bot.guilds:
        if channel and channel.guild.id == guild.id:
            server_name = discord.utils.escape_markdown(guild.name)
            embed = discord.Embed(
                title="Набор",
                description=f"На нашем сервере **{server_name}** проводится набор на хелперов, билдеров, Технических Администраторов и Кураторов. Чтобы подать заявку, выберите внизу ее категорию, и нажмите \"Подать заявку\"."
            )
            embed.set_footer(text="Это пример, настоящая функциональность будет добавлена позже.")
            view = SelectApplicationView()
            await channel.send(embed=embed, view=view)

@bot.event
async def on_member_join(member):
    role = discord.utils.get(member.guild.roles, id=WELCOME_ROLE_ID)
    if role:
        await member.add_roles(role)

    channel = member.guild.get_channel(WELCOME_CHANNEL_ID)
    if channel:
        ping = f'<@{member.id}>'
        server_name = discord.utils.escape_markdown(member.guild.name)
        welcome_message = f'Приветствуем тебя {ping} на сервере **{server_name}**'
        await channel.send(welcome_message)

bot.run(TOKEN)