diff options
author | Emma [it/its]@Rory& <root@rory.gay> | 2023-12-11 01:12:54 +0100 |
---|---|---|
committer | Emma [it/its]@Rory& <root@rory.gay> | 2023-12-11 01:12:54 +0100 |
commit | 0a8ceb9e6349284e75545a01ffad608b020f78e2 (patch) | |
tree | 17a9163f963eddabf9168b0b630096b2f7535b64 /src/util | |
parent | Prettier: use editorconfig (diff) | |
download | server-0a8ceb9e6349284e75545a01ffad608b020f78e2.tar.xz |
Actually run prettier dev/emma-refactors
Diffstat (limited to 'src/util')
72 files changed, 436 insertions, 1338 deletions
diff --git a/src/util/config/Config.ts b/src/util/config/Config.ts index 90b98b7a..cc23b87b 100644 --- a/src/util/config/Config.ts +++ b/src/util/config/Config.ts @@ -59,6 +59,5 @@ export class ConfigValue { defaults: DefaultsConfiguration = new DefaultsConfiguration(); external: ExternalTokensConfiguration = new ExternalTokensConfiguration(); email: EmailConfiguration = new EmailConfiguration(); - passwordReset: PasswordResetConfiguration = - new PasswordResetConfiguration(); + passwordReset: PasswordResetConfiguration = new PasswordResetConfiguration(); } diff --git a/src/util/config/types/EmailConfiguration.ts b/src/util/config/types/EmailConfiguration.ts index ae9d53ba..3d1c01d2 100644 --- a/src/util/config/types/EmailConfiguration.ts +++ b/src/util/config/types/EmailConfiguration.ts @@ -16,11 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - MailGunConfiguration, - MailJetConfiguration, - SMTPConfiguration, -} from "./subconfigurations/email"; +import { MailGunConfiguration, MailJetConfiguration, SMTPConfiguration } from "./subconfigurations/email"; import { SendGridConfiguration } from "./subconfigurations/email/SendGrid"; export class EmailConfiguration { diff --git a/src/util/config/types/GeneralConfiguration.ts b/src/util/config/types/GeneralConfiguration.ts index cff8c527..1548b527 100644 --- a/src/util/config/types/GeneralConfiguration.ts +++ b/src/util/config/types/GeneralConfiguration.ts @@ -20,8 +20,7 @@ import { Snowflake } from "@spacebar/util"; export class GeneralConfiguration { instanceName: string = "Spacebar Instance"; - instanceDescription: string | null = - "This is a Spacebar instance made in the pre-release days"; + instanceDescription: string | null = "This is a Spacebar instance made in the pre-release days"; frontPage: string | null = null; tosPage: string | null = null; correspondenceEmail: string | null = null; diff --git a/src/util/config/types/LimitConfigurations.ts b/src/util/config/types/LimitConfigurations.ts index dfcb9765..a9f9c297 100644 --- a/src/util/config/types/LimitConfigurations.ts +++ b/src/util/config/types/LimitConfigurations.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - ChannelLimits, - GlobalRateLimits, - GuildLimits, - MessageLimits, - RateLimits, - UserLimits, -} from "."; +import { ChannelLimits, GlobalRateLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from "."; export class LimitsConfiguration { user: UserLimits = new UserLimits(); diff --git a/src/util/config/types/RegisterConfiguration.ts b/src/util/config/types/RegisterConfiguration.ts index 9d8e036e..5e9ff374 100644 --- a/src/util/config/types/RegisterConfiguration.ts +++ b/src/util/config/types/RegisterConfiguration.ts @@ -16,15 +16,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - DateOfBirthConfiguration, - PasswordConfiguration, - RegistrationEmailConfiguration, -} from "."; +import { DateOfBirthConfiguration, PasswordConfiguration, RegistrationEmailConfiguration } from "."; export class RegisterConfiguration { - email: RegistrationEmailConfiguration = - new RegistrationEmailConfiguration(); + email: RegistrationEmailConfiguration = new RegistrationEmailConfiguration(); dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration(); password: PasswordConfiguration = new PasswordConfiguration(); disabled: boolean = false; diff --git a/src/util/config/types/SecurityConfiguration.ts b/src/util/config/types/SecurityConfiguration.ts index 35776642..234abc2f 100644 --- a/src/util/config/types/SecurityConfiguration.ts +++ b/src/util/config/types/SecurityConfiguration.ts @@ -29,8 +29,7 @@ export class SecurityConfiguration { // X-Forwarded-For for nginx/reverse proxies // CF-Connecting-IP for cloudflare forwardedFor: string | null = null; - ipdataApiKey: string | null = - "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9"; + ipdataApiKey: string | null = "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9"; mfaBackupCodeCount: number = 10; statsWorldReadable: boolean = true; defaultRegistrationTokenExpiration: number = 1000 * 60 * 60 * 24 * 7; //1 week diff --git a/src/util/config/types/SentryConfiguration.ts b/src/util/config/types/SentryConfiguration.ts index 3d92c62a..70ff9aac 100644 --- a/src/util/config/types/SentryConfiguration.ts +++ b/src/util/config/types/SentryConfiguration.ts @@ -20,8 +20,7 @@ import { hostname } from "os"; export class SentryConfiguration { enabled: boolean = false; - endpoint: string = - "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6"; + endpoint: string = "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6"; traceSampleRate: number = 1.0; environment: string = hostname(); } diff --git a/src/util/connections/Connection.ts b/src/util/connections/Connection.ts index 5bdebd47..181234b7 100644 --- a/src/util/connections/Connection.ts +++ b/src/util/connections/Connection.ts @@ -42,8 +42,7 @@ export abstract class Connection { * @returns redirect_uri for this connection */ getRedirectUri() { - const endpointPublic = - Config.get().api.endpointPublic ?? "http://localhost:3001"; + const endpointPublic = Config.get().api.endpointPublic ?? "http://localhost:3001"; return `${endpointPublic}/connections/${this.id}/callback`; } @@ -51,9 +50,7 @@ export abstract class Connection { * Processes the callback * @param args Callback arguments */ - abstract handleCallback( - params: ConnectionCallbackSchema, - ): Promise<ConnectedAccount | null>; + abstract handleCallback(params: ConnectionCallbackSchema): Promise<ConnectedAccount | null>; /** * Gets a user id from state @@ -91,9 +88,7 @@ export abstract class Connection { * @param data connected account data * @returns the new connected account */ - async createConnection( - data: ConnectedAccountSchema, - ): Promise<ConnectedAccount> { + async createConnection(data: ConnectedAccountSchema): Promise<ConnectedAccount> { const ca = ConnectedAccount.create({ ...data }); await ca.save(); return ca; diff --git a/src/util/connections/ConnectionConfig.ts b/src/util/connections/ConnectionConfig.ts index 5a2239a0..0610b43e 100644 --- a/src/util/connections/ConnectionConfig.ts +++ b/src/util/connections/ConnectionConfig.ts @@ -49,11 +49,7 @@ export const ConnectionConfig = { function applyConfig(val: any) { async function apply(obj: any, key = ""): Promise<any> { if (typeof obj === "object" && obj !== null && !(obj instanceof Date)) - return Promise.all( - Object.keys(obj).map((k) => - apply(obj[k], key ? `${key}_${k}` : k), - ), - ); + return Promise.all(Object.keys(obj).map((k) => apply(obj[k], key ? `${key}_${k}` : k))); let pair = pairs.find((x) => x.key === key); if (!pair) pair = new ConnectionConfigEntity(); @@ -83,8 +79,7 @@ function pairsToConfig(pairs: ConnectionConfigEntity[]) { let i = 0; for (const key of keys) { - if (!isNaN(Number(key)) && !prevObj[prev]?.length) - prevObj[prev] = obj = []; + if (!isNaN(Number(key)) && !prevObj[prev]?.length) prevObj[prev] = obj = []; if (i++ === keys.length - 1) obj[key] = p.value; else if (!obj[key]) obj[key] = {}; diff --git a/src/util/connections/ConnectionLoader.ts b/src/util/connections/ConnectionLoader.ts index e9dc6973..9507d5f6 100644 --- a/src/util/connections/ConnectionLoader.ts +++ b/src/util/connections/ConnectionLoader.ts @@ -67,18 +67,11 @@ export class ConnectionLoader { return cfg; } - public static async setConnectionConfig( - id: string, - config: Partial<unknown>, - ): Promise<void> { - if (!config) - console.warn(`[Connections/WARN] ${id} tried to set config=null!`); + public static async setConnectionConfig(id: string, config: Partial<unknown>): Promise<void> { + if (!config) console.warn(`[Connections/WARN] ${id} tried to set config=null!`); await ConnectionConfig.set({ - [id]: Object.assign( - config, - ConnectionLoader.getConnectionConfig(id) || {}, - ), + [id]: Object.assign(config, ConnectionLoader.getConnectionConfig(id) || {}), }); } } diff --git a/src/util/connections/ConnectionStore.ts b/src/util/connections/ConnectionStore.ts index 95e54fd9..0cc4dc31 100644 --- a/src/util/connections/ConnectionStore.ts +++ b/src/util/connections/ConnectionStore.ts @@ -20,6 +20,5 @@ import { Connection } from "./Connection"; import { RefreshableConnection } from "./RefreshableConnection"; export class ConnectionStore { - public static connections: Map<string, Connection | RefreshableConnection> = - new Map(); + public static connections: Map<string, Connection | RefreshableConnection> = new Map(); } diff --git a/src/util/connections/RefreshableConnection.ts b/src/util/connections/RefreshableConnection.ts index 88ad8dab..08b01c68 100644 --- a/src/util/connections/RefreshableConnection.ts +++ b/src/util/connections/RefreshableConnection.ts @@ -30,17 +30,13 @@ export abstract class RefreshableConnection extends Connection { * Refreshes the token for a connected account. * @param connectedAccount The connected account to refresh */ - abstract refreshToken( - connectedAccount: ConnectedAccount, - ): Promise<ConnectedAccountCommonOAuthTokenResponse>; + abstract refreshToken(connectedAccount: ConnectedAccount): Promise<ConnectedAccountCommonOAuthTokenResponse>; /** * Refreshes the token for a connected account and saves it to the database. * @param connectedAccount The connected account to refresh */ - async refresh( - connectedAccount: ConnectedAccount, - ): Promise<ConnectedAccountCommonOAuthTokenResponse> { + async refresh(connectedAccount: ConnectedAccount): Promise<ConnectedAccountCommonOAuthTokenResponse> { const tokenData = await this.refreshToken(connectedAccount); connectedAccount.token_data = { ...tokenData, fetched_at: Date.now() }; await connectedAccount.save(); diff --git a/src/util/dtos/ConnectedAccountDTO.ts b/src/util/dtos/ConnectedAccountDTO.ts index f9efd980..043c1e73 100644 --- a/src/util/dtos/ConnectedAccountDTO.ts +++ b/src/util/dtos/ConnectedAccountDTO.ts @@ -34,16 +34,11 @@ export class ConnectedAccountDTO { metadata_visibility?: number; two_way_link?: boolean; - constructor( - connectedAccount: ConnectedAccount, - with_token: boolean = false, - ) { + constructor(connectedAccount: ConnectedAccount, with_token: boolean = false) { this.id = connectedAccount.external_id; this.user_id = connectedAccount.user_id; this.access_token = - connectedAccount.token_data && with_token - ? connectedAccount.token_data.access_token - : undefined; + connectedAccount.token_data && with_token ? connectedAccount.token_data.access_token : undefined; this.friend_sync = connectedAccount.friend_sync; this.name = connectedAccount.name; this.revoked = connectedAccount.revoked; @@ -53,9 +48,7 @@ export class ConnectedAccountDTO { this.visibility = +(connectedAccount.visibility || false); this.integrations = connectedAccount.integrations; this.metadata_ = connectedAccount.metadata_; - this.metadata_visibility = +( - connectedAccount.metadata_visibility || false - ); + this.metadata_visibility = +(connectedAccount.metadata_visibility || false); this.two_way_link = connectedAccount.two_way_link; } } diff --git a/src/util/dtos/DmChannelDTO.ts b/src/util/dtos/DmChannelDTO.ts index 8427f7f9..26829d58 100644 --- a/src/util/dtos/DmChannelDTO.ts +++ b/src/util/dtos/DmChannelDTO.ts @@ -29,11 +29,7 @@ export class DmChannelDTO { recipients: MinimalPublicUserDTO[]; type: number; - static async from( - channel: Channel, - excluded_recipients: string[] = [], - origin_channel_id?: string, - ) { + static async from(channel: Channel, excluded_recipients: string[] = [], origin_channel_id?: string) { const obj = new DmChannelDTO(); obj.icon = channel.icon || null; obj.id = channel.id; @@ -51,7 +47,7 @@ export class DmChannelDTO { where: { id: r.user_id }, select: PublicUserProjection, }); - }) || [], + }) || [] ) ).map((u) => new MinimalPublicUserDTO(u)); return obj; @@ -60,9 +56,7 @@ export class DmChannelDTO { excludedRecipients(excluded_recipients: string[]): DmChannelDTO { return { ...this, - recipients: this.recipients.filter( - (r) => !excluded_recipients.includes(r.id), - ), + recipients: this.recipients.filter((r) => !excluded_recipients.includes(r.id)), }; } } diff --git a/src/util/dtos/ReadyGuildDTO.ts b/src/util/dtos/ReadyGuildDTO.ts index 061959a6..a0f291dd 100644 --- a/src/util/dtos/ReadyGuildDTO.ts +++ b/src/util/dtos/ReadyGuildDTO.ts @@ -30,10 +30,7 @@ import { } from "../entities"; // TODO: this is not the best place for this type -export type ReadyUserGuildSettingsEntries = Omit< - UserGuildSettings, - "channel_overrides" -> & { +export type ReadyUserGuildSettingsEntries = Omit<UserGuildSettings, "channel_overrides"> & { channel_overrides: (ChannelOverride & { channel_id: string })[]; }; @@ -51,9 +48,7 @@ export type GuildOrUnavailable = | { id: string; unavailable: boolean } | (Guild & { joined_at?: Date; unavailable: undefined }); -const guildIsAvailable = ( - guild: GuildOrUnavailable, -): guild is Guild & { joined_at: Date; unavailable: false } => { +const guildIsAvailable = (guild: GuildOrUnavailable): guild is Guild & { joined_at: Date; unavailable: false } => { return guild.unavailable != true; }; diff --git a/src/util/entities/Attachment.ts b/src/util/entities/Attachment.ts index d60ac41c..946318dd 100644 --- a/src/util/entities/Attachment.ts +++ b/src/util/entities/Attachment.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - BeforeRemove, - Column, - Entity, - JoinColumn, - ManyToOne, - RelationId, -} from "typeorm"; +import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { URL } from "url"; import { deleteFile } from "../util/cdn"; import { BaseClass } from "./BaseClass"; @@ -56,13 +49,9 @@ export class Attachment extends BaseClass { message_id: string; @JoinColumn({ name: "message_id" }) - @ManyToOne( - () => require("./Message").Message, - (message: import("./Message").Message) => message.attachments, - { - onDelete: "CASCADE", - }, - ) + @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, { + onDelete: "CASCADE", + }) message: import("./Message").Message; @BeforeRemove() diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts index f4b3cf59..2c19d197 100644 --- a/src/util/entities/BaseClass.ts +++ b/src/util/entities/BaseClass.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - BaseEntity, - BeforeInsert, - BeforeUpdate, - FindOptionsWhere, - ObjectIdColumn, - PrimaryColumn, -} from "typeorm"; +import { BaseEntity, BeforeInsert, BeforeUpdate, FindOptionsWhere, ObjectIdColumn, PrimaryColumn } from "typeorm"; import { Snowflake } from "../util/Snowflake"; import { getDatabase } from "../util/Database"; import { OrmUtils } from "../imports/OrmUtils"; @@ -57,15 +50,15 @@ export class BaseClassWithoutId extends BaseEntity { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore this[x.propertyName], - ]), - ), + ]) + ) ); } static increment<T extends BaseClass>( conditions: FindOptionsWhere<T>, propertyPath: string, - value: number | string, + value: number | string ) { const repository = this.getRepository(); return repository.increment(conditions, propertyPath, value); @@ -74,16 +67,14 @@ export class BaseClassWithoutId extends BaseEntity { static decrement<T extends BaseClass>( conditions: FindOptionsWhere<T>, propertyPath: string, - value: number | string, + value: number | string ) { const repository = this.getRepository(); return repository.decrement(conditions, propertyPath, value); } } -export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb") - ? ObjectIdColumn - : PrimaryColumn; +export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryColumn; export class BaseClass extends BaseClassWithoutId { @PrimaryIdColumn() diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index 169eab3d..6672d03d 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -17,24 +17,10 @@ */ import { HTTPError } from "lambert-server"; -import { - Column, - Entity, - JoinColumn, - ManyToOne, - OneToMany, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { DmChannelDTO } from "../dtos"; import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces"; -import { - InvisibleCharacters, - Snowflake, - containsAll, - emitEvent, - getPermission, - trimSpecial, -} from "../util"; +import { InvisibleCharacters, Snowflake, containsAll, emitEvent, getPermission, trimSpecial } from "../util"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { Invite } from "./Invite"; @@ -162,14 +148,10 @@ export class Channel extends BaseClass { }) messages?: Message[]; - @OneToMany( - () => VoiceState, - (voice_state: VoiceState) => voice_state.channel, - { - cascade: true, - orphanedRowAction: "delete", - }, - ) + @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { + cascade: true, + orphanedRowAction: "delete", + }) voice_states?: VoiceState[]; @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { @@ -203,7 +185,7 @@ export class Channel extends BaseClass { skipPermissionCheck?: boolean; skipEventEmit?: boolean; skipNameChecks?: boolean; - }, + } ) { if (!opts?.skipPermissionCheck) { // Always check if user has permission first @@ -221,48 +203,26 @@ export class Channel extends BaseClass { }); if (!opts?.skipNameChecks) { - if ( - !guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && - channel.name - ) { + if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) { for (const character of InvisibleCharacters) if (channel.name.includes(character)) - throw new HTTPError( - "Channel name cannot include invalid characters", - 403, - ); + throw new HTTPError("Channel name cannot include invalid characters", 403); // Categories skip these checks on discord.com - if ( - channel.type !== ChannelType.GUILD_CATEGORY || - guild.features.includes("IRC_LIKE_CATEGORY_NAMES") - ) { + if (channel.type !== ChannelType.GUILD_CATEGORY || guild.features.includes("IRC_LIKE_CATEGORY_NAMES")) { if (channel.name.includes(" ")) - throw new HTTPError( - "Channel name cannot include invalid characters", - 403, - ); + throw new HTTPError("Channel name cannot include invalid characters", 403); if (channel.name.match(/--+/g)) - throw new HTTPError( - "Channel name cannot include multiple adjacent dashes.", - 403, - ); - - if ( - channel.name.charAt(0) === "-" || - channel.name.charAt(channel.name.length - 1) === "-" - ) - throw new HTTPError( - "Channel name cannot start/end with dash.", - 403, - ); + throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403); + + if (channel.name.charAt(0) === "-" || channel.name.charAt(channel.name.length - 1) === "-") + throw new HTTPError("Channel name cannot start/end with dash.", 403); } else channel.name = channel.name.trim(); //category names are trimmed client side on discord.com } if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) { - if (!channel.name) - throw new HTTPError("Channel name cannot be empty.", 403); + if (!channel.name) throw new HTTPError("Channel name cannot be empty.", 403); } } @@ -274,15 +234,9 @@ export class Channel extends BaseClass { const exists = await Channel.findOneOrFail({ where: { id: channel.parent_id }, }); - if (!exists) - throw new HTTPError( - "Parent id channel doesn't exist", - 400, - ); + if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400); if (exists.guild_id !== channel.guild_id) - throw new HTTPError( - "The category channel needs to be in the guild", - ); + throw new HTTPError("The category channel needs to be in the guild"); } break; case ChannelType.GUILD_CATEGORY: @@ -299,9 +253,7 @@ export class Channel extends BaseClass { if (!channel.permission_overwrites) channel.permission_overwrites = []; // TODO: eagerly auto generate position of all guild channels - const position = - (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || - 0; + const position = (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || 0; channel = { ...channel, @@ -327,11 +279,7 @@ export class Channel extends BaseClass { return ret; } - static async createDMChannel( - recipients: string[], - creator_user_id: string, - name?: string, - ) { + static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { recipients = recipients.unique().filter((x) => x !== creator_user_id); // TODO: check config for max number of recipients /** if you want to disallow note to self channels, uncomment the conditional below @@ -342,8 +290,7 @@ export class Channel extends BaseClass { } **/ - const type = - recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM; + const type = recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM; let channel = null; @@ -379,11 +326,8 @@ export class Channel extends BaseClass { recipients: channelRecipients.map((x) => Recipient.create({ user_id: x, - closed: !( - type === ChannelType.GROUP_DM || - x === creator_user_id - ), - }), + closed: !(type === ChannelType.GROUP_DM || x === creator_user_id), + }) ), nsfw: false, }).save(); @@ -413,9 +357,7 @@ export class Channel extends BaseClass { static async removeRecipientFromChannel(channel: Channel, user_id: string) { await Recipient.delete({ channel_id: channel.id, user_id: user_id }); - channel.recipients = channel.recipients?.filter( - (r) => r.user_id !== user_id, - ); + channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id); if (channel.recipients?.length === 0) { await Channel.deleteChannel(channel); @@ -464,11 +406,7 @@ export class Channel extends BaseClass { await Channel.delete({ id: channel.id }); } - static async calculatePosition( - channel_id: string, - guild_id: string, - guild?: Guild, - ) { + static async calculatePosition(channel_id: string, guild_id: string, guild?: Guild) { if (!guild) guild = await Guild.findOneOrFail({ where: { id: guild_id }, @@ -486,9 +424,7 @@ export class Channel extends BaseClass { }); const channels = await Promise.all( - guild.channel_ordering.map((id) => - Channel.findOneOrFail({ where: { id } }), - ), + guild.channel_ordering.map((id) => Channel.findOneOrFail({ where: { id } })) ); return channels.reduce((r, v) => { @@ -499,9 +435,7 @@ export class Channel extends BaseClass { } isDm() { - return ( - this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM - ); + return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM; } // Does the channel support sending messages ( eg categories do not ) diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts index 6e089de1..4af72c14 100644 --- a/src/util/entities/ConnectedAccount.ts +++ b/src/util/entities/ConnectedAccount.ts @@ -21,10 +21,7 @@ import { ConnectedAccountTokenData } from "../interfaces"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; -export type PublicConnectedAccount = Pick< - ConnectedAccount, - "name" | "type" | "verified" ->; +export type PublicConnectedAccount = Pick<ConnectedAccount, "name" | "type" | "verified">; @Entity("connected_accounts") export class ConnectedAccount extends BaseClass { diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts index fcd6b729..1041e3cc 100644 --- a/src/util/entities/Guild.ts +++ b/src/util/entities/Guild.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - JoinColumn, - ManyToOne, - OneToMany, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { Config, GuildWelcomeScreen, Snowflake, handleFile } from ".."; import { Ban } from "./Ban"; import { BaseClass } from "./BaseClass"; @@ -330,15 +323,12 @@ export class Guild extends BaseClass { channel_ordering: [], afk_timeout: Config.get().defaults.guild.afkTimeout, - default_message_notifications: - Config.get().defaults.guild.defaultMessageNotifications, - explicit_content_filter: - Config.get().defaults.guild.explicitContentFilter, + default_message_notifications: Config.get().defaults.guild.defaultMessageNotifications, + explicit_content_filter: Config.get().defaults.guild.explicitContentFilter, features: Config.get().guild.defaultFeatures, max_members: Config.get().limits.guild.maxMembers, max_presences: Config.get().defaults.guild.maxPresences, - max_video_channel_users: - Config.get().defaults.guild.maxVideoChannelUsers, + max_video_channel_users: Config.get().defaults.guild.maxVideoChannelUsers, region: Config.get().regions.default, }).save(); @@ -361,9 +351,7 @@ export class Guild extends BaseClass { }).save(); if (!body.channels || !body.channels.length) - body.channels = [ - { id: "01", type: 0, name: "general", nsfw: false }, - ]; + body.channels = [{ id: "01", type: 0, name: "general", nsfw: false }]; const ids = new Map(); @@ -373,30 +361,19 @@ export class Guild extends BaseClass { } }); - for (const channel of body.channels.sort((a) => - a.parent_id ? 1 : -1, - )) { + for (const channel of body.channels.sort((a) => (a.parent_id ? 1 : -1))) { const id = ids.get(channel.id) || Snowflake.generate(); const parent_id = ids.get(channel.parent_id); - const saved = await Channel.createChannel( - { ...channel, guild_id, id, parent_id }, - body.owner_id, - { - keepId: true, - skipExistsCheck: true, - skipPermissionCheck: true, - skipEventEmit: true, - }, - ); - - await Guild.insertChannelInOrder( - guild.id, - saved.id, - parent_id ?? channel.position ?? 0, - guild, - ); + const saved = await Channel.createChannel({ ...channel, guild_id, id, parent_id }, body.owner_id, { + keepId: true, + skipExistsCheck: true, + skipPermissionCheck: true, + skipEventEmit: true, + }); + + await Guild.insertChannelInOrder(guild.id, saved.id, parent_id ?? channel.position ?? 0, guild); } return guild; @@ -407,25 +384,25 @@ export class Guild extends BaseClass { guild_id: string, channel_id: string, position: number, - guild?: Guild, + guild?: Guild ): Promise<number>; static async insertChannelInOrder( guild_id: string, channel_id: string, parent_id: string, - guild?: Guild, + guild?: Guild ): Promise<number>; static async insertChannelInOrder( guild_id: string, channel_id: string, insertPoint: string | number, - guild?: Guild, + guild?: Guild ): Promise<number>; static async insertChannelInOrder( guild_id: string, channel_id: string, insertPoint: string | number, - guild?: Guild, + guild?: Guild ): Promise<number> { if (!guild) guild = await Guild.findOneOrFail({ @@ -434,17 +411,13 @@ export class Guild extends BaseClass { }); let position; - if (typeof insertPoint == "string") - position = guild.channel_ordering.indexOf(insertPoint) + 1; + if (typeof insertPoint == "string") position = guild.channel_ordering.indexOf(insertPoint) + 1; else position = insertPoint; guild.channel_ordering.remove(channel_id); guild.channel_ordering.splice(position, 0, channel_id); - await Guild.update( - { id: guild_id }, - { channel_ordering: guild.channel_ordering }, - ); + await Guild.update({ id: guild_id }, { channel_ordering: guild.channel_ordering }); return position; } diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts index f7e54fbe..7670a802 100644 --- a/src/util/entities/Invite.ts +++ b/src/util/entities/Invite.ts @@ -99,8 +99,7 @@ export class Invite extends BaseClassWithoutId { static async joinGuild(user_id: string, code: string) { const invite = await Invite.findOneOrFail({ where: { code } }); - if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) - await Invite.delete({ code }); + if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code }); else await invite.save(); await Member.addToGuild(user_id, invite.guild_id); diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index 65942816..275e748f 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -181,8 +181,7 @@ export class Member extends BaseClassWithoutId { select: ["owner_id"], where: { id: guild_id }, }); - if (guild.owner_id === user_id) - throw new Error("The owner cannot be removed of the guild"); + if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild"); const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"], @@ -244,11 +243,7 @@ export class Member extends BaseClassWithoutId { ]); } - static async removeRole( - user_id: string, - guild_id: string, - role_id: string, - ) { + static async removeRole(user_id: string, guild_id: string, role_id: string) { const [member] = await Promise.all([ Member.findOneOrFail({ where: { id: user_id, guild_id }, @@ -278,11 +273,7 @@ export class Member extends BaseClassWithoutId { ]); } - static async changeNickname( - user_id: string, - guild_id: string, - nickname: string, - ) { + static async changeNickname(user_id: string, guild_id: string, nickname: string) { const member = await Member.findOneOrFail({ where: { id: user_id, @@ -316,10 +307,7 @@ export class Member extends BaseClassWithoutId { const { maxGuilds } = Config.get().limits.user; const guild_count = await Member.count({ where: { id: user_id } }); if (guild_count >= maxGuilds) { - throw new HTTPError( - `You are at the ${maxGuilds} server limit.`, - 403, - ); + throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403); } const guild = await Guild.findOneOrFail({ diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts index b519099a..b56f719e 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts @@ -161,14 +161,10 @@ export class Message extends BaseClass { @ManyToMany(() => Sticker, { cascade: true, onDelete: "CASCADE" }) sticker_items?: Sticker[]; - @OneToMany( - () => Attachment, - (attachment: Attachment) => attachment.message, - { - cascade: true, - orphanedRowAction: "delete", - }, - ) + @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { + cascade: true, + orphanedRowAction: "delete", + }) attachments?: Attachment[]; @Column({ type: "simple-json" }) diff --git a/src/util/entities/Migration.ts b/src/util/entities/Migration.ts index 5c4e951d..8f2fa190 100644 --- a/src/util/entities/Migration.ts +++ b/src/util/entities/Migration.ts @@ -16,17 +16,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - ObjectIdColumn, - PrimaryGeneratedColumn, - BaseEntity, -} from "typeorm"; +import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn, BaseEntity } from "typeorm"; -export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith( - "mongodb", -) +export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryGeneratedColumn; diff --git a/src/util/entities/ReadState.ts b/src/util/entities/ReadState.ts index 1b280d12..7add44a2 100644 --- a/src/util/entities/ReadState.ts +++ b/src/util/entities/ReadState.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - Index, - JoinColumn, - ManyToOne, - RelationId, -} from "typeorm"; +import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { User } from "./User"; diff --git a/src/util/entities/Relationship.ts b/src/util/entities/Relationship.ts index 740095c2..fe40c782 100644 --- a/src/util/entities/Relationship.ts +++ b/src/util/entities/Relationship.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - Index, - JoinColumn, - ManyToOne, - RelationId, -} from "typeorm"; +import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts index 61ab1287..85a9fa77 100644 --- a/src/util/entities/StickerPack.ts +++ b/src/util/entities/StickerPack.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - JoinColumn, - ManyToOne, - OneToMany, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { Sticker } from "."; import { BaseClass } from "./BaseClass"; diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts index 7bedc4af..abf68ee6 100644 --- a/src/util/entities/Team.ts +++ b/src/util/entities/Team.ts @@ -16,14 +16,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ -import { - Column, - Entity, - JoinColumn, - ManyToOne, - OneToMany, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { TeamMember } from "./TeamMember"; import { User } from "./User"; diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts index 539da957..5e88e6a4 100644 --- a/src/util/entities/TeamMember.ts +++ b/src/util/entities/TeamMember.ts @@ -38,13 +38,9 @@ export class TeamMember extends BaseClass { team_id: string; @JoinColumn({ name: "team_id" }) - @ManyToOne( - () => require("./Team").Team, - (team: import("./Team").Team) => team.members, - { - onDelete: "CASCADE", - }, - ) + @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, { + onDelete: "CASCADE", + }) team: import("./Team").Team; @Column({ nullable: true }) diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index c6582b00..45a7015c 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -17,14 +17,7 @@ */ import { Request } from "express"; -import { - Column, - Entity, - FindOneOptions, - JoinColumn, - OneToMany, - OneToOne, -} from "typeorm"; +import { Column, Entity, FindOneOptions, JoinColumn, OneToMany, OneToOne } from "typeorm"; import { Config, Email, FieldErrors, Snowflake, trimSpecial } from ".."; import { BitField } from "../util/BitField"; import { BaseClass } from "./BaseClass"; @@ -70,7 +63,7 @@ export enum PrivateUserEnum { export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys; export const PublicUserProjection = Object.values(PublicUserEnum).filter( - (x) => typeof x === "string", + (x) => typeof x === "string" ) as PublicUserKeys[]; export const PrivateUserProjection = [ ...PublicUserProjection, @@ -186,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 }) @@ -281,9 +266,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 @@ -292,10 +275,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) { @@ -309,9 +289,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"], @@ -346,8 +324,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") || "", }, }); } @@ -355,8 +332,7 @@ export class User extends BaseClass { // TODO: save date_of_birth // appearently 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, @@ -374,9 +350,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, @@ -390,18 +364,14 @@ 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)); } } }); diff --git a/src/util/imports/OrmUtils.ts b/src/util/imports/OrmUtils.ts index 039c81fe..3a11be24 100644 --- a/src/util/imports/OrmUtils.ts +++ b/src/util/imports/OrmUtils.ts @@ -12,12 +12,7 @@ export class OrmUtils { return !item.constructor || item.constructor === Object; } - private static mergeArrayKey( - target: any, - key: number, - value: any, - memo: Map<any, any>, - ) { + 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); @@ -46,12 +41,7 @@ export class OrmUtils { memo.delete(value); } - private static mergeObjectKey( - target: any, - key: string, - value: any, - memo: Map<any, any>, - ) { + 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) }); @@ -80,11 +70,7 @@ export class OrmUtils { memo.delete(value); } - private static merge( - target: any, - source: any, - memo: Map<any, any> = new Map(), - ): any { + 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); diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts index deb54428..ca6fac6d 100644 --- a/src/util/interfaces/Event.ts +++ b/src/util/interfaces/Event.ts @@ -94,7 +94,7 @@ export interface ReadyEventData { number, [[number, { e: number; s: number }[]]], [number, [[number, [number, number]]]], - { b: number; k: bigint[] }[], + { b: number; k: bigint[] }[] ][]; guild_join_requests?: unknown[]; // ? what is this? this is new shard?: [number, number]; diff --git a/src/util/migration/mariadb/1673609465036-templateDeleteCascade.ts b/src/util/migration/mariadb/1673609465036-templateDeleteCascade.ts index 483c5070..bfd1344b 100644 --- a/src/util/migration/mariadb/1673609465036-templateDeleteCascade.ts +++ b/src/util/migration/mariadb/1673609465036-templateDeleteCascade.ts @@ -22,20 +22,16 @@ export class templateDeleteCascade1673609465036 implements MigrationInterface { name = "templateDeleteCascade1673609465036"; public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``); await queryRunner.query( - `ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``, - ); - await queryRunner.query( - `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``); await queryRunner.query( - `ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``, - ); - await queryRunner.query( - `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, + `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION` ); } } diff --git a/src/util/migration/mariadb/1675045120206-webauthn.ts b/src/util/migration/mariadb/1675045120206-webauthn.ts index d58ac88d..f20060af 100644 --- a/src/util/migration/mariadb/1675045120206-webauthn.ts +++ b/src/util/migration/mariadb/1675045120206-webauthn.ts @@ -23,23 +23,17 @@ export class webauthn1675045120206 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query( - `CREATE TABLE \`security_keys\` (\`id\` varchar(255) NOT NULL, \`user_id\` varchar(255) NULL, \`key_id\` varchar(255) NOT NULL, \`public_key\` varchar(255) NOT NULL, \`counter\` int NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + `CREATE TABLE \`security_keys\` (\`id\` varchar(255) NOT NULL, \`user_id\` varchar(255) NULL, \`key_id\` varchar(255) NOT NULL, \`public_key\` varchar(255) NOT NULL, \`counter\` int NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB` ); + await queryRunner.query(`ALTER TABLE \`users\` ADD \`webauthn_enabled\` tinyint NOT NULL DEFAULT 0`); await queryRunner.query( - `ALTER TABLE \`users\` ADD \`webauthn_enabled\` tinyint NOT NULL DEFAULT 0`, - ); - await queryRunner.query( - `ALTER TABLE \`security_keys\` ADD CONSTRAINT \`FK_24c97d0771cafedce6d7163eaad\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE \`security_keys\` ADD CONSTRAINT \`FK_24c97d0771cafedce6d7163eaad\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { - await queryRunner.query( - `ALTER TABLE \`security_keys\` DROP FOREIGN KEY \`FK_24c97d0771cafedce6d7163eaad\``, - ); - await queryRunner.query( - `ALTER TABLE \`users\` DROP COLUMN \`webauthn_enabled\``, - ); + await queryRunner.query(`ALTER TABLE \`security_keys\` DROP FOREIGN KEY \`FK_24c97d0771cafedce6d7163eaad\``); + await queryRunner.query(`ALTER TABLE \`users\` DROP COLUMN \`webauthn_enabled\``); await queryRunner.query(`DROP TABLE \`security_keys\``); } } diff --git a/src/util/migration/mariadb/1696420827239-guildChannelOrdering.ts b/src/util/migration/mariadb/1696420827239-guildChannelOrdering.ts index 083f3680..960feb9b 100644 --- a/src/util/migration/mariadb/1696420827239-guildChannelOrdering.ts +++ b/src/util/migration/mariadb/1696420827239-guildChannelOrdering.ts @@ -4,31 +4,21 @@ 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, - ); + const guilds = await queryRunner.query(`SELECT id FROM guilds`, undefined, true); - await queryRunner.query( - `ALTER TABLE guilds ADD channel_ordering text NOT NULL DEFAULT '[]'`, - ); + await queryRunner.query(`ALTER TABLE guilds ADD channel_ordering 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, - ) + 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 channel_ordering = ? WHERE id = ?`, - [JSON.stringify(channels.map((x) => x.id)), guild_id], - ); + await queryRunner.query(`UPDATE guilds SET channel_ordering = ? WHERE id = ?`, [ + JSON.stringify(channels.map((x) => x.id)), + guild_id, + ]); } await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`); diff --git a/src/util/migration/mysql/1673609465036-templateDeleteCascade.ts b/src/util/migration/mysql/1673609465036-templateDeleteCascade.ts index 483c5070..bfd1344b 100644 --- a/src/util/migration/mysql/1673609465036-templateDeleteCascade.ts +++ b/src/util/migration/mysql/1673609465036-templateDeleteCascade.ts @@ -22,20 +22,16 @@ export class templateDeleteCascade1673609465036 implements MigrationInterface { name = "templateDeleteCascade1673609465036"; public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``); await queryRunner.query( - `ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``, - ); - await queryRunner.query( - `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``); await queryRunner.query( - `ALTER TABLE \`templates\` DROP FOREIGN KEY \`FK_445d00eaaea0e60a017a5ed0c11\``, - ); - await queryRunner.query( - `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, + `ALTER TABLE \`templates\` ADD CONSTRAINT \`FK_445d00eaaea0e60a017a5ed0c11\` FOREIGN KEY (\`source_guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION` ); } } diff --git a/src/util/migration/mysql/1675045120206-webauthn.ts b/src/util/migration/mysql/1675045120206-webauthn.ts index d58ac88d..f20060af 100644 --- a/src/util/migration/mysql/1675045120206-webauthn.ts +++ b/src/util/migration/mysql/1675045120206-webauthn.ts @@ -23,23 +23,17 @@ export class webauthn1675045120206 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query( - `CREATE TABLE \`security_keys\` (\`id\` varchar(255) NOT NULL, \`user_id\` varchar(255) NULL, \`key_id\` varchar(255) NOT NULL, \`public_key\` varchar(255) NOT NULL, \`counter\` int NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + `CREATE TABLE \`security_keys\` (\`id\` varchar(255) NOT NULL, \`user_id\` varchar(255) NULL, \`key_id\` varchar(255) NOT NULL, \`public_key\` varchar(255) NOT NULL, \`counter\` int NOT NULL, \`name\` varchar(255) NOT NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB` ); + await queryRunner.query(`ALTER TABLE \`users\` ADD \`webauthn_enabled\` tinyint NOT NULL DEFAULT 0`); await queryRunner.query( - `ALTER TABLE \`users\` ADD \`webauthn_enabled\` tinyint NOT NULL DEFAULT 0`, - ); - await queryRunner.query( - `ALTER TABLE \`security_keys\` ADD CONSTRAINT \`FK_24c97d0771cafedce6d7163eaad\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE \`security_keys\` ADD CONSTRAINT \`FK_24c97d0771cafedce6d7163eaad\` FOREIGN KEY (\`user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { - await queryRunner.query( - `ALTER TABLE \`security_keys\` DROP FOREIGN KEY \`FK_24c97d0771cafedce6d7163eaad\``, - ); - await queryRunner.query( - `ALTER TABLE \`users\` DROP COLUMN \`webauthn_enabled\``, - ); + await queryRunner.query(`ALTER TABLE \`security_keys\` DROP FOREIGN KEY \`FK_24c97d0771cafedce6d7163eaad\``); + await queryRunner.query(`ALTER TABLE \`users\` DROP COLUMN \`webauthn_enabled\``); await queryRunner.query(`DROP TABLE \`security_keys\``); } } diff --git a/src/util/migration/mysql/1696420827239-guildChannelOrdering.ts b/src/util/migration/mysql/1696420827239-guildChannelOrdering.ts index 083f3680..960feb9b 100644 --- a/src/util/migration/mysql/1696420827239-guildChannelOrdering.ts +++ b/src/util/migration/mysql/1696420827239-guildChannelOrdering.ts @@ -4,31 +4,21 @@ 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, - ); + const guilds = await queryRunner.query(`SELECT id FROM guilds`, undefined, true); - await queryRunner.query( - `ALTER TABLE guilds ADD channel_ordering text NOT NULL DEFAULT '[]'`, - ); + await queryRunner.query(`ALTER TABLE guilds ADD channel_ordering 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, - ) + 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 channel_ordering = ? WHERE id = ?`, - [JSON.stringify(channels.map((x) => x.id)), guild_id], - ); + await queryRunner.query(`UPDATE guilds SET channel_ordering = ? WHERE id = ?`, [ + JSON.stringify(channels.map((x) => x.id)), + guild_id, + ]); } await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`); diff --git a/src/util/migration/postgres/1673609867556-templateDeleteCascade.ts b/src/util/migration/postgres/1673609867556-templateDeleteCascade.ts index 504ed557..33c72dea 100644 --- a/src/util/migration/postgres/1673609867556-templateDeleteCascade.ts +++ b/src/util/migration/postgres/1673609867556-templateDeleteCascade.ts @@ -22,20 +22,16 @@ export class templateDeleteCascade1673609867556 implements MigrationInterface { name = "templateDeleteCascade1673609867556"; public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "templates" DROP CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11"`); await queryRunner.query( - `ALTER TABLE "templates" DROP CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11"`, - ); - await queryRunner.query( - `ALTER TABLE "templates" ADD CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "templates" ADD CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "templates" DROP CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11"`); await queryRunner.query( - `ALTER TABLE "templates" DROP CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11"`, - ); - await queryRunner.query( - `ALTER TABLE "templates" ADD CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + `ALTER TABLE "templates" ADD CONSTRAINT "FK_445d00eaaea0e60a017a5ed0c11" FOREIGN KEY ("source_guild_id") REFERENCES "guilds"("id") ON DELETE NO ACTION ON UPDATE NO ACTION` ); } } diff --git a/src/util/migration/postgres/1675044825710-webauthn.ts b/src/util/migration/postgres/1675044825710-webauthn.ts index 4b32d6c7..749ff90a 100644 --- a/src/util/migration/postgres/1675044825710-webauthn.ts +++ b/src/util/migration/postgres/1675044825710-webauthn.ts @@ -23,23 +23,17 @@ export class webauthn1675044825710 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query( - `CREATE TABLE "security_keys" ("id" character varying NOT NULL, "user_id" character varying, "key_id" character varying NOT NULL, "public_key" character varying NOT NULL, "counter" integer NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_6e95cdd91779e7cca06d1fff89c" PRIMARY KEY ("id"))`, + `CREATE TABLE "security_keys" ("id" character varying NOT NULL, "user_id" character varying, "key_id" character varying NOT NULL, "public_key" character varying NOT NULL, "counter" integer NOT NULL, "name" character varying NOT NULL, CONSTRAINT "PK_6e95cdd91779e7cca06d1fff89c" PRIMARY KEY ("id"))` ); + await queryRunner.query(`ALTER TABLE "users" ADD "webauthn_enabled" boolean NOT NULL DEFAULT false`); await queryRunner.query( - `ALTER TABLE "users" ADD "webauthn_enabled" boolean NOT NULL DEFAULT false`, - ); - await queryRunner.query( - `ALTER TABLE "security_keys" ADD CONSTRAINT "FK_24c97d0771cafedce6d7163eaad" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `ALTER TABLE "security_keys" ADD CONSTRAINT "FK_24c97d0771cafedce6d7163eaad" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE NO ACTION` ); } public async down(queryRunner: QueryRunner): Promise<void> { - await queryRunner.query( - `ALTER TABLE "security_keys" DROP CONSTRAINT "FK_24c97d0771cafedce6d7163eaad"`, - ); - await queryRunner.query( - `ALTER TABLE "users" DROP COLUMN "webauthn_enabled"`, - ); + await queryRunner.query(`ALTER TABLE "security_keys" DROP CONSTRAINT "FK_24c97d0771cafedce6d7163eaad"`); + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "webauthn_enabled"`); await queryRunner.query(`DROP TABLE "security_keys"`); } } diff --git a/src/util/migration/postgres/1696420827239-guildChannelOrdering.ts b/src/util/migration/postgres/1696420827239-guildChannelOrdering.ts index 6fc80ffd..de876ff9 100644 --- a/src/util/migration/postgres/1696420827239-guildChannelOrdering.ts +++ b/src/util/migration/postgres/1696420827239-guildChannelOrdering.ts @@ -4,31 +4,21 @@ 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, - ); + const guilds = await queryRunner.query(`SELECT id FROM guilds`, undefined, true); - await queryRunner.query( - `ALTER TABLE guilds ADD channel_ordering text NOT NULL DEFAULT '[]'`, - ); + await queryRunner.query(`ALTER TABLE guilds ADD channel_ordering 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, - ) + 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 channel_ordering = $1 WHERE id = $2`, - [JSON.stringify(channels.map((x) => x.id)), guild_id], - ); + await queryRunner.query(`UPDATE guilds SET channel_ordering = $1 WHERE id = $2`, [ + JSON.stringify(channels.map((x) => x.id)), + guild_id, + ]); } await queryRunner.query(`ALTER TABLE channels DROP COLUMN position`); diff --git a/src/util/schemas/GuildUpdateSchema.ts b/src/util/schemas/GuildUpdateSchema.ts index 19316380..4f33b888 100644 --- a/src/util/schemas/GuildUpdateSchema.ts +++ b/src/util/schemas/GuildUpdateSchema.ts @@ -18,8 +18,7 @@ import { GuildCreateSchema } from "@spacebar/util"; -export interface GuildUpdateSchema - extends Omit<GuildCreateSchema, "channels" | "name"> { +export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels" | "name"> { name?: string; banner?: string | null; splash?: string | null; diff --git a/src/util/schemas/UserGuildSettingsSchema.ts b/src/util/schemas/UserGuildSettingsSchema.ts index 82edae9c..603dbb21 100644 --- a/src/util/schemas/UserGuildSettingsSchema.ts +++ b/src/util/schemas/UserGuildSettingsSchema.ts @@ -19,8 +19,7 @@ import { ChannelOverride, UserGuildSettings } from "@spacebar/util"; // This sucks. I would use a DeepPartial, my own or typeorms, but they both generate inncorect schema -export interface UserGuildSettingsSchema - extends Partial<Omit<UserGuildSettings, "channel_overrides">> { +export interface UserGuildSettingsSchema extends Partial<Omit<UserGuildSettings, "channel_overrides">> { channel_overrides?: { [channel_id: string]: ChannelOverride; }; diff --git a/src/util/schemas/Validator.ts b/src/util/schemas/Validator.ts index 1de511d3..cedc2e73 100644 --- a/src/util/schemas/Validator.ts +++ b/src/util/schemas/Validator.ts @@ -21,14 +21,7 @@ import addFormats from "ajv-formats"; import fs from "fs"; import path from "path"; -const SchemaPath = path.join( - __dirname, - "..", - "..", - "..", - "assets", - "schemas.json", -); +const SchemaPath = path.join(__dirname, "..", "..", "..", "assets", "schemas.json"); const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); export const ajv = new Ajv({ diff --git a/src/util/schemas/WebAuthnSchema.ts b/src/util/schemas/WebAuthnSchema.ts index 3f5e0da7..ada20de1 100644 --- a/src/util/schemas/WebAuthnSchema.ts +++ b/src/util/schemas/WebAuthnSchema.ts @@ -28,9 +28,7 @@ export interface CreateWebAuthnCredentialSchema { ticket: string; } -export type WebAuthnPostSchema = - | GenerateWebAuthnCredentialsSchema - | CreateWebAuthnCredentialSchema; +export type WebAuthnPostSchema = GenerateWebAuthnCredentialsSchema | CreateWebAuthnCredentialSchema; export interface WebAuthnTotpSchema { code: string; diff --git a/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts b/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts index c9a0e5be..069a05e0 100644 --- a/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts +++ b/src/util/schemas/responses/APIErrorOrCaptchaResponse.ts @@ -1,6 +1,4 @@ import { APIErrorResponse } from "./APIErrorResponse"; import { CaptchaRequiredResponse } from "./CaptchaRequiredResponse"; -export type APIErrorOrCaptchaResponse = - | CaptchaRequiredResponse - | APIErrorResponse; +export type APIErrorOrCaptchaResponse = CaptchaRequiredResponse | APIErrorResponse; diff --git a/src/util/schemas/responses/GuildMessagesSearchResponse.ts b/src/util/schemas/responses/GuildMessagesSearchResponse.ts index 0b6248b7..b8e9bcc4 100644 --- a/src/util/schemas/responses/GuildMessagesSearchResponse.ts +++ b/src/util/schemas/responses/GuildMessagesSearchResponse.ts @@ -1,10 +1,4 @@ -import { - Attachment, - Embed, - MessageType, - PublicUser, - Role, -} from "../../entities"; +import { Attachment, Embed, MessageType, PublicUser, Role } from "../../entities"; export interface GuildMessagesSearchMessage { id: string; diff --git a/src/util/schemas/responses/GuildVanityUrl.ts b/src/util/schemas/responses/GuildVanityUrl.ts index ff37bf4e..6d67a932 100644 --- a/src/util/schemas/responses/GuildVanityUrl.ts +++ b/src/util/schemas/responses/GuildVanityUrl.ts @@ -7,10 +7,7 @@ export interface GuildVanityUrlNoInvite { code: null; } -export type GuildVanityUrlResponse = - | GuildVanityUrl - | GuildVanityUrl[] - | GuildVanityUrlNoInvite; +export type GuildVanityUrlResponse = GuildVanityUrl | GuildVanityUrl[] | GuildVanityUrlNoInvite; export interface GuildVanityUrlCreateResponse { code: string; diff --git a/src/util/schemas/responses/UserProfileResponse.ts b/src/util/schemas/responses/UserProfileResponse.ts index eba7cbcc..0dc58629 100644 --- a/src/util/schemas/responses/UserProfileResponse.ts +++ b/src/util/schemas/responses/UserProfileResponse.ts @@ -1,27 +1,15 @@ -import { - Member, - PublicConnectedAccount, - PublicMember, - PublicUser, - User, -} from "@spacebar/util"; +import { Member, PublicConnectedAccount, PublicMember, PublicUser, User } from "@spacebar/util"; export type MutualGuild = { id: string; nick?: string; }; -export type PublicMemberProfile = Pick< - Member, - "banner" | "bio" | "guild_id" -> & { +export type PublicMemberProfile = Pick<Member, "banner" | "bio" | "guild_id"> & { accent_color: null; // TODO }; -export type UserProfile = Pick< - User, - "bio" | "accent_color" | "banner" | "pronouns" | "theme_colors" ->; +export type UserProfile = Pick<User, "bio" | "accent_color" | "banner" | "pronouns" | "theme_colors">; export interface UserProfileResponse { user: PublicUser; diff --git a/src/util/util/ApiError.ts b/src/util/util/ApiError.ts index 4c7b909f..e0621fba 100644 --- a/src/util/util/ApiError.ts +++ b/src/util/util/ApiError.ts @@ -21,34 +21,23 @@ export class ApiError extends Error { readonly message: string, public readonly code: number, public readonly httpStatus: number = 400, - public readonly defaultParams?: string[], + public readonly defaultParams?: string[] ) { super(message); } withDefaultParams(): ApiError { if (this.defaultParams) - return new ApiError( - applyParamsToString(this.message, this.defaultParams), - this.code, - this.httpStatus, - ); + return new ApiError(applyParamsToString(this.message, this.defaultParams), this.code, this.httpStatus); return this; } withParams(...params: (string | number)[]): ApiError { - return new ApiError( - applyParamsToString(this.message, params), - this.code, - this.httpStatus, - ); + return new ApiError(applyParamsToString(this.message, params), this.code, this.httpStatus); } } -export function applyParamsToString( - s: string, - params: (string | number)[], -): string { +export function applyParamsToString(s: string, params: (string | number)[]): string { let newString = s; params.forEach((a) => { newString = newString.replace("{}", "" + a); diff --git a/src/util/util/AutoUpdate.ts b/src/util/util/AutoUpdate.ts index 2af5cf1c..39173d94 100644 --- a/src/util/util/AutoUpdate.ts +++ b/src/util/util/AutoUpdate.ts @@ -37,17 +37,14 @@ export function enableAutoUpdate(opts: { }) { if (!opts.checkInterval) return; const interval = 1000 * 60 * 60 * 24; - if (typeof opts.checkInterval === "number") - opts.checkInterval = 1000 * interval; + if (typeof opts.checkInterval === "number") opts.checkInterval = 1000 * interval; const i = setInterval(async () => { const currentVersion = await getCurrentVersion(opts.path); const latestVersion = await getLatestVersion(opts.packageJsonLink); if (currentVersion !== latestVersion) { clearInterval(i); - console.log( - `[Auto Update] Current version (${currentVersion}) is out of date, updating ...`, - ); + console.log(`[Auto Update] Current version (${currentVersion}) is out of date, updating ...`); await download(opts.downloadUrl, opts.path); } }, interval); @@ -64,7 +61,7 @@ export function enableAutoUpdate(opts: { } else { console.log(`[Auto update] aborted`); } - }, + } ); } }); diff --git a/src/util/util/BitField.ts b/src/util/util/BitField.ts index d8758327..85de8fb7 100644 --- a/src/util/util/BitField.ts +++ b/src/util/util/BitField.ts @@ -4,12 +4,7 @@ // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah // @fc-license-skip -export type BitFieldResolvable = - | number - | bigint - | BitField - | string - | BitFieldResolvable[]; +export type BitFieldResolvable = number | bigint | BitField | string | BitFieldResolvable[]; /** * Data structure that makes it easy to interact with a bitfield. @@ -97,8 +92,7 @@ export class BitField { */ serialize() { const serialized: Record<string, boolean> = {}; - for (const [flag, bit] of Object.entries(BitField.FLAGS)) - serialized[flag] = this.has(bit); + for (const [flag, bit] of Object.entries(BitField.FLAGS)) serialized[flag] = this.has(bit); return serialized; } @@ -144,11 +138,7 @@ export class BitField { else bit = BigInt(bit); } - if ( - (typeof bit === "number" || typeof bit === "bigint") && - bit >= BigInt(0) - ) - return BigInt(bit); + if ((typeof bit === "number" || typeof bit === "bigint") && bit >= BigInt(0)) return BigInt(bit); if (bit instanceof BitField) return bit.bitfield; @@ -156,9 +146,7 @@ export class BitField { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const resolve = this.constructor?.resolve || this.resolve; - return bit - .map((p) => resolve.call(this, p)) - .reduce((prev, p) => BigInt(prev) | BigInt(p), BigInt(0)); + return bit.map((p) => resolve.call(this, p)).reduce((prev, p) => BigInt(prev) | BigInt(p), BigInt(0)); } throw new RangeError("BITFIELD_INVALID: " + bit); diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts index 2624a60a..c26a5ed5 100644 --- a/src/util/util/Config.ts +++ b/src/util/util/Config.ts @@ -41,9 +41,7 @@ export const Config = { } else { console.log(`[Config] Using CONFIG_PATH rather than database`); if (existsSync(process.env.CONFIG_PATH)) { - const file = JSON.parse( - (await fs.readFile(process.env.CONFIG_PATH)).toString(), - ); + const file = JSON.parse((await fs.readFile(process.env.CONFIG_PATH)).toString()); config = file; } else config = new ConfigValue(); pairs = generatePairs(config); @@ -82,7 +80,7 @@ const generatePairs = (obj: object | null, key = ""): ConfigEntity[] => { return Object.keys(obj) .map((k) => // eslint-disable-next-line @typescript-eslint/no-explicit-any - generatePairs((obj as any)[k], key ? `${key}_${k}` : k), + generatePairs((obj as any)[k], key ? `${key}_${k}` : k) ) .flat(); } @@ -94,8 +92,7 @@ const generatePairs = (obj: object | null, key = ""): ConfigEntity[] => { }; async function applyConfig(val: ConfigValue) { - if (process.env.CONFIG_PATH) - await fs.writeFile(overridePath, JSON.stringify(val, null, 4)); + if (process.env.CONFIG_PATH) await fs.writeFile(overridePath, JSON.stringify(val, null, 4)); else { const pairs = generatePairs(val); await Promise.all(pairs.map((pair) => pair.save())); @@ -116,8 +113,7 @@ function pairsToConfig(pairs: ConfigEntity[]) { let i = 0; for (const key of keys) { - if (!isNaN(Number(key)) && !prevObj[prev]?.length) - prevObj[prev] = obj = []; + if (!isNaN(Number(key)) && !prevObj[prev]?.length) prevObj[prev] = obj = []; if (i++ === keys.length - 1) obj[key] = p.value; else if (!obj[key]) obj[key] = {}; @@ -142,18 +138,14 @@ const validateConfig = async () => { if (!found) continue; config[row] = found; } catch (e) { - console.error( - `Config key '${config[row].key}' has invalid JSON value : ${ - (e as Error)?.message - }`, - ); + console.error(`Config key '${config[row].key}' has invalid JSON value : ${(e as Error)?.message}`); hasErrored = true; } } if (hasErrored) { console.error( - "Your config has invalid values. Fix them first https://docs.spacebar.chat/setup/server/configuration", + "Your config has invalid values. Fix them first https://docs.spacebar.chat/setup/server/configuration" ); process.exit(1); } diff --git a/src/util/util/Constants.ts b/src/util/util/Constants.ts index e68bb0b7..151c15f6 100644 --- a/src/util/util/Constants.ts +++ b/src/util/util/Constants.ts @@ -178,13 +178,7 @@ export const ShardEvents = { * sidebar for more information.</warn> * @typedef {string} PartialType */ -export const PartialTypes = keyMirror([ - "USER", - "CHANNEL", - "GUILD_MEMBER", - "MESSAGE", - "REACTION", -]); +export const PartialTypes = keyMirror(["USER", "CHANNEL", "GUILD_MEMBER", "MESSAGE", "REACTION"]); /** * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events: @@ -315,7 +309,7 @@ export const MessageTypes = [ * @typedef {string} SystemMessageType */ export const SystemMessageTypes = MessageTypes.filter( - (type: string | null) => type && type !== "DEFAULT" && type !== "REPLY", + (type: string | null) => type && type !== "DEFAULT" && type !== "REPLY" ); /** @@ -329,14 +323,7 @@ export const SystemMessageTypes = MessageTypes.filter( * * COMPETING * @typedef {string} ActivityType */ -export const ActivityTypes = [ - "PLAYING", - "STREAMING", - "LISTENING", - "WATCHING", - "CUSTOM_STATUS", - "COMPETING", -]; +export const ActivityTypes = ["PLAYING", "STREAMING", "LISTENING", "WATCHING", "CUSTOM_STATUS", "COMPETING"]; export const ChannelTypes = { TEXT: 0, @@ -392,11 +379,7 @@ export const Colors = { * * ALL_MEMBERS * @typedef {string} ExplicitContentFilterLevel */ -export const ExplicitContentFilterLevels = [ - "DISABLED", - "MEMBERS_WITHOUT_ROLES", - "ALL_MEMBERS", -]; +export const ExplicitContentFilterLevels = ["DISABLED", "MEMBERS_WITHOUT_ROLES", "ALL_MEMBERS"]; /** * The value set for the verification levels for a guild: @@ -407,13 +390,7 @@ export const ExplicitContentFilterLevels = [ * * VERY_HIGH * @typedef {string} VerificationLevel */ -export const VerificationLevels = [ - "NONE", - "LOW", - "MEDIUM", - "HIGH", - "VERY_HIGH", -]; +export const VerificationLevels = ["NONE", "LOW", "MEDIUM", "HIGH", "VERY_HIGH"]; /** * An error encountered while performing an API request. Here are the potential errors: @@ -558,10 +535,7 @@ export const VerificationLevels = [ */ export const DiscordApiErrors = { //https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes - GENERAL_ERROR: new ApiError( - "General error (such as a malformed request body, amongst other things)", - 0, - ), + GENERAL_ERROR: new ApiError("General error (such as a malformed request body, amongst other things)", 0), UNKNOWN_ACCOUNT: new ApiError("Unknown account", 10001), UNKNOWN_APPLICATION: new ApiError("Unknown application", 10002), UNKNOWN_CHANNEL: new ApiError("Unknown channel", 10003), @@ -587,420 +561,188 @@ export const DiscordApiErrors = { UNKNOWN_BUILD: new ApiError("Unknown build", 10030), UNKNOWN_LOBBY: new ApiError("Unknown lobby", 10031), UNKNOWN_BRANCH: new ApiError("Unknown branch", 10032), - UNKNOWN_STORE_DIRECTORY_LAYOUT: new ApiError( - "Unknown store directory layout", - 10033, - ), + UNKNOWN_STORE_DIRECTORY_LAYOUT: new ApiError("Unknown store directory layout", 10033), UNKNOWN_REDISTRIBUTABLE: new ApiError("Unknown redistributable", 10036), UNKNOWN_GIFT_CODE: new ApiError("Unknown gift code", 10038), UNKNOWN_STREAM: new ApiError("Unknown stream", 10049), - UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN: new ApiError( - "Unknown premium server subscribe cooldown", - 10050, - ), + UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN: new ApiError("Unknown premium server subscribe cooldown", 10050), UNKNOWN_GUILD_TEMPLATE: new ApiError("Unknown guild template", 10057), - UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: new ApiError( - "Unknown discoverable server category", - 10059, - ), + UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: new ApiError("Unknown discoverable server category", 10059), UNKNOWN_STICKER: new ApiError("Unknown sticker", 10060), UNKNOWN_INTERACTION: new ApiError("Unknown interaction", 10062), - UNKNOWN_APPLICATION_COMMAND: new ApiError( - "Unknown application command", - 10063, - ), - UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: new ApiError( - "Unknown application command permissions", - 10066, - ), + UNKNOWN_APPLICATION_COMMAND: new ApiError("Unknown application command", 10063), + UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: new ApiError("Unknown application command permissions", 10066), UNKNOWN_STAGE_INSTANCE: new ApiError("Unknown Stage Instance", 10067), - UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: new ApiError( - "Unknown Guild Member Verification Form", - 10068, - ), - UNKNOWN_GUILD_WELCOME_SCREEN: new ApiError( - "Unknown Guild Welcome Screen", - 10069, - ), - UNKNOWN_GUILD_SCHEDULED_EVENT: new ApiError( - "Unknown Guild Scheduled Event", - 10070, - ), - UNKNOWN_GUILD_SCHEDULED_EVENT_USER: new ApiError( - "Unknown Guild Scheduled Event User", - 10071, - ), - BOT_PROHIBITED_ENDPOINT: new ApiError( - "Bots cannot use this endpoint", - 20001, - ), + UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: new ApiError("Unknown Guild Member Verification Form", 10068), + UNKNOWN_GUILD_WELCOME_SCREEN: new ApiError("Unknown Guild Welcome Screen", 10069), + UNKNOWN_GUILD_SCHEDULED_EVENT: new ApiError("Unknown Guild Scheduled Event", 10070), + UNKNOWN_GUILD_SCHEDULED_EVENT_USER: new ApiError("Unknown Guild Scheduled Event User", 10071), + BOT_PROHIBITED_ENDPOINT: new ApiError("Bots cannot use this endpoint", 20001), BOT_ONLY_ENDPOINT: new ApiError("Only bots can use this endpoint", 20002), EXPLICIT_CONTENT_CANNOT_BE_SENT_TO_RECIPIENT: new ApiError( "Explicit content cannot be sent to the desired recipient(s)", - 20009, + 20009 ), ACTION_NOT_AUTHORIZED_ON_APPLICATION: new ApiError( "You are not authorized to perform this action on this application", - 20012, - ), - SLOWMODE_RATE_LIMIT: new ApiError( - "This action cannot be performed due to slowmode rate limit", - 20016, - ), - ONLY_OWNER: new ApiError( - "Only the owner of this account can perform this action", - 20018, - ), - ANNOUNCEMENT_RATE_LIMITS: new ApiError( - "This message cannot be edited due to announcement rate limits", - 20022, - ), - CHANNEL_WRITE_RATELIMIT: new ApiError( - "The channel you are writing has hit the write rate limit", - 20028, + 20012 ), + SLOWMODE_RATE_LIMIT: new ApiError("This action cannot be performed due to slowmode rate limit", 20016), + ONLY_OWNER: new ApiError("Only the owner of this account can perform this action", 20018), + ANNOUNCEMENT_RATE_LIMITS: new ApiError("This message cannot be edited due to announcement rate limits", 20022), + CHANNEL_WRITE_RATELIMIT: new ApiError("The channel you are writing has hit the write rate limit", 20028), WORDS_NOT_ALLOWED: new ApiError( "Your Stage topic, server name, server description, or channel names contain words that are not allowed", - 20031, - ), - GUILD_PREMIUM_LEVEL_TOO_LOW: new ApiError( - "Guild premium subscription level too low", - 20035, - ), - MAXIMUM_GUILDS: new ApiError( - "Maximum number of guilds reached ({})", - 30001, - undefined, - ["100"], - ), - MAXIMUM_FRIENDS: new ApiError( - "Maximum number of friends reached ({})", - 30002, - undefined, - ["1000"], - ), - MAXIMUM_PINS: new ApiError( - "Maximum number of pins reached for the channel ({})", - 30003, - undefined, - ["50"], - ), - MAXIMUM_NUMBER_OF_RECIPIENTS_REACHED: new ApiError( - "Maximum number of recipients reached ({})", - 30004, - undefined, - ["10"], - ), - MAXIMUM_ROLES: new ApiError( - "Maximum number of guild roles reached ({})", - 30005, - undefined, - ["250"], - ), - MAXIMUM_WEBHOOKS: new ApiError( - "Maximum number of webhooks reached ({})", - 30007, - undefined, - ["10"], - ), - MAXIMUM_NUMBER_OF_EMOJIS_REACHED: new ApiError( - "Maximum number of emojis reached", - 30008, - ), - MAXIMUM_REACTIONS: new ApiError( - "Maximum number of reactions reached ({})", - 30010, - undefined, - ["20"], - ), - MAXIMUM_CHANNELS: new ApiError( - "Maximum number of guild channels reached ({})", - 30013, - undefined, - ["500"], - ), - MAXIMUM_ATTACHMENTS: new ApiError( - "Maximum number of attachments in a message reached ({})", - 30015, - undefined, - ["10"], - ), - MAXIMUM_INVITES: new ApiError( - "Maximum number of invites reached ({})", - 30016, - undefined, - ["1000"], - ), - MAXIMUM_ANIMATED_EMOJIS: new ApiError( - "Maximum number of animated emojis reached", - 30018, - ), - MAXIMUM_SERVER_MEMBERS: new ApiError( - "Maximum number of server members reached", - 30019, - ), + 20031 + ), + GUILD_PREMIUM_LEVEL_TOO_LOW: new ApiError("Guild premium subscription level too low", 20035), + MAXIMUM_GUILDS: new ApiError("Maximum number of guilds reached ({})", 30001, undefined, ["100"]), + MAXIMUM_FRIENDS: new ApiError("Maximum number of friends reached ({})", 30002, undefined, ["1000"]), + MAXIMUM_PINS: new ApiError("Maximum number of pins reached for the channel ({})", 30003, undefined, ["50"]), + MAXIMUM_NUMBER_OF_RECIPIENTS_REACHED: new ApiError("Maximum number of recipients reached ({})", 30004, undefined, [ + "10", + ]), + MAXIMUM_ROLES: new ApiError("Maximum number of guild roles reached ({})", 30005, undefined, ["250"]), + MAXIMUM_WEBHOOKS: new ApiError("Maximum number of webhooks reached ({})", 30007, undefined, ["10"]), + MAXIMUM_NUMBER_OF_EMOJIS_REACHED: new ApiError("Maximum number of emojis reached", 30008), + MAXIMUM_REACTIONS: new ApiError("Maximum number of reactions reached ({})", 30010, undefined, ["20"]), + MAXIMUM_CHANNELS: new ApiError("Maximum number of guild channels reached ({})", 30013, undefined, ["500"]), + MAXIMUM_ATTACHMENTS: new ApiError("Maximum number of attachments in a message reached ({})", 30015, undefined, [ + "10", + ]), + MAXIMUM_INVITES: new ApiError("Maximum number of invites reached ({})", 30016, undefined, ["1000"]), + MAXIMUM_ANIMATED_EMOJIS: new ApiError("Maximum number of animated emojis reached", 30018), + MAXIMUM_SERVER_MEMBERS: new ApiError("Maximum number of server members reached", 30019), MAXIMUM_SERVER_CATEGORIES: new ApiError( "Maximum number of server categories has been reached ({})", 30030, undefined, - ["5"], - ), - GUILD_ALREADY_HAS_TEMPLATE: new ApiError( - "Guild already has a template", - 30031, - ), - MAXIMUM_THREAD_PARTICIPANTS: new ApiError( - "Max number of thread participants has been reached", - 30033, + ["5"] ), + GUILD_ALREADY_HAS_TEMPLATE: new ApiError("Guild already has a template", 30031), + MAXIMUM_THREAD_PARTICIPANTS: new ApiError("Max number of thread participants has been reached", 30033), MAXIMUM_BANS_FOR_NON_GUILD_MEMBERS: new ApiError( "Maximum number of bans for non-guild members have been exceeded", - 30035, - ), - MAXIMUM_BANS_FETCHES: new ApiError( - "Maximum number of bans fetches has been reached", - 30037, + 30035 ), + MAXIMUM_BANS_FETCHES: new ApiError("Maximum number of bans fetches has been reached", 30037), MAXIMUM_STICKERS: new ApiError("Maximum number of stickers reached", 30039), - MAXIMUM_PRUNE_REQUESTS: new ApiError( - "Maximum number of prune requests has been reached. Try again later", - 30040, - ), - UNAUTHORIZED: new ApiError( - "Unauthorized. Provide a valid token and try again", - 40001, - ), + MAXIMUM_PRUNE_REQUESTS: new ApiError("Maximum number of prune requests has been reached. Try again later", 30040), + UNAUTHORIZED: new ApiError("Unauthorized. Provide a valid token and try again", 40001), ACCOUNT_VERIFICATION_REQUIRED: new ApiError( "You need to verify your account in order to perform this action", - 40002, - ), - OPENING_DIRECT_MESSAGES_TOO_FAST: new ApiError( - "You are opening direct messages too fast", - 40003, - ), - REQUEST_ENTITY_TOO_LARGE: new ApiError( - "Request entity too large. Try sending something smaller in size", - 40005, - ), - FEATURE_TEMPORARILY_DISABLED: new ApiError( - "This feature has been temporarily disabled server-side", - 40006, + 40002 ), + OPENING_DIRECT_MESSAGES_TOO_FAST: new ApiError("You are opening direct messages too fast", 40003), + REQUEST_ENTITY_TOO_LARGE: new ApiError("Request entity too large. Try sending something smaller in size", 40005), + FEATURE_TEMPORARILY_DISABLED: new ApiError("This feature has been temporarily disabled server-side", 40006), USER_BANNED: new ApiError("The user is banned from this guild", 40007), - CONNECTION_REVOKED: new ApiError( - "The connection has been revoked", - 40012, - 400, - ), - TARGET_USER_IS_NOT_CONNECTED_TO_VOICE: new ApiError( - "Target user is not connected to voice", - 40032, - ), - ALREADY_CROSSPOSTED: new ApiError( - "This message has already been crossposted", - 40033, - ), - APPLICATION_COMMAND_ALREADY_EXISTS: new ApiError( - "An application command with that name already exists", - 40041, - ), + CONNECTION_REVOKED: new ApiError("The connection has been revoked", 40012, 400), + TARGET_USER_IS_NOT_CONNECTED_TO_VOICE: new ApiError("Target user is not connected to voice", 40032), + ALREADY_CROSSPOSTED: new ApiError("This message has already been crossposted", 40033), + APPLICATION_COMMAND_ALREADY_EXISTS: new ApiError("An application command with that name already exists", 40041), MISSING_ACCESS: new ApiError("Missing access", 50001), INVALID_ACCOUNT_TYPE: new ApiError("Invalid account type", 50002), - CANNOT_EXECUTE_ON_DM: new ApiError( - "Cannot execute action on a DM channel", - 50003, - ), + CANNOT_EXECUTE_ON_DM: new ApiError("Cannot execute action on a DM channel", 50003), EMBED_DISABLED: new ApiError("Guild widget disabled", 50004), - CANNOT_EDIT_MESSAGE_BY_OTHER: new ApiError( - "Cannot edit a message authored by another user", - 50005, - ), - CANNOT_SEND_EMPTY_MESSAGE: new ApiError( - "Cannot send an empty message", - 50006, - ), - CANNOT_MESSAGE_USER: new ApiError( - "Cannot send messages to this user", - 50007, - ), - CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: new ApiError( - "Cannot send messages in a voice channel", - 50008, - ), + CANNOT_EDIT_MESSAGE_BY_OTHER: new ApiError("Cannot edit a message authored by another user", 50005), + CANNOT_SEND_EMPTY_MESSAGE: new ApiError("Cannot send an empty message", 50006), + CANNOT_MESSAGE_USER: new ApiError("Cannot send messages to this user", 50007), + CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: new ApiError("Cannot send messages in a voice channel", 50008), CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: new ApiError( "Channel verification level is too high for you to gain access", - 50009, - ), - OAUTH2_APPLICATION_BOT_ABSENT: new ApiError( - "OAuth2 application does not have a bot", - 50010, - ), - MAXIMUM_OAUTH2_APPLICATIONS: new ApiError( - "OAuth2 application limit reached", - 50011, + 50009 ), + OAUTH2_APPLICATION_BOT_ABSENT: new ApiError("OAuth2 application does not have a bot", 50010), + MAXIMUM_OAUTH2_APPLICATIONS: new ApiError("OAuth2 application limit reached", 50011), INVALID_OAUTH_STATE: new ApiError("Invalid OAuth2 state", 50012), - MISSING_PERMISSIONS: new ApiError( - "You lack permissions to perform that action ({})", - 50013, - undefined, - [""], - ), - INVALID_AUTHENTICATION_TOKEN: new ApiError( - "Invalid authentication token provided", - 50014, - ), + MISSING_PERMISSIONS: new ApiError("You lack permissions to perform that action ({})", 50013, undefined, [""]), + INVALID_AUTHENTICATION_TOKEN: new ApiError("Invalid authentication token provided", 50014), NOTE_TOO_LONG: new ApiError("Note was too long", 50015), INVALID_BULK_DELETE_QUANTITY: new ApiError( "Provided too few or too many messages to delete. Must provide at least {} and fewer than {} messages to delete", 50016, undefined, - ["2", "100"], + ["2", "100"] ), CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: new ApiError( "A message can only be pinned to the channel it was sent in", - 50019, - ), - INVALID_OR_TAKEN_INVITE_CODE: new ApiError( - "Invite code was either invalid or taken", - 50020, - ), - CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: new ApiError( - "Cannot execute action on a system message", - 50021, - ), - CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE: new ApiError( - "Cannot execute action on this channel type", - 50024, - ), - INVALID_OAUTH_TOKEN: new ApiError( - "Invalid OAuth2 access token provided", - 50025, - ), - MISSING_REQUIRED_OAUTH2_SCOPE: new ApiError( - "Missing required OAuth2 scope", - 50026, - ), - INVALID_WEBHOOK_TOKEN_PROVIDED: new ApiError( - "Invalid webhook token provided", - 50027, - ), + 50019 + ), + INVALID_OR_TAKEN_INVITE_CODE: new ApiError("Invite code was either invalid or taken", 50020), + CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: new ApiError("Cannot execute action on a system message", 50021), + CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE: new ApiError("Cannot execute action on this channel type", 50024), + INVALID_OAUTH_TOKEN: new ApiError("Invalid OAuth2 access token provided", 50025), + MISSING_REQUIRED_OAUTH2_SCOPE: new ApiError("Missing required OAuth2 scope", 50026), + INVALID_WEBHOOK_TOKEN_PROVIDED: new ApiError("Invalid webhook token provided", 50027), INVALID_ROLE: new ApiError("Invalid role", 50028), INVALID_RECIPIENT: new ApiError("Invalid Recipient(s)", 50033), - BULK_DELETE_MESSAGE_TOO_OLD: new ApiError( - "A message provided was too old to bulk delete", - 50034, - ), + BULK_DELETE_MESSAGE_TOO_OLD: new ApiError("A message provided was too old to bulk delete", 50034), INVALID_FORM_BODY: new ApiError( "Invalid form body (returned for both application/json and multipart/form-data bodies), or invalid Content-Type provided", - 50035, + 50035 ), INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: new ApiError( "An invite was accepted to a guild the application's bot is not in", - 50036, + 50036 ), INVALID_API_VERSION: new ApiError("Invalid API version provided", 50041), - FILE_EXCEEDS_MAXIMUM_SIZE: new ApiError( - "File uploaded exceeds the maximum size", - 50045, - ), + FILE_EXCEEDS_MAXIMUM_SIZE: new ApiError("File uploaded exceeds the maximum size", 50045), INVALID_FILE_UPLOADED: new ApiError("Invalid file uploaded", 50046), - CANNOT_SELF_REDEEM_GIFT: new ApiError( - "Cannot self-redeem this gift", - 50054, - ), - PAYMENT_SOURCE_REQUIRED: new ApiError( - "Payment source required to redeem gift", - 50070, - ), + CANNOT_SELF_REDEEM_GIFT: new ApiError("Cannot self-redeem this gift", 50054), + PAYMENT_SOURCE_REQUIRED: new ApiError("Payment source required to redeem gift", 50070), CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: new ApiError( "Cannot delete a channel required for Community guilds", - 50074, + 50074 ), INVALID_STICKER_SENT: new ApiError("Invalid sticker sent", 50081), CANNOT_EDIT_ARCHIVED_THREAD: new ApiError( "Tried to perform an operation on an archived thread, such as editing a message or adding a user to the thread", - 50083, - ), - INVALID_THREAD_NOTIFICATION_SETTINGS: new ApiError( - "Invalid thread notification settings", - 50084, + 50083 ), + INVALID_THREAD_NOTIFICATION_SETTINGS: new ApiError("Invalid thread notification settings", 50084), BEFORE_EARLIER_THAN_THREAD_CREATION_DATE: new ApiError( "before value is earlier than the thread creation date", - 50085, - ), - SERVER_NOT_AVAILABLE_IN_YOUR_LOCATION: new ApiError( - "This server is not available in your location", - 50095, + 50085 ), + SERVER_NOT_AVAILABLE_IN_YOUR_LOCATION: new ApiError("This server is not available in your location", 50095), SERVER_NEEDS_MONETIZATION_ENABLED: new ApiError( "This server needs monetization enabled in order to perform this action", - 50097, - ), - TWO_FACTOR_REQUIRED: new ApiError( - "Two factor is required for this operation", - 60003, - ), - NO_USERS_WITH_DISCORDTAG_EXIST: new ApiError( - "No users with DiscordTag exist", - 80004, + 50097 ), + TWO_FACTOR_REQUIRED: new ApiError("Two factor is required for this operation", 60003), + NO_USERS_WITH_DISCORDTAG_EXIST: new ApiError("No users with DiscordTag exist", 80004), REACTION_BLOCKED: new ApiError("Reaction was blocked", 90001), - RESOURCE_OVERLOADED: new ApiError( - "API resource is currently overloaded. Try again a little later", - 130000, - ), + RESOURCE_OVERLOADED: new ApiError("API resource is currently overloaded. Try again a little later", 130000), STAGE_ALREADY_OPEN: new ApiError("The Stage is already open", 150006), - THREAD_ALREADY_CREATED_FOR_THIS_MESSAGE: new ApiError( - "A thread has already been created for this message", - 160004, - ), + THREAD_ALREADY_CREATED_FOR_THIS_MESSAGE: new ApiError("A thread has already been created for this message", 160004), THREAD_IS_LOCKED: new ApiError("Thread is locked", 160005), - MAXIMUM_NUMBER_OF_ACTIVE_THREADS: new ApiError( - "Maximum number of active threads reached", - 160006, - ), + MAXIMUM_NUMBER_OF_ACTIVE_THREADS: new ApiError("Maximum number of active threads reached", 160006), MAXIMUM_NUMBER_OF_ACTIVE_ANNOUNCEMENT_THREADS: new ApiError( "Maximum number of active announcement threads reached", - 160007, - ), - INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: new ApiError( - "Invalid JSON for uploaded Lottie file", - 170001, + 160007 ), + INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: new ApiError("Invalid JSON for uploaded Lottie file", 170001), LOTTIES_CANNOT_CONTAIN_RASTERIZED_IMAGES: new ApiError( "Uploaded Lotties cannot contain rasterized images such as PNG or JPEG", - 170002, - ), - STICKER_MAXIMUM_FRAMERATE: new ApiError( - "Sticker maximum framerate exceeded", - 170003, - ), - STICKER_MAXIMUM_FRAME_COUNT: new ApiError( - "Sticker frame count exceeds maximum of {} frames", - 170004, - undefined, - ["1000"], - ), - LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS: new ApiError( - "Lottie animation maximum dimensions exceeded", - 170005, + 170002 ), + STICKER_MAXIMUM_FRAMERATE: new ApiError("Sticker maximum framerate exceeded", 170003), + STICKER_MAXIMUM_FRAME_COUNT: new ApiError("Sticker frame count exceeds maximum of {} frames", 170004, undefined, [ + "1000", + ]), + LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS: new ApiError("Lottie animation maximum dimensions exceeded", 170005), STICKER_FRAME_RATE_TOO_SMALL_OR_TOO_LARGE: new ApiError( "Sticker frame rate is either too small or too large", - 170006, + 170006 ), STICKER_ANIMATION_DURATION_MAXIMUM: new ApiError( "Sticker animation duration exceeds maximum of {} seconds", 170007, undefined, - ["5"], - ), - AUTOMODERATOR_BLOCK: new ApiError( - "Message was blocked by automatic moderation", - 200000, + ["5"] ), + AUTOMODERATOR_BLOCK: new ApiError("Message was blocked by automatic moderation", 200000), //Other errors UNKNOWN_VOICE_STATE: new ApiError("Unknown Voice State", 10065, 404), @@ -1010,97 +752,30 @@ export const DiscordApiErrors = { * An error encountered while performing an API request (Spacebar only). Here are the potential errors: */ export const SpacebarApiErrors = { - MANUALLY_TRIGGERED_ERROR: new ApiError( - "This is an artificial error", - 1, - 500, - ), - PREMIUM_DISABLED_FOR_GUILD: new ApiError( - "This guild cannot be boosted", - 25001, - ), - NO_FURTHER_PREMIUM: new ApiError( - "This guild does not receive further boosts", - 25002, - ), - GUILD_PREMIUM_DISABLED_FOR_YOU: new ApiError( - "This guild cannot be boosted by you", - 25003, - 403, - ), + MANUALLY_TRIGGERED_ERROR: new ApiError("This is an artificial error", 1, 500), + PREMIUM_DISABLED_FOR_GUILD: new ApiError("This guild cannot be boosted", 25001), + NO_FURTHER_PREMIUM: new ApiError("This guild does not receive further boosts", 25002), + GUILD_PREMIUM_DISABLED_FOR_YOU: new ApiError("This guild cannot be boosted by you", 25003, 403), CANNOT_FRIEND_SELF: new ApiError("Cannot friend oneself", 25009), - USER_SPECIFIC_INVITE_WRONG_RECIPIENT: new ApiError( - "This invite is not meant for you", - 25010, - ), + USER_SPECIFIC_INVITE_WRONG_RECIPIENT: new ApiError("This invite is not meant for you", 25010), USER_SPECIFIC_INVITE_FAILED: new ApiError("Failed to invite user", 25011), - CANNOT_MODIFY_USER_GROUP: new ApiError( - "This user cannot manipulate this group", - 25050, - 403, - ), - CANNOT_REMOVE_SELF_FROM_GROUP: new ApiError( - "This user cannot remove oneself from user group", - 25051, - ), - CANNOT_BAN_OPERATOR: new ApiError( - "Non-OPERATOR cannot ban OPERATOR from instance", - 25052, - ), - CANNOT_LEAVE_GUILD: new ApiError( - "You are not allowed to leave guilds that you joined by yourself", - 25059, - 403, - ), - EDITS_DISABLED: new ApiError( - "You are not allowed to edit your own messages", - 25060, - 403, - ), - DELETE_MESSAGE_DISABLED: new ApiError( - "You are not allowed to delete your own messages", - 25061, - 403, - ), - FEATURE_PERMANENTLY_DISABLED: new ApiError( - "This feature has been disabled server-side", - 45006, - 501, - ), - FEATURE_IS_IMMUTABLE: new ApiError( - "The feature ({}) cannot be edited.", - 45007, - 403, - ), - MISSING_RIGHTS: new ApiError( - "You lack rights to perform that action ({})", - 50013, - undefined, - [""], - ), - CANNOT_REPLACE_BY_BACKFILL: new ApiError( - "Cannot backfill to message ID that already exists", - 55002, - 409, - ), - CANNOT_BACKFILL_TO_THE_FUTURE: new ApiError( - "You cannot backfill messages in the future", - 55003, - ), + CANNOT_MODIFY_USER_GROUP: new ApiError("This user cannot manipulate this group", 25050, 403), + CANNOT_REMOVE_SELF_FROM_GROUP: new ApiError("This user cannot remove oneself from user group", 25051), + CANNOT_BAN_OPERATOR: new ApiError("Non-OPERATOR cannot ban OPERATOR from instance", 25052), + CANNOT_LEAVE_GUILD: new ApiError("You are not allowed to leave guilds that you joined by yourself", 25059, 403), + EDITS_DISABLED: new ApiError("You are not allowed to edit your own messages", 25060, 403), + DELETE_MESSAGE_DISABLED: new ApiError("You are not allowed to delete your own messages", 25061, 403), + FEATURE_PERMANENTLY_DISABLED: new ApiError("This feature has been disabled server-side", 45006, 501), + FEATURE_IS_IMMUTABLE: new ApiError("The feature ({}) cannot be edited.", 45007, 403), + MISSING_RIGHTS: new ApiError("You lack rights to perform that action ({})", 50013, undefined, [""]), + CANNOT_REPLACE_BY_BACKFILL: new ApiError("Cannot backfill to message ID that already exists", 55002, 409), + CANNOT_BACKFILL_TO_THE_FUTURE: new ApiError("You cannot backfill messages in the future", 55003), CANNOT_GRANT_PERMISSIONS_EXCEEDING_RIGHTS: new ApiError( "You cannot grant permissions exceeding your own rights", - 50050, - ), - ROUTES_LOOPING: new ApiError( - "Loops in the route definition ({})", - 50060, - undefined, - [""], - ), - CANNOT_REMOVE_ROUTE: new ApiError( - "Cannot remove message route while it is in effect and being used", - 50061, + 50050 ), + ROUTES_LOOPING: new ApiError("Loops in the route definition ({})", 50060, undefined, [""]), + CANNOT_REMOVE_ROUTE: new ApiError("Cannot remove message route while it is in effect and being used", 50061), }; /** diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts index 3a45eea0..3b0024d0 100644 --- a/src/util/util/Database.ts +++ b/src/util/util/Database.ts @@ -33,8 +33,7 @@ if (!process.env) { config(); } -const dbConnectionString = - process.env.DATABASE || path.join(process.cwd(), "database.db"); +const dbConnectionString = process.env.DATABASE || path.join(process.cwd(), "database.db"); const DatabaseType = dbConnectionString.includes("://") ? dbConnectionString.split(":")[0]?.replace("+srv", "") @@ -71,8 +70,8 @@ export async function initDatabase(): Promise<DataSource> { if (isSqlite) { console.log( `[Database] ${red( - `You are running sqlite! Please keep in mind that we recommend setting up a dedicated database!`, - )}`, + `You are running sqlite! Please keep in mind that we recommend setting up a dedicated database!` + )}` ); } @@ -83,8 +82,8 @@ export async function initDatabase(): Promise<DataSource> { "[Database]" + red( ` We don't have migrations for DB type '${DatabaseType}'` + - ` To ignore, set DB_SYNC=true in your env. https://docs.spacebar.chat/setup/server/configuration/env/`, - ), + ` To ignore, set DB_SYNC=true in your env. https://docs.spacebar.chat/setup/server/configuration/env/` + ) ); process.exit(); } @@ -104,9 +103,7 @@ export async function initDatabase(): Promise<DataSource> { } }; if (!(await dbExists())) { - console.log( - "[Database] This appears to be a fresh database. Synchronising.", - ); + console.log("[Database] This appears to be a fresh database. Synchronising."); await dbConnection.synchronize(); // On next start, typeorm will try to run all the migrations again from beginning. @@ -116,8 +113,8 @@ export async function initDatabase(): Promise<DataSource> { Migration.insert({ name: migration.name, timestamp: Date.now(), - }), - ), + }) + ) ); } else { console.log("[Database] Applying missing migrations, if any."); diff --git a/src/util/util/Event.ts b/src/util/util/Event.ts index 01f4911a..9556c755 100644 --- a/src/util/util/Event.ts +++ b/src/util/util/Event.ts @@ -23,27 +23,17 @@ import { EVENT, Event } from "../interfaces"; export const events = new EventEmitter(); export async function emitEvent(payload: Omit<Event, "created_at">) { - const id = (payload.channel_id || - payload.user_id || - payload.guild_id) as string; + const id = (payload.channel_id || payload.user_id || payload.guild_id) as string; if (!id) return console.error("event doesn't contain any id", payload); if (RabbitMQ.connection) { - const data = - typeof payload.data === "object" - ? JSON.stringify(payload.data) - : payload.data; // use rabbitmq for event transmission + const data = typeof payload.data === "object" ? JSON.stringify(payload.data) : payload.data; // use rabbitmq for event transmission await RabbitMQ.channel?.assertExchange(id, "fanout", { durable: false, }); // assertQueue isn't needed, because a queue will automatically created if it doesn't exist - const successful = RabbitMQ.channel?.publish( - id, - "", - Buffer.from(`${data}`), - { type: payload.event }, - ); + const successful = RabbitMQ.channel?.publish(id, "", Buffer.from(`${data}`), { type: payload.event }); if (!successful) throw new Error("failed to send event"); } else if (process.env.EVENT_TRANSMISSION === "process") { process.send?.({ type: "event", event: payload, id } as ProcessEvent); @@ -79,17 +69,10 @@ export interface ProcessEvent { id: string; } -export async function listenEvent( - event: string, - callback: (event: EventOpts) => unknown, - opts?: ListenEventOpts, -) { +export async function listenEvent(event: string, callback: (event: EventOpts) => unknown, opts?: ListenEventOpts) { if (RabbitMQ.connection) { const channel = opts?.channel || RabbitMQ.channel; - if (!channel) - throw new Error( - "[Events] An event was sent without an associated channel", - ); + if (!channel) throw new Error("[Events] An event was sent without an associated channel"); return await rabbitListen(channel, event, callback, { acknowledge: opts?.acknowledge, }); @@ -100,9 +83,7 @@ export async function listenEvent( }; const listener = (msg: ProcessEvent) => { - msg.type === "event" && - msg.id === event && - callback({ ...msg.event, cancel }); + msg.type === "event" && msg.id === event && callback({ ...msg.event, cancel }); }; // TODO: assert the type is correct? @@ -127,7 +108,7 @@ async function rabbitListen( channel: Channel, id: string, callback: (event: EventOpts) => unknown, - opts?: { acknowledge?: boolean }, + opts?: { acknowledge?: boolean } ) { await channel.assertExchange(id, "fanout", { durable: false }); const q = await channel.assertQueue("", { @@ -162,7 +143,7 @@ async function rabbitListen( }, { noAck: !opts?.acknowledge, - }, + } ); return cancel; diff --git a/src/util/util/FieldError.ts b/src/util/util/FieldError.ts index 28e7e378..f6d53298 100644 --- a/src/util/util/FieldError.ts +++ b/src/util/util/FieldError.ts @@ -18,9 +18,7 @@ import "missing-native-js-functions"; -export function FieldErrors( - fields: Record<string, { code?: string; message: string }>, -) { +export function FieldErrors(fields: Record<string, { code?: string; message: string }>) { return new FieldError( 50035, "Invalid Form Body", @@ -31,7 +29,7 @@ export function FieldErrors( code: code || "BASE_TYPE_INVALID", }, ], - })), + })) ); } @@ -42,7 +40,7 @@ export class FieldError extends Error { constructor( public code: string | number, public message: string, - public errors?: object, // TODO: I don't like this typing. + public errors?: object // TODO: I don't like this typing. ) { super(message); } diff --git a/src/util/util/Gifs.ts b/src/util/util/Gifs.ts index a5a5e64c..94792877 100644 --- a/src/util/util/Gifs.ts +++ b/src/util/util/Gifs.ts @@ -18,8 +18,7 @@ export function parseGifResult(result: TenorGif) { export function getGifApiKey() { const { enabled, provider, apiKey } = Config.get().gif; if (!enabled) throw new HTTPError(`Gifs are disabled`); - if (provider !== "tenor" || !apiKey) - throw new HTTPError(`${provider} gif provider not supported`); + if (provider !== "tenor" || !apiKey) throw new HTTPError(`${provider} gif provider not supported`); return apiKey; } diff --git a/src/util/util/JSON.ts b/src/util/util/JSON.ts index c7dcf47e..767fc618 100644 --- a/src/util/util/JSON.ts +++ b/src/util/util/JSON.ts @@ -18,11 +18,7 @@ // Discord.com sends ISO strings with +00:00 extension, not Z // This causes issues with Python bot libs -const JSONReplacer = function ( - this: { [key: string]: unknown }, - key: string, - value: unknown, -) { +const JSONReplacer = function (this: { [key: string]: unknown }, key: string, value: unknown) { if (this[key] instanceof Date) { return (this[key] as Date).toISOString().replace("Z", "+00:00"); } diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts index 996c72ea..a030cc97 100644 --- a/src/util/util/Permissions.ts +++ b/src/util/util/Permissions.ts @@ -2,24 +2,13 @@ // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah // @fc-license-skip -import { - Channel, - ChannelPermissionOverwrite, - Guild, - Member, - Role, -} from "../entities"; +import { Channel, ChannelPermissionOverwrite, Guild, Member, Role } from "../entities"; import { BitField } from "./BitField"; import "missing-native-js-functions"; import { BitFieldResolvable, BitFlag } from "./BitField"; import { HTTPError } from "lambert-server"; -export type PermissionResolvable = - | bigint - | number - | Permissions - | PermissionResolvable[] - | PermissionString; +export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString; type PermissionString = keyof typeof Permissions.FLAGS; @@ -86,20 +75,14 @@ export class Permissions extends BitField { }; any(permission: PermissionResolvable, checkAdmin = true) { - return ( - (checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) || - super.any(permission) - ); + return (checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission); } /** * Checks whether the bitfield has a permission, or multiple permissions. */ has(permission: PermissionResolvable, checkAdmin = true) { - return ( - (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || - super.has(permission) - ); + return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission); } /** @@ -107,39 +90,28 @@ export class Permissions extends BitField { */ hasThrow(permission: PermissionResolvable) { if (this.has(permission) && this.has("VIEW_CHANNEL")) return true; - throw new HTTPError( - `You are missing the following permissions ${permission}`, - 403, - ); + throw new HTTPError(`You are missing the following permissions ${permission}`, 403); } overwriteChannel(overwrites: ChannelPermissionOverwrite[]) { if (!overwrites) return this; if (!this.cache) throw new Error("permission chache not available"); overwrites = overwrites.filter((x) => { - if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) - return true; + if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true; if (x.type === 1 && x.id == this.cache.user_id) return true; return false; }); - return new Permissions( - Permissions.channelPermission(overwrites, this.bitfield), - ); + return new Permissions(Permissions.channelPermission(overwrites, this.bitfield)); } - static channelPermission( - overwrites: ChannelPermissionOverwrite[], - init?: bigint, - ) { + static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) { // TODO: do not deny any permissions if admin return overwrites.reduce((permission, overwrite) => { // apply disallowed permission // * permission: current calculated permission (e.g. 010) // * deny contains all denied permissions (e.g. 011) // * allow contains all explicitly allowed permisions (e.g. 100) - return ( - (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow) - ); + return (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow); // ~ operator inverts deny (e.g. 011 -> 100) // & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000) // | operators adds both together (e.g. 000 + 100 -> 100) @@ -148,10 +120,7 @@ export class Permissions extends BitField { static rolePermission(roles: Role[]) { // adds all permissions of all roles together (Bit OR) - return roles.reduce( - (permission, role) => permission | BigInt(role.permissions), - BigInt(0), - ); + return roles.reduce((permission, role) => permission | BigInt(role.permissions), BigInt(0)); } static finalPermission({ @@ -182,8 +151,7 @@ export class Permissions extends BitField { } if (channel?.recipient_ids) { - if (channel?.owner_id === user.id) - return new Permissions("ADMINISTRATOR"); + if (channel?.owner_id === user.id) return new Permissions("ADMINISTRATOR"); if (channel.recipient_ids.includes(user.id)) { // Default dm permissions return new Permissions([ @@ -209,10 +177,7 @@ export class Permissions extends BitField { } } -const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce( - (total, val) => total | val, - BigInt(0), -); +const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce((total, val) => total | val, BigInt(0)); export type PermissionCache = { channel?: Channel | undefined; @@ -233,7 +198,7 @@ export async function getPermission( channel_relations?: string[]; member_select?: (keyof Member)[]; member_relations?: string[]; - } = {}, + } = {} ) { if (!user_id) throw new HTTPError("User not found"); let channel: Channel | undefined; @@ -262,8 +227,7 @@ export async function getPermission( select: ["id", "owner_id", ...(opts.guild_select || [])], relations: opts.guild_relations, }); - if (guild.owner_id === user_id) - return new Permissions(Permissions.FLAGS.ADMINISTRATOR); + if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR); member = await Member.findOneOrFail({ where: { guild_id, id: user_id }, diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts index 90ebe242..e154d927 100644 --- a/src/util/util/Rights.ts +++ b/src/util/util/Rights.ts @@ -22,12 +22,7 @@ import { BitFieldResolvable, BitFlag } from "./BitField"; import { User } from "../entities"; import { HTTPError } from "lambert-server"; -export type RightResolvable = - | bigint - | number - | Rights - | RightResolvable[] - | RightString; +export type RightResolvable = bigint | number | Rights | RightResolvable[] | RightString; type RightString = keyof typeof Rights.FLAGS; // TODO: just like roles for members, users should have privilidges which combine multiple rights into one and make it easy to assign @@ -97,35 +92,23 @@ export class Rights extends BitField { }; any(permission: RightResolvable, checkOperator = true) { - return ( - (checkOperator && super.any(Rights.FLAGS.OPERATOR)) || - super.any(permission) - ); + return (checkOperator && super.any(Rights.FLAGS.OPERATOR)) || super.any(permission); } has(permission: RightResolvable, checkOperator = true) { - return ( - (checkOperator && super.has(Rights.FLAGS.OPERATOR)) || - super.has(permission) - ); + return (checkOperator && super.has(Rights.FLAGS.OPERATOR)) || super.has(permission); } hasThrow(permission: RightResolvable) { if (this.has(permission)) return true; - throw new HTTPError( - `You are missing the following rights ${permission}`, - 403, - ); + throw new HTTPError(`You are missing the following rights ${permission}`, 403); } } -const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce( - (total, val) => total | val, - BigInt(0), -); +const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce((total, val) => total | val, BigInt(0)); export async function getRights( - user_id: string, + user_id: string /**, opts: { in_behalf?: (keyof User)[]; } = {} **/ diff --git a/src/util/util/Sentry.ts b/src/util/util/Sentry.ts index 74a23a1e..b51100f1 100644 --- a/src/util/util/Sentry.ts +++ b/src/util/util/Sentry.ts @@ -29,8 +29,7 @@ let errorHandlersUsed = false; export const Sentry = { /** Call BEFORE registering your routes */ init: async (app?: express.Application) => { - const { enabled, endpoint, traceSampleRate, environment } = - Config.get().sentry; + const { enabled, endpoint, traceSampleRate, environment } = Config.get().sentry; if (!enabled) return; if (SentryNode.getCurrentHub().getClient()) return; // we've already initialised sentry @@ -40,8 +39,8 @@ export const Sentry = { if (traceSampleRate >= 0.8) { console.log( `[Sentry] ${yellow( - "Your sentry trace sampling rate is >= 80%. For large loads, this may degrade performance.", - )}`, + "Your sentry trace sampling rate is >= 80%. For large loads, this may degrade performance." + )}` ); } @@ -61,7 +60,7 @@ export const Sentry = { integrations.push( new SentryNode.Integrations.Express({ app, - }), + }) ); SentryNode.init({ @@ -94,14 +93,8 @@ export const Sentry = { // Filter breadcrumbs that we don't care about if (x.message?.includes("identified as")) return false; if (x.message?.includes("[WebSocket] closed")) return false; - if ( - x.message?.includes( - "Got Resume -> cancel not implemented", - ) - ) - return false; - if (x.message?.includes("[Gateway] New connection from")) - return false; + if (x.message?.includes("Got Resume -> cancel not implemented")) return false; + if (x.message?.includes("[Gateway] New connection from")) return false; return true; }); diff --git a/src/util/util/Snowflake.ts b/src/util/util/Snowflake.ts index 93898fbb..8af567c7 100644 --- a/src/util/util/Snowflake.ts +++ b/src/util/util/Snowflake.ts @@ -18,9 +18,7 @@ export class Snowflake { static workerId = BigInt((cluster.worker?.id || 0) % 31); // max 31 constructor() { - throw new Error( - `The ${this.constructor.name} class may not be instantiated.`, - ); + throw new Error(`The ${this.constructor.name} class may not be instantiated.`); } /** @@ -115,9 +113,7 @@ export class Snowflake { * @returns {DeconstructedSnowflake} Deconstructed snowflake */ static deconstruct(snowflake) { - const BINARY = Snowflake.idToBinary(snowflake) - .toString(2) - .padStart(64, "0"); + const BINARY = Snowflake.idToBinary(snowflake).toString(2).padStart(64, "0"); const res = { timestamp: parseInt(BINARY.substring(0, 42), 2) + Snowflake.EPOCH, workerID: parseInt(BINARY.substring(42, 47), 2), diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts index 97bdec74..d2f5ac35 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts @@ -20,10 +20,7 @@ import jwt, { VerifyOptions } from "jsonwebtoken"; import { Config } from "./Config"; import { User } from "../entities"; // TODO: dont use deprecated APIs lol -import { - FindOptionsRelationByString, - FindOptionsSelectByString, -} from "typeorm"; +import { FindOptionsRelationByString, FindOptionsSelectByString } from "typeorm"; export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] }; @@ -37,50 +34,33 @@ export const checkToken = ( opts?: { select?: FindOptionsSelectByString<User>; relations?: FindOptionsRelationByString; - }, + } ): Promise<UserTokenData> => new Promise((resolve, reject) => { token = token.replace("Bot ", ""); // there is no bot distinction in sb token = token.replace("Bearer ", ""); // allow bearer tokens - jwt.verify( - token, - Config.get().security.jwtSecret, - JWTOptions, - async (err, out) => { - const decoded = out as UserTokenData["decoded"]; - if (err || !decoded) return reject("Invalid Token"); + jwt.verify(token, Config.get().security.jwtSecret, JWTOptions, async (err, out) => { + const decoded = out as UserTokenData["decoded"]; + if (err || !decoded) return reject("Invalid Token"); - const user = await User.findOne({ - where: decoded.email - ? { email: decoded.email } - : { id: decoded.id }, - select: [ - ...(opts?.select || []), - "bot", - "disabled", - "deleted", - "rights", - "data", - ], - relations: opts?.relations, - }); + const user = await User.findOne({ + where: decoded.email ? { email: decoded.email } : { id: decoded.id }, + select: [...(opts?.select || []), "bot", "disabled", "deleted", "rights", "data"], + relations: opts?.relations, + }); - if (!user) return reject("User not found"); + if (!user) return reject("User not found"); - // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds - if ( - decoded.iat * 1000 < - new Date(user.data.valid_tokens_since).setSeconds(0, 0) - ) - return reject("Invalid Token"); + // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds + if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0)) + return reject("Invalid Token"); - if (user.disabled) return reject("User disabled"); - if (user.deleted) return reject("User not found"); + if (user.disabled) return reject("User disabled"); + if (user.deleted) return reject("User not found"); - return resolve({ decoded, user }); - }, - ); + return resolve({ decoded, user }); + }); }); export async function generateToken(id: string, email?: string) { @@ -97,7 +77,7 @@ export async function generateToken(id: string, email?: string) { (err, token) => { if (err) return rej(err); return res(token); - }, + } ); }); } diff --git a/src/util/util/TraverseDirectory.ts b/src/util/util/TraverseDirectory.ts index cc4442fc..41ba6e9f 100644 --- a/src/util/util/TraverseDirectory.ts +++ b/src/util/util/TraverseDirectory.ts @@ -19,14 +19,13 @@ import { Server, traverseDirectory } from "lambert-server"; //if we're using ts-node, use ts files instead of js -const extension = - Symbol.for("ts-node.register.instance") in process ? "ts" : "js"; +const extension = Symbol.for("ts-node.register.instance") in process ? "ts" : "js"; const DEFAULT_FILTER = new RegExp("^([^.].*)(?<!\\.d).(" + extension + ")$"); export function registerRoutes(server: Server, root: string) { return traverseDirectory( { dirname: root, recursive: true, filter: DEFAULT_FILTER }, - server.registerRoute.bind(server, root), + server.registerRoute.bind(server, root) ); } diff --git a/src/util/util/WebAuthn.ts b/src/util/util/WebAuthn.ts index b0027b13..ec9e1760 100644 --- a/src/util/util/WebAuthn.ts +++ b/src/util/util/WebAuthn.ts @@ -37,32 +37,20 @@ export const WebAuthn: { }, }; -export async function generateWebAuthnTicket( - challenge: string, -): Promise<string> { +export async function generateWebAuthnTicket(challenge: string): Promise<string> { return new Promise((res, rej) => { - jwt.sign( - { challenge }, - Config.get().security.jwtSecret, - JWTOptions, - (err, token) => { - if (err || !token) return rej(err || "no token"); - return res(token); - }, - ); + jwt.sign({ challenge }, Config.get().security.jwtSecret, JWTOptions, (err, token) => { + if (err || !token) return rej(err || "no token"); + return res(token); + }); }); } export async function verifyWebAuthnToken(token: string) { return new Promise((res, rej) => { - jwt.verify( - token, - Config.get().security.jwtSecret, - JWTOptions, - async (err, decoded) => { - if (err) return rej(err); - return res(decoded); - }, - ); + jwt.verify(token, Config.get().security.jwtSecret, JWTOptions, async (err, decoded) => { + if (err) return rej(err); + return res(decoded); + }); }); } diff --git a/src/util/util/cdn.ts b/src/util/util/cdn.ts index f7d310a3..ff4e8527 100644 --- a/src/util/util/cdn.ts +++ b/src/util/util/cdn.ts @@ -25,7 +25,7 @@ import { Config } from "./Config"; export async function uploadFile( path: string, // These are the only props we use, don't need to enforce the full type. - file?: Pick<Express.Multer.File, "mimetype" | "originalname" | "buffer">, + file?: Pick<Express.Multer.File, "mimetype" | "originalname" | "buffer"> ): Promise<Attachment> { if (!file?.buffer) throw new HTTPError("Missing file in body"); @@ -35,27 +35,21 @@ export async function uploadFile( filename: file.originalname, }); - const response = await fetch( - `${Config.get().cdn.endpointPrivate || "http://localhost:3001"}${path}`, - { - headers: { - signature: Config.get().security.requestSignature, - ...form.getHeaders(), - }, - method: "POST", - body: form, + const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3001"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, + ...form.getHeaders(), }, - ); + method: "POST", + body: form, + }); const result = (await response.json()) as Attachment; if (response.status !== 200) throw result; return result; } -export async function handleFile( - path: string, - body?: string, -): Promise<string | undefined> { +export async function handleFile(path: string, body?: string): Promise<string | undefined> { if (!body || !body.startsWith("data:")) return undefined; try { const mimetype = body.split(":")[1].split(";")[0]; @@ -74,15 +68,12 @@ export async function handleFile( } export async function deleteFile(path: string) { - const response = await fetch( - `${Config.get().cdn.endpointPrivate || "http://localhost:3001"}${path}`, - { - headers: { - signature: Config.get().security.requestSignature, - }, - method: "DELETE", + const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3001"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, }, - ); + method: "DELETE", + }); const result = await response.json(); if (response.status !== 200) throw result; diff --git a/src/util/util/email/index.ts b/src/util/util/email/index.ts index 619cc5c3..514e3f1b 100644 --- a/src/util/util/email/index.ts +++ b/src/util/util/email/index.ts @@ -27,14 +27,7 @@ import MailJet from "./transports/MailJet"; import SMTP from "./transports/SMTP"; import SendGrid from "./transports/SendGrid"; -const ASSET_FOLDER_PATH = path.join( - __dirname, - "..", - "..", - "..", - "..", - "assets", -); +const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "..", "assets"); enum MailTypes { verify = "verify", @@ -54,22 +47,11 @@ const transporters: { export const Email: { transporter: Transporter | null; init: () => Promise<void>; - generateLink: ( - type: Omit<MailTypes, "pwchange">, - id: string, - email: string, - ) => Promise<string>; - sendMail: ( - type: MailTypes, - user: User, - email: string, - ) => Promise<SentMessageInfo>; + generateLink: (type: Omit<MailTypes, "pwchange">, id: string, email: string) => Promise<string>; + sendMail: (type: MailTypes, user: User, email: string) => Promise<SentMessageInfo>; sendVerifyEmail: (user: User, email: string) => Promise<SentMessageInfo>; sendResetPassword: (user: User, email: string) => Promise<SentMessageInfo>; - sendPasswordChanged: ( - user: User, - email: string, - ) => Promise<SentMessageInfo>; + sendPasswordChanged: (user: User, email: string) => Promise<SentMessageInfo>; doReplacements: ( template: string, user: User, @@ -79,7 +61,7 @@ export const Email: { city: string; region: string; country_name: string; - }, + } ) => string; } = { transporter: null, @@ -88,8 +70,7 @@ export const Email: { if (!provider) return; const transporterFn = transporters[provider]; - if (!transporterFn) - return console.error(`[Email] Invalid provider: ${provider}`); + if (!transporterFn) return console.error(`[Email] Invalid provider: ${provider}`); console.log(`[Email] Initializing ${provider} transport...`); const transporter = await transporterFn(); if (!transporter) return; @@ -108,7 +89,7 @@ export const Email: { city: string; region: string; country_name: string; - }, + } ) { const { instanceName } = Config.get().general; @@ -141,8 +122,7 @@ export const Email: { */ generateLink: async function (type, id, email) { const token = (await generateToken(id, email)) as string; - const instanceUrl = - Config.get().general.frontPage || "http://localhost:3001"; + const instanceUrl = Config.get().general.frontPage || "http://localhost:3001"; const link = `${instanceUrl}/${type}#token=${token}`; return link; }, @@ -163,31 +143,23 @@ export const Email: { pwchange: "password_changed.html", }; - const template = await fs.readFile( - path.join( - ASSET_FOLDER_PATH, - "email_templates", - templateNames[type], - ), - { encoding: "utf-8" }, - ); + const template = await fs.readFile(path.join(ASSET_FOLDER_PATH, "email_templates", templateNames[type]), { + encoding: "utf-8", + }); // replace email template placeholders const html = this.doReplacements( template, user, // password change emails don't have links - type != MailTypes.pwchange - ? await this.generateLink(type, user.id, email) - : undefined, + type != MailTypes.pwchange ? await this.generateLink(type, user.id, email) : undefined ); // extract the title from the email template to use as the email subject const subject = html.match(/<title>(.*)<\/title>/)?.[1] || ""; const message = { - from: - Config.get().general.correspondenceEmail || "noreply@localhost", + from: Config.get().general.correspondenceEmail || "noreply@localhost", to: email, subject, html, diff --git a/src/util/util/email/transports/MailGun.ts b/src/util/util/email/transports/MailGun.ts index badc9880..f961e80b 100644 --- a/src/util/util/email/transports/MailGun.ts +++ b/src/util/util/email/transports/MailGun.ts @@ -24,10 +24,7 @@ export default async function () { const { apiKey, domain } = Config.get().email.mailgun; // ensure all required configuration values are set - if (!apiKey || !domain) - return console.error( - "[Email] Mailgun has not been configured correctly.", - ); + if (!apiKey || !domain) return console.error("[Email] Mailgun has not been configured correctly."); let mg; try { @@ -36,7 +33,7 @@ export default async function () { } catch { // if the package is not installed, log an error and return void so we don't set the transporter console.error( - "[Email] Mailgun transport is not installed. Please run `npm install nodemailer-mailgun-transport --save-optional` to install it.", + "[Email] Mailgun transport is not installed. Please run `npm install nodemailer-mailgun-transport --save-optional` to install it." ); return; } diff --git a/src/util/util/email/transports/MailJet.ts b/src/util/util/email/transports/MailJet.ts index 69be7acf..b786c1db 100644 --- a/src/util/util/email/transports/MailJet.ts +++ b/src/util/util/email/transports/MailJet.ts @@ -24,10 +24,7 @@ export default async function () { const { apiKey, apiSecret } = Config.get().email.mailjet; // ensure all required configuration values are set - if (!apiKey || !apiSecret) - return console.error( - "[Email] Mailjet has not been configured correctly.", - ); + if (!apiKey || !apiSecret) return console.error("[Email] Mailjet has not been configured correctly."); let mj; try { @@ -36,7 +33,7 @@ export default async function () { } catch { // if the package is not installed, log an error and return void so we don't set the transporter console.error( - "[Email] Mailjet transport is not installed. Please run `npm install n0script22/nodemailer-mailjet-transport --save-optional` to install it.", + "[Email] Mailjet transport is not installed. Please run `npm install n0script22/nodemailer-mailjet-transport --save-optional` to install it." ); return; } diff --git a/src/util/util/email/transports/SMTP.ts b/src/util/util/email/transports/SMTP.ts index 5b43a870..cb32f6b4 100644 --- a/src/util/util/email/transports/SMTP.ts +++ b/src/util/util/email/transports/SMTP.ts @@ -29,7 +29,7 @@ export default async function () { if (!Config.get().general.correspondenceEmail) return console.error( - "[Email] Correspondence email has not been configured! This is used as the sender email address.", + "[Email] Correspondence email has not been configured! This is used as the sender email address." ); // construct the transporter diff --git a/src/util/util/email/transports/SendGrid.ts b/src/util/util/email/transports/SendGrid.ts index a863d3ec..7f4d13fb 100644 --- a/src/util/util/email/transports/SendGrid.ts +++ b/src/util/util/email/transports/SendGrid.ts @@ -24,10 +24,7 @@ export default async function () { const { apiKey } = Config.get().email.sendgrid; // ensure all required configuration values are set - if (!apiKey) - return console.error( - "[Email] SendGrid has not been configured correctly.", - ); + if (!apiKey) return console.error("[Email] SendGrid has not been configured correctly."); let sg; try { @@ -36,7 +33,7 @@ export default async function () { } catch { // if the package is not installed, log an error and return void so we don't set the transporter console.error( - "[Email] SendGrid transport is not installed. Please run `npm install Maria-Golomb/nodemailer-sendgrid-transport --save-optional` to install it.", + "[Email] SendGrid transport is not installed. Please run `npm install Maria-Golomb/nodemailer-sendgrid-transport --save-optional` to install it." ); return; } |