aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2022-01-08 12:25:35 -0500
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2022-01-08 12:25:35 -0500
commit0e160ae77477f0986a02746e84158329299f438f (patch)
tree55a70950bae700bbd77ff693aecd1b2cbf0777cf /src/lib
parent42eab3390f7e2fcdc020eb1e3d602a46c9f34273 (diff)
downloadtanzanite-0e160ae77477f0986a02746e84158329299f438f.tar.gz
tanzanite-0e160ae77477f0986a02746e84158329299f438f.tar.bz2
tanzanite-0e160ae77477f0986a02746e84158329299f438f.zip
add shared db
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts76
-rw-r--r--src/lib/extensions/discord-akairo/BushClientUtil.ts42
-rw-r--r--src/lib/index.ts1
-rw-r--r--src/lib/models/Global.ts9
-rw-r--r--src/lib/models/Guild.ts1
-rw-r--r--src/lib/models/Level.ts1
-rw-r--r--src/lib/models/Shared.ts49
-rw-r--r--src/lib/models/__helpers.ts1
-rw-r--r--src/lib/utils/BushCache.ts7
9 files changed, 151 insertions, 36 deletions
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
index 8cbc6fe..65b60eb 100644
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ b/src/lib/extensions/discord-akairo/BushClient.ts
@@ -42,7 +42,7 @@ import {
import EventEmitter from 'events';
import path from 'path';
import readline from 'readline';
-import type { Sequelize as SequelizeType } from 'sequelize';
+import type { Options as SequelizeOptions, Sequelize as SequelizeType } from 'sequelize';
import { fileURLToPath } from 'url';
import UpdateCacheTask from '../../../tasks/updateCache.js';
import UpdateStatsTask from '../../../tasks/updateStats.js';
@@ -52,6 +52,7 @@ import { Guild as GuildModel } from '../../models/Guild.js';
import { Level } from '../../models/Level.js';
import { ModLog } from '../../models/ModLog.js';
import { Reminder } from '../../models/Reminder.js';
+import { Shared } from '../../models/Shared.js';
import { Stat } from '../../models/Stat.js';
import { StickyRole } from '../../models/StickyRole.js';
import { AllowedMentions } from '../../utils/AllowedMentions.js';
@@ -152,9 +153,14 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
public contextMenuCommandHandler: ContextMenuCommandHandler;
/**
- * The database connection for the bot.
+ * The database connection for this instance of the bot (production, beta, or development).
*/
- public db: SequelizeType;
+ public instanceDB: SequelizeType;
+
+ /**
+ * The database connection that is shared between all instances of the bot.
+ */
+ public sharedDB: SequelizeType;
/**
* A custom logging system for the bot.
@@ -201,6 +207,9 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
this.token = config.token as If<Ready, string, string | null>;
this.config = config;
+ this.util = new BushClientUtil(this);
+
+ /* handlers */
this.listenerHandler = new BushListenerHandler(this, {
directory: path.join(__dirname, '..', '..', '..', 'listeners'),
automateCategories: true
@@ -250,9 +259,9 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
directory: path.join(__dirname, '..', '..', '..', 'context-menu-commands'),
automateCategories: true
});
- this.util = new BushClientUtil(this);
- this.db = new Sequelize({
- database: this.config.isDevelopment ? 'bushbot-dev' : this.config.isBeta ? 'bushbot-beta' : 'bushbot',
+
+ /* databases */
+ const sharedDBOptions: SequelizeOptions = {
username: this.config.db.username,
password: this.config.db.password,
dialect: 'postgres',
@@ -260,9 +269,18 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
port: this.config.db.port,
logging: this.config.logging.db ? (sql) => this.logger.debug(sql) : false,
timezone: 'America/New_York'
+ };
+ this.instanceDB = new Sequelize({
+ ...sharedDBOptions,
+ database: this.config.isDevelopment ? 'bushbot-dev' : this.config.isBeta ? 'bushbot-beta' : 'bushbot'
+ });
+ this.sharedDB = new Sequelize({
+ ...sharedDBOptions,
+ database: 'bushbot-shared'
});
- // global objects
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ /* global objects */
global.client = this;
global.util = this.util;
}
@@ -321,7 +339,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
this.commandHandler.useTaskHandler(this.taskHandler);
this.commandHandler.useContextMenuCommandHandler(this.contextMenuCommandHandler);
this.commandHandler.ignorePermissions = this.config.owners;
- this.commandHandler.ignoreCooldown = [...new Set([...this.config.owners, ...this.cache.global.superUsers])];
+ this.commandHandler.ignoreCooldown = [...new Set([...this.config.owners, ...this.cache.shared.superUsers])];
this.listenerHandler.setEmitters({
client: this,
commandHandler: this.commandHandler,
@@ -377,23 +395,36 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
/**
* Connects to the database, initializes models, and creates tables if they do not exist.
*/
- private async dbPreInit() {
+ async dbPreInit() {
+ try {
+ await this.instanceDB.authenticate();
+ GuildModel.initModel(this.instanceDB, this);
+ ModLog.initModel(this.instanceDB);
+ ActivePunishment.initModel(this.instanceDB);
+ Level.initModel(this.instanceDB);
+ StickyRole.initModel(this.instanceDB);
+ Reminder.initModel(this.instanceDB);
+ await this.instanceDB.sync({ alter: true }); // Sync all tables to fix everything if updated
+ await this.console.success('startup', `Successfully connected to <<instance database>>.`, false);
+ } catch (e) {
+ await this.console.error(
+ 'startup',
+ `Failed to connect to <<instance database>> with error:\n${util.inspect(e, { colors: true, depth: 1 })}`,
+ false
+ );
+ process.exit(2);
+ }
try {
- await this.db.authenticate();
- Global.initModel(this.db);
- GuildModel.initModel(this.db, this);
- ModLog.initModel(this.db);
- ActivePunishment.initModel(this.db);
- Level.initModel(this.db);
- StickyRole.initModel(this.db);
- Stat.initModel(this.db);
- Reminder.initModel(this.db);
- await this.db.sync({ alter: true }); // Sync all tables to fix everything if updated
- await this.console.success('startup', `Successfully connected to <<database>>.`, false);
+ await this.sharedDB.authenticate();
+ Stat.initModel(this.sharedDB);
+ Global.initModel(this.sharedDB);
+ Shared.initModel(this.sharedDB);
+ await this.sharedDB.sync({ alter: true }); // Sync all tables to fix everything if updated
+ await this.console.success('startup', `Successfully connected to <<shared database>>.`, false);
} catch (e) {
await this.console.error(
'startup',
- `Failed to connect to <<database>> with error:\n${util.inspect(e, { colors: true, depth: 1 })}`,
+ `Failed to connect to <<shared database>> with error:\n${util.inspect(e, { colors: true, depth: 1 })}`,
false
);
process.exit(2);
@@ -416,7 +447,6 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
});
try {
- await this.dbPreInit();
await UpdateCacheTask.init(this);
void this.console.success('startup', `Successfully created <<cache>>.`, false);
this.stats.commandsUsed = await UpdateStatsTask.init();
@@ -443,7 +473,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
public override isSuperUser(user: BushUserResolvable): boolean {
const userID = this.users.resolveId(user)!;
- return !!client.cache?.global?.superUsers?.includes(userID) || this.config.owners.includes(userID);
+ return !!client.cache.shared.superUsers.includes(userID) || this.config.owners.includes(userID);
}
}
diff --git a/src/lib/extensions/discord-akairo/BushClientUtil.ts b/src/lib/extensions/discord-akairo/BushClientUtil.ts
index 9a8e408..cdb883d 100644
--- a/src/lib/extensions/discord-akairo/BushClientUtil.ts
+++ b/src/lib/extensions/discord-akairo/BushClientUtil.ts
@@ -2,6 +2,8 @@ import {
Arg,
BushConstants,
Global,
+ Shared,
+ SharedCache,
type BushClient,
type BushInspectOptions,
type BushMessage,
@@ -442,6 +444,12 @@ export class BushClientUtil extends ClientUtil {
return key ? client.cache.global[key] : client.cache.global;
}
+ public getShared(): SharedCache;
+ public getShared<K extends keyof SharedCache>(key: K): SharedCache[K];
+ public getShared(key?: keyof SharedCache) {
+ return key ? client.cache.shared[key] : client.cache.shared;
+ }
+
/**
* Add or remove an element from an array stored in the Globals database.
* @param action Either `add` or `remove` an element.
@@ -463,6 +471,25 @@ export class BushClientUtil extends ClientUtil {
}
/**
+ * Add or remove an element from an array stored in the Shared database.
+ * @param action Either `add` or `remove` an element.
+ * @param key The key of the element in the shared cache to update.
+ * @param value The value to add/remove from the array.
+ */
+ public async insertOrRemoveFromShared<K extends keyof typeof client['cache']['shared']>(
+ action: 'add' | 'remove',
+ key: K,
+ value: typeof client['cache']['shared'][K][0]
+ ): Promise<Shared | void> {
+ const row = (await Shared.findByPk(0)) ?? (await Shared.create());
+ const oldValue: any[] = row[key];
+ const newValue = this.addOrRemoveFromArray(action, oldValue, value);
+ row[key] = newValue;
+ client.cache.shared[key] = newValue;
+ return await row.save().catch((e) => this.handleError('insertOrRemoveFromShared', e));
+ }
+
+ /**
* Updates an element in the Globals database.
* @param key The key in the global cache to update.
* @param value The value to set the key to.
@@ -479,6 +506,21 @@ export class BushClientUtil extends ClientUtil {
}
/**
+ * Updates an element in the Shared database.
+ * @param key The key in the shared cache to update.
+ * @param value The value to set the key to.
+ */
+ public async setShared<K extends keyof typeof client['cache']['shared']>(
+ key: K,
+ value: typeof client['cache']['shared'][K]
+ ): Promise<Shared | void> {
+ const row = (await Shared.findByPk(0)) ?? (await Shared.create());
+ row[key] = value;
+ client.cache.shared[key] = value;
+ return await row.save().catch((e) => this.handleError('setShared', e));
+ }
+
+ /**
* Add or remove an item from an array. All duplicates will be removed.
* @param action Either `add` or `remove` an element.
* @param array The array to add/remove an element from.
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 8809e27..37bc443 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -73,6 +73,7 @@ export * from './models/Guild.js';
export * from './models/Level.js';
export * from './models/ModLog.js';
export * from './models/Reminder.js';
+export * from './models/Shared.js';
export * from './models/Stat.js';
export * from './models/StickyRole.js';
export * from './utils/AllowedMentions.js';
diff --git a/src/lib/models/Global.ts b/src/lib/models/Global.ts
index 30a9d38..1deb090 100644
--- a/src/lib/models/Global.ts
+++ b/src/lib/models/Global.ts
@@ -2,12 +2,10 @@ import { type Snowflake } from 'discord.js';
import { type Sequelize } from 'sequelize';
import { BaseModel } from './BaseModel.js';
import { jsonArray } from './__helpers.js';
-
const { DataTypes } = (await import('sequelize')).default;
export interface GlobalModel {
environment: 'production' | 'development' | 'beta';
- superUsers: Snowflake[];
disabledCommands: string[];
blacklistedUsers: Snowflake[];
blacklistedGuilds: Snowflake[];
@@ -16,7 +14,6 @@ export interface GlobalModel {
export interface GlobalModelCreationAttributes {
environment: 'production' | 'development' | 'beta';
- superUsers?: Snowflake[];
disabledCommands?: string[];
blacklistedUsers?: Snowflake[];
blacklistedGuilds?: Snowflake[];
@@ -30,11 +27,6 @@ export class Global extends BaseModel<GlobalModel, GlobalModelCreationAttributes
public declare environment: 'production' | 'development' | 'beta';
/**
- * Trusted users.
- */
- public declare superUsers: Snowflake[];
-
- /**
* Globally disabled commands.
*/
public declare disabledCommands: string[];
@@ -62,7 +54,6 @@ export class Global extends BaseModel<GlobalModel, GlobalModelCreationAttributes
Global.init(
{
environment: { type: DataTypes.STRING, primaryKey: true },
- superUsers: jsonArray('superUsers'),
disabledCommands: jsonArray('disabledCommands'),
blacklistedUsers: jsonArray('blacklistedUsers'),
blacklistedGuilds: jsonArray('blacklistedGuilds'),
diff --git a/src/lib/models/Guild.ts b/src/lib/models/Guild.ts
index dfee37b..80bd119 100644
--- a/src/lib/models/Guild.ts
+++ b/src/lib/models/Guild.ts
@@ -5,7 +5,6 @@ import { type BadWords } from '../common/AutoMod.js';
import { type BushClient } from '../extensions/discord-akairo/BushClient.js';
import { BaseModel } from './BaseModel.js';
import { jsonArray, jsonObject } from './__helpers.js';
-
const { DataTypes } = (await import('sequelize')).default;
export interface GuildModel {
diff --git a/src/lib/models/Level.ts b/src/lib/models/Level.ts
index 2ed787d..e247779 100644
--- a/src/lib/models/Level.ts
+++ b/src/lib/models/Level.ts
@@ -1,7 +1,6 @@
import { type Snowflake } from 'discord.js';
import { type Sequelize } from 'sequelize';
import { BaseModel } from './BaseModel.js';
-
const { DataTypes } = (await import('sequelize')).default;
export interface LevelModel {
diff --git a/src/lib/models/Shared.ts b/src/lib/models/Shared.ts
new file mode 100644
index 0000000..dd7682b
--- /dev/null
+++ b/src/lib/models/Shared.ts
@@ -0,0 +1,49 @@
+import { type Sequelize } from 'sequelize';
+import { BaseModel } from './BaseModel.js';
+import { jsonArray } from './__helpers.js';
+const { DataTypes } = (await import('sequelize')).default;
+
+export interface SharedModel {
+ primaryKey: 0;
+ superUsers: string[];
+ badLinks: string[];
+}
+
+export interface SharedModelCreationAttributes {
+ primaryKey?: 0;
+ superUsers?: string[];
+ badLinks?: string[];
+}
+
+export class Shared extends BaseModel<SharedModel, SharedModelCreationAttributes> implements SharedModel {
+ /**
+ * The primary key of the shared model.
+ */
+ public declare primaryKey: 0;
+
+ /**
+ * Trusted users.
+ */
+ public declare superUsers: string[];
+
+ //todo
+ /**
+ * Bad links.
+ */
+ public declare badLinks: string[];
+
+ /**
+ * Initializes the model.
+ * @param sequelize The sequelize instance.
+ */
+ public static initModel(sequelize: Sequelize): void {
+ Shared.init(
+ {
+ primaryKey: { type: DataTypes.INTEGER, primaryKey: true, validate: { min: 0, max: 0 } },
+ superUsers: jsonArray('superUsers'),
+ badLinks: jsonArray('badLinks')
+ },
+ { sequelize, freezeTableName: true }
+ );
+ }
+}
diff --git a/src/lib/models/__helpers.ts b/src/lib/models/__helpers.ts
index 049dc00..bbfe328 100644
--- a/src/lib/models/__helpers.ts
+++ b/src/lib/models/__helpers.ts
@@ -1,5 +1,4 @@
import { type Model } from 'sequelize';
-
const { DataTypes } = (await import('sequelize')).default;
export function jsonParseGet(this: Model, key: string): any {
diff --git a/src/lib/utils/BushCache.ts b/src/lib/utils/BushCache.ts
index cea0aea..5654495 100644
--- a/src/lib/utils/BushCache.ts
+++ b/src/lib/utils/BushCache.ts
@@ -3,15 +3,20 @@ import { Collection, type Snowflake } from 'discord.js';
export class BushCache {
public global = new GlobalCache();
+ public shared = new SharedCache();
public guilds = new GuildCache();
}
export class GlobalCache {
- public superUsers: Snowflake[] = [];
public disabledCommands: string[] = [];
public blacklistedChannels: Snowflake[] = [];
public blacklistedGuilds: Snowflake[] = [];
public blacklistedUsers: Snowflake[] = [];
}
+export class SharedCache {
+ public superUsers: Snowflake[] = [];
+ public badLinks: string[] = [];
+}
+
export class GuildCache extends Collection<Snowflake, Guild> {}