После закрытия тикета приходит TXT файл, в котором текст не с последнего закрытого тикета, а с предпоследнего

Рейтинг: 0Ответов: 1Опубликовано: 25.05.2023

Решил по надобности создать бота для Discord сервера, вроде написал неплохую систему тикетов, но вот при сохранении тикета, в канал с логами и пользователю, который писал в Support, приходит TXT файл (информация) не из последнего закрытого тикета, а из предпоследнего, уже всё испробовал, сам решить проблему не смог, будет безмерно благодарен за помощь!

async def send_log(title: str, guild: discord.Guild, description: str, color: discord.Color, file: discord.File):
    log_channel = guild.get_channel(1107002290847613059)
    embed = discord.Embed(
        title=title,
        description=description,
        color=color
    )
    await log_channel.send(embed=embed, file=file)

class TrashButton(View):
    def __init__(self):
        super().__init__(timeout=None)

    @button(label="Delete the ticket", style=discord.ButtonStyle.red, emoji="🗑️", custom_id="trash")
    async def trash(self, interaction: discord.Interaction, button: Button):
        admin_role = interaction.guild.get_role(1104481120667586641)
        # Проверяем, есть ли у пользователя эта роль
        if admin_role in interaction.user.roles:
            await interaction.response.defer()
            await interaction.channel.send("Deleting the ticket in 1 seconds")
            await asyncio.sleep(5)
            messages = [message async for message in interaction.channel.history(limit=None, oldest_first=True)]
            print(messages)
            await interaction.channel.delete()
            with open('transcript.txt', 'r+b') as f:
                f.flush()
                await interaction.user.send(file=discord.File(f, 'transcript.txt'))
                await send_log(
                    title="Ticket Deleted",
                    description=f"Deleted by {interaction.user.mention}, ticket: {interaction.channel.name}",
                    color=discord.Color.red(),
                    guild=interaction.guild,
                    file=discord.File(r'transcript.txt')
                    )
            contents = [f"{message.author.display_name}: {message.content}" for message in messages]
            print(contents)
            final = ""
            for msg in contents:
                msg = msg + "\n"
                final = final + msg
            with open('transcript.txt', 'r+b') as f:
                f.truncate(0)
                f.write(final.encode('utf-8'))
                f.close()
                os.remove('transcript.txt')
        else:
            await interaction.response.send_message("You don't have permission to close this ticket.", ephemeral=True)

Ответы

▲ 1

Вы сохраняете текстовый файл до его обновления с последней информацией. Код сохраняет логи в файл до того, как он будет обновлен содержимым последнего закрытого тикета.

Нужно изменить порядок операций. Сначала сохраните содержимое последнего закрытого тикета в файл, а затем отправьте этот файл в канал с логами и пользователю.

upd: ClientOSError: [WinError 64] может возникать при попытке открыть файл в режиме записи ('w'), когда файл уже открыт в другом месте. В вашем коде вы открываете файл дважды, что может вызвать эту ошибку.

Для исправления следует закрыть файл после записи и затем открыть его для отправки пользователю и в канал с логами.

async def send_log(title: str, guild: discord.Guild, description: str, color: discord.Color, file: discord.File):
    log_channel = guild.get_channel(1107002290847613059)
    embed = discord.Embed(
        title=title,
        description=description,
        color=color
    )
    await log_channel.send(embed=embed, file=file)


class TrashButton(View):
    def __init__(self):
        super().__init__(timeout=None)

    @button(label="Delete the ticket", style=discord.ButtonStyle.red, emoji="🗑️", custom_id="trash")
    async def trash(self, interaction: discord.Interaction, button: Button):
        admin_role = interaction.guild.get_role(1104481120667586641)
        # Проверяем, есть ли у пользователя эта роль
        if admin_role in interaction.user.roles:
            await interaction.response.defer()
            await interaction.channel.send("Deleting the ticket in 1 second")
            await asyncio.sleep(5)
            messages = [message async for message in interaction.channel.history(limit=None, oldest_first=True)]
            print(messages)
            contents = [f"{message.author.display_name}: {message.content}" for message in messages]
            print(contents)
            final = ""
            for msg in contents:
                msg = msg + "\n"
                final = final + msg
            with open('transcript.txt', 'w', encoding='utf-8') as f:
                f.write(final)
            
            with open('transcript.txt', 'rb') as f:
                await interaction.user.send(file=discord.File(f, 'transcript.txt'))
            
            with open('transcript.txt', 'rb') as f:
                await send_log(
                    title="Ticket Deleted",
                    description=f"Deleted by {interaction.user.mention}, ticket: {interaction.channel.name}",
                    color=discord.Color.red(),
                    guild=interaction.guild,
                    file=discord.File(f, 'transcript.txt')
                )
            
            os.remove('transcript.txt')
        else:
            await interaction.response.send_message("You don't have permission to close this ticket.", ephemeral=True)

Файл transcript.txt открывается для записи и записывается в него содержимое. Затем файл открывается для отправки пользователю и в канал с логами. После этого файл удаляется.

Если проблема с ClientOSError: [WinError 64] все еще возникает, убедитесь, что никакое другое приложение или процесс не удерживает или блокирует файл transcript.txt во время выполнения вашего кода.