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);
|