using System.Collections.Generic; using DSharpPlus; using MySqlConnector; namespace SupportChild.Database; public class Ticket(MySqlDataReader reader) { public readonly uint id = reader.GetUInt32("id"); public readonly ulong creatorID = reader.GetUInt64("creator_id"); public readonly ulong assignedStaffID = reader.GetUInt64("assigned_staff_id"); public readonly string summary = reader.GetString("summary"); public readonly ulong channelID = reader.GetUInt64("channel_id"); public string DiscordRelativeTime() { return Formatter.Timestamp(channelID.GetSnowflakeTime(), Config.timestampFormat); } public static long GetNumberOfTickets() { try { using MySqlConnection c = Connection.GetConnection(); using MySqlCommand countTickets = new MySqlCommand("SELECT COUNT(*) FROM tickets", c); c.Open(); return (long)(countTickets?.ExecuteScalar() ?? 0); } catch (MySqlException e) { Logger.Error("Error occured when attempting to count number of open tickets.", e); } return -1; } public static long GetNumberOfClosedTickets() { try { using MySqlConnection c = Connection.GetConnection(); using MySqlCommand countTickets = new MySqlCommand("SELECT COUNT(*) FROM ticket_history", c); c.Open(); return (long)(countTickets?.ExecuteScalar() ?? 0); } catch (MySqlException e) { Logger.Error("Error occured when attempting to count number of open tickets.", e); } return -1; } public static bool IsOpenTicket(ulong channelID) { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets WHERE channel_id=@channel_id", c); selection.Parameters.AddWithValue("@channel_id", channelID); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); // Check if ticket exists in the database if (!results.Read()) { return false; } results.Close(); return true; } public static bool TryGetOpenTicket(ulong channelID, out Ticket ticket) { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets WHERE channel_id=@channel_id", c); selection.Parameters.AddWithValue("@channel_id", channelID); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); // Check if ticket exists in the database if (!results.Read()) { ticket = null; return false; } ticket = new Ticket(results); results.Close(); return true; } public static bool TryGetOpenTicketByID(uint id, out Ticket ticket) { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets WHERE id=@id", c); selection.Parameters.AddWithValue("@id", id); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); // Check if open ticket exists in the database if (results.Read()) { ticket = new Ticket(results); results.Close(); return true; } results.Close(); ticket = null; return false; } public static bool TryGetClosedTicket(uint id, out Ticket ticket) { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM ticket_history WHERE id=@id", c); selection.Parameters.AddWithValue("@id", id); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); // Check if closed ticket exists in the database if (results.Read()) { ticket = new Ticket(results); results.Close(); return true; } ticket = null; results.Close(); return false; } public static bool TryGetOpenTickets(ulong userID, out List<Ticket> tickets) { tickets = null; using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets WHERE creator_id=@creator_id", c); selection.Parameters.AddWithValue("@creator_id", userID); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); if (!results.Read()) { return false; } tickets = [new Ticket(results)]; while (results.Read()) { tickets.Add(new Ticket(results)); } results.Close(); return true; } public static bool TryGetOpenTickets(out List<Ticket> tickets) { tickets = null; using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets ORDER BY channel_id", c); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); if (!results.Read()) { return false; } tickets = [new Ticket(results)]; while (results.Read()) { tickets.Add(new Ticket(results)); } results.Close(); return true; } public static bool TryGetClosedTickets(ulong userID, out List<Ticket> tickets) { tickets = null; using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM ticket_history WHERE creator_id=@creator_id", c); selection.Parameters.AddWithValue("@creator_id", userID); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); if (!results.Read()) { return false; } tickets = [new Ticket(results)]; while (results.Read()) { tickets.Add(new Ticket(results)); } results.Close(); return true; } public static bool TryGetAssignedTickets(ulong staffID, out List<Ticket> tickets) { tickets = null; using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand selection = new("SELECT * FROM tickets WHERE assigned_staff_id=@assigned_staff_id", c); selection.Parameters.AddWithValue("@assigned_staff_id", staffID); selection.Prepare(); MySqlDataReader results = selection.ExecuteReader(); if (!results.Read()) { return false; } tickets = [new Ticket(results)]; while (results.Read()) { tickets.Add(new Ticket(results)); } results.Close(); return true; } public static long NewTicket(ulong memberID, ulong staffID, ulong ticketID) { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand cmd = new("INSERT INTO tickets (created_time, creator_id, assigned_staff_id, summary, channel_id) VALUES (UTC_TIMESTAMP(), @creator_id, @assigned_staff_id, @summary, @channel_id);", c); cmd.Parameters.AddWithValue("@creator_id", memberID); cmd.Parameters.AddWithValue("@assigned_staff_id", staffID); cmd.Parameters.AddWithValue("@summary", ""); cmd.Parameters.AddWithValue("@channel_id", ticketID); cmd.ExecuteNonQuery(); return cmd.LastInsertedId; } public static void ArchiveTicket(Ticket ticket) { // Check if ticket already exists in the archive if (TryGetClosedTicket(ticket.id, out Ticket _)) { using MySqlConnection c = Connection.GetConnection(); using MySqlCommand deleteTicket = new("DELETE FROM ticket_history WHERE id=@id OR channel_id=@channel_id", c); deleteTicket.Parameters.AddWithValue("@id", ticket.id); deleteTicket.Parameters.AddWithValue("@channel_id", ticket.channelID); c.Open(); deleteTicket.Prepare(); deleteTicket.ExecuteNonQuery(); } // Create an entry in the ticket history database using MySqlConnection conn = Connection.GetConnection(); using MySqlCommand archiveTicket = new("INSERT INTO ticket_history (id, created_time, closed_time, creator_id, assigned_staff_id, summary, channel_id) VALUES (@id, @created_time, UTC_TIMESTAMP(), @creator_id, @assigned_staff_id, @summary, @channel_id);", conn); archiveTicket.Parameters.AddWithValue("@id", ticket.id); archiveTicket.Parameters.AddWithValue("@created_time", ticket.channelID.GetSnowflakeTime()); archiveTicket.Parameters.AddWithValue("@creator_id", ticket.creatorID); archiveTicket.Parameters.AddWithValue("@assigned_staff_id", ticket.assignedStaffID); archiveTicket.Parameters.AddWithValue("@summary", ticket.summary); archiveTicket.Parameters.AddWithValue("@channel_id", ticket.channelID); conn.Open(); archiveTicket.Prepare(); archiveTicket.ExecuteNonQuery(); } public static bool DeleteOpenTicket(uint ticketID) { try { using MySqlConnection c = Connection.GetConnection(); using MySqlCommand deletion = new("DELETE FROM tickets WHERE id=@id", c); deletion.Parameters.AddWithValue("@id", ticketID); c.Open(); deletion.Prepare(); return deletion.ExecuteNonQuery() > 0; } catch (MySqlException e) { Logger.Warn("Could not delete open ticket in database.", e); return false; } } public static bool SetSummary(ulong channelID, string summary) { try { using MySqlConnection c = Connection.GetConnection(); c.Open(); using MySqlCommand update = new("UPDATE tickets SET summary = @summary WHERE channel_id = @channel_id", c); update.Parameters.AddWithValue("@summary", summary); update.Parameters.AddWithValue("@channel_id", channelID); update.Prepare(); return update.ExecuteNonQuery() > 0; } catch (MySqlException e) { Logger.Warn("Could not set summary in database.", e); return false; } } }