Fix: Using bigint and added backend testing

This commit is contained in:
Aron Malcher 2024-03-10 17:12:50 +01:00
parent ed6195e1e2
commit 89507f8412
Signed by: aronmal
GPG key ID: 816B7707426FC612
20 changed files with 830 additions and 292 deletions

View file

@ -1,7 +1,7 @@
import { relations } from "drizzle-orm";
import {
bigint,
boolean,
integer,
pgTable,
primaryKey,
serial,
@ -39,14 +39,16 @@ export const discordTokens = pgTable("tokens", {
});
export const guilds = pgTable("guilds", {
id: integer("id").primaryKey(),
id: bigint("id", { mode: "bigint" }).primaryKey(),
timezone: text("timezone").notNull().default("Etc/UTC"),
tpEnabled: boolean("tp_enabled").notNull().default(false),
tpChannelId: integer("tp_channel_id"),
tpInterval: smallint("target_interval").notNull(),
tpRoles: boolean("tp_roles").notNull(),
isAvailableRoleId: integer("is_available_role_id"),
wantsToBeNotifieRoledId: integer("wants_to_be_notified_role_id"),
tpChannelId: bigint("tp_channel_id", { mode: "bigint" }),
tpInterval: smallint("target_interval").notNull().default(64),
tpRolesEnabled: boolean("tp_roles_enabled").notNull().default(false),
isAvailableRoleId: bigint("is_available_role_id", { mode: "bigint" }),
wantsToBeNotifieRoledId: bigint("wants_to_be_notified_role_id", {
mode: "bigint",
}),
});
export const guildsRelations = relations(guilds, ({ many }) => ({
@ -57,9 +59,9 @@ export const guildsRelations = relations(guilds, ({ many }) => ({
export const tpMessages = pgTable(
"tp_messages",
{
messageId: integer("message_id"),
messageId: bigint("message_id", { mode: "bigint" }),
day: smallint("day").notNull(),
guildId: integer("guild_id")
guildId: bigint("guild_id", { mode: "bigint" })
.notNull()
.references(() => guilds.id, { onDelete: "cascade" }),
},
@ -79,14 +81,14 @@ export const tpMessagesRelations = relations(tpMessages, ({ one }) => ({
export const matches = pgTable("matches", {
id: serial("id").primaryKey(),
channelId: integer("channel_id").notNull(),
channelId: bigint("channel_id", { mode: "bigint" }).notNull(),
matchType: varchar("match_type", { length: 50 }).notNull(),
createrId: integer("creater_id").notNull(),
roleId: integer("role_id").notNull(),
createrId: bigint("creater_id", { mode: "bigint" }).notNull(),
roleId: bigint("role_id", { mode: "bigint" }).notNull(),
opponentName: varchar("opponent_name", { length: 100 }).notNull(),
messageId: integer("message_id").notNull(),
messageId: bigint("message_id", { mode: "bigint" }).notNull(),
utc_ts: timestamp("utc_ts").notNull(),
guildId: integer("guild_id")
guildId: bigint("guild_id", { mode: "bigint" })
.notNull()
.references(() => guilds.id, { onDelete: "cascade" }),
});

View file

@ -2,14 +2,27 @@ import stringify from "json-stable-stringify";
import objectHash from "object-hash";
import { guilds, matches, tpMessages } from "~/drizzle/schema";
import { ExtractDataTypes, GetColumns } from "~/types/db";
import { components } from "~/types/liljudd";
export const buildMatches = (
queryMatches: ExtractDataTypes<GetColumns<typeof matches>>[],
) =>
): components["schemas"]["match"][] =>
queryMatches.map(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
({ id, guildId, utc_ts, ...match }) => ({
...match,
({
channelId,
createrId,
roleId,
messageId,
matchType,
opponentName,
utc_ts,
}) => ({
channelId: channelId.toString(),
createrId: createrId.toString(),
roleId: roleId.toString(),
messageId: messageId.toString(),
matchType,
opponentName,
utc_ts: utc_ts.toISOString(),
}),
);
@ -19,14 +32,14 @@ export function buildConfig(
tpMessages: ExtractDataTypes<GetColumns<typeof tpMessages>>[];
matches: ExtractDataTypes<GetColumns<typeof matches>>[];
},
) {
): components["schemas"]["guildConfig"] {
const {
id,
timezone,
tpEnabled,
tpChannelId,
tpInterval,
tpRoles,
tpRolesEnabled: tpRoles,
isAvailableRoleId,
wantsToBeNotifieRoledId,
} = guildQuery;
@ -36,20 +49,26 @@ export function buildConfig(
const targetDay = (tpInterval >> 11) & 7;
const payload = {
guildId: id,
guildId: id.toString(),
timezone,
features: {
timePlanning: {
enabled: tpEnabled,
channelId: tpChannelId,
channelId: tpChannelId?.toString() ?? null,
targetMinute,
targetHour,
targetDay,
roles: { enabled: tpRoles, isAvailableRoleId, wantsToBeNotifieRoledId },
roles: {
enabled: tpRoles,
isAvailableRoleId: isAvailableRoleId?.toString() ?? null,
wantsToBeNotifieRoledId: wantsToBeNotifieRoledId?.toString() ?? null,
},
},
},
matches: buildMatches(guildQuery.matches),
checksum: objectHash(stringify(guildQuery)),
};
return payload;
// generate checksum from payload because
// from guildQuery results in bigint serialization error
return { ...payload, checksum: objectHash(stringify(payload)) };
}

View file

@ -12,6 +12,7 @@ export function ErrorResponse<
M extends Methods<P>,
C extends StatusCodes<P, M> = StatusCodes<P, M>,
>(code: C, error?: string): APIResponse<P, M> {
console.log(code, error);
const responseData = {
error: error ?? httpStatus[`${httpStatus[code]}_NAME`],
};

View file

@ -1,13 +1,17 @@
import moment from "moment-timezone";
import { z } from "zod";
export const zodId = z
const zodId = z
.string()
.refine((value) => /^\d{7,20}$/.test(value), "Invalid ID supplied")
.transform((value) => parseInt(value));
.refine((value) => /^\d{7,20}$/.test(value), "Invalid ID supplied");
export const zodBigIntId = zodId.transform((value) => BigInt(value));
export const zodTpMessages = z.object({
channelId: zodId,
enabled: z.boolean(),
channelId: zodId.nullable(),
rolesEnabled: z.boolean(),
isAvailableRoleId: zodId.nullable(),
wantsToBeNotifieRoledId: zodId.nullable(),
messageIds: z.object({
"0": zodId.nullable(),
"1": zodId.nullable(),

View file

@ -1,8 +1,14 @@
import { createMiddleware } from "@solidjs/start/middleware";
import { Session, User, verifyRequestOrigin } from "lucia";
import colors from "colors";
import fs from "fs";
import { verifyRequestOrigin } from "lucia";
import { appendHeader, getCookie, getHeader } from "vinxi/http";
import { lucia } from "./lib/auth";
colors.enable();
let started: boolean = false;
export default createMiddleware({
onRequest: async (event) => {
if (event.nativeEvent.node.req.method !== "GET") {
@ -43,12 +49,52 @@ export default createMiddleware({
event.nativeEvent.context.session = session;
event.nativeEvent.context.user = user;
},
});
onBeforeResponse: async (event, response) => {
let consoleLog = "",
fileLog = "";
declare module "h3" {
// eslint-disable-next-line no-unused-vars
interface H3EventContext {
user: User | null;
session: Session | null;
}
}
if (!started) {
try {
await fs.promises.mkdir("log");
console.log("Created 'log' Folder.");
} catch {}
started = true;
}
const currentDate = new Date();
const year = currentDate.getFullYear();
const month = String(currentDate.getMonth() + 1).padStart(2, "0");
const day = String(currentDate.getDate()).padStart(2, "0");
const hours = String(currentDate.getHours()).padStart(2, "0");
const minutes = String(currentDate.getMinutes()).padStart(2, "0");
const seconds = String(currentDate.getSeconds()).padStart(2, "0");
// Create a short and numeric representation
const date = `[${year}-${month}-${day}_${hours}:${minutes}:${seconds}]`;
const xForwardedFor = event.request.headers.get("x-forwarded-for");
const ip = (xForwardedFor || "127.0.0.1, 192.168.178.1").split(",");
const route = event.request.url;
const frontend = !new URL(event.request.url).pathname.startsWith("/api");
const method = frontend ? "Frontend" : event.request.method;
const code =
(response.body as Response | undefined)?.status ?? event.response.status;
consoleLog += [
date,
ip[0].yellow,
method,
code,
route?.green,
event.nativeEvent.context.user?.discord_id.rainbow,
].join(" ");
fileLog += [
date,
ip[0],
method,
code,
route,
event.nativeEvent.context.user?.discord_id,
].join(" ");
await fs.promises.appendFile("log/log.txt", fileLog + "\n");
console.log(consoleLog);
},
});

View file

@ -5,7 +5,7 @@ import { guilds } from "~/drizzle/schema";
import { BasicAuth } from "~/lib/auth";
import { buildConfig } from "~/lib/responseBuilders";
import { ErrorResponse, Res } from "~/lib/responses";
import { zodId } from "~/lib/zod";
import { zodBigIntId } from "~/lib/zod";
import { APIResponse } from "~/types/backend";
type Path = "/api/{guildId}/config";
@ -22,9 +22,9 @@ export const GET = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
@ -41,6 +41,32 @@ export const GET = async (
return Res("OK", buildConfig(guildQuery));
};
export const POST = async (
event: APIEvent,
): Promise<APIResponse<Path, "post">> => {
switch (event.request.headers.get("authorization")) {
case BasicAuth.unencoded:
case BasicAuth.encoded:
break;
default:
return ErrorResponse("UNAUTHORIZED");
}
let guildId: bigint;
try {
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
const guildQuery = await db.insert(guilds).values({ id: guildId }).execute();
if (!guildQuery) return ErrorResponse("NOT_FOUND");
return Res("NO_CONTENT", null);
};
export const DELETE = async (
event: APIEvent,
): Promise<APIResponse<Path, "delete">> => {
@ -53,9 +79,9 @@ export const DELETE = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}

View file

@ -5,7 +5,7 @@ import { guilds, matches } from "~/drizzle/schema";
import { BasicAuth } from "~/lib/auth";
import { buildMatches } from "~/lib/responseBuilders";
import { ErrorResponse, Res } from "~/lib/responses";
import { zodId, zodMatch } from "~/lib/zod";
import { zodBigIntId, zodMatch } from "~/lib/zod";
import { APIResponse, RequestBody } from "~/types/backend";
type Path = "/api/{guildId}/matches";
@ -22,9 +22,9 @@ export const GET = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
@ -60,9 +60,9 @@ export const POST = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
@ -94,8 +94,13 @@ export const POST = async (
);
await db.insert(matches).values({
...body.match,
guildId: guild.id,
channelId: BigInt(body.match.channelId),
roleId: BigInt(body.match.roleId),
createrId: BigInt(body.match.createrId),
messageId: BigInt(body.match.messageId),
matchType: body.match.matchType,
opponentName: body.match.opponentName,
utc_ts: new Date(body.match.utc_ts),
});

View file

@ -4,14 +4,14 @@ import db from "~/drizzle";
import { guilds, tpMessages } from "~/drizzle/schema";
import { BasicAuth } from "~/lib/auth";
import { ErrorResponse, Res } from "~/lib/responses";
import { zodId, zodTpMessages } from "~/lib/zod";
import { zodBigIntId, zodTpMessages } from "~/lib/zod";
import { APIResponse, RequestBody } from "~/types/backend";
type Path = "/api/{guildId}/tp_messages";
type Path = "/api/{guildId}/timePlanning";
const DayKeys = ["0", "1", "2", "3", "4", "5", "6"] as const;
type DayKeys = (typeof DayKeys)[number];
type Messages = Record<DayKeys, number | null>;
type Messages = Record<DayKeys, string | null>;
export const GET = async (
event: APIEvent,
@ -25,9 +25,9 @@ export const GET = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
@ -41,13 +41,11 @@ export const GET = async (
if (!guild) return ErrorResponse("NOT_FOUND");
if (!guild.tpEnabled || !guild.tpChannelId) return Res("NO_CONTENT", null);
const tpMessages = guild.tpMessages.reduce(
(acc, message) => {
const day = message.day.toString() as DayKeys;
if (!/^[0-6]$/.test(day)) return acc;
acc[day] = message.messageId;
acc[day] = message.messageId?.toString() ?? null;
return acc;
},
{
@ -62,7 +60,11 @@ export const GET = async (
);
return Res("OK", {
channelId: guild.tpChannelId,
enabled: guild.tpEnabled,
channelId: guild.tpChannelId?.toString() ?? null,
rolesEnabled: guild.tpRolesEnabled,
isAvailableRoleId: guild.isAvailableRoleId?.toString() ?? null,
wantsToBeNotifieRoledId: guild.wantsToBeNotifieRoledId?.toString() ?? null,
messageIds: tpMessages,
});
};
@ -79,9 +81,9 @@ export const PUT = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
@ -95,8 +97,6 @@ export const PUT = async (
if (!guild) return ErrorResponse("NOT_FOUND");
if (!guild.tpEnabled) return ErrorResponse("FORBIDDEN");
const unparsedBody = await new Response(event.request.body).json();
let body: RequestBody<Path, "put">;
@ -106,19 +106,36 @@ export const PUT = async (
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}
if (guild.tpChannelId !== body.channelId)
const {
enabled,
channelId,
rolesEnabled,
isAvailableRoleId,
wantsToBeNotifieRoledId,
messageIds,
} = body;
if (guild.tpChannelId !== channelId)
await db
.update(guilds)
.set({ tpChannelId: body.channelId })
.set({
tpEnabled: enabled,
tpChannelId: channelId ? BigInt(channelId) : null,
tpRolesEnabled: rolesEnabled,
isAvailableRoleId: isAvailableRoleId ? BigInt(isAvailableRoleId) : null,
wantsToBeNotifieRoledId: wantsToBeNotifieRoledId
? BigInt(wantsToBeNotifieRoledId)
: null,
})
.where(eq(guilds.id, guild.id))
.execute();
await Promise.all(
DayKeys.map(async (dayStr) => {
const day = parseInt(dayStr);
const messageId = messageIds[dayStr];
await db
.update(tpMessages)
.set({ messageId: body.messageIds[dayStr] })
.set({ messageId: messageId ? BigInt(messageId) : null })
.where(and(eq(tpMessages.guildId, guild.id), eq(tpMessages.day, day)))
.execute();
}),

View file

@ -5,7 +5,7 @@ import { guilds } from "~/drizzle/schema";
import { BasicAuth } from "~/lib/auth";
import { buildConfig } from "~/lib/responseBuilders";
import { ErrorResponse, Res } from "~/lib/responses";
import { zodId } from "~/lib/zod";
import { zodBigIntId } from "~/lib/zod";
import { APIResponse } from "~/types/backend";
type Path = "/api/boot";
@ -22,9 +22,9 @@ export const GET = async (
return ErrorResponse("UNAUTHORIZED");
}
let guildId: number;
let guildId: bigint;
try {
guildId = zodId.parse(event.params.guildId);
guildId = zodBigIntId.parse(event.params.guildId);
} catch (e) {
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
}

4
src/types/db.d.ts vendored
View file

@ -6,6 +6,8 @@ export type GetColumns<T> =
export type ExtractDataTypes<T> = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[K in keyof T]: T[K] extends PgColumn<infer ColumnConfig, any, any>
? ColumnConfig["data"]
? ColumnConfig["notNull"] extends true
? ColumnConfig["data"]
: ColumnConfig["data"] | null
: unknown;
};

1
src/types/env.d.ts vendored
View file

@ -12,7 +12,6 @@ interface ImportMetaEnv {
readonly VITE_DATABASE_URL: string;
}
// eslint-disable-next-line no-unused-vars
interface ImportMeta {
readonly env: ImportMetaEnv;
}

244
src/types/liljudd.d.ts vendored
View file

@ -18,33 +18,38 @@ export interface paths {
* @description Returns a single guild's config.
*/
get: operations["getGuildById"];
/**
* Creates a guild's config by ID
* @description Create a guild's config when the bot is has joined a new guild.
*/
post: operations["postGuildById"];
/**
* Deletes a guild's config by ID
* @description Delete a guild's config when the bot is removed from the guild.
*/
delete: operations["deleteGuildById"];
};
"/api/{guildId}/tp_messages": {
"/api/{guildId}/timePlanning": {
/**
* Find the tp_messages of guild by ID
* @description Returns tp_messages for a guild
* Find the timePlanning of guild by ID
* @description Returns timePlanning for a guild
*/
get: operations["getTp_messagesOfGuildById"];
get: operations["gettimePlanningOfGuildById"];
/**
* Put new message IDs for tp_messages of guild by ID
* @description Returns tp_messages for a guild
* Put new message IDs for timePlanning of guild by ID
* @description Returns timePlanning for a guild
*/
put: operations["putTp_messagesOfGuildById"];
put: operations["puttimePlanningOfGuildById"];
};
"/api/{guildId}/matches": {
/**
* Find all matches of guild by ID
* @description Returns tp_messages for a guild
* @description Returns timePlanning for a guild
*/
get: operations["getMatchesOfGuildById"];
/**
* Save a new created match of guild by ID
* @description Returns tp_messages for a guild
* @description Returns timePlanning for a guild
*/
post: operations["postMatchOfGuildById"];
};
@ -55,8 +60,7 @@ export type webhooks = Record<string, never>;
export interface components {
schemas: {
guildConfig: {
/** @example 1234567890123456800 */
guildId: number;
guildId: components["schemas"]["id"];
/**
* Format: text
* @example Europe/Berlin
@ -65,8 +69,7 @@ export interface components {
features: {
timePlanning: {
enabled: boolean;
/** @example 1234567890123456800 */
channelId: number | null;
channelId: components["schemas"]["idOrNull"];
/** @example 0 */
targetMinute: number;
/** @example 1 */
@ -75,10 +78,8 @@ export interface components {
targetDay: number;
roles: {
enabled: boolean;
/** @example 1234567890123456800 */
isAvailableRoleId: number | null;
/** @example 1234567890123456800 */
wantsToBeNotifieRoledId: number | null;
isAvailableRoleId: components["schemas"]["idOrNull"];
wantsToBeNotifieRoledId: components["schemas"]["idOrNull"];
};
};
};
@ -86,14 +87,10 @@ export interface components {
checksum: string;
};
match: {
/** @example 1234567890123456800 */
channelId: number;
/** @example 1234567890123456800 */
createrId: number;
/** @example 1234567890123456800 */
roleId: number;
/** @example 1234567890123456800 */
messageId: number;
channelId: components["schemas"]["id"];
createrId: components["schemas"]["id"];
roleId: components["schemas"]["id"];
messageId: components["schemas"]["id"];
/**
* Format: varchar(50)
* @example Scrim
@ -107,26 +104,29 @@ export interface components {
/** @example 2020-01-01T00:00:00Z */
utc_ts: string;
};
tp_messages: {
/** @example 1234567890123456800 */
channelId: number;
timePlanning: {
enabled: boolean;
channelId: components["schemas"]["idOrNull"];
rolesEnabled: boolean;
isAvailableRoleId: components["schemas"]["idOrNull"];
wantsToBeNotifieRoledId: components["schemas"]["idOrNull"];
messageIds: {
/** @example 1234567890123456800 */
0: number | null;
/** @example 1234567890123456800 */
1: number | null;
/** @example 1234567890123456800 */
2: number | null;
/** @example 1234567890123456800 */
3: number | null;
/** @example 1234567890123456800 */
4: number | null;
/** @example 1234567890123456800 */
5: number | null;
/** @example 1234567890123456800 */
6: number | null;
0: components["schemas"]["idOrNull"];
1: components["schemas"]["idOrNull"];
2: components["schemas"]["idOrNull"];
3: components["schemas"]["idOrNull"];
4: components["schemas"]["idOrNull"];
5: components["schemas"]["idOrNull"];
6: components["schemas"]["idOrNull"];
};
};
/** @example 1234567890123456789 */
id: string;
/** @example 1234567890123456789 */
idOrNull: string | null;
error: {
error?: string;
};
};
responses: never;
parameters: never;
@ -155,15 +155,21 @@ export interface operations {
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
@ -187,16 +193,58 @@ export interface operations {
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
* Creates a guild's config by ID
* @description Create a guild's config when the bot is has joined a new guild.
*/
postGuildById: {
parameters: {
path: {
/** @description ID of guild's config to create */
guildId: string;
};
};
responses: {
/** @description successful operation */
204: {
content: never;
};
/** @description Invalid ID supplied */
400: {
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
@ -206,7 +254,7 @@ export interface operations {
deleteGuildById: {
parameters: {
path: {
/** @description ID of guild config to delete */
/** @description ID of guild's config to delete */
guildId: string;
};
};
@ -217,26 +265,32 @@ export interface operations {
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
* Find the tp_messages of guild by ID
* @description Returns tp_messages for a guild
* Find the timePlanning of guild by ID
* @description Returns timePlanning for a guild
*/
getTp_messagesOfGuildById: {
gettimePlanningOfGuildById: {
parameters: {
path: {
/** @description ID of guild's tp_messages to return */
/** @description ID of guild's timePlanning to return */
guildId: string;
};
};
@ -244,42 +298,44 @@ export interface operations {
/** @description successful operation */
200: {
content: {
"application/json": components["schemas"]["tp_messages"];
"application/json": components["schemas"]["timePlanning"];
};
};
/** @description Time planning not enabled for this guild */
204: {
content: never;
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
* Put new message IDs for tp_messages of guild by ID
* @description Returns tp_messages for a guild
* Put new message IDs for timePlanning of guild by ID
* @description Returns timePlanning for a guild
*/
putTp_messagesOfGuildById: {
puttimePlanningOfGuildById: {
parameters: {
path: {
/** @description ID of guild's tp_messages to return */
/** @description ID of guild's timePlanning to return */
guildId: string;
};
};
/** @description Put new message IDs for tp_messages in channel */
/** @description Put new message IDs for timePlanning in channel */
requestBody: {
content: {
"application/json": components["schemas"]["tp_messages"];
"application/json": components["schemas"]["timePlanning"];
};
};
responses: {
@ -289,30 +345,32 @@ export interface operations {
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
};
/** @description Time planning not enabled for this guild */
403: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
* Find all matches of guild by ID
* @description Returns tp_messages for a guild
* @description Returns timePlanning for a guild
*/
getMatchesOfGuildById: {
parameters: {
path: {
/** @description ID of guild's tp_messages to return */
/** @description ID of guild's timePlanning to return */
guildId: string;
};
};
@ -330,27 +388,29 @@ export interface operations {
};
};
};
/** @description Time planning not enabled for this guild */
204: {
content: never;
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};
/**
* Save a new created match of guild by ID
* @description Returns tp_messages for a guild
* @description Returns timePlanning for a guild
*/
postMatchOfGuildById: {
parameters: {
@ -380,15 +440,21 @@ export interface operations {
};
/** @description Invalid ID supplied */
400: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Unauthorized */
401: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
/** @description Guild not found */
404: {
content: never;
content: {
"application/json": components["schemas"]["error"];
};
};
};
};

View file

@ -3,7 +3,6 @@ import { lucia } from "~/lib/auth";
import { ExtractDataTypes, GetColumns } from "./db";
declare module "lucia" {
// eslint-disable-next-line no-unused-vars
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: DatabaseUserAttributes;
@ -11,6 +10,4 @@ declare module "lucia" {
}
interface DatabaseUserAttributes
extends ExtractDataTypes<GetColumns<typeof users>> {
warst: string;
}
extends ExtractDataTypes<GetColumns<typeof users>> {}

12
src/types/vinxi.d.ts vendored Normal file
View file

@ -0,0 +1,12 @@
import { H3EventContext as EventContext } from "h3/dist";
import { Session, User } from "lucia";
declare module "vinxi/http" {
interface H3EventContext extends EventContext {
user: User | null;
session: Session | null;
}
class H3Eventt {
context: H3EventContext;
}
}