Untitled

 avatar
unknown
python
a year ago
16 kB
5
Indexable
import discord
from discord.ext import commands, tasks
from discord.ui import Button, View, Modal, InputText
import sqlite3
import os
import datetime
import html

# Konfiguration
TICKET_CATEGORY_ID = 1234149548192956457
TICKET_HANDLER_ROLE_ID = 1063979839478042624
PRIORITY_CHANNEL_ID = 1243627826851352666
TRANSCRIPT_CHANNEL_ID = 1245290800544219146
DATABASE_PATH = './database/tickets.db'


class TicketSystem(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.init_db()
        self.reminder.start()
        self.bot.loop.create_task(self.check_for_existing_panel())

    def init_db(self):
        if not os.path.exists('./database'):
            os.makedirs('./database')
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS tickets (
                        ticket_id INTEGER PRIMARY KEY AUTOINCREMENT,
                        channel_id INTEGER,
                        user_id INTEGER,
                        claimed_by INTEGER,
                        status TEXT,
                        reason TEXT,
                        priority INTEGER DEFAULT 0,
                        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                    )''')
        c.execute('''CREATE TABLE IF NOT EXISTS blocked_users (
                        user_id INTEGER PRIMARY KEY
                    )''')
        c.execute('''CREATE TABLE IF NOT EXISTS snippets (
                        snippet_name TEXT PRIMARY KEY,
                        snippet_content TEXT
                    )''')
        c.execute('''CREATE TABLE IF NOT EXISTS panels (
                        message_id INTEGER PRIMARY KEY,
                        channel_id INTEGER
                    )''')
        conn.commit()
        conn.close()

    async def check_for_existing_panel(self):
        await self.bot.wait_until_ready()
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT message_id, channel_id FROM panels')
        panel = c.fetchone()
        conn.close()
        if panel:
            channel = self.bot.get_channel(panel[1])
            message = await channel.fetch_message(panel[0])
            view = TicketCreateView(self.bot)
            await message.edit(view=view)

    @commands.command()
    @commands.has_permissions(administrator=True)
    async def createticket(self, ctx):
        embed = discord.Embed(title="Guide Ticket", description="Klicke auf den Button, um ein Ticket zu erstellen.", color=0x00ff00)
        view = TicketCreateView(self.bot)
        message = await ctx.send(embed=embed, view=view)
        
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('INSERT INTO panels (message_id, channel_id) VALUES (?, ?)', (message.id, ctx.channel.id))
        conn.commit()
        conn.close()

    @tasks.loop(hours=6)
    async def reminder(self):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT channel_id, user_id FROM tickets WHERE status = ?', ('open',))
        tickets = c.fetchall()
        conn.close()

        for ticket in tickets:
            channel = self.bot.get_channel(ticket[0])
            user = self.bot.get_user(ticket[1])
            if channel and user:
                await channel.send(f'{user.mention}, dein Ticket ist noch offen. Bitte schreibe was, damit das Ticket weitergeführt werden kann.')


class TicketCreateView(View):
    def __init__(self, bot):
        super().__init__(timeout=None)
        self.bot = bot

    @discord.ui.button(label="Ticket erstellen", style=discord.ButtonStyle.green)
    async def initiate_ticket_creation(self, button: discord.ui.Button, interaction: discord.Interaction):
        await interaction.response.send_modal(TicketReasonModal(self.bot))


class TicketReasonModal(Modal):
    def __init__(self, bot):
        super().__init__(title="Ticket Grund angeben")
        self.bot = bot
        self.add_item(InputText(label="Warum möchtest du ein Guide Ticket eröffnen?", style=discord.InputTextStyle.long))

    async def callback(self, interaction: discord.Interaction):
        reason = self.children[0].value
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT 1 FROM blocked_users WHERE user_id = ?', (interaction.user.id,))
        blocked = c.fetchone()
        conn.close()

        if blocked:
            await interaction.response.send_message('Du bist blockiert und kannst keine Tickets erstellen.', ephemeral=True)
        else:
            category = self.bot.get_channel(TICKET_CATEGORY_ID)
            overwrites = {
                interaction.guild.default_role: discord.PermissionOverwrite(read_messages=False),
                interaction.user: discord.PermissionOverwrite(read_messages=True, send_messages=True),
                interaction.guild.get_role(TICKET_HANDLER_ROLE_ID): discord.PermissionOverwrite(read_messages=True, send_messages=True),
            }
            ticket_channel = await category.create_text_channel(f'ticket-{interaction.user.name}', overwrites=overwrites)
            
            # Speichere Ticket in der Datenbank
            conn = sqlite3.connect(DATABASE_PATH)
            c = conn.cursor()
            c.execute('INSERT INTO tickets (channel_id, user_id, status, reason) VALUES (?, ?, ?, ?)', (ticket_channel.id, interaction.user.id, 'open', reason))
            conn.commit()
            conn.close()
            
            embed = discord.Embed(title="Ticket Management", description=f"Grund: {reason}", color=0x00ff00)
            await ticket_channel.send(f'Ticket erstellt von {interaction.user.mention}')
            view = TicketManagementView(ticket_channel.id, self.bot)
            embed = discord.Embed(title="Ticket Management", description=f"Grund: {reason}\nVerwende die untenstehenden Buttons, um das Ticket zu verwalten.", color=0x00ff00)
            await ticket_channel.send(embed=embed, view=view)


class TicketManagementView(View):
    def __init__(self, ticket_channel_id, bot):
        super().__init__(timeout=None)
        self.ticket_channel_id = ticket_channel_id
        self.bot = bot

    @discord.ui.button(label="Beanspruchen", style=discord.ButtonStyle.blurple)
    async def claim_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
        if TICKET_HANDLER_ROLE_ID in [role.id for role in interaction.user.roles]:
            conn = sqlite3.connect(DATABASE_PATH)
            c = conn.cursor()
            c.execute('SELECT claimed_by FROM tickets WHERE channel_id = ?', (self.ticket_channel_id,))
            claimed_by = c.fetchone()
            if claimed_by and claimed_by[0] is not None:
                await interaction.response.send_message('Dieses Ticket wurde bereits beansprucht.', ephemeral=True)
            else:
                c.execute('UPDATE tickets SET claimed_by = ? WHERE channel_id = ?', (interaction.user.id, self.ticket_channel_id))
                conn.commit()
                await interaction.response.send_message(f'Ticket beansprucht von {interaction.user.mention}', ephemeral=True)
            conn.close()
        else:
            await interaction.response.send_message('Du hast keine Berechtigung, dieses Ticket zu beanspruchen.', ephemeral=True)

    @discord.ui.button(label="Freigeben", style=discord.ButtonStyle.gray)
    async def release_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT claimed_by FROM tickets WHERE channel_id = ?', (self.ticket_channel_id,))
        claimed_by = c.fetchone()
        if claimed_by and claimed_by[0] == interaction.user.id:
            c.execute('UPDATE tickets SET claimed_by = NULL WHERE channel_id = ?', (self.ticket_channel_id,))
            conn.commit()
            await interaction.response.send_message(f'Ticket freigegeben von {interaction.user.mention}', ephemeral=True)
        else:
            await interaction.response.send_message('Du hast keine Berechtigung, dieses Ticket freizugeben.', ephemeral=True)
        conn.close()

    @discord.ui.button(label="Schließen", style=discord.ButtonStyle.red)
    async def close_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT claimed_by, user_id FROM tickets WHERE channel_id = ?', (self.ticket_channel_id,))
        ticket = c.fetchone()
        conn.close()
        if ticket and (ticket[0] == interaction.user.id or TICKET_HANDLER_ROLE_ID in [role.id for role in interaction.user.roles]):
            channel = self.bot.get_channel(self.ticket_channel_id)
            user = self.bot.get_user(ticket[1])
            messages = await channel.history(limit=None).flatten()

            transcript_content = f"""
            <html>
            <head>
                <style>
                    body {{ font-family: Arial, sans-serif; background-color: #f4f4f4; color: #333; }}
                    .message {{ border-bottom: 1px solid #ddd; padding: 10px; margin-bottom: 10px; }}
                    .message-author {{ font-weight: bold; color: #0073e6; }}
                    .message-content {{ margin-top: 5px; }}
                    .header {{ margin-bottom: 20px; }}
                    .timestamp {{ color: #666; font-size: 0.8em; }}
                    .container {{ padding: 20px; }}
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>Ticket Transkript - {channel.name}</h1>
                        <p><strong>Erstellt von:</strong> {user.name}</p>
                        <p><strong>Erstellt am:</strong> {channel.created_at.strftime('%Y-%m-%d %H:%M:%S')}</p>
                    </div>
                    <div class="messages">
            """
            for message in messages:
                timestamp = message.created_at.strftime('%Y-%m-%d %H:%M:%S')
                transcript_content += f"""
                    <div class="message">
                        <span class="message-author">{html.escape(message.author.name)}:</span>
                        <span class="timestamp">[{timestamp}]</span>
                        <div class="message-content">{html.escape(message.content)}</div>
                    </div>
                """
            transcript_content += """
                    </div>
                </div>
            </body>
            </html>
            """

            transcript_file_path = f'./database/transcript-{self.ticket_channel_id}.html'
            with open(transcript_file_path, 'w') as f:
                f.write(transcript_content)

            transcript_channel = self.bot.get_channel(TRANSCRIPT_CHANNEL_ID)
            await transcript_channel.send(file=discord.File(transcript_file_path))

            await channel.delete()

            # Logge den Ticketabschluss und lösche den Eintrag aus der Datenbank
            conn = sqlite3.connect(DATABASE_PATH)
            c = conn.cursor()
            c.execute('DELETE FROM tickets WHERE channel_id = ?', (self.ticket_channel_id,))
            conn.commit()
            conn.close()

            await interaction.response.send_message('Ticket geschlossen und gelöscht.', ephemeral=True)
        else:
            await interaction.response.send_message('Du hast keine Berechtigung, dieses Ticket zu schließen.', ephemeral=True)

    @discord.ui.button(label="Priorität erhöhen", style=discord.ButtonStyle.green)
    async def increase_priority(self, button: discord.ui.Button, interaction: discord.Interaction):
        if TICKET_HANDLER_ROLE_ID in [role.id for role in interaction.user.roles]:
            conn = sqlite3.connect(DATABASE_PATH)
            c = conn.cursor()
            c.execute('UPDATE tickets SET priority = priority + 1 WHERE channel_id = ?', (self.ticket_channel_id,))
            conn.commit()
            conn.close()
            await interaction.response.send_message('Priorität erhöht.', ephemeral=True)
        else:
            await interaction.response.send_message('Du hast keine Berechtigung, die Priorität zu ändern.', ephemeral=True)

    @discord.ui.button(label="Ticket übertragen", style=discord.ButtonStyle.blurple)
    async def transfer_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
        await interaction.response.send_modal(TransferModal(self.bot, self.ticket_channel_id))


class TransferModal(Modal):
    def __init__(self, bot, ticket_channel_id):
        super().__init__(title="Ticket übertragen")
        self.bot = bot
        self.ticket_channel_id = ticket_channel_id
        self.add_item(InputText(label="Nutzer-ID"))

    async def callback(self, interaction: discord.Interaction):
        user_id = int(self.children[0].value)
        user = self.bot.get_user(user_id)
        if user:
            conn = sqlite3.connect(DATABASE_PATH)
            c = conn.cursor()
            c.execute('UPDATE tickets SET claimed_by = ? WHERE channel_id = ?', (user.id, self.ticket_channel_id))
            conn.commit()
            conn.close()
            await interaction.response.send_message(f'Ticket wurde an {user.mention} übertragen.', ephemeral=True)
            await user.send(f'Dir wurde ein Ticket im Kanal {self.bot.get_channel(self.ticket_channel_id).mention} zugewiesen.')
        else:
            await interaction.response.send_message(f'Nutzer mit ID {user_id} nicht gefunden.', ephemeral=True)


class SnippetSystem(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.slash_command()
    async def create_snippet(self, ctx, name: str, content: str):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('INSERT OR REPLACE INTO snippets (snippet_name, snippet_content) VALUES (?, ?)', (name, content))
        conn.commit()
        conn.close()
        await ctx.send(f'Snippet "{name}" wurde erstellt.')

    @commands.slash_command()
    async def snippet(self, ctx, name: str):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('SELECT snippet_content FROM snippets WHERE snippet_name = ?', (name,))
        snippet = c.fetchone()
        conn.close()
        if snippet:
            await ctx.send(snippet[0])
        else:
            await ctx.send(f'Snippet "{name}" nicht gefunden.')

    @commands.slash_command()
    @commands.has_permissions(administrator=True)
    async def block_user(self, ctx, user_id: int):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('INSERT OR IGNORE INTO blocked_users (user_id) VALUES (?)', (user_id,))
        conn.commit()
        conn.close()
        await ctx.send(f'Nutzer mit ID {user_id} wurde blockiert.')

    @commands.slash_command()
    @commands.has_permissions(administrator=True)
    async def unblock_user(self, ctx, user_id: int):
        conn = sqlite3.connect(DATABASE_PATH)
        c = conn.cursor()
        c.execute('DELETE FROM blocked_users WHERE user_id = ?', (user_id,))
        conn.commit()
        conn.close()
        await ctx.send(f'Nutzer mit ID {user_id} wurde entblockiert.')


def setup(bot):
    bot.add_cog(TicketSystem(bot))
    bot.add_cog(SnippetSystem(bot))
Editor is loading...
Leave a Comment