pkgs/bot/src/database/schema/tickets.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
import { defineRelations, sql } from "drizzle-orm";
import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
import { randomUUID } from "node:crypto";
export const tickets = sqliteTable(
"tickets",
{
id: integer("id").primaryKey({ autoIncrement: true }),
guildId: text("guild_id").notNull(),
ticketNumber: integer("ticket_number"),
publicId: text("public_id")
.$defaultFn(() => randomUUID())
.unique()
.notNull(),
channelId: text("channel_id"),
authorId: text("author_id").notNull(),
anonymousId: text("anonymous_id").notNull(),
claimedBy: text("claimed_by"),
claimedAt: integer("claimed_at", { mode: "timestamp" }),
addedUsers: text("added_users", { mode: "json" }).$type<string[]>().default([]).notNull(),
type: text("type").notNull(),
status: text("status", { enum: ["open", "closed", "archived"] })
.default("open")
.notNull(),
topic: text("topic"),
openedBy: text("opened_by"),
createdAt: integer("created_at", { mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
closedAt: integer("closed_at", { mode: "timestamp" }),
closedBy: text("closed_by"),
closeReason: text("close_reason"),
privateReason: text("private_reason"),
thankedAt: integer("thanked_at", {
mode: "timestamp",
}).$type<Date | null>(),
warnedAt: integer("warned_at", { mode: "timestamp" }).$type<Date | null>(),
},
(t) => [
index("tickets_guild_idx").on(t.guildId),
index("tickets_author_idx").on(t.authorId),
index("tickets_status_idx").on(t.status),
index("tickets_public_id_idx").on(t.publicId),
],
);
export const ticketMessages = sqliteTable(
"ticket_messages",
{
id: integer("id").primaryKey({ autoIncrement: true }),
ticketId: integer("ticket_id")
.references(() => tickets.id, { onDelete: "cascade" })
.notNull(),
publicId: text("public_id")
.$defaultFn(() => randomUUID())
.unique()
.notNull(),
messageId: text("message_id"),
authorId: text("author_id").notNull(),
authorType: text("author_type", { enum: ["user", "staff", "system"] })
.default("user")
.notNull(),
content: text("content").notNull(),
createdAt: integer("created_at", { mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
editedAt: integer("edited_at", { mode: "timestamp" }).$type<Date | null>(),
deletedAt: integer("deleted_at", {
mode: "timestamp",
}).$type<Date | null>(),
},
(t) => [index("ticket_msgs_ticket_idx").on(t.ticketId)],
);
export const ticketAccessLogs = sqliteTable(
"ticket_access_logs",
{
id: integer("id").primaryKey({ autoIncrement: true }),
ticketId: integer("ticket_id")
.references(() => tickets.id, { onDelete: "cascade" })
.notNull(),
userId: text("user_id").notNull(),
action: text("action", { enum: ["view_transcript"] }).notNull(),
createdAt: integer("created_at", { mode: "timestamp" })
.default(sql`(unixepoch())`)
.notNull(),
},
(t) => [index("ticket_access_logs_ticket_idx").on(t.ticketId)],
);
export const TicketRelations = defineRelations(
{ tickets, ticketMessages, ticketAccessLogs },
(r) => ({
tickets: {
messages: r.many.ticketMessages({
from: r.tickets.id,
to: r.ticketMessages.ticketId,
}),
accessLogs: r.many.ticketAccessLogs({
from: r.tickets.id,
to: r.ticketAccessLogs.ticketId,
}),
},
ticketMessages: {
ticket: r.one.tickets({
from: r.ticketMessages.ticketId,
to: r.tickets.id,
}),
},
ticketAccessLogs: {
ticket: r.one.tickets({
from: r.ticketAccessLogs.ticketId,
to: r.tickets.id,
}),
},
}),
);
export type Ticket = typeof tickets.$inferSelect;
export type TicketMessage = typeof ticketMessages.$inferSelect;
|