diff --git a/package.json b/package.json index 2487290..87b71aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "synergy3", - "version": "3.12.2", + "version": "3.13.2", "description": "Synergy 3 - Powerful Discord BOT Framework.", "license": "MIT", "author": { diff --git a/src/EventManager.ts b/src/EventManager.ts index 56bb46a..eed1f6f 100644 --- a/src/EventManager.ts +++ b/src/EventManager.ts @@ -53,11 +53,11 @@ class EventManager extends EventEmitter{ logger.info(`Fetching system user..`); await this.bot.users.updateAssociations(); - let sys = await this.bot.users.fetchOne(this.bot.client.user?.id ?? "alice"); + let sys = await this.bot.users.fetchOne("0"); if(!sys){ logger.info(`No system user. Creating new one..`); - sys = await this.bot.users.createFromDiscord(this.bot.client.user!, [ Access.ADMIN() ]); - logger.info(`Created system user. ID: ${sys.id}`); + sys = await this.bot.users.createFromDiscord(this.bot.client.user!, [ Access.ADMIN() ], true); + logger.info(`Created system user. ID: ${sys.unifiedId}`); } logger.info(`Database Synchronized.`); diff --git a/src/InteractionsManager.ts b/src/InteractionsManager.ts index a36812a..cadef99 100644 --- a/src/InteractionsManager.ts +++ b/src/InteractionsManager.ts @@ -56,6 +56,22 @@ export default class InteractionsManager{ return cmd; } + /** + * This method allows to emulate incoming interaction. + * @param interaction interaction to emulate + */ + public emulate(interaction: Discord.Interaction) { + this.onInteractionCreate(interaction).catch(e => GlobalLogger.root.error("Error emulating interaction:", e)); + } + + /** + * This method allows to asynchronously emulate incoming interaction. + * @param interaction interaction to emulate + */ + public async emulateAsync(interaction: Discord.Interaction) { + await this.onInteractionCreate(interaction).catch(e => GlobalLogger.root.error("Error emulating interaction:", e)); + } + /** * @param name command name * @param access access targets that allowed to use this command @@ -328,7 +344,7 @@ export default class InteractionsManager{ GlobalLogger.root.warn("InteractionsManager.InteractionProcessing: Passed invalid user access target \"", a + "\""); continue; } - if(user.id.toString() === res[1] || user.discord.id === res[1]){ + if(user.unifiedId === res[1] || user.discord?.id === res[1]){ access_flag = true; break; } diff --git a/src/Models/StorageUser.ts b/src/Models/StorageUser.ts index 5f31621..bbaf0b4 100644 --- a/src/Models/StorageUser.ts +++ b/src/Models/StorageUser.ts @@ -1,6 +1,7 @@ -import { Table, Model, Column, DataType, HasOne } from "sequelize-typescript"; +import { Column, DataType, HasOne, Model, Table } from "sequelize-typescript"; import { StorageUserDiscordInfo } from "./StorageUserDiscordInfo"; import { StorageUserEconomyInfo } from "./StorageUserEconomyInfo"; +import { UnifiedId, UnifiedIdDataType } from "../UnifiedId"; interface StorageUserMeta{ } @@ -11,12 +12,12 @@ interface StorageUserMeta{ export class StorageUser extends Model { //Main Options @Column({ - type: DataType.INTEGER, + type: DataType.STRING, allowNull: false, primaryKey: true, - autoIncrement: true + defaultValue: () => UnifiedId.generate(UnifiedIdDataType.User).toString(16) }) - declare id: number; + declare unifiedId: string; @Column({ type: DataType.STRING, @@ -24,12 +25,6 @@ export class StorageUser extends Model { }) declare nickname: string; - @Column({ - type: DataType.STRING, - allowNull: false, - }) - declare discordId: string; - @Column({ type: DataType.JSONB, allowNull: false, @@ -45,7 +40,7 @@ export class StorageUser extends Model { declare lang: string; @HasOne(() => StorageUserDiscordInfo) - declare discord: StorageUserDiscordInfo; + declare discord?: StorageUserDiscordInfo; @HasOne(() => StorageUserEconomyInfo) declare economy: StorageUserEconomyInfo; diff --git a/src/Models/StorageUserDiscordInfo.ts b/src/Models/StorageUserDiscordInfo.ts index cae680b..cd65d88 100644 --- a/src/Models/StorageUserDiscordInfo.ts +++ b/src/Models/StorageUserDiscordInfo.ts @@ -8,7 +8,7 @@ export class StorageUserDiscordInfo extends Model { @ForeignKey(() => StorageUser) @PrimaryKey @Column - declare id: number; + declare unifiedId: string; @BelongsTo(() => StorageUser) declare user: StorageUser; diff --git a/src/Models/StorageUserEconomyInfo.ts b/src/Models/StorageUserEconomyInfo.ts index 855d02b..f7474e6 100644 --- a/src/Models/StorageUserEconomyInfo.ts +++ b/src/Models/StorageUserEconomyInfo.ts @@ -8,29 +8,29 @@ export class StorageUserEconomyInfo extends Model { @ForeignKey(() => StorageUser) @PrimaryKey @Column - id!: number; + declare unifiedId: string; @BelongsTo(() => StorageUser) - user!: StorageUser + declare user: StorageUser //Economy Options @Column({ type: DataType.REAL, allowNull: false, }) - economyPoints!: number; + declare economyPoints: number; @Column({ type: DataType.INTEGER, allowNull: false, defaultValue: 1 }) - economyLVL!: number; + declare economyLVL: number; @Column({ type: DataType.INTEGER, allowNull: false, defaultValue: 0 }) - economyXP!: number; + declare economyXP: number; } \ No newline at end of file diff --git a/src/ModuleManager.ts b/src/ModuleManager.ts index fa543f4..17a99b3 100644 --- a/src/ModuleManager.ts +++ b/src/ModuleManager.ts @@ -19,9 +19,10 @@ const Modules: Module[] = []; const ModuleRegistry: Map = new Map(); export default class ModuleManager{ - public data: ModuleDataManager = new ModuleDataManager(this.bot); + public data: ModuleDataManager; constructor(public bot: Synergy){ + this.data = new ModuleDataManager(this.bot); } public RegisterModule(mod: typeof Module, uuid: string, preLoad: boolean = false){ diff --git a/src/Modules/Core/Profile.ts b/src/Modules/Core/Profile.ts index d3a3f93..31e8af4 100644 --- a/src/Modules/Core/Profile.ts +++ b/src/Modules/Core/Profile.ts @@ -37,7 +37,7 @@ export default class Profile extends Module{ title: `${user.nickname}'s profile`, thumbnail: user.discord?.avatar ? { url: user.discord.avatar } : undefined, fields: [ - { name: "Info", value: `ID: ${user.id}\n` + + { name: "Info", value: `ID: ${user.unifiedId}\n` + `Groups: ${user.groups.join(", ")}\n` + `Language: ${user.lang}` }, diff --git a/src/Structures/Access.ts b/src/Structures/Access.ts index 08318e2..4ab5f48 100644 --- a/src/Structures/Access.ts +++ b/src/Structures/Access.ts @@ -62,12 +62,15 @@ export default class Access { GlobalLogger.root.warn("Access.Check: Passed invalid user access target \"", a + "\""); continue; } - if(user.id.toString() === res[1] || user.discord.id === res[1]){ + if(user.unifiedId.toString() === res[1] || user.discord?.id === res[1]){ access_flag = true; break; } } if(guild && a.startsWith("role")){ + if(!user.discord) { + continue; + } let res = /role<(.*)>/.exec(a); if(!res || !res[1]){ GlobalLogger.root.warn("Access.Check: Passed invalid role access target \"", a + "\""); @@ -80,6 +83,9 @@ export default class Access { } } if(guild && a.startsWith("perm")){ + if(!user.discord) { + continue; + } let res = /perm<(.*)>/.exec(a); if(!res || !res[1]){ GlobalLogger.root.warn("Access.Check: Passed invalid perm access target \"", a + "\""); @@ -95,6 +101,9 @@ export default class Access { } } if(guild && a.startsWith("server_mod")){ + if(!user.discord) { + continue; + } let member = guild.members.cache.get(user.discord.id); if(member){ let configEntry = user.bot.config.getConfigEntry("guild", "moderator_role"); @@ -117,6 +126,9 @@ export default class Access { } } if(guild && a.startsWith("server_admin")){ + if(!user.discord) { + continue; + } let member = guild.members.cache.get(user.discord.id); if(member){ if(member.permissions.has("Administrator")){ diff --git a/src/Structures/Errors.ts b/src/Structures/Errors.ts index dc97e88..ffe84a3 100644 --- a/src/Structures/Errors.ts +++ b/src/Structures/Errors.ts @@ -30,7 +30,7 @@ export class MissingPermissionsError extends SynergyUserError { export class UserAlreadyExistError extends Error { constructor(user: User | Discord.User){ - super(`Error: User ${user instanceof Discord.User ? user.tag : user.nickname}(${user.id}) already exist.`); + super(`Error: User ${user instanceof Discord.User ? `${user.tag}(${user.id})` : `${user.nickname}(${user.unifiedId})`} already exist.`); } } diff --git a/src/Structures/User.ts b/src/Structures/User.ts index 7fbe1a8..3ea9ac6 100644 --- a/src/Structures/User.ts +++ b/src/Structures/User.ts @@ -19,30 +19,27 @@ export interface UserDiscordOptions { } export interface UserOptions{ - id: number; + unifiedId: string; nickname: string; groups: string[]; lang: string; - discordId: string; - discord: UserDiscordOptions; + discord?: UserDiscordOptions; economy: UserEconomyOptions; } export default class User implements UserOptions{ - public id: number; + public unifiedId: string; public nickname: string; public groups: string[]; public lang: string; - public discordId: string; public economy: UserEconomyOptions; - public discord: UserDiscordOptions; + public discord?: UserDiscordOptions; constructor(public bot: Synergy, opts: UserOptions){ - this.id = opts.id; + this.unifiedId = opts.unifiedId; this.nickname = opts.nickname; this.groups = opts.groups; this.lang = opts.lang; - this.discordId = opts.discordId; this.economy = opts.economy; this.discord = opts.discord; } @@ -51,30 +48,45 @@ export default class User implements UserOptions{ return await Access.Check(this, access, guild); } + public bindDiscord(user: Discord.User) { + this.discord = { + user, + id: user.id, + tag: user.tag, + avatar: user.avatarURL() ?? undefined, + banner: user.bannerURL() ?? undefined, + createdAt: user.createdAt + } + } + public async fetchDiscordUser() { - this.discord.user = await this.bot.client.users.fetch(this.discordId); + if(!this.discord) return; + + this.discord.user = await this.bot.client.users.fetch(this.discord.id); this.discord.tag = this.discord.user.tag; - this.discord.avatar = this.discord.user.displayAvatarURL(); - this.discord.banner = this.discord.user.banner ?? undefined; + this.discord.avatar = this.discord.user.avatarURL() ?? undefined; + this.discord.banner = this.discord.user.bannerURL() ?? undefined; return this.discord.user; } public static fromStorageUser(bot: Synergy, storageUser: StorageUser): User { - let discordOpts: UserDiscordOptions = { - id: storageUser.discord.discordId, - tag: storageUser.discord.discordTag, - createdAt: storageUser.discord.discordCreatedAt, - avatar: storageUser.discord.discordAvatar ?? undefined, - banner: storageUser.discord.discordBanner ?? undefined, - user: undefined - }; + let discordOpts: UserDiscordOptions | undefined; + + if(storageUser.discord) { + discordOpts = { + id: storageUser.discord.discordId, + tag: storageUser.discord.discordTag, + avatar: storageUser.discord.discordAvatar ?? undefined, + banner: storageUser.discord.discordBanner ?? undefined, + createdAt: storageUser.discord.discordCreatedAt, + }; + } - let user = new User(bot, { - id: storageUser.id, + return new User(bot, { + unifiedId: storageUser.unifiedId, nickname: storageUser.nickname, groups: storageUser.groups, lang: storageUser.lang, - discordId: storageUser.discordId, discord: discordOpts, economy: { points: storageUser.economy.economyPoints, @@ -82,6 +94,5 @@ export default class User implements UserOptions{ xp: storageUser.economy.economyXP } }); - return user; } } \ No newline at end of file diff --git a/src/UnifiedId.ts b/src/UnifiedId.ts new file mode 100644 index 0000000..a5d0c02 --- /dev/null +++ b/src/UnifiedId.ts @@ -0,0 +1,68 @@ +/* + +--------------------------------------------------------------------+ + | Unified ID Binary Structure | + +--------------------------------------------------------------------+ + | 64 20 15 0 | + | 11111111111111111111111111111111111111111111 11111 111111111111111 | + +--------------------------------------------------------------------+ + + +------------------------------------------------------------------------------------------+ + | Unified ID components description | + +---------+--------------------------------------------------------------------------------+ + | [64-20] | Milliseconds from RainbowBOT Epoch (April 28 of 2019 TZ=GMT+0 - 1556409600000) | + +---------+--------------------------------------------------------------------------------+ + | [20-15] | Associated data type: | + | | 0 - Reserved | + | | 1 - Any data | + | | 2 - User | + | | 3 - Discord Guild | + | | 4 - Discord Channel | + | | 5 - Other channel | + | | ... | + +---------+--------------------------------------------------------------------------------+ + | [15-00] | Increment number | + +---------+--------------------------------------------------------------------------------+ + */ + +export const RainbowBOTEpoch = 1556409600000; + +export enum UnifiedIdDataType { + RESERVED = 0, + AnyData = 1, + User = 2, + DiscordGuild = 3, + DiscordChannel = 4, + OtherChannel = 5, +} + +export class UnifiedId { + private static increment = 0; + public static generate(dataType: UnifiedIdDataType = UnifiedIdDataType.AnyData, milliseconds?: number, increment?: number) { + if(milliseconds === undefined) { + milliseconds = new Date().getTime() - RainbowBOTEpoch; + } + if(increment === undefined) { + UnifiedId.increment++; + if(UnifiedId.increment >= 32768) { + UnifiedId.increment = 0; + } + increment = UnifiedId.increment; + } + + return BigInt(increment) + + (BigInt(dataType) << 15n) + + (BigInt(milliseconds) << 20n) + } + + public static parse(id: bigint) { + let milliseconds = id >> 20n; + let dataType = (id - (milliseconds << 20n)) >> 15n; + let increment = (id - (milliseconds << 20n) - (dataType << 15n)); + + return { + milliseconds: Number(milliseconds), + dataType: Number(dataType) as UnifiedIdDataType, + increment: Number(increment) + } + } +} \ No newline at end of file diff --git a/src/UserManager.ts b/src/UserManager.ts index fd0c72f..4121696 100644 --- a/src/UserManager.ts +++ b/src/UserManager.ts @@ -1,6 +1,6 @@ import Discord from "discord.js"; -import { Op } from "sequelize"; +import { Op, Transaction } from "sequelize"; import { sequelize } from "./Database"; import { StorageUserDiscordInfo } from "./Models/StorageUserDiscordInfo"; import { StorageUserEconomyInfo } from "./Models/StorageUserEconomyInfo"; @@ -8,32 +8,32 @@ import { StorageUser } from "./Models/StorageUser"; import { GlobalLogger } from "./GlobalLogger"; import Synergy from "./Synergy"; -import User, { UserDiscordOptions } from "./Structures/User"; +import User, { UserOptions } from "./Structures/User"; import { Access } from "."; import { UserAlreadyExistError } from "./Structures/Errors"; import CachedManager from "./Structures/CachedManager"; export default class UserManager extends CachedManager{ - private discordIdsAssociations: Map = new Map(); + private discordIdsAssociations: Map = new Map(); constructor(public bot: Synergy){ super(); this.cacheStorage.on("del", this.onCacheEntryDeleted.bind(this)); } /** - * Get legacy underlying database User id from Discord id - * @param id + * Get unified User id from Discord id + * @param unifiedId */ - public idFromDiscordId(id: string): number | undefined{ - return this.discordIdsAssociations.get(id); + public unifiedIdFromDiscordId(unifiedId: string): string | undefined{ + return this.discordIdsAssociations.get(unifiedId); } /** - * Get User Discord id from legacy underlying database id - * @param id + * Get User Discord id from unified id + * @param discordId */ - public discordIdFromLegacyId(id: number): string | undefined { - let entry = Array.from(this.discordIdsAssociations.entries()).find(e => e[1] === id); + public discordIdFromUnifiedId(discordId: string): string | undefined { + let entry = Array.from(this.discordIdsAssociations.entries()).find(e => e[1] === discordId); if(entry) { return entry[0]; } @@ -41,39 +41,37 @@ export default class UserManager extends CachedManager{ /** * Fetches User from storage - * @param id Discord id of user to fetch + * @param id Unified id of user to fetch */ - public async fetchOne(id: string) { + public async fetchOne(id: string): Promise { let storageUser = await StorageUser.findOne({ where: { - discordId: id + unifiedId: id }, include: [StorageUserDiscordInfo, StorageUserEconomyInfo] }); - let user; if (!storageUser) { - let discordUser = await this.bot.client.users.fetch(id); - user = await this.createFromDiscord(discordUser); - } else { - user = User.fromStorageUser(this.bot, storageUser); - await user.fetchDiscordUser(); + return; } + let user = User.fromStorageUser(this.bot, storageUser); + await user.fetchDiscordUser(); + this.cacheStorage.set(id, user); return user; } /** * Fetches multiple Users from storage - * @param ids Discord ids of users to fetch + * @param ids Unified ids of users to fetch */ public async fetchBulk(ids: string[]) { let res: Map = new Map(); let storageUsers = await StorageUser.findAll({ where: { - discordId: { + unifiedId: { [Op.in]: ids } }, @@ -84,21 +82,44 @@ export default class UserManager extends CachedManager{ let user = User.fromStorageUser(this.bot, storageUser); await user.fetchDiscordUser(); - this.cacheStorage.set(user.id, user); - res.set(user.discordId, user); + this.cacheStorage.set(user.unifiedId, user); + res.set(user.unifiedId, user); } - let unfetchedUsers = ids.filter(id => storageUsers.findIndex(su => su.discordId === id) === -1); + let unfetchedUsers = ids.filter(id => storageUsers.findIndex(su => su.unifiedId === id) === -1); for(let id of unfetchedUsers) { let user = await this.fetchOne(id); - this.cacheStorage.set(user.id, user); - res.set(user.discordId, user); + if(!user) continue; + this.cacheStorage.set(user.unifiedId, user); + res.set(user.unifiedId, user); } return res; } - public async createFromDiscord(dUser: Discord.User, groups: string[] = [ Access.PLAYER() ]){ + public async createUser(options: Omit & Partial>, system: boolean = false) { + let storageUser = await StorageUser.create({ + unifiedId: system ? "0" : undefined, + nickname: options.nickname, + groups: options.groups, + lang: options.lang, + } as StorageUser); + + let user = new User(this.bot, { + ...options, + economy: options.economy ?? this.bot.options.userDefaultEconomy ?? { + points: 0.0005, + lvl: 1, + xp: 0 + }, + unifiedId: storageUser.unifiedId + }); + + this.cacheStorage.set(user.unifiedId, user); + return user; + } + + public async createFromDiscord(dUser: Discord.User, groups: string[] = [ Access.PLAYER() ], system: boolean = false){ let userDiscordInfo = await StorageUserDiscordInfo.findOne({ where: { discordId: dUser.id @@ -107,43 +128,71 @@ export default class UserManager extends CachedManager{ if(userDiscordInfo) throw new UserAlreadyExistError(dUser); - let storageUser = await StorageUser.create({ + let user = await this.createUser({ nickname: dUser.tag, groups, - lang: "en", - discordId: dUser.id - } as StorageUser); + lang: "en" + }, system); - let discord: UserDiscordOptions = { - id: dUser.id, - tag: dUser.tag, - createdAt: dUser.createdAt, - avatar: dUser.displayAvatarURL(), - banner: dUser.banner ?? undefined, - user: dUser + user.bindDiscord(dUser); + return user; + } + + public async forceStorageUpdate(unifiedId: string, transaction?: Transaction) { + let user = await this.get(unifiedId); + if(!user) return; + + let t = transaction; + if(!t) { + t = await sequelize().transaction(); } - let user = new User(this.bot, { - id: storageUser.id, - nickname: storageUser.nickname, - groups: storageUser.groups, - lang: storageUser.lang, - discordId: storageUser.discordId, - discord, - economy: this.bot.options.userDefaultEconomy || { - points: 0.0005, - lvl: 1, - xp: 0 + + try { + await StorageUser.update({ + nickname: user.nickname, + groups: user.groups, + lang: user.lang, + }, { + where: { + unifiedId: user.unifiedId + }, + transaction: t + }); + + await StorageUserEconomyInfo.upsert({ + unifiedId: user.unifiedId, + economyPoints: user.economy.points, + economyLVL: user.economy.lvl, + economyXP: user.economy.xp, + } as StorageUserEconomyInfo, { + transaction: t + }); + + if(user.discord) { + await StorageUserDiscordInfo.upsert({ + unifiedId: user.unifiedId, + discordId: user.discord.id, + discordTag: user.discord.tag, + discordAvatar: user.discord.avatar, + discordBanner: user.discord.banner, + discordCreatedAt: user.discord.createdAt, + } as StorageUserDiscordInfo, { + transaction: t + }); } - }); - this.cacheStorage.set(user.discordId, user); - return user; + if(!transaction) { + await t.commit(); + } + } catch(e) { + GlobalLogger.root.warn("UserManager.forceStorageUpdate Error:", e); + } } public async updateAssociations(){ let infos = await StorageUserDiscordInfo.findAll(); for(let i of infos){ - this.discordIdsAssociations.set(i.discordId, i.id); + this.discordIdsAssociations.set(i.discordId, i.unifiedId); } } @@ -154,40 +203,7 @@ export default class UserManager extends CachedManager{ await super.destroy(); } - private async onCacheEntryDeleted(discordId: string, user: User) { - let t = await sequelize().transaction(); - - await StorageUser.update({ - nickname: user.nickname, - groups: user.groups, - lang: user.lang, - }, { - where: { - id: user.id - }, - transaction: t - }).catch(err => GlobalLogger.root.warn("UserManager.onCacheEntryDeleted Error Updating StorageUser:", err)); - - await StorageUserEconomyInfo.upsert({ - id: user.id, - economyPoints: user.economy.points, - economyLVL: user.economy.lvl, - economyXP: user.economy.xp, - } as StorageUserEconomyInfo, { - transaction: t - }).catch(err => GlobalLogger.root.warn("UserManager.onCacheEntryDeleted Error Upserting StorageUserEconomyInfo:", err)); - - await StorageUserDiscordInfo.upsert({ - id: user.id, - discordId: user.discord.id, - discordTag: user.discord.tag, - discordAvatar: user.discord.avatar, - discordBanner: user.discord.banner, - discordCreatedAt: user.discord.createdAt, - } as StorageUserDiscordInfo, { - transaction: t - }).catch(err => GlobalLogger.root.warn("UserManager.onCacheEntryDeleted Error Upserting StorageUserDiscordInfo:", err)); - - await t.commit(); + private async onCacheEntryDeleted(unifiedId: string, user: User) { + await this.forceStorageUpdate(unifiedId); } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index aef3aa1..23da7b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,6 +38,7 @@ import { dataStructureToString } from "./ConfigManager/ConfigDataStructures" import { ConfigCommonDataType, TypeOfConfigDataType } from "./ConfigManager/ConfigDataTypes" +import { UnifiedId } from "./UnifiedId" export { Guild, @@ -83,7 +84,7 @@ export { ArrayConfigEntry, -EventManager, + EventManager, InteractionsManager, InteractiveCommand, @@ -109,5 +110,7 @@ EventManager, SynergyUserError, GuildOnlyError, NoConfigEntryError, - MissingPermissionsError + MissingPermissionsError, + + UnifiedId } \ No newline at end of file diff --git a/tests/DummyBOT.ts b/tests/DummyBOT.ts index 78f99d5..599ab7a 100644 --- a/tests/DummyBOT.ts +++ b/tests/DummyBOT.ts @@ -15,7 +15,8 @@ class DummyClient extends EventEmitter { return { id, tag: "TestUser#1337", - avatar: "https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp", + avatarURL: () => "https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp", + bannerURL: () => "banner url lol", createdAt: new Date(), displayAvatarURL: () => "https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp" } @@ -30,10 +31,10 @@ class DummyBOT { }; public isReady = true; public users = { - idFromDiscordId: (id: string) => { return 1337 }, + unifiedIdFromDiscordId: (id: string) => { return "234abc" }, fetchOne: (id: string) => { return new User(this as unknown as Synergy, { - id: this.users.idFromDiscordId(id), + unifiedId: this.users.unifiedIdFromDiscordId(id), nickname: "TestUser#1337", groups: [ "palayer" ], lang: "en", @@ -42,7 +43,6 @@ class DummyBOT { xp: 0, lvl: 1 }, - discordId: id, discord: { id, tag: "TestUser#1337", @@ -54,7 +54,7 @@ class DummyBOT { fetchBulk: (ids: string[]) => { return ids.map(id => new User(this as unknown as Synergy, { - id: this.users.idFromDiscordId(id), + unifiedId: this.users.unifiedIdFromDiscordId(id), nickname: "TestUser#1337", groups: [ "palayer" ], lang: "en", @@ -63,7 +63,6 @@ class DummyBOT { xp: 0, lvl: 1 }, - discordId: id, discord: { id, tag: "TestUser#1337", diff --git a/tests/UserManager.test.ts b/tests/UserManager.test.ts index b46499f..e04428f 100644 --- a/tests/UserManager.test.ts +++ b/tests/UserManager.test.ts @@ -12,33 +12,31 @@ test("UserManager - Test ids associations", async () => { initsequelize("sqlite:database.sqlite"); await sequelize().sync({ force: true }); - let ids: Map = new Map(); + let ids: Map = new Map(); for(let i = 0; i < 100; i++){ let d_id = crypto.pseudoRandomBytes(12).toString("hex"); try { let user = await StorageUser.create({ - discordId: d_id, nickname: `TestUser#${i}`, groups: [ "player" ], lang: "en", } as StorageUser); let economy = await StorageUserEconomyInfo.create({ - id: user.id, + unifiedId: user.unifiedId, economyPoints: 1337, economyLVL: 69, economyXP: 420, } as StorageUserEconomyInfo); let discord = await StorageUserDiscordInfo.create({ - id: user.id, + unifiedId: user.unifiedId, discordId: d_id, discordTag: `TestUser#${i}`, - discordAvatar: `https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp`, discordCreatedAt: new Date(), } as StorageUserDiscordInfo); - ids.set(d_id, user.id); + ids.set(d_id, user.unifiedId); } catch (error) { return console.log(error); } @@ -48,7 +46,7 @@ test("UserManager - Test ids associations", async () => { await umgr.updateAssociations(); for(let e of ids){ - let id = umgr.idFromDiscordId(e[0]); + let id = umgr.unifiedIdFromDiscordId(e[0]); expect(id).toBe(e[1]); } @@ -61,33 +59,31 @@ test("UserManager - fetchOne", async () => { initsequelize("sqlite::memory:"); await sequelize().sync({ force: true }); - let ids: Map = new Map(); + let ids: Map = new Map(); for(let i = 0; i < 100; i++){ let d_id = crypto.pseudoRandomBytes(12).toString("hex"); try { let user = await StorageUser.create({ - discordId: d_id, nickname: `TestUser#${i}`, groups: [ "player" ], lang: "en", } as StorageUser); let economy = await StorageUserEconomyInfo.create({ - id: user.id, + unifiedId: user.unifiedId, economyPoints: 1337, economyLVL: 69, economyXP: 420, } as StorageUserEconomyInfo); let discord = await StorageUserDiscordInfo.create({ - id: user.id, + unifiedId: user.unifiedId, discordId: d_id, discordTag: `TestUser#${i}`, - discordAvatar: `https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp`, discordCreatedAt: new Date(), } as StorageUserDiscordInfo); - ids.set(d_id, user.id); + ids.set(d_id, user.unifiedId); } catch (error) { return console.log(error); } @@ -97,12 +93,12 @@ test("UserManager - fetchOne", async () => { await umgr.updateAssociations(); for(let e of ids){ - let user = await umgr.fetchOne(e[0]); + let user = await umgr.fetchOne(e[1]); if(!user) return fail(`User ${e} failed to fetch.`); expect(user).toBeTruthy(); - expect(user.id).toBe(e[1]); - expect(user.discord.id).toBe(e[0]); + expect(user.unifiedId).toBe(e[1]); + expect(user.discord?.id).toBe(e[0]); } bot.events.emit("Stop"); @@ -114,33 +110,31 @@ test("UserManager - fetchBulk", async () => { initsequelize("sqlite::memory:"); await sequelize().sync({ force: true }); - let ids: Map = new Map(); + let ids: Map = new Map(); for(let i = 0; i < 100; i++){ let d_id = crypto.pseudoRandomBytes(12).toString("hex"); try { let user = await StorageUser.create({ - discordId: d_id, nickname: `TestUser#${i}`, groups: [ "player" ], lang: "en", } as StorageUser); let economy = await StorageUserEconomyInfo.create({ - id: user.id, + unifiedId: user.unifiedId, economyPoints: 1337, economyLVL: 69, economyXP: 420, } as StorageUserEconomyInfo); let discord = await StorageUserDiscordInfo.create({ - id: user.id, + unifiedId: user.unifiedId, discordId: d_id, discordTag: `TestUser#${i}`, - discordAvatar: `https://cdn.discordapp.com/avatars/508637328349331462/ced8cce78f895423ffa0fda824697c2e.webp`, discordCreatedAt: new Date(), } as StorageUserDiscordInfo); - ids.set(d_id, user.id); + ids.set(d_id, user.unifiedId); } catch (error) { return console.log(error); } @@ -149,13 +143,13 @@ test("UserManager - fetchBulk", async () => { let umgr = new UserManager(bot); await umgr.updateAssociations(); - let users = await umgr.fetchBulk(Array.from(ids.keys())); + let users = await umgr.fetchBulk(Array.from(ids.values())); expect(users.size).toBe(ids.size); for(let u of users.values()){ expect(u).toBeTruthy(); - expect(ids.get(u.discord.id)).toBe(u.id); + expect(ids.get(u.discord!.id)).toBe(u.unifiedId); } bot.events.emit("Stop"); diff --git a/tsconfig.json b/tsconfig.json index af5dbae..5e044d1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */