193 lines
5.3 KiB
TypeScript

import { sqlWrapper } from "../../core/db.ts";
export async function rotateEventPin(
eventId: string,
userId: string,
isGlobalAdmin: boolean,
): Promise<string | null> {
const randPin = Math.floor(100000 + Math.random() * 900000).toString();
const formattedPin = `${randPin.slice(0, 3)}-${randPin.slice(3)}`;
const result = await sqlWrapper.sql`
UPDATE event_passes
SET pin_code = ${formattedPin}
WHERE id = ${eventId}
AND (created_by = ${userId} OR ${isGlobalAdmin})
AND is_active = TRUE
RETURNING pin_code
`;
if (!result || result.length === 0) return null;
return result[0].pin_code;
}
export async function getEventAttendees(
eventId: string,
userId: string,
isGlobalAdmin: boolean,
) {
const event = await sqlWrapper.sql`
SELECT slug FROM event_passes
WHERE id = ${eventId}
AND (created_by = ${userId} OR ${isGlobalAdmin})
`;
if (!event || event.length === 0) return null;
const slug = event[0].slug;
const guestPattern = `guest_${slug}_%`;
const users = await sqlWrapper.sql`
SELECT id, username, display_name, created_at
FROM users
WHERE username LIKE ${guestPattern}
ORDER BY created_at DESC
`;
return users;
}
export async function getEventBySlugOrPin(code: string) {
const rawNormalized = code.trim().toLowerCase();
const pinNormalized = code.trim().replace(/[-\s]/g, "");
const eventLookup = await sqlWrapper.sql`
SELECT * FROM event_passes
WHERE (LOWER(slug) = ${rawNormalized} OR REPLACE(pin_code, '-', '') = ${pinNormalized})
AND is_active = TRUE
AND (expires_at IS NULL OR expires_at > NOW())
`;
if (!eventLookup || eventLookup.length === 0) return null;
return eventLookup[0];
}
export async function incrementEventSeats(eventId: string) {
const updateResult = await sqlWrapper.sql`
UPDATE event_passes
SET seats_claimed = seats_claimed + 1
WHERE id = ${eventId}
AND (max_seats = 0 OR seats_claimed < max_seats)
RETURNING *
`;
if (!updateResult || updateResult.length === 0) return null;
return updateResult[0];
}
export async function createGuestUser(
guestUuid: string,
username: string,
displayName: string,
eventId: string,
) {
await sqlWrapper.sql`
INSERT INTO users (id, username, display_name, account_status, event_pass_id)
VALUES (${guestUuid}, ${username}, ${displayName}, 'guest', ${eventId})
ON CONFLICT DO NOTHING
`;
}
export async function getAppById(appId: string) {
const apps = await sqlWrapper
.sql`SELECT name, domain FROM apps WHERE id = ${appId}`;
if (apps.length > 0) return apps[0];
return null;
}
export async function endEvent(
eventId: string,
userId: string,
isGlobalAdmin: boolean,
) {
const result = await sqlWrapper.sql`
UPDATE event_passes
SET is_active = FALSE
WHERE id = ${eventId}
AND (created_by = ${userId} OR ${isGlobalAdmin})
RETURNING slug
`;
if (!result || result.length === 0) return null;
return result[0].slug;
}
export async function createEventSession(
sessionId: string,
userId: string,
label: string,
customScopes: string[],
expiresAt: Date,
) {
await sqlWrapper.sql`
INSERT INTO sessions (id, user_id, label, is_agent, custom_scopes, expires_at)
VALUES (${sessionId}, ${userId}, ${label}, false, ${customScopes}, ${expiresAt})
`;
}
export async function expandEventSeats(
eventId: string,
addSeats: number,
userId: string,
isGlobalAdmin: boolean,
) {
const eventResult = await sqlWrapper.sql`
UPDATE event_passes
SET max_seats = max_seats + ${addSeats}
WHERE id = ${eventId}
AND (created_by = ${userId} OR ${isGlobalAdmin})
AND is_active = TRUE
RETURNING max_seats
`;
if (!eventResult || eventResult.length === 0) return null;
return eventResult[0].max_seats;
}
export async function createEventPass(
name: string,
slug: string,
pinCode: string,
appId: string | null,
role: string,
maxSeats: number,
lifespanHours: number,
userId: string,
expiresAt: Date,
) {
const result = await sqlWrapper.sql`
INSERT INTO event_passes (name, slug, pin_code, app_id, role, max_seats, lifespan_hours, created_by, expires_at)
VALUES (${name}, ${slug}, ${pinCode}, ${appId || null}, ${role}, ${
Number(maxSeats)
}, ${Number(lifespanHours)}, ${userId}, ${expiresAt.toISOString()})
RETURNING *
`;
if (!result || result.length === 0) return null;
return result[0];
}
export async function getEventById(eventId: string) {
const result = await sqlWrapper.sql`
SELECT * FROM event_passes WHERE id = ${eventId}
`;
if (!result || result.length === 0) return null;
return result[0];
}
export async function getEventBySlug(slug: string) {
const result = await sqlWrapper.sql`
SELECT * FROM event_passes WHERE slug = ${slug} AND is_active = TRUE
`;
if (!result || result.length === 0) return null;
return result[0];
}
export async function getUserEventPasses(userId: string) {
const result = await sqlWrapper.sql`
SELECT ep.*, a.name as app_name, a.domain as app_domain
FROM event_passes ep
LEFT JOIN apps a ON ep.app_id = a.id
WHERE ep.created_by = ${userId}
AND ep.is_active = TRUE
ORDER BY ep.created_at DESC
`;
return result;
}