Untitled
unknown
python
a year ago
17 kB
10
Indexable
import discord
from discord.ext import commands, tasks
import sqlite3
import asyncio
import datetime
import os
from io import StringIO
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'
def setup_database():
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS tickets
(id INTEGER PRIMARY KEY AUTOINCREMENT,
channel_id INTEGER,
user_id INTEGER,
handler_id INTEGER,
reason TEXT,
status TEXT,
created_at DATETIME,
closed_at DATETIME,
last_activity DATETIME)''')
conn.commit()
conn.close()
class TicketView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
@discord.ui.button(label="Guide-Ticket erstellen", style=discord.ButtonStyle.green, custom_id="create_guide_ticket")
async def create_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
if await self.user_has_open_ticket(interaction.user.id):
await interaction.response.send_message("Du hast bereits ein offenes Ticket.", ephemeral=True)
return
modal = TicketReasonModal()
await interaction.response.send_modal(modal)
await modal.wait()
if modal.reason:
await self.create_ticket_channel(interaction, modal.reason)
async def user_has_open_ticket(self, user_id):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT COUNT(*) FROM tickets WHERE user_id = ? AND status = 'open'", (user_id,))
count = c.fetchone()[0]
conn.close()
return count > 0
async def create_ticket_channel(self, interaction, reason):
guild = interaction.guild
category = guild.get_channel(TICKET_CATEGORY_ID)
ticket_handler_role = guild.get_role(TICKET_HANDLER_ROLE_ID)
overwrites = {
guild.default_role: discord.PermissionOverwrite(read_messages=False),
interaction.user: discord.PermissionOverwrite(read_messages=True, send_messages=True),
ticket_handler_role: discord.PermissionOverwrite(read_messages=True, send_messages=True),
guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True, manage_channels=True)
}
channel = await category.create_text_channel(f"guide-ticket-{interaction.user.name}", overwrites=overwrites)
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("INSERT INTO tickets (channel_id, user_id, reason, status, created_at, last_activity) VALUES (?, ?, ?, ?, ?, ?)",
(channel.id, interaction.user.id, reason, 'open', datetime.datetime.now(), datetime.datetime.now()))
conn.commit()
conn.close()
embed = discord.Embed(title="Neues Guide-Ticket", description=f"Erstellt von {interaction.user.mention}\nGrund: {reason}", color=discord.Color.green())
await channel.send(embed=embed, view=TicketManagementView())
await channel.send(f"{interaction.user.mention} {ticket_handler_role.mention}")
await interaction.followup.send(f"Dein Guide-Ticket wurde erstellt: {channel.mention}", ephemeral=True)
class TicketReasonModal(discord.ui.Modal):
def __init__(self):
super().__init__(title="Grund für das Guide-Ticket")
self.reason = None
self.add_item(discord.ui.InputText(label="Grund", style=discord.InputTextStyle.paragraph))
async def callback(self, interaction: discord.Interaction):
self.reason = self.children[0].value
await interaction.response.defer()
class TicketManagementView(discord.ui.View):
def __init__(self):
super().__init__(timeout=None)
@discord.ui.button(label="schließen", style=discord.ButtonStyle.red, custom_id="close_ticket")
async def close_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
if interaction.user.get_role(TICKET_HANDLER_ROLE_ID):
await self.close_ticket_channel(interaction)
else:
await interaction.response.send_message("Du hast keine Berechtigung, das Ticket zu schließen.", ephemeral=True)
@discord.ui.button(label="beanspruchen", style=discord.ButtonStyle.green, custom_id="claim_ticket")
async def claim_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
if interaction.user.get_role(TICKET_HANDLER_ROLE_ID):
await self.claim_ticket_channel(interaction)
else:
await interaction.response.send_message("Du hast keine Berechtigung, das Ticket zu beanspruchen.", ephemeral=True)
@discord.ui.button(label="freigeben", style=discord.ButtonStyle.gray, custom_id="release_ticket")
async def release_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
if interaction.user.get_role(TICKET_HANDLER_ROLE_ID):
await self.release_ticket_channel(interaction)
else:
await interaction.response.send_message("Du hast keine Berechtigung, das Ticket freizugeben.", ephemeral=True)
@discord.ui.button(label="priorität erhöhen", style=discord.ButtonStyle.blurple, custom_id="increase_priority")
async def increase_priority(self, button: discord.ui.Button, interaction: discord.Interaction):
await self.increase_ticket_priority(interaction)
@discord.ui.button(label="ticket übertragen", style=discord.ButtonStyle.gray, custom_id="transfer_ticket")
async def transfer_ticket(self, button: discord.ui.Button, interaction: discord.Interaction):
if interaction.user.get_role(TICKET_HANDLER_ROLE_ID):
await self.transfer_ticket_channel(interaction)
else:
await interaction.response.send_message("Du hast keine Berechtigung, das Ticket zu übertragen.", ephemeral=True)
async def close_ticket_channel(self, interaction):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("UPDATE tickets SET status = 'closed', closed_at = ? WHERE channel_id = ?",
(datetime.datetime.now(), interaction.channel.id))
conn.commit()
conn.close()
transcript = await self.create_transcript(interaction.channel)
transcript_channel = interaction.guild.get_channel(TRANSCRIPT_CHANNEL_ID)
file = discord.File(StringIO(transcript), filename=f"transcript-{interaction.channel.name}.html")
await transcript_channel.send(f"Transcript für {interaction.channel.mention}", file=file)
user_id = await self.get_ticket_user(interaction.channel.id)
user = interaction.guild.get_member(user_id)
if user:
await self.send_rating_form(user)
await interaction.channel.delete()
async def claim_ticket_channel(self, interaction):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("UPDATE tickets SET handler_id = ? WHERE channel_id = ?", (interaction.user.id, interaction.channel.id))
conn.commit()
conn.close()
await interaction.channel.set_permissions(interaction.user, send_messages=True)
await interaction.channel.set_permissions(interaction.guild.get_role(TICKET_HANDLER_ROLE_ID), send_messages=False)
await interaction.response.send_message(f"{interaction.user.mention} hat dieses Ticket beansprucht.")
async def release_ticket_channel(self, interaction):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("UPDATE tickets SET handler_id = NULL WHERE channel_id = ?", (interaction.channel.id,))
conn.commit()
conn.close()
await interaction.channel.set_permissions(interaction.guild.get_role(TICKET_HANDLER_ROLE_ID), send_messages=True)
await interaction.response.send_message(f"{interaction.user.mention} hat dieses Ticket freigegeben.")
async def increase_ticket_priority(self, interaction):
priority_channel = interaction.guild.get_channel(PRIORITY_CHANNEL_ID)
await priority_channel.send(f"<@&{TICKET_HANDLER_ROLE_ID}> Das Ticket {interaction.channel.mention} benötigt dringende Bearbeitung!")
await interaction.response.send_message("Die Priorität des Tickets wurde erhöht.")
async def transfer_ticket_channel(self, interaction):
modal = TicketTransferModal()
await interaction.response.send_modal(modal)
await modal.wait()
if modal.transfer_to:
member = interaction.guild.get_member_named(modal.transfer_to)
if member and member.get_role(TICKET_HANDLER_ROLE_ID):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("UPDATE tickets SET handler_id = ? WHERE channel_id = ?", (member.id, interaction.channel.id))
conn.commit()
conn.close()
await interaction.channel.set_permissions(member, send_messages=True)
await interaction.channel.set_permissions(interaction.user, send_messages=False)
await interaction.followup.send(f"Das Ticket wurde an {member.mention} übertragen.")
await member.send(f"Das Ticket {interaction.channel.mention} wurde an dich übertragen.")
else:
await interaction.followup.send("Der angegebene Benutzer wurde nicht gefunden oder hat nicht die erforderliche Rolle.", ephemeral=True)
async def create_transcript(self, channel):
messages = await channel.history(limit=None).flatten()
transcript = "<html><head><style>body{font-family:Arial,sans-serif;} .message{margin-bottom:10px;} .author{font-weight:bold;}</style></head><body>"
for message in reversed(messages):
transcript += f"<div class='message'><span class='author'>{html.escape(message.author.name)}:</span> {html.escape(message.content)}</div>"
transcript += "</body></html>"
return transcript
async def get_ticket_user(self, channel_id):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT user_id FROM tickets WHERE channel_id = ?", (channel_id,))
user_id = c.fetchone()[0]
conn.close()
return user_id
async def send_rating_form(self, user):
embed = discord.Embed(title="Ticket-Bewertung", description="Bitte bewerte deine Erfahrung mit diesem Ticket.")
view = RatingView(self.bot)
await user.send(embed=embed, view=view)
class TicketTransferModal(discord.ui.Modal):
def __init__(self):
super().__init__(title="Ticket übertragen")
self.transfer_to = None
self.add_item(discord.ui.InputText(label="Übertragen an (Benutzername#Diskriminator)"))
async def callback(self, interaction: discord.Interaction):
self.transfer_to = self.children[0].value
await interaction.response.defer()
class TicketCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.check_inactivity.start()
def cog_unload(self):
self.check_inactivity.cancel()
@commands.Cog.listener()
async def on_ready(self):
print(f"Ticket-System ist bereit. Überprüfe bestehende Tickets...")
await self.setup_existing_tickets()
@commands.Cog.listener()
async def on_message(self, message):
if isinstance(message.channel, discord.TextChannel) and message.channel.category_id == TICKET_CATEGORY_ID:
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("UPDATE tickets SET last_activity = ? WHERE channel_id = ?", (datetime.datetime.now(), message.channel.id))
conn.commit()
conn.close()
@commands.slash_command(name="ticketsetup", description="Richtet das Ticket-System ein")
@commands.has_permissions(administrator=True)
async def ticket_setup(self, ctx):
embed = discord.Embed(title="Guide-Ticket System", description="Klicke auf den Button, um ein Guide-Ticket zu erstellen.")
await ctx.send(embed=embed, view=TicketView())
@commands.slash_command(name="tickettrack", description="Zeigt die Anzahl der bearbeiteten Guide-Tickets in den letzten zwei Wochen")
async def ticket_track(self, ctx):
two_weeks_ago = datetime.datetime.now() - datetime.timedelta(weeks=2)
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT COUNT(*) FROM tickets WHERE closed_at > ? AND status = 'closed'", (two_weeks_ago,))
count = c.fetchone()[0]
conn.close()
await ctx.respond(f"In den letzten zwei Wochen wurden {count} Guide-Tickets bearbeitet.")
@tasks.loop(minutes=5)
async def check_inactivity(self):
now = datetime.datetime.now()
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT channel_id, user_id, handler_id, last_activity FROM tickets WHERE status = 'open'")
tickets = c.fetchall()
for channel_id, user_id, handler_id, last_activity in tickets:
last_activity = datetime.datetime.fromisoformat(last_activity)
if now - last_activity > datetime.timedelta(hours=3):
await self.remind_ticket(channel_id, user_id, handler_id)
elif now - last_activity > datetime.timedelta(days=1):
await self.auto_close_ticket(channel_id, user_id, handler_id)
conn.close()
async def remind_ticket(self, channel_id, user_id, handler_id):
channel = self.bot.get_channel(channel_id)
if channel:
mentions = [f"<@{user_id}>"]
if handler_id:
mentions.append(f"<@{handler_id}>")
else:
mentions.append(f"<@&{TICKET_HANDLER_ROLE_ID}>")
await channel.send(f"{' '.join(mentions)} Dieses Ticket ist seit 3 Stunden inaktiv. Bitte setzt die Bearbeitung fort.")
async def auto_close_ticket(self, channel_id, user_id, handler_id):
channel = self.bot.get_channel(channel_id)
if channel:
await channel.send("Dieses Ticket wird aufgrund von Inaktivität geschlossen.")
await self.close_ticket_channel(channel)
user = self.bot.get_user(user_id)
if user:
await user.send("Dein Ticket wurde aufgrund von Inaktivität geschlossen.")
if handler_id:
handler = self.bot.get_user(handler_id)
if handler:
await handler.send(f"Das von dir beanspruchte Ticket in {channel.name} wurde aufgrund von Inaktivität geschlossen.")
async def setup_existing_tickets(self):
conn = sqlite3.connect(DATABASE_PATH)
c = conn.cursor()
c.execute("SELECT channel_id FROM tickets WHERE status = 'open'")
open_tickets = c.fetchall()
conn.close()
for channel_id in open_tickets:
channel = self.bot.get_channel(channel_id[0])
if channel:
await channel.send("Der Bot wurde neugestartet. Das Ticket-Management wurde wiederhergestellt.", view=TicketManagementView())
else:
print(f"Kanal mit ID {channel_id[0]} nicht gefunden. Möglicherweise wurde er gelöscht.")
class RatingView(discord.ui.View):
def __init__(self, bot):
super().__init__(timeout=None)
self.bot = bot
@discord.ui.select(
placeholder="Wähle eine Bewertung",
options=[discord.SelectOption(label=str(i), value=str(i)) for i in range(1, 6)]
)
async def select_rating(self, select: discord.ui.Select, interaction: discord.Interaction):
rating = int(select.values[0])
await interaction.response.send_modal(FeedbackModal(rating))
class FeedbackModal(discord.ui.Modal):
def __init__(self, rating):
super().__init__(title=f"Feedback für {rating}-Sterne Bewertung")
self.rating = rating
self.feedback = discord.ui.InputText(label="Dein Feedback", style=discord.InputTextStyle.long)
self.add_item(self.feedback)
async def callback(self, interaction: discord.Interaction):
feedback = self.feedback.value
transcript_channel = interaction.guild.get_channel(TRANSCRIPT_CHANNEL_ID)
embed = discord.Embed(title="Ticket-Bewertung", description=f"Bewertung: {self.rating} Sterne\nFeedback: {feedback}")
await transcript_channel.send(embed=embed)
await interaction.response.send_message("Vielen Dank für dein Feedback!", ephemeral=True)
def setup(bot):
setup_database()
bot.add_cog(TicketCog(bot))Editor is loading...
Leave a Comment