Merge remote-tracking branch 'spacebar/master' into webrtc-test
merge
This commit is contained in:
commit
d8e1045d59
@ -5171,7 +5171,10 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": "string"
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
@ -60170,7 +60170,10 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"parent_id": {
|
||||
"type": "string"
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
@ -108,70 +108,93 @@ router.patch(
|
||||
async (req: Request, res: Response) => {
|
||||
// changes guild channel position
|
||||
const { guild_id } = req.params;
|
||||
const body = req.body as ChannelReorderSchema;
|
||||
let body = req.body as ChannelReorderSchema;
|
||||
|
||||
const guild = await Guild.findOneOrFail({
|
||||
where: { id: guild_id },
|
||||
select: { channel_ordering: true },
|
||||
});
|
||||
|
||||
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);
|
||||
return apos - bpos;
|
||||
});
|
||||
|
||||
// The channels not listed for this query
|
||||
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);
|
||||
const withParents = body.filter((x) => x.parent_id !== undefined);
|
||||
const withPositions = body.filter((x) => x.position !== undefined);
|
||||
// You can't do it with Promise.all or the way this is being done is super incorrect
|
||||
for await (const opt of withPositions) {
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: opt.id },
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
withPositions.map(async (opt) => {
|
||||
const channel = await Channel.findOneOrFail({
|
||||
where: { id: opt.id },
|
||||
});
|
||||
|
||||
channel.position = opt.position as number;
|
||||
notMentioned.splice(opt.position as number, 0, channel.id);
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_UPDATE",
|
||||
data: channel,
|
||||
channel_id: channel.id,
|
||||
guild_id,
|
||||
} as ChannelUpdateEvent);
|
||||
}),
|
||||
);
|
||||
notMentioned.splice(opt.position as number, 0, channel.id);
|
||||
channel.position = notMentioned.findIndex((_) => _ === channel.id);
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_UPDATE",
|
||||
data: channel,
|
||||
channel_id: channel.id,
|
||||
guild_id,
|
||||
} as ChannelUpdateEvent);
|
||||
}
|
||||
// Due to this also being able to change the order, this needs to be done in order
|
||||
// have to do the parents after the positions
|
||||
await Promise.all(
|
||||
withParents.map(async (opt) => {
|
||||
const [channel, parent] = await Promise.all([
|
||||
Channel.findOneOrFail({
|
||||
where: { id: opt.id },
|
||||
}),
|
||||
Channel.findOneOrFail({
|
||||
where: { id: opt.parent_id as string },
|
||||
select: { permission_overwrites: true },
|
||||
}),
|
||||
]);
|
||||
|
||||
if (opt.lock_permissions)
|
||||
await Channel.update(
|
||||
{ id: channel.id },
|
||||
{ permission_overwrites: parent.permission_overwrites },
|
||||
);
|
||||
for await (const opt of withParents) {
|
||||
const [channel, parent] = await Promise.all([
|
||||
Channel.findOneOrFail({
|
||||
where: { id: opt.id },
|
||||
}),
|
||||
opt.parent_id
|
||||
? Channel.findOneOrFail({
|
||||
where: { id: opt.parent_id },
|
||||
select: {
|
||||
permission_overwrites: true,
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
: null,
|
||||
]);
|
||||
|
||||
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);
|
||||
channel.position = (parentPos + 1) as number;
|
||||
}
|
||||
channel.parent = parent || undefined;
|
||||
channel.parent_id = parent?.id || null;
|
||||
await channel.save();
|
||||
|
||||
await emitEvent({
|
||||
event: "CHANNEL_UPDATE",
|
||||
data: channel,
|
||||
channel_id: channel.id,
|
||||
guild_id,
|
||||
} as ChannelUpdateEvent);
|
||||
}),
|
||||
);
|
||||
await emitEvent({
|
||||
event: "CHANNEL_UPDATE",
|
||||
data: channel,
|
||||
channel_id: channel.id,
|
||||
guild_id,
|
||||
} as ChannelUpdateEvent);
|
||||
}
|
||||
|
||||
await Guild.update(
|
||||
{ id: guild_id },
|
||||
|
@ -28,7 +28,6 @@ import {
|
||||
ajv,
|
||||
getPermission,
|
||||
getRights,
|
||||
normalizeBody,
|
||||
} from "@spacebar/util";
|
||||
import { AnyValidateFunction } from "ajv/dist/core";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
@ -121,7 +120,7 @@ export function route(opts: RouteOptions) {
|
||||
}
|
||||
|
||||
if (validate) {
|
||||
const valid = validate(normalizeBody(req.body));
|
||||
const valid = validate(req.body);
|
||||
if (!valid) {
|
||||
const fields: Record<
|
||||
string,
|
||||
|
@ -20,5 +20,5 @@ export type ChannelReorderSchema = {
|
||||
id: string;
|
||||
position?: number;
|
||||
lock_permissions?: boolean;
|
||||
parent_id?: string;
|
||||
parent_id?: null | string;
|
||||
}[];
|
||||
|
@ -46,44 +46,7 @@ export const ajv = new Ajv({
|
||||
addFormats(ajv);
|
||||
|
||||
export function validateSchema<G extends object>(schema: string, data: G): G {
|
||||
const valid = ajv.validate(schema, normalizeBody(data));
|
||||
const valid = ajv.validate(schema, data);
|
||||
if (!valid) throw ajv.errors;
|
||||
return data;
|
||||
}
|
||||
|
||||
// Normalizer is introduced to workaround https://github.com/ajv-validator/ajv/issues/1287
|
||||
// this removes null values as ajv doesn't treat them as undefined
|
||||
// normalizeBody allows to handle circular structures without issues
|
||||
// taken from https://github.com/serverless/serverless/blob/master/lib/classes/ConfigSchemaHandler/index.js#L30 (MIT license)
|
||||
export const normalizeBody = (body: object = {}) => {
|
||||
const normalizedObjectsSet = new WeakSet();
|
||||
const normalizeObject = (object: object) => {
|
||||
if (normalizedObjectsSet.has(object)) return;
|
||||
normalizedObjectsSet.add(object);
|
||||
if (Array.isArray(object)) {
|
||||
for (const [, value] of object.entries()) {
|
||||
if (typeof value === "object") normalizeObject(value);
|
||||
}
|
||||
} else {
|
||||
for (const [key, value] of Object.entries(object)) {
|
||||
if (value == null) {
|
||||
if (
|
||||
key === "icon" ||
|
||||
key === "avatar" ||
|
||||
key === "banner" ||
|
||||
key === "splash" ||
|
||||
key === "discovery_splash"
|
||||
)
|
||||
continue;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
delete object[key];
|
||||
} else if (typeof value === "object") {
|
||||
normalizeObject(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
normalizeObject(body);
|
||||
return body;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user