From 716ed6da4e459b7792f8d746464777124dfd51b2 Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:59:31 +0000 Subject: [PATCH 1/6] Made File --- TicketDiscord.py | 183 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 TicketDiscord.py diff --git a/TicketDiscord.py b/TicketDiscord.py new file mode 100644 index 0000000..f5471dd --- /dev/null +++ b/TicketDiscord.py @@ -0,0 +1,183 @@ +# way to run: python TicketDiscord.py token mode_role_id ticket_creation_channel ticket_transcript_channel + +import argparse +import nextcord +import logging +import asyncio +import sys +import os + +from nextcord.ext import commands + +class AddUser(nextcord.ui.UserSelect): + def __init__(self, channel): + super.__init__( + "Add User To Ticket", + timeout = None + ) + self.thread = channel + + self.user = nextcord.ui.UserSelect( + custom_id = "add_user:1", + placeholder = "Select a user to add to the ticket.", + max_values = 1 + ) + + self.add_item(self.user) + + async def callback(self, interaction: nextcord.Interaction) -> None: + user = self.user + if user == None: + return await interaction.send("Please set a user next time | 404 No user found on input") + overwrite = nextcord.PermissionOverwrite() + overwrite.read_messages = True + await self.channel.set_permissions(user, overwrite = overwrite) + await interaction.send(f"{user.mention} Has been added to the ticket | Success") + +class RemoveUser(nextcord.ui.UserSelect): + def __init__(self, channel): + super.__init__( + "Remove User From Ticket", + timeout = None + ) + self.thread = channel + + self.user = nextcord.ui.UserSelect( + custom_id = "remove_user:1", + placeholder = "Select a user to add to the ticket.", + max_values = 1 + ) + + self.add_item(self.user) + + async def callback(self, interaction: nextcord.Interaction) -> None: + user = self.user + if user == None: + return await interaction.send("Please set a user next time | 404 No user found on input") + overwrite = nextcord.PermissionOverwrite() + overwrite.read_messages = False + await self.channel.set_permissions(user, overwrite = overwrite) + await interaction.send(f"{user.mention} Has been removed from the ticket | Success") + +class CreateTicket(nextcord.ui.View): + def __init__(self): + super.__init__(timeout = None) + + args = self.parse_args() + + @nextcord.ui.button( + label = "Create A Ticket", style = nextcord.ButtonStyle.blurple, custom_id = "create_ticket:blurple" + ) + async def CreateTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + msg = await interaction.send("A ticket is being created... ", ephemeral = True) + + overwrites = { + interaction.guild.default_role: nextcord.PermissionOverwrite(read_messages = False), + interaction.guild.me: nextcord.PermissonOverwrite(read_messages = True), + interaction.guild.get_role(args.mod_role): nextcord.PermissionOverwrite(read_messages = True) + } + + channel = args.ticket_creation_channel + thread = await channel.create_thread(name = f"{interaction.user.name} | Ticket ", overwrites = overwrites) + + embed = nextcord.Embed(title = f"Ticket created! | {interaction.user.mention} Created a ticket!", description = "Click on the buttons below to change the ticket's settings!") + await thread.send(embed = embed, view = TicketSettings()) + + + await asyncio.sleep(10) + await msg.edit(f"Success! A ticket has been created! {interaction.channel.mention}") + +class TicketSettings(nextcord.ui.View): + def __init__(self): + super.__init__(timeout = None) + + args = self.parse_args() + + @nextcord.ui.button( + label = "Close Ticket", style = nextcord.ButtonStyle.red, custom_id = "ticket_settings:red" + ) + async def CloseTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + messages = await interaction.channel.history(limit = None, oldest_first=True).flatten() + contents = [message.content for message in messages] + final = "" + for msg in contents: + msg = msg + "\n" + final = final + msg + + with open('transcript.txt', 'w') as f: + f.write(final) + + await interaction.response.send_message("The ticket will be closed shortly!") + await asyncio.sleep(10) + await self.thread.delete() + channel = args.ticket_transcript_channel + await interaction.user.send(f"Your ticket in {interaction.guild_id} was closed succesfully!") + await channel.send(file=nextcord.File(r"transcript.txt")) + os.remove("transcript.txt") + + @nextcord.ui.button( + label = "Add Member", style = nextcord.ButtonStyle.green, custom_id = "ticket_settings:green" + ) + async def AddUserToTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + await interaction.response.send_modal(AddUser(interaction.channel)) + + @nextcord.ui.button( + label = "Remove Member", style = nextcord.ButtonStyle.gray, custom_id = "ticket_settings:gray" + ) + async def RemoveUserFromTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + await interaction.response.send_modal(RemoveUser(interaction.channel)) + +class Bot: + def __init__(self, *args, **kwargs): + super.__init__(*args, **kwargs) + self.persisent_views_added = False + + async def on_ready(self): + if not self.persisent_views_added(): + self.add_view(CreateTicket()) + self.add_view(TicketSettings()) + self.persisent_views_added = True + print("✅Persistent views added!") + + print(f"Bot is up! | Logged in as {self.user}") + +class TicketBot: + def __init__(self, token): + self.bot = Bot(command_prefix = "!", intents = nextcord.Intents.all()) + self.token = token + + @self.bot.slash_command() + @commands.application_checks.has_permission(manage_guild = True) + async def setup(interaction: nextcord.Interaction, channel: nextcord.TextChannel): + await channel.send(embed = nextcord.Embed(type = "rich", title = "Create a ticket", description = "Click the button below to create a ticket and a moderator will be with you shortly!"), view = CreateTicket) + + def run(self): + self.bot.run(self.token) + +def parse_args(): + parser = argparse.ArgumentParser(description="Run a ticket bot on Discord.") + parser.add_argument('token', type=str, help='Discord Bot Token') + parser.add_argument("mod_role_id", type = int, help = "Discord Ticket Moderator Role ID") + parser.add_argument("ticket_creation_channel", type = str, help = "Discord Channel ID to create the ticket threads in") + parser.add_argument("ticket_transcript_channel", type = str, help = "Discord Channel ID to send the transcrpits at") + return parser.parse_args() + +if __name__ == '__main__': + args = parse_args() + + if args.token == "PUTYOURTOKENHERE": + print("You need to set the token in the startup tab.") + sys.exit(1) + elif args.mod_role_id == "PUTYOURTICKETMODROLEIDHERE": + print("You need to set your ticket moderator role id") + sys.exit(1) + elif args.ticket_creation_channel == "PUTYOURTICKETCREATIONCHANNELIDHERE": + print("You need to set your ticket creation channel id") + sys.exit(1) + elif args.ticket_creation_channel == "PUTYOURDISCORDTRANSCRIPTCHANNELIDHERE": + print("You need to set a channel id for ticket trascripts") + sys.exit(1) + + ticket_bot = TicketBot(args.token) + ticket_bot.run() + \ No newline at end of file From 12b9fbcef5b9207be2612deec81a69c96821fb1b Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:16:14 +0000 Subject: [PATCH 2/6] Working version, I believe --- TicketDiscord.py | 237 ++++++++++++++++++++++------------------------- 1 file changed, 111 insertions(+), 126 deletions(-) diff --git a/TicketDiscord.py b/TicketDiscord.py index f5471dd..cf2ba85 100644 --- a/TicketDiscord.py +++ b/TicketDiscord.py @@ -1,183 +1,168 @@ -# way to run: python TicketDiscord.py token mode_role_id ticket_creation_channel ticket_transcript_channel +# way to run: python TicketDiscord.py token mod_role_id ticket_creation_channel ticket_transcript_channel import argparse import nextcord -import logging import asyncio import sys import os from nextcord.ext import commands -class AddUser(nextcord.ui.UserSelect): +class AddUser(nextcord.ui.Modal): def __init__(self, channel): - super.__init__( - "Add User To Ticket", - timeout = None - ) - self.thread = channel - - self.user = nextcord.ui.UserSelect( - custom_id = "add_user:1", - placeholder = "Select a user to add to the ticket.", - max_values = 1 + super().__init__(title="Add User To Ticket", timeout=None) + self.channel = channel + self.user = nextcord.ui.TextInput( + label="User ID", + placeholder="Enter the user ID to add to the ticket", + required=True ) - self.add_item(self.user) - async def callback(self, interaction: nextcord.Interaction) -> None: - user = self.user - if user == None: - return await interaction.send("Please set a user next time | 404 No user found on input") - overwrite = nextcord.PermissionOverwrite() - overwrite.read_messages = True - await self.channel.set_permissions(user, overwrite = overwrite) - await interaction.send(f"{user.mention} Has been added to the ticket | Success") + async def callback(self, interaction: nextcord.Interaction): + try: + user_id = int(self.user.value) + user = await interaction.guild.fetch_member(user_id) + overwrite = nextcord.PermissionOverwrite() + overwrite.read_messages = True + await self.channel.set_permissions(user, overwrite=overwrite) + await interaction.response.send_message(f"{user.mention} has been added to the ticket!", ephemeral=True) + except Exception as e: + await interaction.response.send_message(f"Error: {e}", ephemeral=True) -class RemoveUser(nextcord.ui.UserSelect): + +class RemoveUser(nextcord.ui.Modal): def __init__(self, channel): - super.__init__( - "Remove User From Ticket", - timeout = None - ) - self.thread = channel - - self.user = nextcord.ui.UserSelect( - custom_id = "remove_user:1", - placeholder = "Select a user to add to the ticket.", - max_values = 1 + super().__init__(title="Remove User From Ticket", timeout=None) + self.channel = channel + self.user = nextcord.ui.TextInput( + label="User ID", + placeholder="Enter the user ID to remove from the ticket", + required=True ) - self.add_item(self.user) - async def callback(self, interaction: nextcord.Interaction) -> None: - user = self.user - if user == None: - return await interaction.send("Please set a user next time | 404 No user found on input") - overwrite = nextcord.PermissionOverwrite() - overwrite.read_messages = False - await self.channel.set_permissions(user, overwrite = overwrite) - await interaction.send(f"{user.mention} Has been removed from the ticket | Success") + async def callback(self, interaction: nextcord.Interaction): + try: + user_id = int(self.user.value) + user = await interaction.guild.fetch_member(user_id) + overwrite = nextcord.PermissionOverwrite() + overwrite.read_messages = False + await self.channel.set_permissions(user, overwrite=overwrite) + await interaction.response.send_message(f"{user.mention} has been removed from the ticket!", ephemeral=True) + except Exception as e: + await interaction.response.send_message(f"Error: {e}", ephemeral=True) -class CreateTicket(nextcord.ui.View): - def __init__(self): - super.__init__(timeout = None) - args = self.parse_args() +class CreateTicket(nextcord.ui.View): + def __init__(self, mod_role_id, ticket_creation_channel): + super().__init__(timeout=None) + self.mod_role_id = mod_role_id + self.ticket_creation_channel = ticket_creation_channel @nextcord.ui.button( - label = "Create A Ticket", style = nextcord.ButtonStyle.blurple, custom_id = "create_ticket:blurple" + label="Create A Ticket", style=nextcord.ButtonStyle.blurple, custom_id="create_ticket" ) - async def CreateTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - msg = await interaction.send("A ticket is being created... ", ephemeral = True) + async def create_ticket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + msg = await interaction.response.send_message("Creating ticket...", ephemeral=True) overwrites = { - interaction.guild.default_role: nextcord.PermissionOverwrite(read_messages = False), - interaction.guild.me: nextcord.PermissonOverwrite(read_messages = True), - interaction.guild.get_role(args.mod_role): nextcord.PermissionOverwrite(read_messages = True) + interaction.guild.default_role: nextcord.PermissionOverwrite(read_messages=False), + interaction.guild.me: nextcord.PermissionOverwrite(read_messages=True), + interaction.guild.get_role(self.mod_role_id): nextcord.PermissionOverwrite(read_messages=True), } - channel = args.ticket_creation_channel - thread = await channel.create_thread(name = f"{interaction.user.name} | Ticket ", overwrites = overwrites) - - embed = nextcord.Embed(title = f"Ticket created! | {interaction.user.mention} Created a ticket!", description = "Click on the buttons below to change the ticket's settings!") - await thread.send(embed = embed, view = TicketSettings()) + channel = interaction.guild.get_channel(self.ticket_creation_channel) + thread = await channel.create_thread(name=f"{interaction.user.name}-ticket", type=nextcord.ChannelType.public_thread) + embed = nextcord.Embed(title="Ticket Created!", description=f"{interaction.user.mention} created a ticket!") + await thread.send(embed=embed, view=TicketSettings(thread)) - await asyncio.sleep(10) - await msg.edit(f"Success! A ticket has been created! {interaction.channel.mention}") + await asyncio.sleep(2) + await msg.edit(content=f"Success! Your ticket has been created: {thread.mention}") class TicketSettings(nextcord.ui.View): - def __init__(self): - super.__init__(timeout = None) - - args = self.parse_args() + def __init__(self, thread): + super().__init__(timeout=None) + self.thread = thread @nextcord.ui.button( - label = "Close Ticket", style = nextcord.ButtonStyle.red, custom_id = "ticket_settings:red" + label="Close Ticket", style=nextcord.ButtonStyle.red, custom_id="close_ticket" ) - async def CloseTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - messages = await interaction.channel.history(limit = None, oldest_first=True).flatten() - contents = [message.content for message in messages] - final = "" - for msg in contents: - msg = msg + "\n" - final = final + msg - - with open('transcript.txt', 'w') as f: - f.write(final) - - await interaction.response.send_message("The ticket will be closed shortly!") - await asyncio.sleep(10) + async def close_ticket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + messages = [msg async for msg in self.thread.history(limit=None, oldest_first=True)] + content = "\n".join([msg.content for msg in messages]) + + with open("transcript.txt", "w") as f: + f.write(content) + + await interaction.response.send_message("Closing ticket...", ephemeral=True) + await asyncio.sleep(2) await self.thread.delete() - channel = args.ticket_transcript_channel - await interaction.user.send(f"Your ticket in {interaction.guild_id} was closed succesfully!") - await channel.send(file=nextcord.File(r"transcript.txt")) + + transcript_channel = interaction.guild.get_channel(args.ticket_transcript_channel) + await transcript_channel.send(file=nextcord.File("transcript.txt")) os.remove("transcript.txt") - + @nextcord.ui.button( - label = "Add Member", style = nextcord.ButtonStyle.green, custom_id = "ticket_settings:green" + label="Add Member", style=nextcord.ButtonStyle.green, custom_id="add_member" ) - async def AddUserToTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - await interaction.response.send_modal(AddUser(interaction.channel)) - + async def add_user(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + await interaction.response.send_modal(AddUser(self.thread)) + @nextcord.ui.button( - label = "Remove Member", style = nextcord.ButtonStyle.gray, custom_id = "ticket_settings:gray" + label="Remove Member", style=nextcord.ButtonStyle.gray, custom_id="remove_member" ) - async def RemoveUserFromTicket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - await interaction.response.send_modal(RemoveUser(interaction.channel)) + async def remove_user(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + await interaction.response.send_modal(RemoveUser(self.thread)) -class Bot: - def __init__(self, *args, **kwargs): - super.__init__(*args, **kwargs) - self.persisent_views_added = False - async def on_ready(self): - if not self.persisent_views_added(): - self.add_view(CreateTicket()) - self.add_view(TicketSettings()) - self.persisent_views_added = True - print("✅Persistent views added!") - - print(f"Bot is up! | Logged in as {self.user}") - -class TicketBot: - def __init__(self, token): - self.bot = Bot(command_prefix = "!", intents = nextcord.Intents.all()) +class TicketBot(commands.Bot): + def __init__(self, token, mod_role_id, ticket_creation_channel, ticket_transcript_channel): + intents = nextcord.Intents.all() + super().__init__(command_prefix="!", intents=intents) self.token = token - - @self.bot.slash_command() - @commands.application_checks.has_permission(manage_guild = True) - async def setup(interaction: nextcord.Interaction, channel: nextcord.TextChannel): - await channel.send(embed = nextcord.Embed(type = "rich", title = "Create a ticket", description = "Click the button below to create a ticket and a moderator will be with you shortly!"), view = CreateTicket) + self.mod_role_id = mod_role_id + self.ticket_creation_channel = ticket_creation_channel + self.ticket_transcript_channel = ticket_transcript_channel + + async def on_ready(self): + self.add_view(CreateTicket(self.mod_role_id, self.ticket_creation_channel)) + print(f"✅ Bot is online as {self.user}") + + @nextcord.slash_command() + async def setup(self, interaction: nextcord.Interaction, channel: nextcord.TextChannel): + embed = nextcord.Embed(title="Create a Ticket", description="Click the button below to create a ticket!") + await channel.send(embed=embed, view=CreateTicket(self.mod_role_id, self.ticket_creation_channel)) + + def run_bot(self): + self.run(self.token) - def run(self): - self.bot.run(self.token) def parse_args(): parser = argparse.ArgumentParser(description="Run a ticket bot on Discord.") - parser.add_argument('token', type=str, help='Discord Bot Token') - parser.add_argument("mod_role_id", type = int, help = "Discord Ticket Moderator Role ID") - parser.add_argument("ticket_creation_channel", type = str, help = "Discord Channel ID to create the ticket threads in") - parser.add_argument("ticket_transcript_channel", type = str, help = "Discord Channel ID to send the transcrpits at") + parser.add_argument("token", type=str, help="Discord Bot Token") + parser.add_argument("mod_role_id", type=int, help="Discord Ticket Moderator Role ID") + parser.add_argument("ticket_creation_channel", type=int, help="Discord Channel ID to create the ticket threads in") + parser.add_argument("ticket_transcript_channel", type=int, help="Discord Channel ID to send the transcripts to") return parser.parse_args() -if __name__ == '__main__': + +if __name__ == "__main__": args = parse_args() if args.token == "PUTYOURTOKENHERE": - print("You need to set the token in the startup tab.") + print("You need to set the token in the startup.") sys.exit(1) - elif args.mod_role_id == "PUTYOURTICKETMODROLEIDHERE": - print("You need to set your ticket moderator role id") + if args.mod_role_id == "PUTYOURTICKETMODROLEIDHERE": + print("You need to set your ticket moderator role ID.") sys.exit(1) - elif args.ticket_creation_channel == "PUTYOURTICKETCREATIONCHANNELIDHERE": - print("You need to set your ticket creation channel id") + if args.ticket_creation_channel == "PUTYOURTICKETCREATIONCHANNELIDHERE": + print("You need to set your ticket creation channel ID.") sys.exit(1) - elif args.ticket_creation_channel == "PUTYOURDISCORDTRANSCRIPTCHANNELIDHERE": - print("You need to set a channel id for ticket trascripts") + if args.ticket_transcript_channel == "PUTYOURDISCORDTRANSCRIPTCHANNELIDHERE": + print("You need to set your ticket transcript channel ID.") sys.exit(1) - ticket_bot = TicketBot(args.token) - ticket_bot.run() - \ No newline at end of file + bot = TicketBot(args.token, args.mod_role_id, args.ticket_creation_channel, args.ticket_transcript_channel) + bot.run_bot() \ No newline at end of file From 3ef7030ca4fd0c7756d697f569b0826db5e400cb Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:30:21 +0000 Subject: [PATCH 3/6] finished, working stage i believe --- TicketDiscord.py | 3 + TicketDiscordRequirements.txt | 129 ++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 TicketDiscordRequirements.txt diff --git a/TicketDiscord.py b/TicketDiscord.py index cf2ba85..bf5fcc0 100644 --- a/TicketDiscord.py +++ b/TicketDiscord.py @@ -1,4 +1,7 @@ # way to run: python TicketDiscord.py token mod_role_id ticket_creation_channel ticket_transcript_channel +# python 3.12.1: version tested to work +# gonna need to do `pip install setuptools` for the 3.12 version of the panel, or `pip install setuptools==pip install setuptools==39.1.0` +# or setuptools==69.5.1 import argparse import nextcord diff --git a/TicketDiscordRequirements.txt b/TicketDiscordRequirements.txt new file mode 100644 index 0000000..8a02138 --- /dev/null +++ b/TicketDiscordRequirements.txt @@ -0,0 +1,129 @@ +aiohappyeyeballs==2.4.6 +aiohttp==3.11.12 +aiosignal==1.3.2 +anyio==4.7.0 +argon2-cffi==23.1.0 +argon2-cffi-bindings==21.2.0 +arrow==1.3.0 +asttokens==3.0.0 +async-lru==2.0.4 +attrs==24.2.0 +babel==2.16.0 +beautifulsoup4==4.12.3 +bleach==6.2.0 +certifi==2024.8.30 +cffi==1.17.1 +charset-normalizer==3.4.0 +colorama==0.4.6 +comm==0.2.2 +contourpy==1.3.1 +cycler==0.12.1 +debugpy==1.8.9 +decorator==5.1.1 +defusedxml==0.7.1 +executing==2.1.0 +fastjsonschema==2.21.1 +filelock==3.13.1 +fonttools==4.55.3 +fqdn==1.5.1 +frozenlist==1.5.0 +fsspec==2024.2.0 +gitdb==4.0.11 +GitPython==3.1.43 +h11==0.14.0 +httpcore==1.0.7 +httpx==0.28.1 +idna==3.10 +ipykernel==6.29.5 +ipython==8.30.0 +isoduration==20.11.0 +jedi==0.19.2 +Jinja2==3.1.4 +joblib==1.4.2 +json5==0.10.0 +jsonpointer==3.0.0 +jsonschema==4.23.0 +jsonschema-specifications==2024.10.1 +jupyter-events==0.10.0 +jupyter-lsp==2.2.5 +jupyter-server-mathjax==0.2.6 +jupyter_client==8.6.3 +jupyter_core==5.7.2 +jupyter_server==2.14.2 +jupyter_server_terminals==0.5.3 +jupyterlab==4.3.3 +jupyterlab_git==0.50.2 +jupyterlab_pygments==0.3.0 +jupyterlab_server==2.27.3 +kiwisolver==1.4.7 +MarkupSafe==3.0.2 +matplotlib==3.9.3 +matplotlib-inline==0.1.7 +mistune==3.0.2 +mpmath==1.3.0 +multidict==6.1.0 +nbclient==0.10.1 +nbconvert==7.16.4 +nbdime==4.0.2 +nbformat==5.10.4 +nest-asyncio==1.6.0 +networkx==3.2.1 +nextcord==3.0.1 +notebook_shim==0.2.4 +numpy==2.2.0 +overrides==7.7.0 +packaging==24.2 +pandas==2.2.3 +pandocfilters==1.5.1 +parso==0.8.4 +pexpect==4.9.0 +pillow==11.0.0 +platformdirs==4.3.6 +plotly==5.24.1 +prometheus_client==0.21.1 +prompt_toolkit==3.0.48 +propcache==0.3.0 +psutil==6.1.0 +ptyprocess==0.7.0 +pure_eval==0.2.3 +pycparser==2.22 +Pygments==2.18.0 +pyparsing==3.2.0 +python-dateutil==2.9.0.post0 +python-json-logger==3.2.0 +pytz==2024.2 +PyYAML==6.0.2 +pyzmq==26.2.0 +referencing==0.35.1 +requests==2.32.3 +rfc3339-validator==0.1.4 +rfc3986-validator==0.1.1 +rpds-py==0.22.3 +scikit-learn==1.6.0 +scipy==1.14.1 +seaborn==0.13.2 +Send2Trash==1.8.3 +setuptools==75.6.0 +six==1.17.0 +smmap==5.0.1 +sniffio==1.3.1 +soupsieve==2.6 +stack-data==0.6.3 +sympy==1.13.1 +tenacity==9.0.0 +terminado==0.18.1 +threadpoolctl==3.5.0 +tinycss2==1.4.0 +torch==2.5.1+cpu +tornado==6.4.2 +traitlets==5.14.3 +types-python-dateutil==2.9.0.20241206 +typing_extensions==4.12.2 +tzdata==2024.2 +uri-template==1.3.0 +urllib3==2.2.3 +wcwidth==0.2.13 +webcolors==24.11.1 +webencodings==0.5.1 +websocket-client==1.8.0 +yarl==1.18.3 \ No newline at end of file From 01b25914de04e73635b85c72f9f543f54ceb4ba4 Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:23:25 +0300 Subject: [PATCH 4/6] Delete TicketDiscord.py --- TicketDiscord.py | 171 ----------------------------------------------- 1 file changed, 171 deletions(-) delete mode 100644 TicketDiscord.py diff --git a/TicketDiscord.py b/TicketDiscord.py deleted file mode 100644 index bf5fcc0..0000000 --- a/TicketDiscord.py +++ /dev/null @@ -1,171 +0,0 @@ -# way to run: python TicketDiscord.py token mod_role_id ticket_creation_channel ticket_transcript_channel -# python 3.12.1: version tested to work -# gonna need to do `pip install setuptools` for the 3.12 version of the panel, or `pip install setuptools==pip install setuptools==39.1.0` -# or setuptools==69.5.1 - -import argparse -import nextcord -import asyncio -import sys -import os - -from nextcord.ext import commands - -class AddUser(nextcord.ui.Modal): - def __init__(self, channel): - super().__init__(title="Add User To Ticket", timeout=None) - self.channel = channel - self.user = nextcord.ui.TextInput( - label="User ID", - placeholder="Enter the user ID to add to the ticket", - required=True - ) - self.add_item(self.user) - - async def callback(self, interaction: nextcord.Interaction): - try: - user_id = int(self.user.value) - user = await interaction.guild.fetch_member(user_id) - overwrite = nextcord.PermissionOverwrite() - overwrite.read_messages = True - await self.channel.set_permissions(user, overwrite=overwrite) - await interaction.response.send_message(f"{user.mention} has been added to the ticket!", ephemeral=True) - except Exception as e: - await interaction.response.send_message(f"Error: {e}", ephemeral=True) - - -class RemoveUser(nextcord.ui.Modal): - def __init__(self, channel): - super().__init__(title="Remove User From Ticket", timeout=None) - self.channel = channel - self.user = nextcord.ui.TextInput( - label="User ID", - placeholder="Enter the user ID to remove from the ticket", - required=True - ) - self.add_item(self.user) - - async def callback(self, interaction: nextcord.Interaction): - try: - user_id = int(self.user.value) - user = await interaction.guild.fetch_member(user_id) - overwrite = nextcord.PermissionOverwrite() - overwrite.read_messages = False - await self.channel.set_permissions(user, overwrite=overwrite) - await interaction.response.send_message(f"{user.mention} has been removed from the ticket!", ephemeral=True) - except Exception as e: - await interaction.response.send_message(f"Error: {e}", ephemeral=True) - - -class CreateTicket(nextcord.ui.View): - def __init__(self, mod_role_id, ticket_creation_channel): - super().__init__(timeout=None) - self.mod_role_id = mod_role_id - self.ticket_creation_channel = ticket_creation_channel - - @nextcord.ui.button( - label="Create A Ticket", style=nextcord.ButtonStyle.blurple, custom_id="create_ticket" - ) - async def create_ticket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - msg = await interaction.response.send_message("Creating ticket...", ephemeral=True) - - overwrites = { - interaction.guild.default_role: nextcord.PermissionOverwrite(read_messages=False), - interaction.guild.me: nextcord.PermissionOverwrite(read_messages=True), - interaction.guild.get_role(self.mod_role_id): nextcord.PermissionOverwrite(read_messages=True), - } - - channel = interaction.guild.get_channel(self.ticket_creation_channel) - thread = await channel.create_thread(name=f"{interaction.user.name}-ticket", type=nextcord.ChannelType.public_thread) - - embed = nextcord.Embed(title="Ticket Created!", description=f"{interaction.user.mention} created a ticket!") - await thread.send(embed=embed, view=TicketSettings(thread)) - - await asyncio.sleep(2) - await msg.edit(content=f"Success! Your ticket has been created: {thread.mention}") - -class TicketSettings(nextcord.ui.View): - def __init__(self, thread): - super().__init__(timeout=None) - self.thread = thread - - @nextcord.ui.button( - label="Close Ticket", style=nextcord.ButtonStyle.red, custom_id="close_ticket" - ) - async def close_ticket(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - messages = [msg async for msg in self.thread.history(limit=None, oldest_first=True)] - content = "\n".join([msg.content for msg in messages]) - - with open("transcript.txt", "w") as f: - f.write(content) - - await interaction.response.send_message("Closing ticket...", ephemeral=True) - await asyncio.sleep(2) - await self.thread.delete() - - transcript_channel = interaction.guild.get_channel(args.ticket_transcript_channel) - await transcript_channel.send(file=nextcord.File("transcript.txt")) - os.remove("transcript.txt") - - @nextcord.ui.button( - label="Add Member", style=nextcord.ButtonStyle.green, custom_id="add_member" - ) - async def add_user(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - await interaction.response.send_modal(AddUser(self.thread)) - - @nextcord.ui.button( - label="Remove Member", style=nextcord.ButtonStyle.gray, custom_id="remove_member" - ) - async def remove_user(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): - await interaction.response.send_modal(RemoveUser(self.thread)) - - -class TicketBot(commands.Bot): - def __init__(self, token, mod_role_id, ticket_creation_channel, ticket_transcript_channel): - intents = nextcord.Intents.all() - super().__init__(command_prefix="!", intents=intents) - self.token = token - self.mod_role_id = mod_role_id - self.ticket_creation_channel = ticket_creation_channel - self.ticket_transcript_channel = ticket_transcript_channel - - async def on_ready(self): - self.add_view(CreateTicket(self.mod_role_id, self.ticket_creation_channel)) - print(f"✅ Bot is online as {self.user}") - - @nextcord.slash_command() - async def setup(self, interaction: nextcord.Interaction, channel: nextcord.TextChannel): - embed = nextcord.Embed(title="Create a Ticket", description="Click the button below to create a ticket!") - await channel.send(embed=embed, view=CreateTicket(self.mod_role_id, self.ticket_creation_channel)) - - def run_bot(self): - self.run(self.token) - - -def parse_args(): - parser = argparse.ArgumentParser(description="Run a ticket bot on Discord.") - parser.add_argument("token", type=str, help="Discord Bot Token") - parser.add_argument("mod_role_id", type=int, help="Discord Ticket Moderator Role ID") - parser.add_argument("ticket_creation_channel", type=int, help="Discord Channel ID to create the ticket threads in") - parser.add_argument("ticket_transcript_channel", type=int, help="Discord Channel ID to send the transcripts to") - return parser.parse_args() - - -if __name__ == "__main__": - args = parse_args() - - if args.token == "PUTYOURTOKENHERE": - print("You need to set the token in the startup.") - sys.exit(1) - if args.mod_role_id == "PUTYOURTICKETMODROLEIDHERE": - print("You need to set your ticket moderator role ID.") - sys.exit(1) - if args.ticket_creation_channel == "PUTYOURTICKETCREATIONCHANNELIDHERE": - print("You need to set your ticket creation channel ID.") - sys.exit(1) - if args.ticket_transcript_channel == "PUTYOURDISCORDTRANSCRIPTCHANNELIDHERE": - print("You need to set your ticket transcript channel ID.") - sys.exit(1) - - bot = TicketBot(args.token, args.mod_role_id, args.ticket_creation_channel, args.ticket_transcript_channel) - bot.run_bot() \ No newline at end of file From a1dd14cf81cec14f7734b386a8b7f51084b8be7b Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:23:54 +0300 Subject: [PATCH 5/6] Delete TicketDiscordRequirements.txt --- TicketDiscordRequirements.txt | 129 ---------------------------------- 1 file changed, 129 deletions(-) delete mode 100644 TicketDiscordRequirements.txt diff --git a/TicketDiscordRequirements.txt b/TicketDiscordRequirements.txt deleted file mode 100644 index 8a02138..0000000 --- a/TicketDiscordRequirements.txt +++ /dev/null @@ -1,129 +0,0 @@ -aiohappyeyeballs==2.4.6 -aiohttp==3.11.12 -aiosignal==1.3.2 -anyio==4.7.0 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 -asttokens==3.0.0 -async-lru==2.0.4 -attrs==24.2.0 -babel==2.16.0 -beautifulsoup4==4.12.3 -bleach==6.2.0 -certifi==2024.8.30 -cffi==1.17.1 -charset-normalizer==3.4.0 -colorama==0.4.6 -comm==0.2.2 -contourpy==1.3.1 -cycler==0.12.1 -debugpy==1.8.9 -decorator==5.1.1 -defusedxml==0.7.1 -executing==2.1.0 -fastjsonschema==2.21.1 -filelock==3.13.1 -fonttools==4.55.3 -fqdn==1.5.1 -frozenlist==1.5.0 -fsspec==2024.2.0 -gitdb==4.0.11 -GitPython==3.1.43 -h11==0.14.0 -httpcore==1.0.7 -httpx==0.28.1 -idna==3.10 -ipykernel==6.29.5 -ipython==8.30.0 -isoduration==20.11.0 -jedi==0.19.2 -Jinja2==3.1.4 -joblib==1.4.2 -json5==0.10.0 -jsonpointer==3.0.0 -jsonschema==4.23.0 -jsonschema-specifications==2024.10.1 -jupyter-events==0.10.0 -jupyter-lsp==2.2.5 -jupyter-server-mathjax==0.2.6 -jupyter_client==8.6.3 -jupyter_core==5.7.2 -jupyter_server==2.14.2 -jupyter_server_terminals==0.5.3 -jupyterlab==4.3.3 -jupyterlab_git==0.50.2 -jupyterlab_pygments==0.3.0 -jupyterlab_server==2.27.3 -kiwisolver==1.4.7 -MarkupSafe==3.0.2 -matplotlib==3.9.3 -matplotlib-inline==0.1.7 -mistune==3.0.2 -mpmath==1.3.0 -multidict==6.1.0 -nbclient==0.10.1 -nbconvert==7.16.4 -nbdime==4.0.2 -nbformat==5.10.4 -nest-asyncio==1.6.0 -networkx==3.2.1 -nextcord==3.0.1 -notebook_shim==0.2.4 -numpy==2.2.0 -overrides==7.7.0 -packaging==24.2 -pandas==2.2.3 -pandocfilters==1.5.1 -parso==0.8.4 -pexpect==4.9.0 -pillow==11.0.0 -platformdirs==4.3.6 -plotly==5.24.1 -prometheus_client==0.21.1 -prompt_toolkit==3.0.48 -propcache==0.3.0 -psutil==6.1.0 -ptyprocess==0.7.0 -pure_eval==0.2.3 -pycparser==2.22 -Pygments==2.18.0 -pyparsing==3.2.0 -python-dateutil==2.9.0.post0 -python-json-logger==3.2.0 -pytz==2024.2 -PyYAML==6.0.2 -pyzmq==26.2.0 -referencing==0.35.1 -requests==2.32.3 -rfc3339-validator==0.1.4 -rfc3986-validator==0.1.1 -rpds-py==0.22.3 -scikit-learn==1.6.0 -scipy==1.14.1 -seaborn==0.13.2 -Send2Trash==1.8.3 -setuptools==75.6.0 -six==1.17.0 -smmap==5.0.1 -sniffio==1.3.1 -soupsieve==2.6 -stack-data==0.6.3 -sympy==1.13.1 -tenacity==9.0.0 -terminado==0.18.1 -threadpoolctl==3.5.0 -tinycss2==1.4.0 -torch==2.5.1+cpu -tornado==6.4.2 -traitlets==5.14.3 -types-python-dateutil==2.9.0.20241206 -typing_extensions==4.12.2 -tzdata==2024.2 -uri-template==1.3.0 -urllib3==2.2.3 -wcwidth==0.2.13 -webcolors==24.11.1 -webencodings==0.5.1 -websocket-client==1.8.0 -yarl==1.18.3 \ No newline at end of file From 6e6cdc6db58d3bfeb8112ff06de866ff82becf37 Mon Sep 17 00:00:00 2001 From: NoobAndCoding <167626518+NoobAndCoding@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:25:43 +0300 Subject: [PATCH 6/6] Completely working version of the ticket preset bo... Completely working version of the ticketing preset bot I was making. --- TicketDiscord.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 TicketDiscord.py diff --git a/TicketDiscord.py b/TicketDiscord.py new file mode 100644 index 0000000..d4d493f --- /dev/null +++ b/TicketDiscord.py @@ -0,0 +1,133 @@ +""" +Ticketing System +------------------- +Python version: 3.13.5 +------------------- +Argument usage: python TicketDiscord.py --token --channel --guild --helper-role-id +------------------- +requirements.txt: +nextcord==3.1.0 +argparse==1.4.0 +------------------- +REQUIREMENTS MAY BE PRESENT IN YOUR PYTHON ENVIRONMENT, CHECK BEFORE CREATING. IF THERE IS NOT A REQUIREMENTS FILE, CREATE ONE AND USE THE CONTENT ABOVE. +PYTHON 3.13.5 MAY BE REQUIRED FOR THE BOT TO WORK, DO NOT CHANGE THE ENVIRONMENT. +------------------- +Made by @techwithnoob +""" + + +import nextcord +from nextcord.ext import commands +import argparse +import logging +import asyncio + +logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) + +open_tickets = {} + +class CloseTicketView(nextcord.ui.View): + def __init__(self): + super().__init__(timeout=None) + + @nextcord.ui.button(label="Close Ticket", style=nextcord.ButtonStyle.red, custom_id="close_ticket") + async def close_ticket_button(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + await interaction.response.send_message("Closing ticket...", ephemeral=True) + await asyncio.sleep(2) + try: + del open_tickets[interaction.user.id] + except KeyError: + pass + await interaction.channel.delete() + +class TicketPanelView(nextcord.ui.View): + def __init__(self, bot, channel_id: int, helper_role_id: int): + super().__init__(timeout=None) + self.bot = bot + self.channel_id = channel_id + self.helper_role_id = helper_role_id + + @nextcord.ui.button(label="Create Ticket", style=nextcord.ButtonStyle.green, custom_id="create_ticket") + async def create_ticket_button(self, button: nextcord.ui.Button, interaction: nextcord.Interaction): + user_id = interaction.user.id + + if user_id in open_tickets: + await interaction.response.send_message("You already have an open ticket.", ephemeral=True) + return + + guild = interaction.guild + channel = guild.get_channel(self.channel_id) + helper_role = guild.get_role(self.helper_role_id) + + thread = await channel.create_thread( + name=f"ticket-{interaction.user.name}", + type=nextcord.ChannelType.private_thread, + invitable=False + ) + + await thread.add_user(interaction.user) + + if helper_role: + for member in helper_role.members: + try: + await thread.add_user(member) + except: + continue + + open_tickets[user_id] = thread.id + + embed = nextcord.Embed( + title="Ticket Opened", + description=f"Hey {interaction.user.mention}, a helper will be with you shortly.", + color=0x00ff00 + ) + await thread.send(embed=embed, view=CloseTicketView()) + + await interaction.response.send_message("✅ Ticket created!", ephemeral=True) + +class TicketBot: + def __init__(self, token, channel_id, guild_id, helper_role_id): + self.token = token + self.channel_id = channel_id + self.guild_id = guild_id + self.helper_role_id = helper_role_id + + intents = nextcord.Intents.default() + intents.members = True + intents.guilds = True + intents.messages = True + intents.message_content = True + + self.bot = commands.Bot(command_prefix='!', intents=intents) + + @self.bot.event + async def on_ready(): + logger.info(f'{self.bot.user} has connected to Discord!') + + @self.bot.slash_command(name="create_ticket_panel", description="Create a ticket panel", guild_ids=[self.guild_id]) + async def create_ticket_panel(interaction: nextcord.Interaction): + embed = nextcord.Embed( + title="🎫 Ticket Panel", + description="Click the button below to open a ticket.", + color=0x00ff00 + ) + embed.set_footer(text="Silly Dev - Ticketing System") + view = TicketPanelView(self.bot, self.channel_id, self.helper_role_id) + await interaction.response.send_message(embed=embed, view=view) + + def run(self): + self.bot.run(self.token) + +def parse_args(): + parser = argparse.ArgumentParser(description='Discord Bot for Ticketing System') + parser.add_argument('--token', type=str, required=True, help='Discord Bot Token') + parser.add_argument('--channel', type=int, required=True, help='Channel ID for ticket threads') + parser.add_argument('--guild', type=int, required=True, help='Guild ID') + parser.add_argument('--helper-role-id', type=int, required=True, help='Role ID of helpers') + return parser.parse_args() + +if __name__ == '__main__': + args = parse_args() + ticket_bot = TicketBot(args.token, args.channel, args.guild, args.helper_role_id) + ticket_bot.run() \ No newline at end of file