mirror of
https://github.com/spacebarchat/server.git
synced 2026-08-06 23:19:47 +00:00
Use deep merge everywhere
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
} from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
// TODO: delete channel
|
||||
@@ -78,7 +79,7 @@ router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANN
|
||||
if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon);
|
||||
|
||||
let channel = await Channel.findOneOrFail({ where: { id: channel_id } });
|
||||
channel = Object.assign(channel, payload);
|
||||
channel = OrmUtils.mergeDeep(channel, payload);
|
||||
|
||||
await Promise.all([
|
||||
channel.save(),
|
||||
|
||||
@@ -4,6 +4,7 @@ import { route } from "@fosscord/api";
|
||||
import { random } from "@fosscord/api";
|
||||
import { Channel, Invite, InviteCreateEvent, emitEvent, User, Guild, PublicInviteRelation } from "@fosscord/util";
|
||||
import { isTextChannel } from "./messages";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -33,7 +34,7 @@ router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT
|
||||
|
||||
const expires_at = new Date(req.body.max_age * 1000 + Date.now());
|
||||
|
||||
const invite = await Object.assign(new Invite(),{
|
||||
const invite = await OrmUtils.mergeDeep(new Invite(),{
|
||||
code: random(),
|
||||
temporary: req.body.temporary,
|
||||
uses: 0,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { emitEvent, getPermission, MessageAckEvent, ReadState, Snowflake } from "@fosscord/util";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -20,7 +21,7 @@ router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Reques
|
||||
permission.hasThrow("VIEW_CHANNEL");
|
||||
|
||||
let read_state = await ReadState.findOne({ where: { user_id: req.user_id, channel_id } });
|
||||
if (!read_state) read_state = Object.assign(new ReadState(), { user_id: req.user_id, channel_id });
|
||||
if (!read_state) read_state = OrmUtils.mergeDeep(new ReadState(), { user_id: req.user_id, channel_id }) as ReadState;
|
||||
read_state.last_message_id = message_id;
|
||||
|
||||
await read_state.save();
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
User
|
||||
} from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -28,7 +29,7 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
|
||||
throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
|
||||
}
|
||||
|
||||
channel.recipients!.push(Object.assign(new Recipient(), { channel_id, user_id: user_id }));
|
||||
channel.recipients!.push(OrmUtils.mergeDeep(new Recipient(), { channel_id, user_id: user_id }));
|
||||
await channel.save();
|
||||
|
||||
await emitEvent({
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response, Router } from "express";
|
||||
import { DiscordApiErrors, emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, Guild, Ban, User, Member } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { getIpAdress, route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
export interface BanCreateSchema {
|
||||
delete_message_days?: string;
|
||||
@@ -90,7 +91,7 @@ router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBER
|
||||
|
||||
const banned_user = await User.getPublicUser(banned_user_id);
|
||||
|
||||
const ban = Object.assign(new Ban(),{
|
||||
const ban = OrmUtils.mergeDeep(new Ban(),{
|
||||
user_id: banned_user_id,
|
||||
guild_id: guild_id,
|
||||
ip: getIpAdress(req),
|
||||
@@ -122,7 +123,7 @@ router.put("/@me", route({ body: "BanCreateSchema"}), async (req: Request, res:
|
||||
if (req.permission!.cache.guild?.owner_id === req.params.user_id)
|
||||
throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
|
||||
|
||||
const ban = Object.assign(new Ban(), {
|
||||
const ban = OrmUtils.mergeDeep(new Ban(), {
|
||||
user_id: req.params.user_id,
|
||||
guild_id: guild_id,
|
||||
ip: getIpAdress(req),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -50,7 +51,7 @@ router.post("/", route({ body: "EmojiCreateSchema", permission: "MANAGE_EMOJIS_A
|
||||
const user = await User.findOneOrFail({ where: { id: req.user_id } });
|
||||
body.image = (await handleFile(`/emojis/${id}`, body.image)) as string;
|
||||
|
||||
const emoji = await Object.assign(new Emoji(), {
|
||||
const emoji = await OrmUtils.mergeDeep(new Emoji(), {
|
||||
id: id,
|
||||
guild_id: guild_id,
|
||||
...body,
|
||||
@@ -80,7 +81,7 @@ router.patch(
|
||||
const { emoji_id, guild_id } = req.params;
|
||||
const body = req.body as EmojiModifySchema;
|
||||
|
||||
const emoji = await Object.assign(new Emoji(), { ...body, id: emoji_id, guild_id: guild_id }).save();
|
||||
const emoji = await OrmUtils.mergeDeep(new Emoji(), { ...body, id: emoji_id, guild_id: guild_id }).save();
|
||||
|
||||
await emitEvent({
|
||||
event: "GUILD_EMOJIS_UPDATE",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpda
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { GuildCreateSchema } from "../index";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -59,7 +60,7 @@ router.patch("/", route({ body: "GuildUpdateSchema"}), async (req: Request, res:
|
||||
relations: ["emojis", "roles", "stickers"]
|
||||
});
|
||||
// TODO: check if body ids are valid
|
||||
guild = Object.assign(guild, body);
|
||||
guild = OrmUtils.mergeDeep(guild, body);
|
||||
|
||||
//TODO: check this, removed toJSON call
|
||||
const data = JSON.parse(JSON.stringify(guild));
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response, Router } from "express";
|
||||
import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -31,7 +32,7 @@ router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, re
|
||||
permission.hasThrow("MANAGE_ROLES");
|
||||
|
||||
if (body.roles.indexOf(everyone.id) === -1) body.roles.push(everyone.id);
|
||||
member.roles = body.roles.map((x) => Object.assign(new Role(), { id: x })); // foreign key constraint will fail if role doesn't exist
|
||||
member.roles = body.roles.map((x) => OrmUtils.mergeDeep(new Role(), { id: x })); // foreign key constraint will fail if role doesn't exist
|
||||
}
|
||||
|
||||
await member.save();
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, ha
|
||||
import { route } from "@fosscord/api";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { RoleModifySchema } from "../";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -43,7 +44,7 @@ router.patch("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }
|
||||
|
||||
if (body.icon) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
|
||||
|
||||
const role = Object.assign(new Role(), {
|
||||
const role = OrmUtils.mergeDeep(new Role(), {
|
||||
...body,
|
||||
id: role_id,
|
||||
guild_id,
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -51,7 +52,7 @@ router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" })
|
||||
|
||||
if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
|
||||
|
||||
let role: Role = Object.assign(new Role(),{
|
||||
let role: Role = OrmUtils.mergeDeep(new Role(),{
|
||||
// values before ...body are default and can be overriden
|
||||
position: 0,
|
||||
hoist: false,
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import multer from "multer";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
const router = Router();
|
||||
|
||||
router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
@@ -43,7 +44,7 @@ router.post(
|
||||
const id = Snowflake.generate();
|
||||
|
||||
const [sticker] = await Promise.all([
|
||||
Object.assign(new Sticker(), {
|
||||
OrmUtils.mergeDeep(new Sticker(), {
|
||||
...body,
|
||||
guild_id,
|
||||
id,
|
||||
@@ -105,7 +106,7 @@ router.patch(
|
||||
const { guild_id, sticker_id } = req.params;
|
||||
const body = req.body as ModifyGuildStickerSchema;
|
||||
|
||||
const sticker = await Object.assign(new Sticker(), { ...body, guild_id, id: sticker_id }).save();
|
||||
const sticker = await OrmUtils.mergeDeep(new Sticker(), { ...body, guild_id, id: sticker_id }).save();
|
||||
await sendStickerUpdateEvent(guild_id);
|
||||
|
||||
return res.json(sticker);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Guild, Template } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { generateCode } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -47,7 +48,7 @@ router.post("/", route({ body: "TemplateCreateSchema", permission: "MANAGE_GUILD
|
||||
const exists = await Template.findOneOrFail({ where: { id: guild_id } }).catch((e) => {});
|
||||
if (exists) throw new HTTPError("Template already exists", 400);
|
||||
|
||||
const template = await Object.assign(new Template(), {
|
||||
const template = await OrmUtils.mergeDeep(new Template(), {
|
||||
...req.body,
|
||||
code: generateCode(),
|
||||
creator_id: req.user_id,
|
||||
@@ -75,7 +76,7 @@ router.put("/:code", route({ permission: "MANAGE_GUILD" }), async (req: Request,
|
||||
const { code, guild_id } = req.params;
|
||||
const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection });
|
||||
|
||||
const template = await Object.assign(new Template(), { code, serialized_source_guild: guild }).save();
|
||||
const template = await OrmUtils.mergeDeep(new Template(), { code, serialized_source_guild: guild }).save();
|
||||
|
||||
res.json(template);
|
||||
});
|
||||
@@ -84,7 +85,7 @@ router.patch("/:code", route({ body: "TemplateModifySchema", permission: "MANAGE
|
||||
const { code, guild_id } = req.params;
|
||||
const { name, description } = req.body;
|
||||
|
||||
const template = await Object.assign(new Template(), { code, name: name, description: description, source_guild_id: guild_id }).save();
|
||||
const template = await OrmUtils.mergeDeep(new Template(), { code, name: name, description: description, source_guild_id: guild_id }).save();
|
||||
|
||||
res.json(template);
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from
|
||||
import { Router, Request, Response } from "express";
|
||||
import { route } from "@fosscord/api";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -47,7 +48,7 @@ router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" })
|
||||
|
||||
const { id } = await Channel.findOneOrFail({ where: { guild_id, type: ChannelType.GUILD_TEXT } });
|
||||
|
||||
await Object.assign(new Invite(), {
|
||||
await OrmUtils.mergeDeep(new Invite(), {
|
||||
vanity_url: true,
|
||||
code: code,
|
||||
temporary: false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { Request, Response, Router } from "express";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
//TODO need more testing when community guild and voice stage channel are working
|
||||
@@ -42,7 +43,7 @@ router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request
|
||||
});
|
||||
if (!voice_state) throw DiscordApiErrors.UNKNOWN_VOICE_STATE;
|
||||
|
||||
voice_state = Object.assign(voice_state, body);
|
||||
voice_state = OrmUtils.mergeDeep(voice_state, body) as VoiceState;
|
||||
const channel = await Channel.findOneOrFail({ where: { guild_id, id: body.channel_id } });
|
||||
if (channel.type !== ChannelType.GUILD_STAGE_VOICE) {
|
||||
throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Request, Response, Router } from "express";
|
||||
import { Config, Permissions, Guild, Invite, Channel, Member } from "@fosscord/util";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { random, route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -41,7 +42,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
|
||||
inviter_id: null
|
||||
};
|
||||
|
||||
invite = await new Invite(body).save();
|
||||
invite = await OrmUtils.mergeDeep(new Invite(), body).save();
|
||||
}
|
||||
|
||||
// Fetch voice channels, and the @everyone permissions object
|
||||
|
||||
@@ -4,6 +4,7 @@ import { route } from "@fosscord/api";
|
||||
import { DiscordApiErrors } from "@fosscord/util";
|
||||
import fetch from "node-fetch";
|
||||
const router: Router = Router();
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
export interface GuildTemplateCreateSchema {
|
||||
name: string;
|
||||
@@ -57,13 +58,13 @@ router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req:
|
||||
const guild_id = Snowflake.generate();
|
||||
|
||||
const [guild, role] = await Promise.all([
|
||||
Object.assign(new Guild(), {
|
||||
OrmUtils.mergeDeep(new Guild(), {
|
||||
...body,
|
||||
...template.serialized_source_guild,
|
||||
id: guild_id,
|
||||
owner_id: req.user_id
|
||||
}).save(),
|
||||
(Object.assign(new Role(), {
|
||||
(OrmUtils.mergeDeep(new Role(), {
|
||||
id: guild_id,
|
||||
guild_id: guild_id,
|
||||
color: 0,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Router, Request, Response } from "express";
|
||||
import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import bcrypt from "bcrypt";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router: Router = Router();
|
||||
|
||||
@@ -32,7 +33,8 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
|
||||
const body = req.body as UserModifySchema;
|
||||
|
||||
if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
|
||||
if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);let user = await User.findOneOrFail({ where: { id: req.user_id }, select: [...PrivateUserProjection, "data"] });
|
||||
if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
|
||||
let user = await User.findOneOrFail({ where: { id: req.user_id }, select: [...PrivateUserProjection, "data"] });
|
||||
|
||||
if (body.password) {
|
||||
if (user.data?.hash) {
|
||||
@@ -63,7 +65,7 @@ router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res:
|
||||
}
|
||||
}
|
||||
|
||||
user = Object.assign(user, body);
|
||||
user = OrmUtils.mergeDeep(user, body);
|
||||
await user.save();
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Router, Response, Request } from "express";
|
||||
import { HTTPError } from "@fosscord/util";
|
||||
import { DiscordApiErrors } from "@fosscord/util";
|
||||
import { route } from "@fosscord/api";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -140,7 +141,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
|
||||
relationship.type = RelationshipType.blocked;
|
||||
await relationship.save();
|
||||
} else {
|
||||
relationship = await Object.assign(new Relationship(), { to_id: id, type: RelationshipType.blocked, from_id: req.user_id }).save();
|
||||
relationship = await (OrmUtils.mergeDeep(new Relationship(), { to_id: id, type: RelationshipType.blocked, from_id: req.user_id }) as Relationship).save();
|
||||
}
|
||||
|
||||
if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
|
||||
@@ -166,8 +167,8 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
|
||||
const { maxFriends } = Config.get().limits.user;
|
||||
if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
|
||||
|
||||
let incoming_relationship = Object.assign(new Relationship(), { nickname: undefined, type: RelationshipType.incoming, to: user, from: friend });
|
||||
let outgoing_relationship = Object.assign(new Relationship(), {
|
||||
let incoming_relationship = OrmUtils.mergeDeep(new Relationship(), { nickname: undefined, type: RelationshipType.incoming, to: user, from: friend });
|
||||
let outgoing_relationship = OrmUtils.mergeDeep(new Relationship(), {
|
||||
nickname: undefined,
|
||||
type: RelationshipType.outgoing,
|
||||
to: friend,
|
||||
|
||||
@@ -26,6 +26,7 @@ import { HTTPError } from "@fosscord/util";
|
||||
import fetch from "node-fetch";
|
||||
import cheerio from "cheerio";
|
||||
import { MessageCreateSchema } from "../../routes/channels/#channel_id/messages";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
const allow_empty = false;
|
||||
// TODO: check webhook, application, system author, stickers
|
||||
// TODO: embed gifs/videos/images
|
||||
@@ -47,7 +48,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
|
||||
const channel = await Channel.findOneOrFail({ where: { id: opts.channel_id }, relations: ["recipients"] });
|
||||
if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404);
|
||||
|
||||
const message = Object.assign(new Message(), {
|
||||
const message = OrmUtils.mergeDeep(new Message(), {
|
||||
...opts,
|
||||
sticker_items: opts.sticker_ids?.map((x) => ({ id: x })),
|
||||
guild_id: channel.guild_id,
|
||||
@@ -132,9 +133,9 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> {
|
||||
}
|
||||
}
|
||||
|
||||
message.mention_channels = mention_channel_ids.map((x) => Object.assign(new Channel(), { id: x }));
|
||||
message.mention_roles = mention_role_ids.map((x) => Object.assign(new Role(), { id: x }));
|
||||
message.mentions = mention_user_ids.map((x) => Object.assign(new User(), { id: x }));
|
||||
message.mention_channels = mention_channel_ids.map((x) => OrmUtils.mergeDeep(new Channel(), { id: x }));
|
||||
message.mention_roles = mention_role_ids.map((x) => OrmUtils.mergeDeep(new Role(), { id: x }));
|
||||
message.mentions = mention_user_ids.map((x) => OrmUtils.mergeDeep(new User(), { id: x }));
|
||||
message.mention_everyone = mention_everyone;
|
||||
|
||||
// TODO: check and put it all in the body
|
||||
|
||||
@@ -28,6 +28,7 @@ import { IdentifySchema } from "../schema/Identify";
|
||||
const experiments: any = [];
|
||||
import { check } from "./instanceOf";
|
||||
import { Recipient } from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
// TODO: user sharding
|
||||
// TODO: check privileged intents, if defined in the config
|
||||
@@ -50,7 +51,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
||||
|
||||
const session_id = genSessionId();
|
||||
this.session_id = session_id; //Set the session of the WebSocket object
|
||||
|
||||
|
||||
const [user, read_states, members, recipients, session, application] =
|
||||
await Promise.all([
|
||||
User.findOneOrFail({
|
||||
@@ -83,7 +84,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
||||
// TODO: public user selection
|
||||
}),
|
||||
// save the session and delete it when the websocket is closed
|
||||
Object.assign(new Session(),{
|
||||
await OrmUtils.mergeDeep(new Session(), {
|
||||
user_id: this.user_id,
|
||||
session_id: session_id,
|
||||
// TODO: check if status is only one of: online, dnd, offline, idle
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
VoiceState,
|
||||
VoiceStateUpdateEvent,
|
||||
} from "@fosscord/util";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
// TODO: check if a voice server is setup
|
||||
// Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not.
|
||||
|
||||
@@ -47,9 +48,9 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
|
||||
|
||||
//The event send by Discord's client on channel leave has both guild_id and channel_id as null
|
||||
if (body.guild_id === null) body.guild_id = voiceState.guild_id;
|
||||
voiceState = Object.assign(voiceState, body);
|
||||
voiceState = OrmUtils.mergeDeep(voiceState, body);
|
||||
} catch (error) {
|
||||
voiceState = Object.assign(new VoiceState(), {
|
||||
voiceState = OrmUtils.mergeDeep(new VoiceState(), {
|
||||
...body,
|
||||
user_id: this.user_id,
|
||||
deaf: false,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
|
||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId} from "typeorm";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { BaseClass } from "./BaseClass";
|
||||
import { Guild } from "./Guild";
|
||||
import { PublicUserProjection, User } from "./User";
|
||||
@@ -222,7 +223,7 @@ export class Channel extends BaseClass {
|
||||
};
|
||||
|
||||
await Promise.all([
|
||||
Object.assign(new Channel(),channel).save(),
|
||||
OrmUtils.mergeDeep(new Channel(),channel).save(),
|
||||
!opts?.skipEventEmit
|
||||
? emitEvent({
|
||||
event: "CHANNEL_CREATE",
|
||||
@@ -263,7 +264,7 @@ export class Channel extends BaseClass {
|
||||
if (containsAll(re, channelRecipients)) {
|
||||
if (channel == null) {
|
||||
channel = ur.channel;
|
||||
ur = Object.assign(ur, { closed: false });
|
||||
ur = OrmUtils.mergeDeep(ur, { closed: false });
|
||||
await ur.save();
|
||||
}
|
||||
}
|
||||
@@ -273,7 +274,7 @@ export class Channel extends BaseClass {
|
||||
if (channel == null) {
|
||||
name = trimSpecial(name);
|
||||
|
||||
channel = await (Object.assign(new Channel(), {
|
||||
channel = await (OrmUtils.mergeDeep(new Channel(), {
|
||||
name,
|
||||
type,
|
||||
owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server
|
||||
@@ -281,7 +282,7 @@ export class Channel extends BaseClass {
|
||||
last_message_id: null,
|
||||
recipients: channelRecipients.map(
|
||||
(x) =>
|
||||
Object.assign(new Recipient(), { user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })
|
||||
OrmUtils.mergeDeep(new Recipient(), { user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })
|
||||
),
|
||||
}) as Channel).save();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
|
||||
import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId} from "typeorm";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { Config, handleFile, Snowflake } from "..";
|
||||
import { Ban } from "./Ban";
|
||||
import { BaseClass } from "./BaseClass";
|
||||
@@ -285,7 +286,7 @@ export class Guild extends BaseClass {
|
||||
}) {
|
||||
const guild_id = Snowflake.generate();
|
||||
|
||||
const guild: Guild = Object.assign(new Guild(),{
|
||||
const guild: Guild = OrmUtils.mergeDeep(new Guild(),{
|
||||
name: body.name || "Fosscord",
|
||||
icon: await handleFile(`/icons/${guild_id}`, body.icon as string),
|
||||
region: Config.get().regions.default,
|
||||
@@ -321,7 +322,7 @@ export class Guild extends BaseClass {
|
||||
|
||||
// we have to create the role _after_ the guild because else we would get a "SQLITE_CONSTRAINT: FOREIGN KEY constraint failed" error
|
||||
// TODO: make the @everyone a pseudorole that is dynamically generated at runtime so we can save storage
|
||||
let role: Role = Object.assign(new Role(), {
|
||||
let role: Role = OrmUtils.mergeDeep(new Role(), {
|
||||
id: guild_id,
|
||||
guild_id: guild_id,
|
||||
color: 0,
|
||||
|
||||
@@ -25,6 +25,7 @@ import { Role } from "./Role";
|
||||
import { BaseClassWithoutId } from "./BaseClass";
|
||||
import { Ban, PublicGuildRelations } from ".";
|
||||
import { DiscordApiErrors } from "../util/Constants";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
|
||||
export const MemberPrivateProjection: (keyof Member)[] = [
|
||||
"id",
|
||||
@@ -161,7 +162,7 @@ export class Member extends BaseClassWithoutId {
|
||||
}),
|
||||
Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }),
|
||||
]);
|
||||
member.roles.push(Object.assign(new Role(), { id: role_id }));
|
||||
member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id }));
|
||||
|
||||
await Promise.all([
|
||||
member.save(),
|
||||
@@ -256,7 +257,7 @@ export class Member extends BaseClassWithoutId {
|
||||
nick: undefined,
|
||||
roles: [guild_id], // @everyone role
|
||||
joined_at: new Date(),
|
||||
premium_since: (new Date()).getTime(),
|
||||
premium_since: new Date(),
|
||||
deaf: false,
|
||||
mute: false,
|
||||
pending: false,
|
||||
@@ -264,9 +265,9 @@ export class Member extends BaseClassWithoutId {
|
||||
//TODO: check for bugs
|
||||
if(guild.member_count) guild.member_count++;
|
||||
await Promise.all([
|
||||
Object.assign(new Member(), {
|
||||
OrmUtils.mergeDeep(new Member(), {
|
||||
...member,
|
||||
roles: [Object.assign(new Role(), { id: guild_id })],
|
||||
roles: [OrmUtils.mergeDeep(new Role(), { id: guild_id })],
|
||||
// read_state: {},
|
||||
settings: {
|
||||
channel_overrides: [],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, ManyToMany, OneToMany, RelationId } from "typeorm";
|
||||
import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, ManyToMany, OneToMany, RelationId} from "typeorm";
|
||||
import { OrmUtils } from "@fosscord/util";
|
||||
import { BaseClass } from "./BaseClass";
|
||||
import { BitField } from "../util/BitField";
|
||||
import { Relationship } from "./Relationship";
|
||||
@@ -255,7 +256,7 @@ export class User extends BaseClass {
|
||||
// if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false
|
||||
const language = req.language === "en" ? "en-US" : req.language || "en-US";
|
||||
|
||||
const user = Object.assign(new User(), {
|
||||
const user = OrmUtils.mergeDeep(new User(), {
|
||||
created_at: new Date(),
|
||||
username: username,
|
||||
discriminator,
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
//source: https://github.com/typeorm/typeorm/blob/master/src/util/OrmUtils.ts
|
||||
export class OrmUtils {
|
||||
// Checks if it's an object made by Object.create(null), {} or new Object()
|
||||
private static isPlainObject(item: any) {
|
||||
if (item === null || item === undefined) {
|
||||
return false
|
||||
}
|
||||
|
||||
return !item.constructor || item.constructor === Object
|
||||
}
|
||||
|
||||
private static mergeArrayKey(
|
||||
target: any,
|
||||
key: number,
|
||||
value: any,
|
||||
memo: Map<any, any>,
|
||||
) {
|
||||
// Have we seen this before? Prevent infinite recursion.
|
||||
if (memo.has(value)) {
|
||||
target[key] = memo.get(value)
|
||||
return
|
||||
}
|
||||
|
||||
if (value instanceof Promise) {
|
||||
// Skip promises entirely.
|
||||
// This is a hold-over from the old code & is because we don't want to pull in
|
||||
// the lazy fields. Ideally we'd remove these promises via another function first
|
||||
// but for now we have to do it here.
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.isPlainObject(value) && !Array.isArray(value)) {
|
||||
target[key] = value
|
||||
return
|
||||
}
|
||||
|
||||
if (!target[key]) {
|
||||
target[key] = Array.isArray(value) ? [] : {}
|
||||
}
|
||||
|
||||
memo.set(value, target[key])
|
||||
this.merge(target[key], value, memo)
|
||||
memo.delete(value)
|
||||
}
|
||||
|
||||
private static mergeObjectKey(
|
||||
target: any,
|
||||
key: string,
|
||||
value: any,
|
||||
memo: Map<any, any>,
|
||||
) {
|
||||
// Have we seen this before? Prevent infinite recursion.
|
||||
if (memo.has(value)) {
|
||||
Object.assign(target, { [key]: memo.get(value) })
|
||||
return
|
||||
}
|
||||
|
||||
if (value instanceof Promise) {
|
||||
// Skip promises entirely.
|
||||
// This is a hold-over from the old code & is because we don't want to pull in
|
||||
// the lazy fields. Ideally we'd remove these promises via another function first
|
||||
// but for now we have to do it here.
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.isPlainObject(value) && !Array.isArray(value)) {
|
||||
Object.assign(target, { [key]: value })
|
||||
return
|
||||
}
|
||||
|
||||
if (!target[key]) {
|
||||
Object.assign(target, { [key]: value })
|
||||
}
|
||||
|
||||
memo.set(value, target[key])
|
||||
this.merge(target[key], value, memo)
|
||||
memo.delete(value)
|
||||
}
|
||||
|
||||
private static merge(
|
||||
target: any,
|
||||
source: any,
|
||||
memo: Map<any, any> = new Map(),
|
||||
): any {
|
||||
if (Array.isArray(target) && Array.isArray(source)) {
|
||||
for (let key = 0; key < source.length; key++) {
|
||||
this.mergeArrayKey(target, key, source[key], memo)
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const key of Object.keys(source)) {
|
||||
this.mergeObjectKey(target, key, source[key], memo)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep Object.assign.
|
||||
*/
|
||||
static mergeDeep(target: any, ...sources: any[]): any {
|
||||
if (!sources.length) {
|
||||
return target
|
||||
}
|
||||
|
||||
for (const source of sources) {
|
||||
OrmUtils.merge(target, source)
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './Checks';
|
||||
export * from './HTTPError';
|
||||
export * from './OrmUtils';
|
||||
Reference in New Issue
Block a user