refactor: Update time planning feature
- Update checksums for browser compatibility - Add script to kill running server process - Refactor time planning structure and handling - Adjust database schema and type definitions accordingly
This commit is contained in:
parent
faa42f0899
commit
3c404ab5fa
8 changed files with 130 additions and 146 deletions
|
@ -41,7 +41,6 @@ export const discordTokens = pgTable("tokens", {
|
|||
export const guilds = pgTable("guilds", {
|
||||
id: bigint("id", { mode: "bigint" }).primaryKey(),
|
||||
timezone: text("timezone").notNull().default("Etc/UTC"),
|
||||
tpEnabled: boolean("tp_enabled").notNull().default(false),
|
||||
tpChannelId: bigint("tp_channel_id", { mode: "bigint" }),
|
||||
tpInterval: smallint("target_interval").notNull().default(64),
|
||||
tpRolesEnabled: boolean("tp_roles_enabled").notNull().default(false),
|
||||
|
|
|
@ -27,6 +27,39 @@ export const buildMatches = (
|
|||
}),
|
||||
);
|
||||
|
||||
export const splitInterval = (tpInterval: number) => {
|
||||
const targetMinute = tpInterval & 63;
|
||||
const targetHour = (tpInterval >> 6) & 31;
|
||||
const targetDay = (tpInterval >> 11) & 7;
|
||||
|
||||
return { targetMinute, targetHour, targetDay };
|
||||
};
|
||||
|
||||
export const DayKeys = ["0", "1", "2", "3", "4", "5", "6"] as const;
|
||||
export type DayKeys = (typeof DayKeys)[number];
|
||||
export type Messages = Record<DayKeys, string | null>;
|
||||
|
||||
export const buildTpMessages = (
|
||||
messages: ExtractDataTypes<GetColumns<typeof tpMessages>>[],
|
||||
) =>
|
||||
messages.reduce(
|
||||
(acc, message) => {
|
||||
const day = message.day.toString() as DayKeys;
|
||||
if (!/^[0-6]$/.test(day)) return acc;
|
||||
acc[day] = message.messageId?.toString() ?? null;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
"0": null,
|
||||
"1": null,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": null,
|
||||
"5": null,
|
||||
"6": null,
|
||||
} as Messages,
|
||||
);
|
||||
|
||||
export function buildConfig(
|
||||
guildQuery: ExtractDataTypes<GetColumns<typeof guilds>> & {
|
||||
tpMessages: ExtractDataTypes<GetColumns<typeof tpMessages>>[];
|
||||
|
@ -36,33 +69,27 @@ export function buildConfig(
|
|||
const {
|
||||
id,
|
||||
timezone,
|
||||
tpEnabled,
|
||||
tpChannelId,
|
||||
tpInterval,
|
||||
tpRolesEnabled: tpRoles,
|
||||
tpRolesEnabled,
|
||||
isAvailableRoleId,
|
||||
wantsToBeNotifieRoledId,
|
||||
tpMessages,
|
||||
} = guildQuery;
|
||||
|
||||
const targetMinute = tpInterval & 63;
|
||||
const targetHour = (tpInterval >> 6) & 31;
|
||||
const targetDay = (tpInterval >> 11) & 7;
|
||||
|
||||
const payload = {
|
||||
guildId: id.toString(),
|
||||
timezone,
|
||||
features: {
|
||||
timePlanning: {
|
||||
enabled: tpEnabled,
|
||||
channelId: tpChannelId?.toString() ?? null,
|
||||
targetMinute,
|
||||
targetHour,
|
||||
targetDay,
|
||||
...splitInterval(tpInterval),
|
||||
roles: {
|
||||
enabled: tpRoles,
|
||||
enabled: tpRolesEnabled,
|
||||
isAvailableRoleId: isAvailableRoleId?.toString() ?? null,
|
||||
wantsToBeNotifieRoledId: wantsToBeNotifieRoledId?.toString() ?? null,
|
||||
},
|
||||
messageIds: buildTpMessages(tpMessages),
|
||||
},
|
||||
},
|
||||
matches: buildMatches(guildQuery.matches),
|
||||
|
|
|
@ -7,11 +7,15 @@ const zodId = z
|
|||
export const zodBigIntId = zodId.transform((value) => BigInt(value));
|
||||
|
||||
export const zodTpMessages = z.object({
|
||||
enabled: z.boolean(),
|
||||
channelId: zodId.nullable(),
|
||||
rolesEnabled: z.boolean(),
|
||||
isAvailableRoleId: zodId.nullable(),
|
||||
wantsToBeNotifieRoledId: zodId.nullable(),
|
||||
targetMinute: z.number().nonnegative().max(59),
|
||||
targetHour: z.number().nonnegative().max(23),
|
||||
targetDay: z.number().nonnegative().max(6),
|
||||
roles: z.object({
|
||||
enabled: z.boolean(),
|
||||
isAvailableRoleId: zodId.nullable(),
|
||||
wantsToBeNotifieRoledId: zodId.nullable(),
|
||||
}),
|
||||
messageIds: z.object({
|
||||
"0": zodId.nullable(),
|
||||
"1": zodId.nullable(),
|
||||
|
|
|
@ -3,16 +3,17 @@ import { and, eq } from "drizzle-orm";
|
|||
import db from "~/drizzle";
|
||||
import { guilds, tpMessages } from "~/drizzle/schema";
|
||||
import { BasicAuth } from "~/lib/auth";
|
||||
import {
|
||||
DayKeys,
|
||||
buildTpMessages,
|
||||
splitInterval,
|
||||
} from "~/lib/responseBuilders";
|
||||
import { ErrorResponse, Res } from "~/lib/responses";
|
||||
import { zodBigIntId, zodTpMessages } from "~/lib/zod";
|
||||
import { APIResponse, RequestBody } from "~/types/backend";
|
||||
|
||||
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, string | null>;
|
||||
|
||||
export const GET = async (
|
||||
event: APIEvent,
|
||||
): Promise<APIResponse<Path, "get">> => {
|
||||
|
@ -41,31 +42,16 @@ export const GET = async (
|
|||
|
||||
if (!guild) return ErrorResponse("NOT_FOUND");
|
||||
|
||||
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?.toString() ?? null;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
"0": null,
|
||||
"1": null,
|
||||
"2": null,
|
||||
"3": null,
|
||||
"4": null,
|
||||
"5": null,
|
||||
"6": null,
|
||||
} as Messages,
|
||||
);
|
||||
|
||||
return Res("OK", {
|
||||
enabled: guild.tpEnabled,
|
||||
channelId: guild.tpChannelId?.toString() ?? null,
|
||||
rolesEnabled: guild.tpRolesEnabled,
|
||||
isAvailableRoleId: guild.isAvailableRoleId?.toString() ?? null,
|
||||
wantsToBeNotifieRoledId: guild.wantsToBeNotifieRoledId?.toString() ?? null,
|
||||
messageIds: tpMessages,
|
||||
...splitInterval(guild.tpInterval),
|
||||
roles: {
|
||||
enabled: guild.tpRolesEnabled,
|
||||
isAvailableRoleId: guild.isAvailableRoleId?.toString() ?? null,
|
||||
wantsToBeNotifieRoledId:
|
||||
guild.wantsToBeNotifieRoledId?.toString() ?? null,
|
||||
},
|
||||
messageIds: buildTpMessages(guild.tpMessages),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -106,24 +92,18 @@ export const PUT = async (
|
|||
return ErrorResponse("BAD_REQUEST", JSON.stringify(e));
|
||||
}
|
||||
|
||||
const {
|
||||
enabled,
|
||||
channelId,
|
||||
rolesEnabled,
|
||||
isAvailableRoleId,
|
||||
wantsToBeNotifieRoledId,
|
||||
messageIds,
|
||||
} = body;
|
||||
const { channelId, roles, messageIds } = body;
|
||||
if (guild.tpChannelId !== channelId)
|
||||
await db
|
||||
.update(guilds)
|
||||
.set({
|
||||
tpEnabled: enabled,
|
||||
tpChannelId: channelId ? BigInt(channelId) : null,
|
||||
tpRolesEnabled: rolesEnabled,
|
||||
isAvailableRoleId: isAvailableRoleId ? BigInt(isAvailableRoleId) : null,
|
||||
wantsToBeNotifieRoledId: wantsToBeNotifieRoledId
|
||||
? BigInt(wantsToBeNotifieRoledId)
|
||||
tpRolesEnabled: roles.enabled,
|
||||
isAvailableRoleId: roles.isAvailableRoleId
|
||||
? BigInt(roles.isAvailableRoleId)
|
||||
: null,
|
||||
wantsToBeNotifieRoledId: roles.wantsToBeNotifieRoledId
|
||||
? BigInt(roles.wantsToBeNotifieRoledId)
|
||||
: null,
|
||||
})
|
||||
.where(eq(guilds.id, guild.id))
|
||||
|
|
31
src/types/liljudd.d.ts
vendored
31
src/types/liljudd.d.ts
vendored
|
@ -67,21 +67,7 @@ export interface components {
|
|||
*/
|
||||
timezone: string;
|
||||
features: {
|
||||
timePlanning: {
|
||||
enabled: boolean;
|
||||
channelId: components["schemas"]["idOrNull"];
|
||||
/** @example 0 */
|
||||
targetMinute: number;
|
||||
/** @example 1 */
|
||||
targetHour: number;
|
||||
/** @example 1 */
|
||||
targetDay: number;
|
||||
roles: {
|
||||
enabled: boolean;
|
||||
isAvailableRoleId: components["schemas"]["idOrNull"];
|
||||
wantsToBeNotifieRoledId: components["schemas"]["idOrNull"];
|
||||
};
|
||||
};
|
||||
timePlanning: components["schemas"]["timePlanning"];
|
||||
};
|
||||
matches: components["schemas"]["match"][];
|
||||
checksum: string;
|
||||
|
@ -105,11 +91,18 @@ export interface components {
|
|||
utc_ts: string;
|
||||
};
|
||||
timePlanning: {
|
||||
enabled: boolean;
|
||||
channelId: components["schemas"]["idOrNull"];
|
||||
rolesEnabled: boolean;
|
||||
isAvailableRoleId: components["schemas"]["idOrNull"];
|
||||
wantsToBeNotifieRoledId: components["schemas"]["idOrNull"];
|
||||
/** @example 0 */
|
||||
targetMinute: number;
|
||||
/** @example 1 */
|
||||
targetHour: number;
|
||||
/** @example 1 */
|
||||
targetDay: number;
|
||||
roles: {
|
||||
enabled: boolean;
|
||||
isAvailableRoleId: components["schemas"]["idOrNull"];
|
||||
wantsToBeNotifieRoledId: components["schemas"]["idOrNull"];
|
||||
};
|
||||
messageIds: {
|
||||
0: components["schemas"]["idOrNull"];
|
||||
1: components["schemas"]["idOrNull"];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue