Prettier u5

This commit is contained in:
Rory&
2025-12-17 09:12:13 +01:00
parent 9613ffa834
commit 1b178b5ac3
13 changed files with 69 additions and 278 deletions
+10 -47
View File
@@ -17,14 +17,9 @@
*/
import { route } from "@spacebar/api";
import {
Channel,
ChannelUpdateEvent,
Guild,
emitEvent,
} from "@spacebar/util";
import { Channel, ChannelUpdateEvent, Guild, emitEvent } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { ChannelModifySchema, ChannelReorderSchema } from "@spacebar/schemas"
import { ChannelModifySchema, ChannelReorderSchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
router.get(
@@ -41,11 +36,7 @@ router.get(
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,
);
channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
}
channels.sort((a, b) => a.position - b.position);
@@ -75,15 +66,8 @@ router.post(
const { guild_id } = req.params;
const body = req.body as ChannelModifySchema;
const channel = await Channel.createChannel(
{ ...body, guild_id },
req.user_id,
);
channel.position = await Channel.calculatePosition(
channel.id,
guild_id,
channel.guild,
);
const channel = await Channel.createChannel({ ...body, guild_id }, req.user_id);
channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
res.status(201).json(channel);
},
@@ -115,27 +99,13 @@ router.patch(
});
body = body.sort((a, b) => {
const apos =
a.position ||
(a.parent_id
? guild.channel_ordering.findIndex(
(_) => _ === a.parent_id,
) + 1
: 0);
const bpos =
b.position ||
(b.parent_id
? guild.channel_ordering.findIndex(
(_) => _ === b.parent_id,
) + 1
: 0);
const apos = a.position || (a.parent_id ? guild.channel_ordering.findIndex((_) => _ === a.parent_id) + 1 : 0);
const bpos = b.position || (b.parent_id ? guild.channel_ordering.findIndex((_) => _ === b.parent_id) + 1 : 0);
return apos - bpos;
});
// The channels not listed for this query
const notMentioned = guild.channel_ordering.filter(
(x) => !body.find((c) => c.id == x),
);
const notMentioned = guild.channel_ordering.filter((x) => !body.find((c) => c.id == x));
const withParents = body.filter((x) => x.parent_id !== undefined);
const withPositions = body.filter((x) => x.position !== undefined);
@@ -173,11 +143,7 @@ router.patch(
: null,
]);
if (opt.lock_permissions && parent)
await Channel.update(
{ id: channel.id },
{ permission_overwrites: parent.permission_overwrites },
);
if (opt.lock_permissions && parent) await Channel.update({ id: channel.id }, { permission_overwrites: parent.permission_overwrites });
if (parent && opt.position === undefined) {
const parentPos = notMentioned.indexOf(parent.id);
notMentioned.splice(parentPos + 1, 0, channel.id);
@@ -195,10 +161,7 @@ router.patch(
} as ChannelUpdateEvent);
}
await Guild.update(
{ id: guild_id },
{ channel_ordering: notMentioned },
);
await Guild.update({ id: guild_id }, { channel_ordering: notMentioned });
return res.sendStatus(204);
},
@@ -17,17 +17,10 @@
*/
import { route } from "@spacebar/api";
import {
emitEvent,
GuildRoleDeleteEvent,
GuildRoleUpdateEvent,
handleFile,
Member,
Role,
} from "@spacebar/util";
import { emitEvent, GuildRoleDeleteEvent, GuildRoleUpdateEvent, handleFile, Member, Role } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
import { RoleModifySchema } from "@spacebar/schemas"
import { RoleModifySchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
@@ -75,8 +68,7 @@ router.delete(
}),
async (req: Request, res: Response) => {
const { guild_id, role_id } = req.params;
if (role_id === guild_id)
throw new HTTPError("You can't delete the @everyone role");
if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
await Promise.all([
Role.delete({
@@ -123,11 +115,7 @@ router.patch(
const { role_id, guild_id } = req.params;
const body = req.body as RoleModifySchema;
if (body.icon && body.icon.length)
body.icon = await handleFile(
`/role-icons/${role_id}`,
body.icon as string,
);
if (body.icon && body.icon.length) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
else body.icon = undefined;
const role = await Role.findOneOrFail({
@@ -135,10 +123,7 @@ router.patch(
});
role.assign({
...body,
permissions: String(
(req.permission?.bitfield || 0n) &
BigInt(body.permissions || "0"),
),
permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
});
await Promise.all([
+5 -22
View File
@@ -17,19 +17,10 @@
*/
import { route } from "@spacebar/api";
import {
Config,
DiscordApiErrors,
emitEvent,
GuildRoleCreateEvent,
GuildRoleUpdateEvent,
Member,
Role,
Snowflake,
} from "@spacebar/util";
import { Config, DiscordApiErrors, emitEvent, GuildRoleCreateEvent, GuildRoleUpdateEvent, Member, Role, Snowflake } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { Not } from "typeorm";
import { RoleModifySchema, RolePositionUpdateSchema } from "@spacebar/schemas"
import { RoleModifySchema, RolePositionUpdateSchema } from "@spacebar/schemas";
const router: Router = Router({ mergeParams: true });
@@ -67,8 +58,7 @@ router.post(
const role_count = await Role.count({ where: { guild_id } });
const { maxRoles } = Config.get().limits.guild;
if (role_count > maxRoles)
throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
const role = Role.create({
// values before ...body are default and can be overridden
@@ -79,10 +69,7 @@ router.post(
...body,
guild_id: guild_id,
managed: false,
permissions: String(
(req.permission?.bitfield || 0n) &
BigInt(body.permissions || "0"),
),
permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
tags: undefined,
icon: undefined,
unicode_emoji: undefined,
@@ -140,11 +127,7 @@ router.patch(
const { guild_id } = req.params;
const body = req.body as RolePositionUpdateSchema;
await Promise.all(
body.map(async (x) =>
Role.update({ guild_id, id: x.id }, { position: x.position }),
),
);
await Promise.all(body.map(async (x) => Role.update({ guild_id, id: x.id }, { position: x.position })));
const roles = await Role.find({
where: body.map((x) => ({ id: x.id, guild_id })),
@@ -17,14 +17,7 @@
*/
import { route } from "@spacebar/api";
import {
Channel,
DiscordApiErrors,
emitEvent,
getPermission,
VoiceState,
VoiceStateUpdateEvent,
} from "@spacebar/util";
import { Channel, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { ChannelType, VoiceStateUpdateSchema } from "@spacebar/schemas";
@@ -51,14 +44,9 @@ router.patch(
async (req: Request, res: Response) => {
const body = req.body as VoiceStateUpdateSchema;
const { guild_id } = req.params;
const user_id =
req.params.user_id === "@me" ? req.user_id : req.params.user_id;
const user_id = req.params.user_id === "@me" ? req.user_id : req.params.user_id;
const perms = await getPermission(
req.user_id,
guild_id,
body.channel_id,
);
const perms = await getPermission(req.user_id, guild_id, body.channel_id);
/*
From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state
@@ -1,18 +1,10 @@
import { route } from "@spacebar/api";
import {
Config,
DiscordApiErrors,
emitEvent,
handleFile,
ValidateName,
Webhook,
WebhooksUpdateEvent,
} from "@spacebar/util";
import { Config, DiscordApiErrors, emitEvent, handleFile, ValidateName, Webhook, WebhooksUpdateEvent } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
import multer from "multer";
import { executeWebhook } from "../../../../util/handlers/Webhook";
import { WebhookUpdateSchema } from "@spacebar/schemas"
import { WebhookUpdateSchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
router.get(
@@ -32,14 +24,7 @@ router.get(
where: {
id: webhook_id,
},
relations: [
"user",
"channel",
"source_channel",
"guild",
"source_guild",
"application",
],
relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
});
if (!webhook) {
@@ -50,8 +35,7 @@ router.get(
throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
}
const instanceUrl =
Config.get().api.endpointPublic || "http://localhost:3001";
const instanceUrl = Config.get().api.endpointPublic || "http://localhost:3001";
return res.json({
...webhook,
url: instanceUrl + "/webhooks/" + webhook.id + "/" + webhook.token,
@@ -87,14 +71,12 @@ router.post(
wait: {
type: "boolean",
required: false,
description:
"waits for server confirmation of message send before response, and returns the created message body",
description: "waits for server confirmation of message send before response, and returns the created message body",
},
thread_id: {
type: "string",
required: false,
description:
"Send a message to the specified thread within a webhook's channel.",
description: "Send a message to the specified thread within a webhook's channel.",
},
},
responses: {
@@ -173,24 +155,13 @@ router.patch(
const webhook = await Webhook.findOneOrFail({
where: { id: webhook_id },
relations: [
"user",
"channel",
"source_channel",
"guild",
"source_guild",
"application",
],
relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
});
const channel_id = webhook.channel_id;
if (!body.name && !body.avatar) {
throw new HTTPError("Empty webhook updates are not allowed", 50006);
}
if (body.avatar)
body.avatar = await handleFile(
`/avatars/${webhook_id}`,
body.avatar as string,
);
if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
if (body.name) {
ValidateName(body.name);
+17 -69
View File
@@ -1,25 +1,14 @@
import { route } from "@spacebar/api";
import {
Config,
DiscordApiErrors,
getPermission,
Webhook,
WebhooksUpdateEvent,
emitEvent,
Channel,
handleFile,
ValidateName,
} from "@spacebar/util";
import { Config, DiscordApiErrors, getPermission, Webhook, WebhooksUpdateEvent, emitEvent, Channel, handleFile, ValidateName } from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
import { WebhookUpdateSchema } from "@spacebar/schemas"
import { WebhookUpdateSchema } from "@spacebar/schemas";
const router = Router({ mergeParams: true });
router.get(
"/",
route({
description:
"Returns a webhook object for the given id. Requires the MANAGE_WEBHOOKS permission or to be the owner of the webhook.",
description: "Returns a webhook object for the given id. Requires the MANAGE_WEBHOOKS permission or to be the owner of the webhook.",
responses: {
200: {
body: "APIWebhook",
@@ -31,29 +20,16 @@ router.get(
const { webhook_id } = req.params;
const webhook = await Webhook.findOneOrFail({
where: { id: webhook_id },
relations: [
"user",
"channel",
"source_channel",
"guild",
"source_guild",
"application",
],
relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
});
if (webhook.guild_id) {
const permission = await getPermission(
req.user_id,
webhook.guild_id,
);
const permission = await getPermission(req.user_id, webhook.guild_id);
if (!permission.has("MANAGE_WEBHOOKS"))
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id)
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
const instanceUrl =
Config.get().api.endpointPublic || "http://localhost:3001";
const instanceUrl = Config.get().api.endpointPublic || "http://localhost:3001";
return res.json({
...webhook,
url: instanceUrl + "/webhooks/" + webhook.id + "/" + webhook.token,
@@ -77,26 +53,14 @@ router.delete(
const webhook = await Webhook.findOneOrFail({
where: { id: webhook_id },
relations: [
"user",
"channel",
"source_channel",
"guild",
"source_guild",
"application",
],
relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
});
if (webhook.guild_id) {
const permission = await getPermission(
req.user_id,
webhook.guild_id,
);
const permission = await getPermission(req.user_id, webhook.guild_id);
if (!permission.has("MANAGE_WEBHOOKS"))
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id)
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
const channel_id = webhook.channel_id;
await Webhook.delete({ id: webhook_id });
@@ -135,36 +99,20 @@ router.patch(
const webhook = await Webhook.findOneOrFail({
where: { id: webhook_id },
relations: [
"user",
"channel",
"source_channel",
"guild",
"source_guild",
"application",
],
relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
});
if (webhook.guild_id) {
const permission = await getPermission(
req.user_id,
webhook.guild_id,
);
const permission = await getPermission(req.user_id, webhook.guild_id);
if (!permission.has("MANAGE_WEBHOOKS"))
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id)
throw DiscordApiErrors.UNKNOWN_WEBHOOK;
if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
} else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
if (!body.name && !body.avatar && !body.channel_id) {
throw new HTTPError("Empty webhook updates are not allowed", 50006);
}
if (body.avatar)
body.avatar = await handleFile(
`/avatars/${webhook_id}`,
body.avatar as string,
);
if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
if (body.name) {
ValidateName(body.name);
+2 -7
View File
@@ -21,9 +21,7 @@ import { distanceBetweenLocations } from "../utility/ipAddress";
export async function getVoiceRegions(ipAddress: string, vip: boolean) {
const regions = Config.get().regions;
const availableRegions = regions.available.filter((ar) =>
vip ? true : !ar.vip,
);
const availableRegions = regions.available.filter((ar) => (vip ? true : !ar.vip));
let optimalId = regions.default;
if (!regions.useDefaultAsOptimal) {
@@ -33,10 +31,7 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) {
for (const ar of availableRegions) {
//TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
const dist = distanceBetweenLocations(
clientIpAnalysis!,
ar.location || (await IpDataClient.getIpInfo(ar.endpoint))!,
);
const dist = distanceBetweenLocations(clientIpAnalysis!, ar.location || (await IpDataClient.getIpInfo(ar.endpoint))!);
if (dist < min) {
min = dist;
+4 -16
View File
@@ -64,28 +64,16 @@ async function main() {
app.use(
morgan("combined", {
skip: (req, res) => {
let skip = !(
process.env["LOG_REQUESTS"]?.includes(
res.statusCode.toString(),
) ?? false
);
if (process.env["LOG_REQUESTS"]?.charAt(0) == "-")
skip = !skip;
let skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip;
return skip;
},
}),
);
}
await new Promise((resolve) =>
server.listen({ port }, () => resolve(undefined)),
);
await Promise.all([
api.start(),
cdn.start(),
gateway.start(),
webrtc.start(),
]);
await new Promise((resolve) => server.listen({ port }, () => resolve(undefined)));
await Promise.all([api.start(), cdn.start(), gateway.start(), webrtc.start()]);
console.log(`[Server] ${green(`Listening on port ${bold(port)}`)}`);
}
+4 -7
View File
@@ -29,8 +29,7 @@ function getPath(path: string) {
const root = process.env.STORAGE_LOCATION || "../";
const filename = join(root, path);
if (path.indexOf("\0") !== -1 || !filename.startsWith(root))
throw new Error("invalid path");
if (path.indexOf("\0") !== -1 || !filename.startsWith(root)) throw new Error("invalid path");
return filename;
}
@@ -54,17 +53,15 @@ export class FileStorage implements Storage {
path = getPath(path);
newPath = getPath(newPath);
if (!fs.existsSync(dirname(newPath)))
fs.mkdirSync(dirname(newPath), { recursive: true });
if (!fs.existsSync(dirname(newPath))) fs.mkdirSync(dirname(newPath), { recursive: true });
// use reflink if possible, in order to not duplicate files at the block layer...
fs.copyFileSync(path, newPath, fs.constants.COPYFILE_FICLONE)
fs.copyFileSync(path, newPath, fs.constants.COPYFILE_FICLONE);
}
async set(path: string, value: Buffer) {
path = getPath(path);
if (!fs.existsSync(dirname(path)))
fs.mkdirSync(dirname(path), { recursive: true });
if (!fs.existsSync(dirname(path))) fs.mkdirSync(dirname(path), { recursive: true });
const ret = Readable.from(value);
const cleaned_file = fs.createWriteStream(path);
+3 -9
View File
@@ -50,16 +50,12 @@ if (process.env.STORAGE_PROVIDER === "file" || !process.env.STORAGE_PROVIDER) {
bucket = process.env.STORAGE_BUCKET;
if (!region) {
console.error(
`[CDN] You must provide a region when using the S3 storage provider.`,
);
console.error(`[CDN] You must provide a region when using the S3 storage provider.`);
process.exit(1);
}
if (!bucket) {
console.error(
`[CDN] You must provide a bucket when using the S3 storage provider.`,
);
console.error(`[CDN] You must provide a bucket when using the S3 storage provider.`);
process.exit(1);
}
@@ -67,9 +63,7 @@ if (process.env.STORAGE_PROVIDER === "file" || !process.env.STORAGE_PROVIDER) {
let location = process.env.STORAGE_LOCATION;
if (!location) {
console.warn(
`[CDN] STORAGE_LOCATION unconfigured for S3 provider, defaulting to the bucket root...`,
);
console.warn(`[CDN] STORAGE_LOCATION unconfigured for S3 provider, defaulting to the bucket root...`);
location = undefined;
}
+1 -8
View File
@@ -16,14 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
ChannelLimits,
GlobalRateLimits,
GuildLimits,
MessageLimits,
RateLimits,
UserLimits,
} from ".";
import { ChannelLimits, GlobalRateLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from ".";
export class LimitsConfiguration {
user: UserLimits = new UserLimits();
@@ -16,15 +16,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
DateOfBirthConfiguration,
PasswordConfiguration,
RegistrationEmailConfiguration,
} from ".";
import { DateOfBirthConfiguration, PasswordConfiguration, RegistrationEmailConfiguration } from ".";
export class RegisterConfiguration {
email: RegistrationEmailConfiguration =
new RegistrationEmailConfiguration();
email: RegistrationEmailConfiguration = new RegistrationEmailConfiguration();
dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration();
password: PasswordConfiguration = new PasswordConfiguration();
disabled: boolean = false;
+5 -14
View File
@@ -22,12 +22,8 @@ import { green, red } from "picocolors";
export let mediaServer: SignalingDelegate;
export const WRTC_PUBLIC_IP = process.env.WRTC_PUBLIC_IP ?? "127.0.0.1";
export const WRTC_PORT_MIN = process.env.WRTC_PORT_MIN
? parseInt(process.env.WRTC_PORT_MIN)
: 2000;
export const WRTC_PORT_MAX = process.env.WRTC_PORT_MAX
? parseInt(process.env.WRTC_PORT_MAX)
: 65000;
export const WRTC_PORT_MIN = process.env.WRTC_PORT_MIN ? parseInt(process.env.WRTC_PORT_MIN) : 2000;
export const WRTC_PORT_MAX = process.env.WRTC_PORT_MAX ? parseInt(process.env.WRTC_PORT_MAX) : 65000;
const selectedWrtcLibrary = process.env.WRTC_LIBRARY;
@@ -47,21 +43,16 @@ class NoConfiguredLibraryError implements Error {
export const loadWebRtcLibrary = async () => {
try {
//mediaServer = require('medooze-spacebar-wrtc');
if (!selectedWrtcLibrary)
throw new NoConfiguredLibraryError("No library configured in .env");
if (!selectedWrtcLibrary) throw new NoConfiguredLibraryError("No library configured in .env");
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
mediaServer = new // @ts-ignore
(await import(selectedWrtcLibrary)).default();
console.log(
`[WebRTC] ${green(`Succesfully loaded ${selectedWrtcLibrary}`)}`,
);
console.log(`[WebRTC] ${green(`Succesfully loaded ${selectedWrtcLibrary}`)}`);
return Promise.resolve();
} catch (error) {
console.log(
`[WebRTC] ${red(`Failed to import ${selectedWrtcLibrary}: ${error instanceof NoConfiguredLibraryError ? error.message : ""}`)}`,
);
console.log(`[WebRTC] ${red(`Failed to import ${selectedWrtcLibrary}: ${error instanceof NoConfiguredLibraryError ? error.message : ""}`)}`);
return Promise.reject();
}