summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTomatoCake <60300461+DEVTomatoCake@users.noreply.github.com>2024-07-18 16:08:06 +0200
committerGitHub <noreply@github.com>2024-07-18 16:08:06 +0200
commitd79669f7712c467136e22761a4779a9ebd679b5e (patch)
treec42a8a211c5b88a5d0cb82510aade40b52f697e3 /src
parentFix build by using ts-ignore (diff)
parentMake channel ID optional when replying (diff)
downloadserver-ts-d79669f7712c467136e22761a4779a9ebd679b5e.tar.xz
Merge branch 'master' into feat/local-image-proxy
Diffstat (limited to 'src')
-rw-r--r--src/api/Server.ts14
-rw-r--r--src/api/routes/auth/verify/index.ts2
-rw-r--r--src/api/routes/channels/#channel_id/index.ts6
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts7
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/index.ts9
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts20
-rw-r--r--src/api/routes/channels/#channel_id/permissions.ts11
-rw-r--r--src/api/routes/connections/index.ts45
-rw-r--r--src/api/routes/guilds/#guild_id/channels.ts20
-rw-r--r--src/api/routes/guilds/#guild_id/emojis.ts12
-rw-r--r--src/api/routes/guilds/#guild_id/messages/search.ts7
-rw-r--r--src/api/routes/users/#id/profile.ts5
-rw-r--r--src/api/util/handlers/Message.ts56
-rw-r--r--src/cdn/routes/badge-icons.ts40
-rw-r--r--src/cdn/routes/embed.ts12
-rw-r--r--src/connections/BattleNet/index.ts20
-rw-r--r--src/connections/Discord/index.ts13
-rw-r--r--src/connections/EpicGames/index.ts20
-rw-r--r--src/connections/Facebook/index.ts13
-rw-r--r--src/connections/GitHub/index.ts13
-rw-r--r--src/connections/Reddit/index.ts13
-rw-r--r--src/connections/Spotify/index.ts14
-rw-r--r--src/connections/Twitch/index.ts13
-rw-r--r--src/connections/Twitter/index.ts13
-rw-r--r--src/connections/Xbox/index.ts13
-rw-r--r--src/connections/Youtube/index.ts13
-rw-r--r--src/util/config/types/EmailConfiguration.ts1
-rw-r--r--src/util/connections/Connection.ts8
-rw-r--r--src/util/dtos/UserDTO.ts2
-rw-r--r--src/util/entities/Badge.ts35
-rw-r--r--src/util/entities/Member.ts15
-rw-r--r--src/util/entities/Message.ts40
-rw-r--r--src/util/entities/User.ts4
-rw-r--r--src/util/entities/index.ts1
-rw-r--r--src/util/migration/mariadb/1719776735000-newUserSettings.ts23
-rw-r--r--src/util/migration/mariadb/1720157926878-messagePollObject.ts13
-rw-r--r--src/util/migration/mariadb/1720628601997-badges.ts21
-rw-r--r--src/util/migration/mysql/1719776735000-newUserSettings.ts23
-rw-r--r--src/util/migration/mysql/1720157926878-messagePollObject.ts13
-rw-r--r--src/util/migration/mysql/1720628601997-badges.ts21
-rw-r--r--src/util/migration/postgres/1719776735000-newUserSettings.ts23
-rw-r--r--src/util/migration/postgres/1720157926878-messagePollObject.ts13
-rw-r--r--src/util/migration/postgres/1720628601997-badges.ts16
-rw-r--r--src/util/schemas/MessageCreateSchema.ts29
-rw-r--r--src/util/schemas/responses/GuildMessagesSearchResponse.ts11
-rw-r--r--src/util/schemas/responses/TypedResponses.ts13
-rw-r--r--src/util/schemas/responses/UserProfileResponse.ts2
-rw-r--r--src/util/util/email/index.ts7
-rw-r--r--src/util/util/email/transports/SMTP.ts7
49 files changed, 613 insertions, 152 deletions
diff --git a/src/api/Server.ts b/src/api/Server.ts

