summary refs log tree commit diff
path: root/src/util/entities/User.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/entities/User.ts')
-rw-r--r--src/util/entities/User.ts105
1 files changed, 43 insertions, 62 deletions
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts

index 7f79f008..42b46146 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts
@@ -17,15 +17,8 @@ */ import { Request } from "express"; -import { - Column, - Entity, - FindOneOptions, - JoinColumn, - OneToMany, - OneToOne, -} from "typeorm"; -import { Config, Email, FieldErrors, Snowflake, trimSpecial } from ".."; +import { Column, Entity, FindOneOptions, JoinColumn, OneToMany, OneToOne } from "typeorm"; +import { Channel, ChannelType, Config, Email, FieldErrors, Recipient, Snowflake, trimSpecial } from ".."; import { BitField } from "../util/BitField"; import { BaseClass } from "./BaseClass"; import { ConnectedAccount } from "./ConnectedAccount"; @@ -71,13 +64,8 @@ export enum PrivateUserEnum { } export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys; -export const PublicUserProjection = Object.values(PublicUserEnum).filter( - (x) => typeof x === "string", -) as PublicUserKeys[]; -export const PrivateUserProjection = [ - ...PublicUserProjection, - ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string"), -] as PrivateUserKeys[]; +export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[]; +export const PrivateUserProjection = [...PublicUserProjection, ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string")] as PrivateUserKeys[]; // Private user data that should never get sent to the client export type PublicUser = Pick<User, PublicUserKeys>; @@ -191,25 +179,17 @@ export class User extends BaseClass { sessions: Session[]; @JoinColumn({ name: "relationship_ids" }) - @OneToMany( - () => Relationship, - (relationship: Relationship) => relationship.from, - { - cascade: true, - orphanedRowAction: "delete", - }, - ) + @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, { + cascade: true, + orphanedRowAction: "delete", + }) relationships: Relationship[]; @JoinColumn({ name: "connected_account_ids" }) - @OneToMany( - () => ConnectedAccount, - (account: ConnectedAccount) => account.user, - { - cascade: true, - orphanedRowAction: "delete", - }, - ) + @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, { + cascade: true, + orphanedRowAction: "delete", + }) connected_accounts: ConnectedAccount[]; @Column({ type: "simple-json", select: false }) @@ -243,13 +223,7 @@ export class User extends BaseClass { validate() { if (this.discriminator) { const discrim = Number(this.discriminator); - if ( - isNaN(discrim) || - !(typeof discrim == "number") || - !Number.isInteger(discrim) || - discrim <= 0 || - discrim >= 10000 - ) + if (isNaN(discrim) || !(typeof discrim == "number") || !Number.isInteger(discrim) || discrim <= 0 || discrim >= 10000) throw FieldErrors({ discriminator: { message: "Discriminator must be a number.", @@ -289,9 +263,7 @@ export class User extends BaseClass { }); } - public static async generateDiscriminator( - username: string, - ): Promise<string | undefined> { + public static async generateDiscriminator(username: string): Promise<string | undefined> { if (Config.get().register.incrementingDiscriminators) { // discriminator will be incrementally generated @@ -300,10 +272,7 @@ export class User extends BaseClass { where: { username }, select: ["discriminator"], }); - const highestDiscriminator = Math.max( - 0, - ...users.map((u) => Number(u.discriminator)), - ); + const highestDiscriminator = Math.max(0, ...users.map((u) => Number(u.discriminator))); const discriminator = highestDiscriminator + 1; if (discriminator >= 10000) { @@ -317,9 +286,7 @@ export class User extends BaseClass { // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists // TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the database? for (let tries = 0; tries < 5; tries++) { - const discriminator = Math.randomIntBetween(1, 9999) - .toString() - .padStart(4, "0"); + const discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0"); const exists = await User.findOne({ where: { discriminator, username: username }, select: ["id"], @@ -354,8 +321,7 @@ export class User extends BaseClass { throw FieldErrors({ username: { code: "USERNAME_TOO_MANY_USERS", - message: - req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "", + message: req?.t("auth:register.USERNAME_TOO_MANY_USERS") || "", }, }); } @@ -363,8 +329,7 @@ export class User extends BaseClass { // TODO: save date_of_birth // apparently discord doesn't save the date of birth and just calculate if nsfw is allowed // 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 language = req?.language === "en" ? "en-US" : req?.language || "en-US"; const settings = UserSettings.create({ locale: language, @@ -382,9 +347,7 @@ export class User extends BaseClass { extended_settings: "{}", settings: settings, - premium_since: Config.get().defaults.user.premium - ? new Date() - : undefined, + premium_since: Config.get().defaults.user.premium ? new Date() : undefined, rights: Config.get().register.defaultRights, premium: Config.get().defaults.user.premium ?? false, premium_type: Config.get().defaults.user.premiumType ?? 0, @@ -398,24 +361,42 @@ export class User extends BaseClass { // send verification email if users aren't verified by default and we have an email if (!Config.get().defaults.user.verified && email) { await Email.sendVerifyEmail(user, email).catch((e) => { - console.error( - `Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`, - ); + console.error(`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`); }); } setImmediate(async () => { if (Config.get().guild.autoJoin.enabled) { for (const guild of Config.get().guild.autoJoin.guilds || []) { - await Member.addToGuild(user.id, guild).catch((e) => - console.error("[Autojoin]", e), - ); + await Member.addToGuild(user.id, guild).catch((e) => console.error("[Autojoin]", e)); } } }); return user; } + + async getDmChannelWith(user_id: string) { + const qry = await Channel.getRepository() + .createQueryBuilder() + .leftJoinAndSelect("Channel.recipients", "rcp") + .where("Channel.type = :type", { type: ChannelType.DM }) + .andWhere("rcp.user_id IN (:...user_ids)", { user_ids: [this.id, user_id] }) + .groupBy("Channel.id") + .having("COUNT(rcp.user_id) = 2") + .getMany(); + + // Emma [it/its]@Rory&: is this technically a bug, or am I being too over-cautious? + if (qry.length > 1) { + console.warn(`[WARN] User(${this.id})#getDmChannel(${user_id}) returned multiple channels:`); + for (const channel of qry) { + console.warn(JSON.stringify(channel)); + } + } + + // throw if multiple + return qry.single((_) => true); + } } export const CUSTOM_USER_FLAG_OFFSET = BigInt(1) << BigInt(32);