mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-25 11:43:07 +01:00
refactor channel positions in guild
This commit is contained in:
parent
551d2bf5e6
commit
7795f1b36b
@ -22,10 +22,10 @@ import {
|
|||||||
ChannelModifySchema,
|
ChannelModifySchema,
|
||||||
ChannelReorderSchema,
|
ChannelReorderSchema,
|
||||||
ChannelUpdateEvent,
|
ChannelUpdateEvent,
|
||||||
|
Guild,
|
||||||
emitEvent,
|
emitEvent,
|
||||||
} from "@spacebar/util";
|
} from "@spacebar/util";
|
||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { HTTPError } from "lambert-server";
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
@ -96,44 +96,72 @@ router.patch(
|
|||||||
const { guild_id } = req.params;
|
const { guild_id } = req.params;
|
||||||
const body = req.body as ChannelReorderSchema;
|
const body = req.body as ChannelReorderSchema;
|
||||||
|
|
||||||
await Promise.all([
|
const guild = await Guild.findOneOrFail({
|
||||||
body.map(async (x) => {
|
where: { id: guild_id },
|
||||||
if (x.position == null && !x.parent_id)
|
select: { channelOrdering: true },
|
||||||
throw new HTTPError(
|
});
|
||||||
`You need to at least specify position or parent_id`,
|
|
||||||
400,
|
// The channels not listed for this query
|
||||||
|
const notMentioned = guild.channelOrdering.filter(
|
||||||
|
(x) => !body.find((c) => c.id == x),
|
||||||
);
|
);
|
||||||
|
|
||||||
const opts: Partial<Channel> = {};
|
const withParents = body.filter((x) => x.parent_id != undefined);
|
||||||
if (x.position != null) opts.position = x.position;
|
const withPositions = body.filter((x) => x.position != undefined);
|
||||||
|
|
||||||
if (x.parent_id) {
|
await Promise.all(
|
||||||
opts.parent_id = x.parent_id;
|
withPositions.map(async (opt) => {
|
||||||
const parent_channel = await Channel.findOneOrFail({
|
|
||||||
where: { id: x.parent_id, guild_id },
|
|
||||||
select: ["permission_overwrites"],
|
|
||||||
});
|
|
||||||
if (x.lock_permissions) {
|
|
||||||
opts.permission_overwrites =
|
|
||||||
parent_channel.permission_overwrites;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Channel.update({ guild_id, id: x.id }, opts);
|
|
||||||
const channel = await Channel.findOneOrFail({
|
const channel = await Channel.findOneOrFail({
|
||||||
where: { guild_id, id: x.id },
|
where: { id: opt.id },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
channel.position = opt.position as number;
|
||||||
|
notMentioned.splice(opt.position as number, 0, channel.id);
|
||||||
|
|
||||||
await emitEvent({
|
await emitEvent({
|
||||||
event: "CHANNEL_UPDATE",
|
event: "CHANNEL_UPDATE",
|
||||||
data: channel,
|
data: channel,
|
||||||
channel_id: x.id,
|
channel_id: channel.id,
|
||||||
guild_id,
|
guild_id,
|
||||||
} as ChannelUpdateEvent);
|
} as ChannelUpdateEvent);
|
||||||
}),
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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 },
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
res.sendStatus(204);
|
if (opt.lock_permissions)
|
||||||
|
await Channel.update(
|
||||||
|
{ id: channel.id },
|
||||||
|
{ permission_overwrites: parent.permission_overwrites },
|
||||||
|
);
|
||||||
|
|
||||||
|
const parentPos = notMentioned.indexOf(parent.id);
|
||||||
|
notMentioned.splice(parentPos + 1, 0, channel.id);
|
||||||
|
channel.position = (parentPos + 1) as number;
|
||||||
|
|
||||||
|
await emitEvent({
|
||||||
|
event: "CHANNEL_UPDATE",
|
||||||
|
data: channel,
|
||||||
|
channel_id: channel.id,
|
||||||
|
guild_id,
|
||||||
|
} as ChannelUpdateEvent);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
await Guild.update({ id: guild_id }, { channelOrdering: notMentioned });
|
||||||
|
|
||||||
|
return res.sendStatus(204);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -161,12 +161,6 @@ router.patch(
|
|||||||
guild.assign(body);
|
guild.assign(body);
|
||||||
|
|
||||||
if (body.public_updates_channel_id == "1") {
|
if (body.public_updates_channel_id == "1") {
|
||||||
// move all channels up 1
|
|
||||||
await Channel.createQueryBuilder("channels")
|
|
||||||
.where({ guild: { id: guild_id } })
|
|
||||||
.update({ position: () => "position + 1" })
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
// create an updates channel for them
|
// create an updates channel for them
|
||||||
const channel = await Channel.createChannel(
|
const channel = await Channel.createChannel(
|
||||||
{
|
{
|
||||||
@ -188,6 +182,8 @@ router.patch(
|
|||||||
{ skipPermissionCheck: true },
|
{ skipPermissionCheck: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
|
||||||
|
|
||||||
guild.public_updates_channel_id = channel.id;
|
guild.public_updates_channel_id = channel.id;
|
||||||
} else if (body.public_updates_channel_id != undefined) {
|
} else if (body.public_updates_channel_id != undefined) {
|
||||||
// ensure channel exists in this guild
|
// ensure channel exists in this guild
|
||||||
@ -198,12 +194,6 @@ router.patch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (body.rules_channel_id == "1") {
|
if (body.rules_channel_id == "1") {
|
||||||
// move all channels up 1
|
|
||||||
await Channel.createQueryBuilder("channels")
|
|
||||||
.where({ guild: { id: guild_id } })
|
|
||||||
.update({ position: () => "position + 1" })
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
// create a rules for them
|
// create a rules for them
|
||||||
const channel = await Channel.createChannel(
|
const channel = await Channel.createChannel(
|
||||||
{
|
{
|
||||||
@ -225,6 +215,8 @@ router.patch(
|
|||||||
{ skipPermissionCheck: true },
|
{ skipPermissionCheck: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
|
||||||
|
|
||||||
guild.rules_channel_id = channel.id;
|
guild.rules_channel_id = channel.id;
|
||||||
} else if (body.rules_channel_id != undefined) {
|
} else if (body.rules_channel_id != undefined) {
|
||||||
// ensure channel exists in this guild
|
// ensure channel exists in this guild
|
||||||
|
@ -77,12 +77,7 @@ router.get(
|
|||||||
// Fetch voice channels, and the @everyone permissions object
|
// Fetch voice channels, and the @everyone permissions object
|
||||||
const channels: { id: string; name: string; position: number }[] = [];
|
const channels: { id: string; name: string; position: number }[] = [];
|
||||||
|
|
||||||
(
|
(await Channel.getOrderedChannels(guild.id, guild)).filter((doc) => {
|
||||||
await Channel.find({
|
|
||||||
where: { guild_id: guild_id, type: 2 },
|
|
||||||
order: { position: "ASC" },
|
|
||||||
})
|
|
||||||
).filter((doc) => {
|
|
||||||
// Only return channels where @everyone has the CONNECT permission
|
// Only return channels where @everyone has the CONNECT permission
|
||||||
if (
|
if (
|
||||||
doc.permission_overwrites === undefined ||
|
doc.permission_overwrites === undefined ||
|
||||||
|
@ -54,6 +54,7 @@ import {
|
|||||||
UserSettings,
|
UserSettings,
|
||||||
checkToken,
|
checkToken,
|
||||||
emitEvent,
|
emitEvent,
|
||||||
|
getDatabase,
|
||||||
} from "@spacebar/util";
|
} from "@spacebar/util";
|
||||||
import { check } from "./instanceOf";
|
import { check } from "./instanceOf";
|
||||||
|
|
||||||
@ -167,7 +168,12 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
// guild channels, emoji, roles, stickers
|
// guild channels, emoji, roles, stickers
|
||||||
// but we do want almost everything from guild.
|
// but we do want almost everything from guild.
|
||||||
// How do you do that without just enumerating the guild props?
|
// How do you do that without just enumerating the guild props?
|
||||||
guild: true,
|
guild: Object.fromEntries(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
getDatabase()!
|
||||||
|
.getMetadata(Guild)
|
||||||
|
.columns.map((x) => [x.propertyName, true]),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
relations: [
|
relations: [
|
||||||
"guild",
|
"guild",
|
||||||
@ -253,7 +259,8 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
const guilds: GuildOrUnavailable[] = members.map((member) => {
|
const guilds: GuildOrUnavailable[] = members.map((member) => {
|
||||||
// filter guild channels we don't have permission to view
|
// filter guild channels we don't have permission to view
|
||||||
// TODO: check if this causes issues when the user is granted other roles?
|
// TODO: check if this causes issues when the user is granted other roles?
|
||||||
member.guild.channels = member.guild.channels.filter((channel) => {
|
member.guild.channels = member.guild.channels
|
||||||
|
.filter((channel) => {
|
||||||
const perms = Permissions.finalPermission({
|
const perms = Permissions.finalPermission({
|
||||||
user: {
|
user: {
|
||||||
id: member.id,
|
id: member.id,
|
||||||
@ -264,7 +271,14 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return perms.has("VIEW_CHANNEL");
|
return perms.has("VIEW_CHANNEL");
|
||||||
});
|
})
|
||||||
|
.map((channel) => {
|
||||||
|
channel.position = member.guild.channelOrdering.indexOf(
|
||||||
|
channel.id,
|
||||||
|
);
|
||||||
|
return channel;
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.position - b.position);
|
||||||
|
|
||||||
if (user.bot) {
|
if (user.bot) {
|
||||||
pending_guilds.push(member.guild);
|
pending_guilds.push(member.guild);
|
||||||
|
@ -126,9 +126,6 @@ export class Channel extends BaseClass {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
default_auto_archive_duration?: number;
|
default_auto_archive_duration?: number;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
|
||||||
position?: number;
|
|
||||||
|
|
||||||
@Column({ type: "simple-json", nullable: true })
|
@Column({ type: "simple-json", nullable: true })
|
||||||
permission_overwrites?: ChannelPermissionOverwrite[];
|
permission_overwrites?: ChannelPermissionOverwrite[];
|
||||||
|
|
||||||
@ -193,6 +190,9 @@ export class Channel extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
default_thread_rate_limit_per_user: number = 0;
|
default_thread_rate_limit_per_user: number = 0;
|
||||||
|
|
||||||
|
/** Must be calculated Channel.calculatePosition */
|
||||||
|
position: number;
|
||||||
|
|
||||||
// TODO: DM channel
|
// TODO: DM channel
|
||||||
static async createChannel(
|
static async createChannel(
|
||||||
channel: Partial<Channel>,
|
channel: Partial<Channel>,
|
||||||
@ -211,10 +211,16 @@ export class Channel extends BaseClass {
|
|||||||
permissions.hasThrow("MANAGE_CHANNELS");
|
permissions.hasThrow("MANAGE_CHANNELS");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts?.skipNameChecks) {
|
|
||||||
const guild = await Guild.findOneOrFail({
|
const guild = await Guild.findOneOrFail({
|
||||||
where: { id: channel.guild_id },
|
where: { id: channel.guild_id },
|
||||||
|
select: {
|
||||||
|
features: !opts?.skipNameChecks,
|
||||||
|
channelOrdering: true,
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!opts?.skipNameChecks) {
|
||||||
if (
|
if (
|
||||||
!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") &&
|
!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") &&
|
||||||
channel.name
|
channel.name
|
||||||
@ -293,14 +299,15 @@ export class Channel extends BaseClass {
|
|||||||
if (!channel.permission_overwrites) channel.permission_overwrites = [];
|
if (!channel.permission_overwrites) channel.permission_overwrites = [];
|
||||||
// TODO: eagerly auto generate position of all guild channels
|
// TODO: eagerly auto generate position of all guild channels
|
||||||
|
|
||||||
|
const position =
|
||||||
|
(channel.type === ChannelType.UNHANDLED ? 0 : channel.position) ||
|
||||||
|
0;
|
||||||
|
|
||||||
channel = {
|
channel = {
|
||||||
...channel,
|
...channel,
|
||||||
...(!opts?.keepId && { id: Snowflake.generate() }),
|
...(!opts?.keepId && { id: Snowflake.generate() }),
|
||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
position:
|
position,
|
||||||
(channel.type === ChannelType.UNHANDLED
|
|
||||||
? 0
|
|
||||||
: channel.position) || 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ret = Channel.create(channel);
|
const ret = Channel.create(channel);
|
||||||
@ -314,6 +321,7 @@ export class Channel extends BaseClass {
|
|||||||
guild_id: channel.guild_id,
|
guild_id: channel.guild_id,
|
||||||
} as ChannelCreateEvent)
|
} as ChannelCreateEvent)
|
||||||
: Promise.resolve(),
|
: Promise.resolve(),
|
||||||
|
Guild.insertChannelInOrder(guild.id, ret.id, position, guild),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -456,6 +464,40 @@ export class Channel extends BaseClass {
|
|||||||
await Channel.delete({ id: channel.id });
|
await Channel.delete({ id: channel.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async calculatePosition(
|
||||||
|
channel_id: string,
|
||||||
|
guild_id: string,
|
||||||
|
guild?: Guild,
|
||||||
|
) {
|
||||||
|
if (!guild)
|
||||||
|
guild = await Guild.findOneOrFail({
|
||||||
|
where: { id: guild_id },
|
||||||
|
select: { channelOrdering: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
return guild.channelOrdering.findIndex((id) => channel_id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getOrderedChannels(guild_id: string, guild?: Guild) {
|
||||||
|
if (!guild)
|
||||||
|
guild = await Guild.findOneOrFail({
|
||||||
|
where: { id: guild_id },
|
||||||
|
select: { channelOrdering: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const channels = await Promise.all(
|
||||||
|
guild.channelOrdering.map((id) =>
|
||||||
|
Channel.findOneOrFail({ where: { id } }),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return channels.reduce((r, v) => {
|
||||||
|
v.position = (guild as Guild).channelOrdering.indexOf(v.id);
|
||||||
|
r[v.position] = v;
|
||||||
|
return r;
|
||||||
|
}, [] as Array<Channel>);
|
||||||
|
}
|
||||||
|
|
||||||
isDm() {
|
isDm() {
|
||||||
return (
|
return (
|
||||||
this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM
|
this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM
|
||||||
|
@ -297,6 +297,9 @@ export class Guild extends BaseClass {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
premium_progress_bar_enabled: boolean = false;
|
premium_progress_bar_enabled: boolean = false;
|
||||||
|
|
||||||
|
@Column({ select: false, type: "simple-array" })
|
||||||
|
channelOrdering: string[];
|
||||||
|
|
||||||
static async createGuild(body: {
|
static async createGuild(body: {
|
||||||
name?: string;
|
name?: string;
|
||||||
icon?: string | null;
|
icon?: string | null;
|
||||||
@ -324,6 +327,7 @@ export class Guild extends BaseClass {
|
|||||||
description: "",
|
description: "",
|
||||||
welcome_channels: [],
|
welcome_channels: [],
|
||||||
},
|
},
|
||||||
|
channelOrdering: [],
|
||||||
|
|
||||||
afk_timeout: Config.get().defaults.guild.afkTimeout,
|
afk_timeout: Config.get().defaults.guild.afkTimeout,
|
||||||
default_message_notifications:
|
default_message_notifications:
|
||||||
@ -376,7 +380,7 @@ export class Guild extends BaseClass {
|
|||||||
|
|
||||||
const parent_id = ids.get(channel.parent_id);
|
const parent_id = ids.get(channel.parent_id);
|
||||||
|
|
||||||
await Channel.createChannel(
|
const saved = await Channel.createChannel(
|
||||||
{ ...channel, guild_id, id, parent_id },
|
{ ...channel, guild_id, id, parent_id },
|
||||||
body.owner_id,
|
body.owner_id,
|
||||||
{
|
{
|
||||||
@ -386,15 +390,69 @@ export class Guild extends BaseClass {
|
|||||||
skipEventEmit: true,
|
skipEventEmit: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await Guild.insertChannelInOrder(
|
||||||
|
guild.id,
|
||||||
|
saved.id,
|
||||||
|
parent_id ?? channel.position ?? 0,
|
||||||
|
guild,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return guild;
|
return guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
/** Insert a channel into the guild ordering by parent channel id or position */
|
||||||
|
static async insertChannelInOrder(
|
||||||
|
guild_id: string,
|
||||||
|
channel_id: string,
|
||||||
|
position: number,
|
||||||
|
guild?: Guild,
|
||||||
|
): Promise<number>;
|
||||||
|
static async insertChannelInOrder(
|
||||||
|
guild_id: string,
|
||||||
|
channel_id: string,
|
||||||
|
parent_id: string,
|
||||||
|
guild?: Guild,
|
||||||
|
): Promise<number>;
|
||||||
|
static async insertChannelInOrder(
|
||||||
|
guild_id: string,
|
||||||
|
channel_id: string,
|
||||||
|
insertPoint: string | number,
|
||||||
|
guild?: Guild,
|
||||||
|
): Promise<number>;
|
||||||
|
static async insertChannelInOrder(
|
||||||
|
guild_id: string,
|
||||||
|
channel_id: string,
|
||||||
|
insertPoint: string | number,
|
||||||
|
guild?: Guild,
|
||||||
|
): Promise<number> {
|
||||||
|
if (!guild)
|
||||||
|
guild = await Guild.findOneOrFail({
|
||||||
|
where: { id: guild_id },
|
||||||
|
select: { channelOrdering: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
let position;
|
||||||
|
if (typeof insertPoint == "string")
|
||||||
|
position = guild.channelOrdering.indexOf(insertPoint) + 1;
|
||||||
|
else position = insertPoint;
|
||||||
|
|
||||||
|
guild.channelOrdering.remove(channel_id);
|
||||||
|
|
||||||
|
guild.channelOrdering.splice(position, 0, channel_id);
|
||||||
|
await Guild.update(
|
||||||
|
{ id: guild_id },
|
||||||
|
{ channelOrdering: guild.channelOrdering },
|
||||||
|
);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): Guild {
|
||||||
return {
|
return {
|
||||||
...this,
|
...this,
|
||||||
unavailable: this.unavailable == false ? undefined : true,
|
unavailable: this.unavailable == false ? undefined : true,
|
||||||
|
channelOrdering: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class guildChannelOrdering1696420827239 implements MigrationInterface {
|
||||||
|
name = "guildChannelOrdering1696420827239";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const guilds = await queryRunner.query(
|
||||||
|
`SELECT id FROM guilds`,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE guilds ADD channelOrdering text NOT NULL DEFAULT '[]'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const guild_id of guilds.records.map((x) => x.id)) {
|
||||||
|
const channels: Array<{ position: number; id: string }> = (
|
||||||
|
await queryRunner.query(
|
||||||
|
`SELECT id, position FROM channels WHERE guild_id = ?`,
|
||||||
|
[guild_id],
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
).records;
|
||||||
|
|
||||||
|
channels.sort((a, b) => a.position - b.position);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE guilds SET channelOrdering = ? WHERE id = ?`,
|
||||||
|
[JSON.stringify(channels.map((x) => x.id)), guild_id],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(): Promise<void> {
|
||||||
|
// don't care actually, sorry.
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class guildChannelOrdering1696420827239 implements MigrationInterface {
|
||||||
|
name = "guildChannelOrdering1696420827239";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const guilds = await queryRunner.query(
|
||||||
|
`SELECT id FROM guilds`,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE guilds ADD channelOrdering text NOT NULL DEFAULT '[]'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const guild_id of guilds.records.map((x) => x.id)) {
|
||||||
|
const channels: Array<{ position: number; id: string }> = (
|
||||||
|
await queryRunner.query(
|
||||||
|
`SELECT id, position FROM channels WHERE guild_id = ?`,
|
||||||
|
[guild_id],
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
).records;
|
||||||
|
|
||||||
|
channels.sort((a, b) => a.position - b.position);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE guilds SET channelOrdering = ? WHERE id = ?`,
|
||||||
|
[JSON.stringify(channels.map((x) => x.id)), guild_id],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(): Promise<void> {
|
||||||
|
// don't care actually, sorry.
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||||
|
|
||||||
|
export class guildChannelOrdering1696420827239 implements MigrationInterface {
|
||||||
|
name = "guildChannelOrdering1696420827239";
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
const guilds = await queryRunner.query(
|
||||||
|
`SELECT id FROM guilds`,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`ALTER TABLE guilds ADD channelOrdering text NOT NULL DEFAULT '[]'`,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const guild_id of guilds.records.map((x) => x.id)) {
|
||||||
|
const channels: Array<{ position: number; id: string }> = (
|
||||||
|
await queryRunner.query(
|
||||||
|
`SELECT id, position FROM channels WHERE guild_id = $1`,
|
||||||
|
[guild_id],
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
).records;
|
||||||
|
|
||||||
|
channels.sort((a, b) => a.position - b.position);
|
||||||
|
|
||||||
|
await queryRunner.query(
|
||||||
|
`UPDATE guilds SET channelOrdering = $1 WHERE id = $2`,
|
||||||
|
[JSON.stringify(channels.map((x) => x.id)), guild_id],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(): Promise<void> {
|
||||||
|
// don't care actually, sorry.
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user