index 0f5df490..bea75d7e 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts
@@ -18,15 +18,15 @@ import { Config, + ConnectionConfig, + ConnectionLoader, Email, - initDatabase, - initEvent, JSONReplacer, - registerRoutes, Sentry, WebAuthn, - ConnectionConfig, - ConnectionLoader, + initDatabase, + initEvent, + registerRoutes, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { Server, ServerOptions } from "lambert-server"; @@ -143,6 +143,10 @@ export class SpacebarServer extends Server { res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html")), ); + app.get("/verify", (req, res) => + res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "verify.html")), + ); + this.app.use(ErrorHandler); Sentry.errorHandler(this.app); diff --git a/src/api/routes/auth/verify/index.ts b/src/api/routes/auth/verify/index.ts
index 49f74277..32c3f305 100644 --- a/src/api/routes/auth/verify/index.ts +++ b/src/api/routes/auth/verify/index.ts
@@ -85,7 +85,7 @@ router.post( user = userTokenData.user; } catch { throw FieldErrors({ - password: { + token: { message: req.t("auth:password_reset.INVALID_TOKEN"), code: "INVALID_TOKEN", }, diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts
index 99f9a647..291b6472 100644 --- a/src/api/routes/channels/#channel_id/index.ts +++ b/src/api/routes/channels/#channel_id/index.ts
@@ -50,7 +50,13 @@ router.get( const channel = await Channel.findOneOrFail({ where: { id: channel_id }, }); + if (!channel.guild_id) return res.send(channel); + channel.position = await Channel.calculatePosition( + channel_id, + channel.guild_id, + channel.guild, + ); return res.send(channel); }, ); diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
index 5ca645c0..6362941c 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -56,6 +56,7 @@ router.post( edited_timestamp: null, flags: 1, components: [], + poll: {}, }).status(200); }, ); diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
index c4d2e1e8..211cf997 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -91,11 +91,10 @@ router.patch( } } else rights.hasThrow("SELF_EDIT_MESSAGES"); + // @ts-expect-error Something is wrong with message_reference here, TS complains since "channel_id" is optional in MessageCreateSchema const new_message = await handleMessage({ ...message, // TODO: should message_reference be overridable? - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore message_reference: message.message_reference, ...body, author_id: message.author_id, diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index a5bfcfd7..645c6db2 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -183,9 +183,17 @@ router.get( const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`; - y.proxy_url = `${endpoint == null ? "" : endpoint}${ - new URL(uri).pathname - }`; + + let pathname = new URL(uri).pathname; + while ( + pathname.split("/")[0] != "attachments" && + pathname.length > 30 + ) { + pathname = pathname.split("/").slice(1).join("/"); + } + if (!endpoint?.endsWith("/")) pathname = "/" + pathname; + + y.proxy_url = `${endpoint == null ? "" : endpoint}${pathname}`; }); /** diff --git a/src/api/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts
index d3edb0fa..fe289f23 100644 --- a/src/api/routes/channels/#channel_id/permissions.ts +++ b/src/api/routes/channels/#channel_id/permissions.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -53,6 +53,11 @@ router.put( where: { id: channel_id }, }); if (!channel.guild_id) throw new HTTPError("Channel not found", 404); + channel.position = await Channel.calculatePosition( + channel_id, + channel.guild_id, + channel.guild, + ); if (body.type === 0) { if (!(await Role.count({ where: { id: overwrite_id } }))) diff --git a/src/api/routes/connections/index.ts b/src/api/routes/connections/index.ts new file mode 100644
index 00000000..37c20a37 --- /dev/null +++ b/src/api/routes/connections/index.ts
@@ -0,0 +1,45 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. +*/ + +import { route } from "@spacebar/api"; +import { ConnectionConfig } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +const router = Router(); + +router.get( + "/", + route({ + responses: { + 200: { + body: "APIConnectionsConfiguration", + }, + }, + }), + async (req: Request, res: Response) => { + const config = ConnectionConfig.get(); + + Object.keys(config).forEach((key) => { + delete config[key].clientId; + delete config[key].clientSecret; + }); + + res.json(config); + }, +); + +export default router; diff --git a/src/api/routes/guilds/#guild_id/channels.ts b/src/api/routes/guilds/#guild_id/channels.ts
index 68208fee..3488b64d 100644 --- a/src/api/routes/guilds/#guild_id/channels.ts +++ b/src/api/routes/guilds/#guild_id/channels.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -41,6 +41,15 @@ router.get( const { guild_id } = req.params; const channels = await Channel.find({ where: { guild_id } }); + for await (const channel of channels) { + channel.position = await Channel.calculatePosition( + channel.id, + guild_id, + channel.guild, + ); + } + channels.sort((a, b) => a.position - b.position); + res.json(channels); }, ); @@ -71,6 +80,11 @@ router.post( { ...body, guild_id }, req.user_id, ); + channel.position = await Channel.calculatePosition( + channel.id, + guild_id, + channel.guild, + ); res.status(201).json(channel); }, diff --git a/src/api/routes/guilds/#guild_id/emojis.ts b/src/api/routes/guilds/#guild_id/emojis.ts
index ef28f989..f3f0fd8b 100644 --- a/src/api/routes/guilds/#guild_id/emojis.ts +++ b/src/api/routes/guilds/#guild_id/emojis.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -125,6 +125,7 @@ router.post( const user = await User.findOneOrFail({ where: { id: req.user_id } }); body.image = (await handleFile(`/emojis/${id}`, body.image)) as string; + const mimeType = body.image.split(":")[1].split(";")[0]; const emoji = await Emoji.create({ id: id, guild_id: guild_id, @@ -132,7 +133,10 @@ router.post( require_colons: body.require_colons ?? undefined, // schema allows nulls, db does not user: user, managed: false, - animated: false, // TODO: Add support animated emojis + animated: + mimeType == "image/gif" || + mimeType == "image/apng" || + mimeType == "video/webm", available: true, roles: [], }).save(); diff --git a/src/api/routes/guilds/#guild_id/messages/search.ts b/src/api/routes/guilds/#guild_id/messages/search.ts
index 637d1e43..94adf9c6 100644 --- a/src/api/routes/guilds/#guild_id/messages/search.ts +++ b/src/api/routes/guilds/#guild_id/messages/search.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -162,6 +162,7 @@ router.get( edited_timestamp: x.edited_timestamp, flags: x.flags, components: x.components, + poll: x.poll, hit: true, }, ]); diff --git a/src/api/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts
index eecec0f3..db0922d6 100644 --- a/src/api/routes/users/#id/profile.ts +++ b/src/api/routes/users/#id/profile.ts
@@ -18,6 +18,7 @@ import { route } from "@spacebar/api"; import { + Badge, Member, PrivateUserProjection, User, @@ -98,6 +99,9 @@ router.get( bio: guild_member?.bio || "", guild_id, }; + + const badges = await Badge.find(); + res.json({ connected_accounts: user.connected_accounts.filter( (x) => x.visibility != 0, @@ -111,6 +115,7 @@ router.get( user_profile: userProfile, guild_member: guild_member?.toPublicMember(), guild_member_profile: guild_id && guildMemberProfile, + badges: badges.filter((x) => user.badge_ids?.includes(x.id)), }); }, ); diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 6172a3d0..c3658668 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts
@@ -1,57 +1,57 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ +import * as Sentry from "@sentry/node"; +import { EmbedHandlers } from "@spacebar/api"; import { + Application, + Attachment, Channel, + Config, Embed, + EmbedCache, emitEvent, + EVERYONE_MENTION, + getPermission, + getRights, Guild, + HERE_MENTION, Message, MessageCreateEvent, + MessageCreateSchema, + MessageType, MessageUpdateEvent, - getPermission, - getRights, - //CHANNEL_MENTION, - USER_MENTION, - ROLE_MENTION, Role, - EVERYONE_MENTION, - HERE_MENTION, - MessageType, + ROLE_MENTION, + Sticker, User, - Application, + //CHANNEL_MENTION, + USER_MENTION, Webhook, - Attachment, - Config, - Sticker, - MessageCreateSchema, - EmbedCache, } from "@spacebar/util"; import { HTTPError } from "lambert-server"; import { In } from "typeorm"; -import { EmbedHandlers } from "@spacebar/api"; -import * as Sentry from "@sentry/node"; const allow_empty = false; // TODO: check webhook, application, system author, stickers // TODO: embed gifs/videos/images const LINK_REGEX = - /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g; + /<?https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)>?/g; export async function handleMessage(opts: MessageOptions): Promise<Message> { const channel = await Channel.findOneOrFail({ @@ -66,6 +66,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { : undefined; const message = Message.create({ ...opts, + poll: opts.poll, sticker_items: stickers, guild_id: channel.guild_id, channel_id: opts.channel_id, @@ -116,6 +117,12 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id }, }); + + if (!opts.message_reference.guild_id) + opts.message_reference.guild_id = channel.guild_id; + if (!opts.message_reference.channel_id) + opts.message_reference.channel_id = opts.channel_id; + if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) { if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError( @@ -126,6 +133,8 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { "You can only reference messages from this channel", ); } + + message.message_reference = opts.message_reference; } /** Q: should be checked if the referenced message exists? ANSWER: NO otherwise backfilling won't work **/ @@ -138,7 +147,9 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { !opts.content && !opts.embeds?.length && !opts.attachments?.length && - !opts.sticker_ids?.length + !opts.sticker_ids?.length && + !opts.poll && + !opts.components?.length ) { throw new HTTPError("Empty messages are not allowed", 50006); } @@ -213,6 +224,9 @@ export async function postHandleMessage(message: Message) { const cachePromises = []; for (const link of links) { + // Don't embed links in <> + if (link.startsWith("<") && link.endsWith(">")) continue; + const url = new URL(link); const cached = await EmbedCache.findOne({ where: { url: link } }); diff --git a/src/cdn/routes/badge-icons.ts b/src/cdn/routes/badge-icons.ts new file mode 100644
index 00000000..04e96f2f --- /dev/null +++ b/src/cdn/routes/badge-icons.ts
@@ -0,0 +1,40 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. +*/ + +import { Router, Response, Request } from "express"; +import { storage } from "../util/Storage"; +import FileType from "file-type"; +import { HTTPError } from "lambert-server"; + +const router = Router(); + +router.get("/:badge_id", async (req: Request, res: Response) => { + const { badge_id } = req.params; + const path = `badge-icons/${badge_id}`; + + const file = await storage.get(path); + if (!file) throw new HTTPError("not found", 404); + const type = await FileType.fromBuffer(file); + + res.set("Content-Type", type?.mime); + res.set("Cache-Control", "public, max-age=31536000, must-revalidate"); + + return res.send(file); +}); + +export default router; diff --git a/src/cdn/routes/embed.ts b/src/cdn/routes/embed.ts
index b99396eb..95ac720d 100644 --- a/src/cdn/routes/embed.ts +++ b/src/cdn/routes/embed.ts
@@ -23,12 +23,12 @@ import { HTTPError } from "lambert-server"; import { join } from "path"; const defaultAvatarHashMap = new Map([ - ["0", "823a3de61c4dc2415cc4dbc38fca4299"], - ["1", "e56a89224be0b2b1f7c04eca975be468"], - ["2", "0c8138dcc0dfe2689cdd73f7952c2475"], - ["3", "5ac2728593bb455250d11b848a0c36c6"], - ["4", "addd2f3268df46459e1d6012ad8e75bd"], - ["5", "c4e0c8300fa491d94acfd2a1fb26cea8"], + ["0", "4a8562cf00887030c416d3ec2d46385a"], + ["1", "9b0bb198936784c45c72833cc426cc55"], + ["2", "22341bdb500c7b63a93bbce957d1601e"], + ["3", "d9977836b82058bf2f74eebd50edc095"], + ["4", "9d6ddb4e4d899a533a8cc617011351c9"], + ["5", "7213ab6677377974697dfdfbaf5f6a6f"], ]); const defaultGroupDMAvatarHashMap = new Map([ diff --git a/src/connections/BattleNet/index.ts b/src/connections/BattleNet/index.ts
index 4fdfccb1..8f44944c 100644 --- a/src/connections/BattleNet/index.ts +++ b/src/connections/BattleNet/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -47,13 +47,15 @@ export default class BattleNetConnection extends Connection { settings: BattleNetSettings = new BattleNetSettings(); init(): void { - const settings = - ConnectionLoader.getConnectionConfig<BattleNetSettings>( - this.id, - this.settings, - ); + this.settings = ConnectionLoader.getConnectionConfig<BattleNetSettings>( + this.id, + this.settings, + ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Discord/index.ts b/src/connections/Discord/index.ts
index 731086f1..e5508f48 100644 --- a/src/connections/Discord/index.ts +++ b/src/connections/Discord/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -43,12 +43,15 @@ export default class DiscordConnection extends Connection { settings: DiscordSettings = new DiscordSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<DiscordSettings>( + this.settings = ConnectionLoader.getConnectionConfig<DiscordSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/EpicGames/index.ts b/src/connections/EpicGames/index.ts
index e5b2d336..cedfcd0a 100644 --- a/src/connections/EpicGames/index.ts +++ b/src/connections/EpicGames/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -53,13 +53,15 @@ export default class EpicGamesConnection extends Connection { settings: EpicGamesSettings = new EpicGamesSettings(); init(): void { - const settings = - ConnectionLoader.getConnectionConfig<EpicGamesSettings>( - this.id, - this.settings, - ); + this.settings = ConnectionLoader.getConnectionConfig<EpicGamesSettings>( + this.id, + this.settings, + ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Facebook/index.ts b/src/connections/Facebook/index.ts
index 2bf26f34..bcb90b4c 100644 --- a/src/connections/Facebook/index.ts +++ b/src/connections/Facebook/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -52,12 +52,15 @@ export default class FacebookConnection extends Connection { settings: FacebookSettings = new FacebookSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<FacebookSettings>( + this.settings = ConnectionLoader.getConnectionConfig<FacebookSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/GitHub/index.ts b/src/connections/GitHub/index.ts
index 25e5f89f..78bf510e 100644 --- a/src/connections/GitHub/index.ts +++ b/src/connections/GitHub/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -42,12 +42,15 @@ export default class GitHubConnection extends Connection { settings: GitHubSettings = new GitHubSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<GitHubSettings>( + this.settings = ConnectionLoader.getConnectionConfig<GitHubSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Reddit/index.ts b/src/connections/Reddit/index.ts
index 149cce02..0db23731 100644 --- a/src/connections/Reddit/index.ts +++ b/src/connections/Reddit/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -54,12 +54,15 @@ export default class RedditConnection extends Connection { settings: RedditSettings = new RedditSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<RedditSettings>( + this.settings = ConnectionLoader.getConnectionConfig<RedditSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Spotify/index.ts b/src/connections/Spotify/index.ts
index ece404d8..4eb12602 100644 --- a/src/connections/Spotify/index.ts +++ b/src/connections/Spotify/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -63,12 +63,16 @@ export default class SpotifyConnection extends RefreshableConnection { * So to prevent spamming the spotify api we disable the ability to refresh. */ this.refreshEnabled = false; - const settings = ConnectionLoader.getConnectionConfig<SpotifySettings>( + + this.settings = ConnectionLoader.getConnectionConfig<SpotifySettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Twitch/index.ts b/src/connections/Twitch/index.ts
index 9a6cea35..953669a1 100644 --- a/src/connections/Twitch/index.ts +++ b/src/connections/Twitch/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -55,12 +55,15 @@ export default class TwitchConnection extends RefreshableConnection { settings: TwitchSettings = new TwitchSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<TwitchSettings>( + this.settings = ConnectionLoader.getConnectionConfig<TwitchSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Twitter/index.ts b/src/connections/Twitter/index.ts
index 62fd7da1..eba8ceb5 100644 --- a/src/connections/Twitter/index.ts +++ b/src/connections/Twitter/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -55,12 +55,15 @@ export default class TwitterConnection extends RefreshableConnection { settings: TwitterSettings = new TwitterSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<TwitterSettings>( + this.settings = ConnectionLoader.getConnectionConfig<TwitterSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Xbox/index.ts b/src/connections/Xbox/index.ts
index 935ff7ab..84066def 100644 --- a/src/connections/Xbox/index.ts +++ b/src/connections/Xbox/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -62,12 +62,15 @@ export default class XboxConnection extends Connection { settings: XboxSettings = new XboxSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<XboxSettings>( + this.settings = ConnectionLoader.getConnectionConfig<XboxSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/connections/Youtube/index.ts b/src/connections/Youtube/index.ts
index 844803cf..38edbb0d 100644 --- a/src/connections/Youtube/index.ts +++ b/src/connections/Youtube/index.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -62,12 +62,15 @@ export default class YoutubeConnection extends Connection { settings: YoutubeSettings = new YoutubeSettings(); init(): void { - const settings = ConnectionLoader.getConnectionConfig<YoutubeSettings>( + this.settings = ConnectionLoader.getConnectionConfig<YoutubeSettings>( this.id, this.settings, ); - if (settings.enabled && (!settings.clientId || !settings.clientSecret)) + if ( + this.settings.enabled && + (!this.settings.clientId || !this.settings.clientSecret) + ) throw new Error(`Invalid settings for connection ${this.id}`); } diff --git a/src/util/config/types/EmailConfiguration.ts b/src/util/config/types/EmailConfiguration.ts
index ae9d53ba..62305d10 100644 --- a/src/util/config/types/EmailConfiguration.ts +++ b/src/util/config/types/EmailConfiguration.ts
@@ -25,6 +25,7 @@ import { SendGridConfiguration } from "./subconfigurations/email/SendGrid"; export class EmailConfiguration { provider: string | null = null; + senderAddress: string | null = null; smtp: SMTPConfiguration = new SMTPConfiguration(); mailgun: MailGunConfiguration = new MailGunConfiguration(); mailjet: MailJetConfiguration = new MailJetConfiguration(); diff --git a/src/util/connections/Connection.ts b/src/util/connections/Connection.ts
index 5bdebd47..638dde2c 100644 --- a/src/util/connections/Connection.ts +++ b/src/util/connections/Connection.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -43,7 +43,7 @@ export abstract class Connection { */ getRedirectUri() { const endpointPublic = - Config.get().api.endpointPublic ?? "http://localhost:3001"; + Config.get().general.frontPage ?? "http://localhost:3001"; return `${endpointPublic}/connections/${this.id}/callback`; } diff --git a/src/util/dtos/UserDTO.ts b/src/util/dtos/UserDTO.ts
index a24c8d96..17e4435f 100644 --- a/src/util/dtos/UserDTO.ts +++ b/src/util/dtos/UserDTO.ts
@@ -24,6 +24,7 @@ export class MinimalPublicUserDTO { id: string; public_flags: number; username: string; + badge_ids?: string[] | null; constructor(user: User) { this.avatar = user.avatar; @@ -31,5 +32,6 @@ export class MinimalPublicUserDTO { this.id = user.id; this.public_flags = user.public_flags; this.username = user.username; + this.badge_ids = user.badge_ids; } } diff --git a/src/util/entities/Badge.ts b/src/util/entities/Badge.ts new file mode 100644
index 00000000..9535e207 --- /dev/null +++ b/src/util/entities/Badge.ts
@@ -0,0 +1,35 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. +*/ + +import { Column, Entity } from "typeorm"; +import { BaseClassWithoutId } from "./BaseClass"; + +@Entity("badges") +export class Badge extends BaseClassWithoutId { + @Column({ primary: true }) + id: string; + + @Column() + description: string; + + @Column() + icon: string; + + @Column({ nullable: true }) + link?: string; +} diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts
index 65942816..3ef778ac 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -31,7 +31,7 @@ import { PrimaryGeneratedColumn, RelationId, } from "typeorm"; -import { Ban, PublicGuildRelations } from "."; +import { Ban, Channel, PublicGuildRelations } from "."; import { ReadyGuildDTO } from "../dtos"; import { GuildCreateEvent, @@ -330,6 +330,13 @@ export class Member extends BaseClassWithoutId { relationLoadStrategy: "query", }); + for await (const channel of guild.channels) { + channel.position = await Channel.calculatePosition( + channel.id, + guild_id, + ); + } + const memberCount = await Member.count({ where: { guild_id } }); const memberPreview = ( diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index 4a9cff4a..d28c8c29 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -218,6 +218,9 @@ export class Message extends BaseClass { @Column({ type: "simple-json", nullable: true }) components?: MessageComponent[]; + @Column({ type: "simple-json", nullable: true }) + poll?: Poll; + toJSON(): Message { return { ...this, @@ -238,6 +241,7 @@ export class Message extends BaseClass { activity: this.activity ?? undefined, application: this.application ?? undefined, components: this.components ?? undefined, + poll: this.poll ?? undefined, content: this.content ?? "", }; } @@ -249,6 +253,7 @@ export interface MessageComponent { label?: string; emoji?: PartialEmoji; custom_id?: string; + sku_id?: string; url?: string; disabled?: boolean; components: MessageComponent[]; @@ -327,3 +332,32 @@ export interface AllowedMentions { users?: string[]; replied_user?: boolean; } + +export interface Poll { + question: PollMedia; + answers: PollAnswer[]; + expiry: Date; + allow_multiselect: boolean; + results?: PollResult; +} + +export interface PollMedia { + text?: string; + emoji?: PartialEmoji; +} + +export interface PollAnswer { + answer_id?: string; + poll_media: PollMedia; +} + +export interface PollResult { + is_finalized: boolean; + answer_counts: PollAnswerCount[]; +} + +export interface PollAnswerCount { + id: string; + count: number; + me_voted: boolean; +} diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index c6582b00..c929039e 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts
@@ -49,6 +49,7 @@ export enum PublicUserEnum { premium_type, theme_colors, pronouns, + badge_ids, } export type PublicUserKeys = keyof typeof PublicUserEnum; @@ -231,6 +232,9 @@ export class User extends BaseClass { @OneToMany(() => SecurityKey, (key: SecurityKey) => key.user) security_keys: SecurityKey[]; + @Column({ type: "simple-array", nullable: true }) + badge_ids?: string[]; + // TODO: I don't like this method? validate() { if (this.discriminator) { diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts
index aa943dca..b2356aa7 100644 --- a/src/util/entities/index.ts +++ b/src/util/entities/index.ts
@@ -20,6 +20,7 @@ export * from "./Application"; export * from "./Attachment"; export * from "./AuditLog"; export * from "./BackupCodes"; +export * from "./Badge"; export * from "./Ban"; export * from "./BaseClass"; export * from "./Categories"; diff --git a/src/util/migration/mariadb/1719776735000-newUserSettings.ts b/src/util/migration/mariadb/1719776735000-newUserSettings.ts new file mode 100644
index 00000000..f7c37ca9 --- /dev/null +++ b/src/util/migration/mariadb/1719776735000-newUserSettings.ts
@@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class NewUserSettings1719776735000 implements MigrationInterface { + name = "NewUserSettings1719776735000"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE `user_settings` ADD friend_discovery_flags integer NULL DEFAULT 0;", + ); + await queryRunner.query( + "ALTER TABLE `user_settings` ADD view_nsfw_guilds tinyint NULL DEFAULT 1;", + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE `user_settings` DROP COLUMN friend_discovery_flags;", + ); + await queryRunner.query( + "ALTER TABLE `user_settings` DROP COLUMN view_nsfw_guilds;", + ); + } +} diff --git a/src/util/migration/mariadb/1720157926878-messagePollObject.ts b/src/util/migration/mariadb/1720157926878-messagePollObject.ts new file mode 100644
index 00000000..c0866426 --- /dev/null +++ b/src/util/migration/mariadb/1720157926878-messagePollObject.ts
@@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MessagePollObject1720157926878 implements MigrationInterface { + name = "MessagePollObject1720157926878"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE `messages` ADD `poll` text NULL"); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE `messages` DROP COLUMN `poll`"); + } +} diff --git a/src/util/migration/mariadb/1720628601997-badges.ts b/src/util/migration/mariadb/1720628601997-badges.ts new file mode 100644
index 00000000..af298e42 --- /dev/null +++ b/src/util/migration/mariadb/1720628601997-badges.ts
@@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Badges1720628601997 implements MigrationInterface { + name = "Badges1720628601997"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `CREATE TABLE \`badges\` (\`id\` varchar(255) NOT NULL, \`description\` varchar(255) NOT NULL, \`icon\` varchar(255) NOT NULL, \`link\` varchar(255) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `ALTER TABLE \`users\` ADD \`badge_ids\` text NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE \`users\` DROP COLUMN \`badge_ids\``, + ); + await queryRunner.query(`DROP TABLE \`badges\``); + } +} diff --git a/src/util/migration/mysql/1719776735000-newUserSettings.ts b/src/util/migration/mysql/1719776735000-newUserSettings.ts new file mode 100644
index 00000000..f7c37ca9 --- /dev/null +++ b/src/util/migration/mysql/1719776735000-newUserSettings.ts
@@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class NewUserSettings1719776735000 implements MigrationInterface { + name = "NewUserSettings1719776735000"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE `user_settings` ADD friend_discovery_flags integer NULL DEFAULT 0;", + ); + await queryRunner.query( + "ALTER TABLE `user_settings` ADD view_nsfw_guilds tinyint NULL DEFAULT 1;", + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE `user_settings` DROP COLUMN friend_discovery_flags;", + ); + await queryRunner.query( + "ALTER TABLE `user_settings` DROP COLUMN view_nsfw_guilds;", + ); + } +} diff --git a/src/util/migration/mysql/1720157926878-messagePollObject.ts b/src/util/migration/mysql/1720157926878-messagePollObject.ts new file mode 100644
index 00000000..c0866426 --- /dev/null +++ b/src/util/migration/mysql/1720157926878-messagePollObject.ts
@@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MessagePollObject1720157926878 implements MigrationInterface { + name = "MessagePollObject1720157926878"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE `messages` ADD `poll` text NULL"); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE `messages` DROP COLUMN `poll`"); + } +} diff --git a/src/util/migration/mysql/1720628601997-badges.ts b/src/util/migration/mysql/1720628601997-badges.ts new file mode 100644
index 00000000..af298e42 --- /dev/null +++ b/src/util/migration/mysql/1720628601997-badges.ts
@@ -0,0 +1,21 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Badges1720628601997 implements MigrationInterface { + name = "Badges1720628601997"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `CREATE TABLE \`badges\` (\`id\` varchar(255) NOT NULL, \`description\` varchar(255) NOT NULL, \`icon\` varchar(255) NOT NULL, \`link\` varchar(255) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `ALTER TABLE \`users\` ADD \`badge_ids\` text NULL`, + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `ALTER TABLE \`users\` DROP COLUMN \`badge_ids\``, + ); + await queryRunner.query(`DROP TABLE \`badges\``); + } +} diff --git a/src/util/migration/postgres/1719776735000-newUserSettings.ts b/src/util/migration/postgres/1719776735000-newUserSettings.ts new file mode 100644
index 00000000..dbee0b0d --- /dev/null +++ b/src/util/migration/postgres/1719776735000-newUserSettings.ts
@@ -0,0 +1,23 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class NewUserSettings1719776735000 implements MigrationInterface { + name = "NewUserSettings1719776735000"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE user_settings ADD COLUMN friend_discovery_flags integer DEFAULT 0;", + ); + await queryRunner.query( + "ALTER TABLE user_settings ADD COLUMN view_nsfw_guilds boolean DEFAULT true;", + ); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + "ALTER TABLE user_settings DROP COLUMN friend_discovery_flags;", + ); + await queryRunner.query( + "ALTER TABLE user_settings DROP COLUMN view_nsfw_guilds;", + ); + } +} diff --git a/src/util/migration/postgres/1720157926878-messagePollObject.ts b/src/util/migration/postgres/1720157926878-messagePollObject.ts new file mode 100644
index 00000000..7c3c95a0 --- /dev/null +++ b/src/util/migration/postgres/1720157926878-messagePollObject.ts
@@ -0,0 +1,13 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class MessagePollObject1720157926878 implements MigrationInterface { + name = "MessagePollObject1720157926878"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE messages ADD poll text NULL"); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query("ALTER TABLE messages DROP COLUMN poll"); + } +} diff --git a/src/util/migration/postgres/1720628601997-badges.ts b/src/util/migration/postgres/1720628601997-badges.ts new file mode 100644
index 00000000..f7b9958b --- /dev/null +++ b/src/util/migration/postgres/1720628601997-badges.ts
@@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Badges1720628601997 implements MigrationInterface { + name = "Badges1720628601997"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query( + `CREATE TABLE "badges" ("id" character varying NOT NULL, "description" character varying NOT NULL, "icon" character varying NOT NULL, "link" character varying, CONSTRAINT "PK_8a651318b8de577e8e217676466" PRIMARY KEY ("id"))`, + ); + await queryRunner.query(`ALTER TABLE "users" ADD "badge_ids" text`); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "badge_ids"`); + } +} diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
index 57abf62f..014f6c87 100644 --- a/src/util/schemas/MessageCreateSchema.ts +++ b/src/util/schemas/MessageCreateSchema.ts
@@ -1,22 +1,22 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ -import { Embed } from "@spacebar/util"; +import { Embed, MessageComponent, PollAnswer, PollMedia } from "@spacebar/util"; type Attachment = { id: string; @@ -42,7 +42,7 @@ export interface MessageCreateSchema { }; message_reference?: { message_id: string; - channel_id: string; + channel_id?: string; guild_id?: string; fail_if_not_exists?: boolean; }; @@ -54,6 +54,21 @@ export interface MessageCreateSchema { **/ attachments?: Attachment[]; sticker_ids?: string[]; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - components?: any[]; + components?: MessageComponent[]; + // TODO: Fix TypeScript errors in src\api\util\handlers\Message.ts once this is enabled + poll?: PollCreationSchema; + enforce_nonce?: boolean; // For Discord compatibility, it's the default behavior here + applied_tags?: string[]; // Not implemented yet, for webhooks in forums + thread_name?: string; // Not implemented yet, for webhooks + avatar_url?: string; // Not implemented yet, for webhooks +} + +// TypeScript complains once this is used above +// eslint-disable-next-line @typescript-eslint/no-unused-vars +interface PollCreationSchema { + question: PollMedia; + answers: PollAnswer[]; + duration?: number; + allow_multiselect?: boolean; + layout_type?: number; } diff --git a/src/util/schemas/responses/GuildMessagesSearchResponse.ts b/src/util/schemas/responses/GuildMessagesSearchResponse.ts
index b42aafd3..6121983e 100644 --- a/src/util/schemas/responses/GuildMessagesSearchResponse.ts +++ b/src/util/schemas/responses/GuildMessagesSearchResponse.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -19,7 +19,9 @@ import { Attachment, Embed, + MessageComponent, MessageType, + Poll, PublicUser, Role, } from "../../entities"; @@ -40,7 +42,8 @@ export interface GuildMessagesSearchMessage { timestamp: string; edited_timestamp: string | null; flags: number; - components: unknown[]; + components: MessageComponent[]; + poll: Poll; hit: true; } diff --git a/src/util/schemas/responses/TypedResponses.ts b/src/util/schemas/responses/TypedResponses.ts
index fa169c25..8214ff7b 100644 --- a/src/util/schemas/responses/TypedResponses.ts +++ b/src/util/schemas/responses/TypedResponses.ts
@@ -1,17 +1,17 @@ /* Spacebar: A FOSS re-implementation and extension of the Discord.com backend. Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */ @@ -104,3 +104,10 @@ export type APIGuildVoiceRegion = GuildVoiceRegion[]; export type APILimitsConfiguration = LimitsConfiguration; export type APIStickerPackArray = StickerPack[]; + +export type APIConnectionsConfiguration = Record< + string, + { + enabled: boolean; + } +>; diff --git a/src/util/schemas/responses/UserProfileResponse.ts b/src/util/schemas/responses/UserProfileResponse.ts
index 26e7e3bc..7b63542e 100644 --- a/src/util/schemas/responses/UserProfileResponse.ts +++ b/src/util/schemas/responses/UserProfileResponse.ts
@@ -17,6 +17,7 @@ */ import { + Badge, Member, PublicConnectedAccount, PublicMember, @@ -52,4 +53,5 @@ export interface UserProfileResponse { user_profile: UserProfile; guild_member?: PublicMember; guild_member_profile?: PublicMemberProfile; + badges: Badge[]; } diff --git a/src/util/util/email/index.ts b/src/util/util/email/index.ts
index 619cc5c3..e3382794 100644 --- a/src/util/util/email/index.ts +++ b/src/util/util/email/index.ts
@@ -141,8 +141,9 @@ export const Email: { */ generateLink: async function (type, id, email) { const token = (await generateToken(id, email)) as string; + // puyodead1: this is set to api endpoint because the verification page is on the server since no clients have one, and not all 3rd party clients will have one const instanceUrl = - Config.get().general.frontPage || "http://localhost:3001"; + Config.get().api.endpointPublic || "http://localhost:3001"; const link = `${instanceUrl}/${type}#token=${token}`; return link; }, @@ -187,7 +188,9 @@ export const Email: { const message = { from: - Config.get().general.correspondenceEmail || "noreply@localhost", + Config.get().email.senderAddress || + Config.get().general.correspondenceEmail || + "noreply@localhost", to: email, subject, html, diff --git a/src/util/util/email/transports/SMTP.ts b/src/util/util/email/transports/SMTP.ts
index 5b43a870..e3031943 100644 --- a/src/util/util/email/transports/SMTP.ts +++ b/src/util/util/email/transports/SMTP.ts
@@ -27,9 +27,12 @@ export default async function () { if (!host || !port || secure === null || !username || !password) return console.error("[Email] SMTP has not been configured correctly."); - if (!Config.get().general.correspondenceEmail) + if ( + !Config.get().email.senderAddress && + !Config.get().general.correspondenceEmail + ) return console.error( - "[Email] Correspondence email has not been configured! This is used as the sender email address.", + '[Email] You have to configure either "email_senderAddress" or "general_correspondenceEmail" for emails to work. The configured value is used as the sender address.', ); // construct the transporter