Skip to content

Commit

Permalink
Implement staff notification for new tickets
Browse files Browse the repository at this point in the history
  • Loading branch information
No767 committed Dec 13, 2023
1 parent ffec9a3 commit afbf5a3
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 19 deletions.
69 changes: 60 additions & 9 deletions bot/cogs/tickets.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
from __future__ import annotations

import random
import uuid
from typing import TYPE_CHECKING, NamedTuple, Optional
from typing import TYPE_CHECKING, NamedTuple, Optional, Union

import asyncpg
import discord
from discord.ext import commands
from libs.tickets.structs import ReservedTags, TicketThread
from libs.tickets.utils import get_cached_thread, get_partial_ticket

from .config import GuildWebhookDispatcher

if TYPE_CHECKING:
from libs.utils import RoboContext

from rodhaj import Rodhaj

STAFF_ROLE_ID = 1184257456419913798
TICKET_CHANNEL = 1183305410304806922 # maybe fetch it from the DB? probably not needed


def is_ticket_or_dm():
def pred(ctx: RoboContext) -> bool:
return (
isinstance(ctx.channel, discord.Thread)
and ctx.channel.parent_id == TICKET_CHANNEL
) or ctx.guild is None

return commands.check(pred)


class TicketOutput(NamedTuple):
status: bool
ticket: discord.channel.ThreadWithMessage
msg: str


