import db, { and, eq } from ".."; import { type Actor, actors, guilds, users } from "../schemas"; import { upsertGuild } from "./guild"; export async function upsertUser(user: { username: string; displayName: string | null; id: string; avatar: string | null; }) { const [upsertedUser] = await db .insert(users) .values({ discordId: user.id, username: user.username, displayName: user.displayName, avatar: user.avatar, createdAt: new Date(), updatedAt: new Date(), }) .onConflictDoUpdate({ target: users.discordId, set: { username: user.username, displayName: user.displayName, avatar: user.avatar, updatedAt: new Date(), }, }) .returning(); return upsertedUser; } export async function upsertActor(data: { guild: { discordId: string; name: string; icon: string | null; }; user: { discordId: string; username: string; displayName: string | null; avatar: string | null; }; moderator: boolean; }) { const [dbGuild, dbUser] = await Promise.all([ upsertGuild(data.guild), upsertUser({ id: data.user.discordId, username: data.user.username, displayName: data.user.displayName, avatar: data.user.avatar, }), ]); if (!dbGuild || !dbUser) { throw new Error("Failed to upsert guild or user"); } const [actor] = await db .insert(actors) .values({ guildId: dbGuild.id, userId: dbUser.id, discordId: data.user.discordId, username: data.user.username, displayName: data.user.displayName, avatar: data.user.avatar, moderator: data.moderator, createdAt: new Date(), updatedAt: new Date(), }) .onConflictDoUpdate({ target: [actors.guildId, actors.userId], set: { username: data.user.username, displayName: data.user.displayName, avatar: data.user.avatar, moderator: data.moderator, updatedAt: new Date(), }, }) .returning(); if (!actor) throw new Error("Failed to insert actor"); return { actor: actor, user: dbUser, guild: dbGuild, }; } export async function setActorPin(id: number, pin: string) { const fiveMinutes = 5 * 60 * 1000; const pinExpiresIn = new Date(Date.now() + fiveMinutes); const result = await db .update(actors) .set({ pin, pinExpiresIn, updatedAt: new Date(), }) .where(eq(actors.id, id)) .returning(); return result; } export async function getActorByPin(pin: string) { const [result] = await db.select().from(actors).where(eq(actors.pin, pin)); return result; } export async function getActorByRobloxId(robloxId: string) { const [result] = await db.select().from(actors).where(eq(actors.robloxId, robloxId)); return result; } export async function editActor(id: number, data: Partial) { const result = await db .update(actors) .set({ ...data, updatedAt: new Date(), }) .where(eq(actors.id, id)) .returning(); return result; } export async function anonymiseUser(id: number) { const result = await db .update(actors) .set({ username: `Anonymised User`, displayName: null, avatar: null, updatedAt: new Date(), }) .where(eq(actors.id, id)) .returning(); return result; } export async function getUser(id: number) { const [result] = await db.select().from(users).where(eq(users.id, id)); return result; } export async function getUserByDiscordId(discordId: string) { const [result] = await db.select().from(users).where(eq(users.discordId, discordId)); return result; } export async function getActor(id: number) { const [result] = await db.select().from(actors).where(eq(actors.id, id)); return result; } export async function getActorByDiscordId(discordId: string, guildId: number) { const [result] = await db .select() .from(actors) .where(and(eq(actors.discordId, discordId), eq(actors.guildId, guildId))); return result; } export async function getActorByDiscordIdAndGuildDiscordId( discordId: string, guildDiscordId: string, ) { const [guild] = await db.select().from(guilds).where(eq(guilds.discordId, guildDiscordId)); if (!guild) return null; return getActorByDiscordId(discordId, guild.id); } export async function getModerators(guildId: number) { const result = await db .select() .from(actors) .where(and(eq(actors.guildId, guildId), eq(actors.moderator, true))); return result; }