diff --git a/assets/openapi.json b/assets/openapi.json index 09506ad..efd3a4c 100644 --- a/assets/openapi.json +++ b/assets/openapi.json @@ -5473,11 +5473,14 @@ "items": { "type": "string" } + }, + "channel_ids": { + "type": "array", + "items": { + "type": "string" + } } - }, - "required": [ - "channels" - ] + } }, "PruneSchema": { "type": "object", @@ -6638,6 +6641,72 @@ "$ref": "#/components/schemas/ApplicationCommandCreateSchema" } }, + "CreateReportSchema": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "name": { + "type": "string" + }, + "language": { + "type": "string" + }, + "breadcrumbs": { + "type": "array", + "items": { + "type": "integer" + } + }, + "elements": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "channel_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "stage_instance_id": { + "type": "string" + }, + "guild_scheduled_event_id": { + "type": "string" + }, + "reported_user_id": { + "type": "string" + }, + "application_id": { + "type": "string" + }, + "user_id": { + "type": "string" + }, + "widget_id": { + "type": "string" + } + }, + "required": [ + "breadcrumbs", + "language", + "name", + "variant", + "version" + ] + }, "SessionsLogoutSchema": { "type": "object", "properties": { @@ -16117,7 +16186,7 @@ ] } }, - "/reporting/menu/": { + "/reporting/": { "get": { "security": [ { @@ -16152,7 +16221,14 @@ "description": "Get reporting menu options for guild reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16180,6 +16256,44 @@ ] } }, + "/reporting/guild": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for guild reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/guild_discovery": { "get": { "security": [ @@ -16190,7 +16304,14 @@ "description": "Get reporting menu options for guild_discovery reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16218,6 +16339,44 @@ ] } }, + "/reporting/guild_discovery": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for guild_discovery reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/guild_directory_entry": { "get": { "security": [ @@ -16228,7 +16387,14 @@ "description": "Get reporting menu options for guild_directory_entry reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16256,6 +16422,44 @@ ] } }, + "/reporting/guild_directory_entry": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for guild_directory_entry reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/guild_scheduled_event": { "get": { "security": [ @@ -16266,7 +16470,14 @@ "description": "Get reporting menu options for guild_scheduled_event reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16294,6 +16505,44 @@ ] } }, + "/reporting/guild_scheduled_event": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for guild_scheduled_event reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/message": { "get": { "security": [ @@ -16304,7 +16553,14 @@ "description": "Get reporting menu options for message reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16332,6 +16588,44 @@ ] } }, + "/reporting/message": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for message reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/stage_channel": { "get": { "security": [ @@ -16342,7 +16636,14 @@ "description": "Get reporting menu options for stage_channel reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16370,6 +16671,44 @@ ] } }, + "/reporting/stage_channel": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for stage_channel reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/first_dm": { "get": { "security": [ @@ -16380,7 +16719,14 @@ "description": "Get reporting menu options for first_dm reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16408,6 +16754,44 @@ ] } }, + "/reporting/first_dm": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for first_dm reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/user": { "get": { "security": [ @@ -16418,7 +16802,14 @@ "description": "Get reporting menu options for user reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16446,6 +16837,44 @@ ] } }, + "/reporting/user": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for user reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/application": { "get": { "security": [ @@ -16456,7 +16885,14 @@ "description": "Get reporting menu options for application reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16484,6 +16920,44 @@ ] } }, + "/reporting/application": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for application reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/reporting/menu/widget": { "get": { "security": [ @@ -16494,7 +16968,14 @@ "description": "Get reporting menu options for widget reports.", "responses": { "200": { - "description": "No description available" + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } }, "204": { "description": "No description available" @@ -16522,6 +17003,44 @@ ] } }, + "/reporting/widget": { + "post": { + "security": [ + { + "bearer": [] + } + ], + "description": "Get reporting menu options for widget reports.", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateReportSchema" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReportingMenuResponse" + } + } + } + }, + "204": { + "description": "No description available" + } + }, + "tags": [ + "reporting" + ] + } + }, "/read-states/ack-bulk/": { "post": { "security": [ diff --git a/assets/schemas.json b/assets/schemas.json index d3b2404..a7d759f 100644 --- a/assets/schemas.json +++ b/assets/schemas.json @@ -5814,12 +5814,15 @@ "items": { "type": "string" } + }, + "channel_ids": { + "type": "array", + "items": { + "type": "string" + } } }, "additionalProperties": false, - "required": [ - "channels" - ], "$schema": "http://json-schema.org/draft-07/schema#" }, "PruneSchema": { @@ -7074,6 +7077,74 @@ }, "$schema": "http://json-schema.org/draft-07/schema#" }, + "CreateReportSchema": { + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "variant": { + "type": "string" + }, + "name": { + "type": "string" + }, + "language": { + "type": "string" + }, + "breadcrumbs": { + "type": "array", + "items": { + "type": "integer" + } + }, + "elements": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "channel_id": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "stage_instance_id": { + "type": "string" + }, + "guild_scheduled_event_id": { + "type": "string" + }, + "reported_user_id": { + "type": "string" + }, + "application_id": { + "type": "string" + }, + "user_id": { + "type": "string" + }, + "widget_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "breadcrumbs", + "language", + "name", + "variant", + "version" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, "SessionsLogoutSchema": { "type": "object", "properties": { diff --git a/src/api/routes/channels/preload-messages.ts b/src/api/routes/channels/preload-messages.ts index f50129f..09743cc 100644 --- a/src/api/routes/channels/preload-messages.ts +++ b/src/api/routes/channels/preload-messages.ts @@ -37,6 +37,7 @@ }), async (req: Request, res: Response) => { const body = req.body as PreloadMessagesRequestSchema; + body.channels ??= body.channel_ids ?? []; if (body.channels.length > Config.get().limits.message.maxPreloadCount) return res.status(400).send({ code: 400, diff --git a/src/api/routes/reporting/index.ts b/src/api/routes/reporting/index.ts new file mode 100644 index 0000000..f061cdf --- /dev/null +++ b/src/api/routes/reporting/index.ts @@ -0,0 +1,202 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2025 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; +import { ReportMenuType, ReportMenuTypeNames } from "../../../schemas/api/reports/ReportMenu"; +import path from "path"; +import { HTTPError } from "lambert-server"; +import { CreateReportSchema } from "../../../schemas/api/reports/CreateReport"; +import { FieldErrors } from "@spacebar/util"; +import fs from "fs"; + +const router = Router({ mergeParams: true }); + +console.log("[Server] Registering reporting menu routes..."); +router.get( + "/", + route({ + description: "[EXT] Get available reporting menu types.", + responses: { + 200: { + body: "Array", + }, + }, + }), + (req: Request, res: Response) => { + res.json(Object.values(ReportMenuTypeNames)); + }, +); + +for (const type of Object.values(ReportMenuTypeNames)) { + router.get( + `/menu/${type}`, + route({ + description: `Get reporting menu options for ${type} reports.`, + query: { + variant: { type: "string", required: false, description: "Version variant of the menu to retrieve (max 256 characters, default active)" }, + }, + responses: { + 200: { + body: "ReportingMenuResponse", + }, + 204: {}, + }, + }), + (req: Request, res: Response) => { + // TODO: implement + // res.send([] as ReportingMenuResponseSchema); + res.sendFile(path.join(__dirname, "..", "..", "..", "..", "assets", "temp_report_menu_responses", `${type}.json`)); + }, + ); + console.log(`[Server] Route /reporting/menu/${type} registered (reports).`); + router.post( + `/${type}`, + route({ + description: `Get reporting menu options for ${type} reports.`, + requestBody: "CreateReportSchema", + responses: { + 200: { + body: "ReportingMenuResponse", + }, + 204: {}, + }, + }), + (req: Request, res: Response) => { + // TODO: implement + const body = req.body as CreateReportSchema; + if (body.name !== type) + throw FieldErrors({ + name: { + message: `Expected report type ${type} but got ${body.name}`, + code: "INVALID_REPORT_TYPE", + }, + }); + + const menuPath = path.join(__dirname, "..", "..", "..", "..", "assets", "temp_report_menu_responses", `${type}.json`); + const menuData = JSON.parse(fs.readFileSync(menuPath, "utf-8")); + if (body.version !== menuData.version) { + throw FieldErrors({ + version: { + message: `Expected report menu version ${menuData.version} but got ${body.version}`, + code: "INVALID_REPORT_MENU_VERSION", + }, + }); + } + + if (body.variant !== menuData.variant) { + throw FieldErrors({ + variant: { + message: `Expected report menu variant ${menuData.variant} but got ${body.variant}`, + code: "INVALID_REPORT_MENU_VARIANT", + }, + }); + } + + if (body.breadcrumbs != menuData.breadcrumbs) { + throw FieldErrors({ + breadcrumbs: { + message: `Invalid report menu breadcrumbs.`, + code: "INVALID_REPORT_MENU_BREADCRUMBS", + }, + }); + } + + const validateBreadcrumbs = (currentNode: unknown, breadcrumbs: number[]): boolean => { + // navigate via node.children ([name, id][]) according to breadcrumbs + let node: { children: [string, number][] } = currentNode as { children: [string, number][] }; + for (const crumb of breadcrumbs) { + if (!node || !node.children || !Array.isArray(node.children)) return false; + const nextNode = node.children.find((child: [string, number]) => child[1] === crumb); + if (!nextNode) return false; + // load next node + const nextNodeData = menuData.nodes[crumb]; + if (!nextNodeData) return false; + node = nextNodeData; + } + return true; + }; + + if (!validateBreadcrumbs(menuData.nodes[menuData.root_node_id], body.breadcrumbs)) + throw FieldErrors({ + breadcrumbs: { + message: `Invalid report menu breadcrumbs path.`, + code: "INVALID_REPORT_MENU_BREADCRUMBS_PATH", + }, + }); + + const requireFields = (obj: CreateReportSchema, fields: string[]) => { + const missingFields: string[] = []; + for (const field of fields) if (!(field in obj)) missingFields.push(field); + + if (missingFields.length > 0) + throw FieldErrors( + Object.fromEntries( + missingFields.map((f) => [ + f, + { + message: `Missing required field ${f}.`, + code: "MISSING_FIELD", + }, + ]), + ), + ); + }; + + const t = Number(Object.entries(ReportMenuTypeNames).find((x) => x[1] === type)?.[0]) as ReportMenuType; + // TODO: did i miss anything? + switch (t) { + case ReportMenuType.GUILD: + case ReportMenuType.GUILD_DISCOVERY: + requireFields(body, ["guild_id"]); + break; + case ReportMenuType.GUILD_DIRECTORY_ENTRY: + requireFields(body, ["guild_id", "channel_id"]); + break; + case ReportMenuType.GUILD_SCHEDULED_EVENT: + requireFields(body, ["guild_id", "scheduled_event_id"]); + break; + case ReportMenuType.MESSAGE: + requireFields(body, ["channel_id", "message_id"]); + // NOTE: is body.guild_id set if the channel is in a guild? is body.user_id ever set???? + break; + case ReportMenuType.STAGE_CHANNEL: + requireFields(body, ["channel_id", "guild_id", "stage_instance_id"]); + break; + case ReportMenuType.FIRST_DM: + requireFields(body, ["user_id", "channel_id"]); + break; + case ReportMenuType.USER: + requireFields(body, ["reported_user_id"]); + break; + case ReportMenuType.APPLICATION: + requireFields(body, ["application_id"]); + break; + case ReportMenuType.WIDGET: + requireFields(body, ["user_id", "widget_id"]); + break; + default: + throw new HTTPError("Unknown report menu type", 400); + } + + throw new HTTPError("Validation success - implementation TODO", 418); + }, + ); + console.log(`[Server] Route /reporting/${type} registered (reports).`); +} +export default router; diff --git a/src/api/routes/reporting/menu.ts b/src/api/routes/reporting/menu.ts deleted file mode 100644 index 3cff084..0000000 --- a/src/api/routes/reporting/menu.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2025 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -import { route } from "@spacebar/api"; -import { Request, Response, Router } from "express"; -import { ReportMenuTypeNames } from "../../../schemas/api/reports/ReportMenu"; -import path from "path"; - -const router = Router({ mergeParams: true }); - -console.log("[Server] Registering reporting menu routes..."); -router.get( - "/", - route({ - description: "[EXT] Get available reporting menu types.", - responses: { - 200: { - body: "Array", - }, - }, - }), - (req: Request, res: Response) => { - res.json(Object.values(ReportMenuTypeNames)); - }, -); - -for (const type of Object.values(ReportMenuTypeNames)) { - console.log(`[Server] Route /reporting/menu/${type} registered (reports).`); - router.get( - `/${type}`, - route({ - description: `Get reporting menu options for ${type} reports.`, - query: { - variant: { type: "string", required: false, description: "Version variant of the menu to retrieve (max 256 characters, default active)" }, - }, - responses: { - 200: { - // body: "ReportingMenuResponse", - }, - 204: {}, - }, - }), - (req: Request, res: Response) => { - // TODO: implement - // res.send([] as ReportingMenuResponseSchema); - res.sendFile(path.join(__dirname, "..", "..", "..", "..", "assets", "temp_report_menu_responses", `${type}.json`)); - }, - ); -} -export default router; diff --git a/src/schemas/api/reports/CreateReport.ts b/src/schemas/api/reports/CreateReport.ts new file mode 100644 index 0000000..7c5606d --- /dev/null +++ b/src/schemas/api/reports/CreateReport.ts @@ -0,0 +1,36 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2025 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +// TODO: check +export interface CreateReportSchema { + version: string; + variant: string; + name: string; + language: string; + breadcrumbs: number[]; + elements?: { [key: string]: string[] }; + channel_id?: string; // snowflake + message_id?: string; // snowflake + guild_id?: string; // snowflake + stage_instance_id?: string; // snowflake + guild_scheduled_event_id?: string; // snowflake + reported_user_id?: string; // snowflake + application_id?: string; // snowflake + user_id?: string; // snowflake + widget_id?: string; // snowflake +} diff --git a/src/schemas/uncategorised/PreloadMessagesRequestSchema.ts b/src/schemas/uncategorised/PreloadMessagesRequestSchema.ts index 1dc1eec..5705e7f 100644 --- a/src/schemas/uncategorised/PreloadMessagesRequestSchema.ts +++ b/src/schemas/uncategorised/PreloadMessagesRequestSchema.ts @@ -17,5 +17,6 @@ */ export interface PreloadMessagesRequestSchema { - channels: string[]; + channels?: string[]; + channel_ids?: string[]; } diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts index 5338837..1aaf147 100644 --- a/src/util/entities/BaseClass.ts +++ b/src/util/entities/BaseClass.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { BaseEntity, BeforeInsert, BeforeUpdate, FindOptionsWhere, InsertResult, ObjectIdColumn, ObjectLiteral, PrimaryColumn } from "typeorm"; +import { BaseEntity, BeforeInsert, BeforeUpdate, Column, ColumnOptions, FindOptionsWhere, InsertResult, ObjectIdColumn, ObjectLiteral, PrimaryColumn } from "typeorm"; import { Snowflake } from "../util/Snowflake"; import { getDatabase } from "../util/Database"; import { OrmUtils } from "../imports/OrmUtils"; @@ -83,3 +83,5 @@ if (!this.id) this.id = Snowflake.generate(); } } + +export const ArrayColumn = (opts: ColumnOptions) => (process.env.DATABASE?.startsWith("postgres") ? Column({ ...opts, array: true }) : Column({ ...opts, type: "simple-array" })); diff --git a/src/util/entities/ReportMenu.ts b/src/util/entities/ReportMenu.ts new file mode 100644 index 0000000..26d66ad --- /dev/null +++ b/src/util/entities/ReportMenu.ts @@ -0,0 +1,43 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2024 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { BaseClass, BaseClassWithoutId } from "./BaseClass"; +import { Entity, JoinColumn, ManyToOne, Column } from "typeorm"; +import { User } from "./User"; +import { AutomodAction, AutomodRuleActionType, AutomodRuleEventType, AutomodRuleTriggerMetadata, AutomodRuleTriggerType } from "@spacebar/schemas"; +import { ReportMenuType } from "../../schemas/api/reports/ReportMenu"; + +@Entity({ + name: "report_menus", +}) +export class ReportMenu extends BaseClass { + @Column() + type: ReportMenuType; + + @Column() + variant: string; + + @Column() + isCurrent: boolean; + + @Column({ nullable: true }) + inherits?: string; + + @Column({ type: "jsonb" }) + content: unknown; +}