Expand All @@ -41,6 +59,21 @@ async def lock_ticket(
locked_thread = await thread.edit(archived=True, locked=True, reason=reason)
return locked_thread

def determine_active_mod(self, guild: discord.Guild) -> Optional[discord.Member]:
mod_role = guild.get_role(STAFF_ROLE_ID)
if mod_role is None:
return None

active_members = [
member
for member in mod_role.members
if member.status == discord.Status.online
or member.status == discord.Status.dnd
]
# Ideally this needs to be weighted but I'm not so sure how to implement that
selected_mod = random.choice(active_members) # nosec
return selected_mod

async def create_ticket(self, ticket: TicketThread) -> Optional[TicketOutput]:
query = """
SELECT ticket_channel_id
Expand Down Expand Up @@ -72,10 +105,7 @@ async def create_ticket(self, ticket: TicketThread) -> Optional[TicketOutput]:

thread_display_id = uuid.uuid4()
thread_name = f"{ticket.user.display_name} | {thread_display_id}"
content = (
f"{ticket.user.display_name} has submitted a ticket. The initial message is shown below:\n"
f"{ticket.user.display_name} ({discord.utils.format_dt(ticket.created_at)}):\n{ticket.content}"
)
content = f"({ticket.user.display_name}, {discord.utils.format_dt(ticket.created_at)})\n\n{ticket.content}"
created_ticket = await tc.create_thread(
name=thread_name,
content=content,
Expand All @@ -101,6 +131,7 @@ async def create_ticket(self, ticket: TicketThread) -> Optional[TicketOutput]:
)
return TicketOutput(
status=False,
ticket=created_ticket,
msg="You already have an ticket. Please ensure that you have closed all tickets before creating a new one.",
)
except Exception:
Expand All @@ -109,26 +140,46 @@ async def create_ticket(self, ticket: TicketThread) -> Optional[TicketOutput]:
created_ticket[0],
reason=f"Failed to create ticket (User ID: {ticket.user.id})",
)
return TicketOutput(status=False, msg="Could not create ticket")
return TicketOutput(
status=False, ticket=created_ticket, msg="Could not create ticket"
)
else:
await tr.commit()
get_partial_ticket.cache_invalidate(ticket.user.id, self.pool)
get_cached_thread.cache_invalidate(self.bot, ticket.user.id)
return TicketOutput(
status=True,
ticket=created_ticket,
msg="Ticket successfully created. In order to use this ticket, please continue sending messages to Rodhaj. The messages will be directed towards the appropriate ticket.",
)

@is_ticket_or_dm()
@commands.hybrid_command(name="close", aliases=["solved", "closed", "resolved"])
async def close(self, ctx: RoboContext) -> None:
"""Closes the thread"""
# I'll finish this later - Noelle
await ctx.send("Sending close msg")

@commands.Cog.listener()
async def on_ticket_create(self):
# This is where the mod assignment will get done. As of now, i'm gonna do that later
self.bot.logger.info("Assigning mod to handle ticket")
async def on_ticket_create(
self,
guild: discord.Guild,
user: Union[discord.User, discord.Member],
ticket: discord.channel.ThreadWithMessage,
init_message: str,
):
selected_mod = self.determine_active_mod(guild)
dispatcher = GuildWebhookDispatcher(self.bot, guild.id)
webhook = await dispatcher.get_webhook()

select_mod_mention = f"{selected_mod.mention}, " if selected_mod else ""

if webhook is not None:
msg = (
f"{select_mod_mention}{user.display_name} has created a ticket at {ticket.thread.mention}. The initial message has been provided below:\n\n"
f"{init_message}"
)
await webhook.send(content=msg)


async def setup(bot: Rodhaj) -> None:
Expand Down
3 changes: 3 additions & 0 deletions bot/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from aiohttp import ClientSession
from environs import Env
from libs.utils import RodhajLogger

from rodhaj import Rodhaj

if os.name == "nt":
Expand All @@ -23,6 +24,8 @@

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


async def main() -> None:
Expand Down
18 changes: 12 additions & 6 deletions bot/libs/tickets/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ def __init__(
ctx: RoboContext,
cog: Tickets,
content: str,
guild_id: int,
guild: discord.Guild,
delete_after: bool = True,
) -> None:
super().__init__(ctx=ctx, display_message=False)
super().__init__(ctx=ctx, timeout=300.0)
self.bot = bot
self.ctx = ctx
self.cog = cog
self.content = content
self.guild_id = guild_id
self.guild = guild
self.delete_after = delete_after
self.pool = self.bot.pool

Expand All @@ -54,7 +54,7 @@ async def confirm(
author = self.ctx.author
ticket = TicketThread(
user=author,
location_id=self.guild_id,
location_id=self.guild.id,
content=self.content,
created_at=discord.utils.utcnow(),
)
Expand All @@ -67,7 +67,13 @@ async def confirm(
)
return

self.bot.dispatch("ticket_create")
self.bot.dispatch(
"ticket_create",
self.guild,
self.ctx.author,
created_ticket.ticket,
self.content,
)
embed = discord.Embed(
title="\U0001f3ab Ticket created", color=discord.Color.from_rgb(124, 252, 0)
)
Expand Down Expand Up @@ -100,5 +106,5 @@ async def on_timeout(self) -> None:
"Timed out waiting for a response. Not creating a ticket. "
"In order to create a ticket, please resend your message and properly confirm"
)
await self.message.edit(content=None, embed=embed, view=None)
await self.message.edit(embed=embed, view=None, delete_after=60.0)
return
6 changes: 6 additions & 0 deletions bot/libs/utils/embeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ def __init__(self, **kwargs):
super().__init__(**kwargs)


class LoggingEmbed(discord.Embed):
def __init__(self, **kwargs):
kwargs.setdefault("color", discord.Color.from_rgb(212, 252, 255))
super().__init__(**kwargs)


class ErrorEmbed(discord.Embed):
def __init__(self, **kwargs):
kwargs.setdefault("color", discord.Color.from_rgb(214, 6, 6))
Expand Down
7 changes: 4 additions & 3 deletions bot/rodhaj.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ async def on_message(self, message: discord.Message) -> None:
tickets_cog.reserved_tags[author.id] = ReservedTags(
question=True, serious=False, private=False
)
guild = self.get_guild(TRANSPROGRAMMER_SERVER_ID) or (
await self.fetch_guild(TRANSPROGRAMMER_SERVER_ID)
)

embed = discord.Embed(
title="Ready to create a ticket?",
Expand All @@ -133,9 +136,7 @@ async def on_message(self, message: discord.Message) -> None:
"\n\nNote: Once you have created your ticket, this prompt will not show up again"
)

view = TicketConfirmView(
self, ctx, tickets_cog, message.content, TRANSPROGRAMMER_SERVER_ID
)
view = TicketConfirmView(self, ctx, tickets_cog, message.content, guild)
view.message = await author.send(embed=embed, view=view)
return

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ reportUnnecessaryTypeIgnoreComment = "warning"
skips = ["B311", "B101"]

[tool.ruff]
ignore = ["E501", "N999", "E402"]
ignore = ["E501", "N999", "E402", "S311"]
select = ["E", "F", "N", "ASYNC", "S", "ERA"]

[build-system]
Expand Down

0 comments on commit afbf5a3

Please sign in to comment.