diff --git a/assets/openapi.json b/assets/openapi.json index 62f4cbaa7..cced6947f 100644 Binary files a/assets/openapi.json and b/assets/openapi.json differ diff --git a/assets/schemas.json b/assets/schemas.json index 678371708..fe58930aa 100644 Binary files a/assets/schemas.json and b/assets/schemas.json differ diff --git a/scripts/schemaExclusions.json b/scripts/schemaExclusions.json index 82e545ab0..3305a4e4b 100644 --- a/scripts/schemaExclusions.json +++ b/scripts/schemaExclusions.json @@ -31,7 +31,6 @@ "UpdateRouteResponse", "MessagesSendAPIResponse", "APIWebhook", - "WebhookResponse", "WebhookValidationResponse", "MessageResponse", "ConnectionSettingsResponse", diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts index c9b7a5406..762eae171 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts @@ -78,7 +78,7 @@ router.get( }, responses: { 200: { - body: "PublicMessageArray", + body: "PublicMessageListResponse", }, 400: { body: "APIErrorResponse", diff --git a/src/api/routes/channels/#channel_id/messages/pins/index.ts b/src/api/routes/channels/#channel_id/messages/pins/index.ts index 062084e58..1b1254b92 100644 --- a/src/api/routes/channels/#channel_id/messages/pins/index.ts +++ b/src/api/routes/channels/#channel_id/messages/pins/index.ts @@ -165,7 +165,7 @@ router.get( permission: ["READ_MESSAGE_HISTORY"], responses: { 200: { - body: "PublicMessageArray", + body: "PublicMessageListResponse", }, 400: { body: "APIErrorResponse", diff --git a/src/api/routes/channels/#channel_id/pins.ts b/src/api/routes/channels/#channel_id/pins.ts index 499e3a980..2169d05cc 100644 --- a/src/api/routes/channels/#channel_id/pins.ts +++ b/src/api/routes/channels/#channel_id/pins.ts @@ -166,7 +166,7 @@ router.get( permission: ["READ_MESSAGE_HISTORY"], responses: { 200: { - body: "PublicMessageArray", + body: "PublicMessageListResponse", }, 400: { body: "APIErrorResponse", diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts index d38e18d7c..a27e1cf28 100644 --- a/src/api/routes/channels/#channel_id/webhooks.ts +++ b/src/api/routes/channels/#channel_id/webhooks.ts @@ -34,7 +34,7 @@ router.get( permission: "MANAGE_WEBHOOKS", responses: { 200: { - body: "WebhookArray", + body: "WebhookListResponse", }, }, }), diff --git a/src/api/routes/channels/preload-messages.ts b/src/api/routes/channels/preload-messages.ts index 8b860bc98..f8b0d9a09 100644 --- a/src/api/routes/channels/preload-messages.ts +++ b/src/api/routes/channels/preload-messages.ts @@ -20,7 +20,7 @@ import { Request, Response, Router } from "express"; import { route } from "@spacebar/api/middlewares"; import { Message } from "@spacebar/database"; import { Config } from "@spacebar/util"; -import { PreloadMessagesRequestSchema, PublicMessageArray } from "@spacebar/schemas"; +import { PreloadMessagesRequestSchema, PublicMessageListResponse } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); @@ -30,7 +30,7 @@ router.post( requestBody: "PreloadMessagesRequestSchema", responses: { 200: { - body: "PublicMessageArray", + body: "PublicMessageListResponse", }, 400: { body: "APIErrorResponse", @@ -62,7 +62,7 @@ router.post( // https://docs.discord.food/resources/message#preload-messages - reactions are not included in the response x.reactions = undefined; return x; - }) as unknown as PublicMessageArray; + }) as unknown as PublicMessageListResponse; return res.status(200).send(filteredMessages); }, diff --git a/src/api/routes/guilds/#guild_id/members/index.ts b/src/api/routes/guilds/#guild_id/members/index.ts index ba8f4b3b9..fabc48f96 100644 --- a/src/api/routes/guilds/#guild_id/members/index.ts +++ b/src/api/routes/guilds/#guild_id/members/index.ts @@ -42,7 +42,7 @@ router.get( }, responses: { 200: { - body: "PublicMemberArray", + body: "PublicMemberListResponse", }, 403: { body: "APIErrorResponse", diff --git a/src/api/routes/guilds/#guild_id/webhooks.ts b/src/api/routes/guilds/#guild_id/webhooks.ts index 3ae2ad7ee..bc9c91a53 100644 --- a/src/api/routes/guilds/#guild_id/webhooks.ts +++ b/src/api/routes/guilds/#guild_id/webhooks.ts @@ -31,7 +31,7 @@ router.get( permission: "MANAGE_WEBHOOKS", responses: { 200: { - body: "WebhookArray", + body: "WebhookListResponse", }, }, }), diff --git a/src/api/routes/users/#user_id/index.ts b/src/api/routes/users/#user_id/index.ts index 228c87bb2..bee48dcb9 100644 --- a/src/api/routes/users/#user_id/index.ts +++ b/src/api/routes/users/#user_id/index.ts @@ -27,7 +27,7 @@ router.get( route({ responses: { 200: { - body: "APIPublicUser", + body: "PublicUser", }, }, }), diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts index 2ed525e82..f58f87ff2 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts @@ -30,7 +30,7 @@ router.get( route({ responses: { 200: { - body: "APIPrivateUser", + body: "PrivateUser", }, }, }), diff --git a/src/schemas/api/channels/Webhook.ts b/src/schemas/api/channels/Webhook.ts index 22f78946f..fcceb1a83 100644 --- a/src/schemas/api/channels/Webhook.ts +++ b/src/schemas/api/channels/Webhook.ts @@ -29,7 +29,7 @@ export interface WebhookCreateResponse { hook: WebhookResponse; } -export type WebhookArray = WebhookResponse[]; +export type WebhookListResponse = WebhookResponse[]; export interface WebhookResponse { id: Snowflake; type: WebhookType; diff --git a/src/schemas/api/guilds/Emoji.ts b/src/schemas/api/guilds/Emoji.ts index b0b358fda..607434748 100644 --- a/src/schemas/api/guilds/Emoji.ts +++ b/src/schemas/api/guilds/Emoji.ts @@ -1,3 +1,21 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 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 { Snowflake } from "../../Identifiers"; import { PartialUser } from "../users"; diff --git a/src/schemas/api/guilds/GuildScheduledEvents.ts b/src/schemas/api/guilds/GuildScheduledEvents.ts new file mode 100644 index 000000000..11522da3f --- /dev/null +++ b/src/schemas/api/guilds/GuildScheduledEvents.ts @@ -0,0 +1,24 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 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 { Snowflake } from "../../Identifiers"; + +export enum EventPrivacyLevel { + PUBLIC = 1, + GUILD_ONLY = 2, +} diff --git a/src/schemas/api/guilds/GuildSchema.ts b/src/schemas/api/guilds/GuildSchema.ts index a4c671c8a..96bb97391 100644 --- a/src/schemas/api/guilds/GuildSchema.ts +++ b/src/schemas/api/guilds/GuildSchema.ts @@ -1,6 +1,6 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2025 Spacebar and Spacebar Contributors + Copyright (C) 2026 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 @@ -28,3 +28,36 @@ export interface IntegrationGuild { name: string; icon: string | null; } + +export enum GuildVerificationLevel { + NONE = 0, + // Verified email + LOW = 1, + // Registered >5min ago + MEDIUM = 2, + // Member for >10min + HIGH = 3, + // Verified phone number + VERY_HIGH = 4, +} + +export enum GuildNsfwLevel { + DEFAULT = 0, + EXPLICIT = 1, + SAFE = 2, + AGE_RESTRICTED = 3, +} + +// Unlocked boost perk level +export enum GuildPremiumTier { + NONE = 0, + TIER_1 = 1, + TIER_2 = 2, + TIER_3 = 3, +} + +export enum GuildHubType { + DEFAULT = 0, + HIGH_SCHOOL = 1, + COLLEGE = 2, +} diff --git a/src/schemas/api/guilds/Invite.ts b/src/schemas/api/guilds/Invite.ts new file mode 100644 index 000000000..35e458592 --- /dev/null +++ b/src/schemas/api/guilds/Invite.ts @@ -0,0 +1,88 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 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 { Snowflake } from "../../Identifiers"; +import { PartialUser } from "../users"; +import { GuildNsfwLevel, GuildPremiumTier, GuildVerificationLevel } from "./GuildSchema"; +import { GuildProfileResponse, PublicChannel, RoleColors } from "@spacebar/schemas"; +import { Role } from "@spacebar/database"; + +export interface Invite { + code: string; + type: number; + channel: PublicChannel | null; // TODO: Figure out what fields this is *supposed* to have as it's labeled as "Partial channel object" + guild_id?: Snowflake; + guild?: InviteGuild; + profile?: GuildProfileResponse; + inviter?: PartialUser; + flags?: number; + target_type?: number; + target_user?: PartialUser; + // target_application?: PartialApplication; // TODO - voice activities + roles?: InviteRole[]; // TODO: This is labeled as "Partial role object", is this used anywhere else? + approximate_member_count?: number; + approximate_presence_count?: number; + expires_at: string | null; + // guild_scheduled_event?: GuildScheduledEvent; //TODO - scheduled events + new_member?: boolean; + show_verification_form?: boolean; + is_nickname_changeable?: boolean; + target_users_job_status?: InviteTargetUsersJob; // TODO +} + +export interface InviteTargetUsersJob { + status: InviteTargetUsersJobStatus; + total_users: number; + processed_users: number; + created_at: Date | null; + completed_at: Date | null; + error_message: string | null; +} + +export enum InviteTargetUsersJobStatus { + UNSPECIFIED = 0, + PROCESSING = 1, + COMPLETED = 2, + FAILED = 3, +} + +export interface InviteGuild { + id: Snowflake; + name: string; + icon: string | null; + description: string | null; + banner: string | null; + splash: string | null; + verification_level: GuildVerificationLevel; + features: string[]; + vanity_url_code: string | null; + premium_subscription_count?: number; + premium_tier: GuildPremiumTier; + nsfw: boolean; + nsfw_level: GuildNsfwLevel; +} + +export interface InviteRole { + id: Snowflake; + name: string; + position: number; + color: number; + colors: RoleColors; + icon?: string | null; + unicode_emoji?: string | null; +} diff --git a/src/schemas/api/messages/Message.ts b/src/schemas/api/messages/Message.ts index 8d736aa68..b340a8637 100644 --- a/src/schemas/api/messages/Message.ts +++ b/src/schemas/api/messages/Message.ts @@ -163,7 +163,7 @@ export interface MessageSnapshot { }; } -export type PublicMessageArray = PublicMessage[]; +export type PublicMessageListResponse = PublicMessage[]; export interface PublicMessage { id: Snowflake; channel_id: Snowflake; diff --git a/src/schemas/api/users/Member.ts b/src/schemas/api/users/Member.ts index f6778509e..691b085bc 100644 --- a/src/schemas/api/users/Member.ts +++ b/src/schemas/api/users/Member.ts @@ -116,4 +116,4 @@ export type PublicMember = Omit, "roles"> & { roles: string[]; // only role ids not objects }; -export type PublicMemberArray = PublicMember[]; +export type PublicMemberListResponse = PublicMember[]; diff --git a/src/schemas/responses/TypedResponses.ts b/src/schemas/responses/TypedResponses.ts index e43114201..b37c4b741 100644 --- a/src/schemas/responses/TypedResponses.ts +++ b/src/schemas/responses/TypedResponses.ts @@ -21,17 +21,15 @@ import { GeneralConfiguration, LimitsConfiguration } from "../../util/config/typ import { DmChannelDTO } from "../../util/dtos"; // TODO: remove entity imports import { Application, Categories, Channel, Guild, Invite, Template } from "@spacebar/database"; -import { GuildCreateResponse, PrivateUser, PublicUser } from "@spacebar/schemas"; +import { GuildCreateResponse, PrivateUser } from "@spacebar/schemas"; // TODO: remove this entire file! // removes internal properties from the guild class export type APIGuild = Omit; -export type APIPublicUser = PublicUser; -export type APIPrivateUser = PrivateUser; export type APIGuildArray = APIGuild[]; export type APIDMChannelArray = DmChannelDTO[]; -export interface UserUpdateResponse extends APIPrivateUser { +export interface UserUpdateResponse extends PrivateUser { newToken?: string; }