@somehiddenkey/discord-command-utils 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,7 +21,7 @@ We will use 3 different kinds of configurations:
21
21
  ### Local configuration
22
22
  Loads the local configuration of that specific bot. It only contains public configs, no secrets, and may thus be included in the git tracing. Load a new instance of your local config through the following code:
23
23
  ```js
24
- export const localConfig = LocalConfig.load("./configs/local_config.json", Environments.DEV);
24
+ export const localConfig = LocalConfig.load("./configs/local_config.json");
25
25
  ```
26
26
 
27
27
  Your local configuration JSON file should look like this:
@@ -62,7 +62,7 @@ Your local configuration JSON file should look like this:
62
62
  ### Global configuration
63
63
  Loads the global configuration that contains information related to all bot instances, like snowflake IDs of channels, categories, guild, etc. Load a new instance of your global config through the following code:
64
64
  ```js
65
- export const globalConfig = GlobalConfig.load("../global_config.json", Environments.DEV);
65
+ export const globalConfig = GlobalConfig.load("../global_config.json");
66
66
  ```
67
67
  It contains the IDs of the following sections: guilds, categories, channels, log channels and roles. These can be used as constant values throughout your code, making sure that if an ID ever changes, that all bot instances would take the new updated value by simply updating the json once.
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@somehiddenkey/discord-command-utils",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "description": "A utility library for building Discord bot commands using discord.js",
5
5
  "author": {
6
6
  "email": "k3y.throwaway@gmail.com",
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import consola from 'consola';
6
+ import { Client } from 'discord.js';
7
+
8
+ export default class Fetchable {
9
+ /** @type {string[]} */
10
+ _config_keys = [];
11
+
12
+ /**
13
+ * @param {Client} bot
14
+ * @param {Snowflake} id
15
+ * @param {((id: Snowflake) => Promise<any>)} fetcher
16
+ * @returns {Proxy<any>}
17
+ */
18
+ _createLazyObject(id, fetcher) {
19
+ let cachedObject = null;
20
+
21
+ return new Proxy(
22
+ {},
23
+ {
24
+ get(_, prop) {
25
+ if (prop === "id")
26
+ return id;
27
+
28
+ if (prop === "fetch") {
29
+ return async () => {
30
+ if (!cachedObject){
31
+ cachedObject = await fetcher(id);
32
+ if (!cachedObject)
33
+ throw new Error(`Cannot fetch config object for ID "${id}"`);
34
+ consola.debug(`Fetched config object with ID ${id}`);
35
+ }
36
+ return cachedObject;
37
+ };
38
+ }
39
+
40
+ if (!cachedObject)
41
+ throw new Error(`Cannot access property "${prop}" of unfetched object with ID ${id}. Call "fetch()" first.`);
42
+
43
+ const value = cachedObject[prop];
44
+ return typeof value === "function"
45
+ ? value.bind(cachedObject)
46
+ : value;
47
+ }
48
+ }
49
+ );
50
+ }
51
+
52
+ constructor(data) {
53
+ const lazy = Object.fromEntries(
54
+ Object.entries(data).map(([k, v]) => [k, Array.isArray(v) ? new Set(v) : this._createLazyObject(v)])
55
+ );
56
+ this._config_keys = Object.entries(data).filter(([_, v]) => !Array.isArray(v)).map(([k, _]) => k);
57
+
58
+ Object.assign(this, lazy);
59
+ }
60
+
61
+ /**
62
+ * @returns {Promise<void[]>}
63
+ */
64
+ fetch() {
65
+ return Promise.all(
66
+ this._config_keys.map((key) => this[key]?.fetch())
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import fs from 'fs';
6
+ import consola from 'consola';
7
+ import { InteractionScope } from "../../Utils/enums.js";
8
+ import {default as GuildMain} from './GlobalConfigMain.js';
9
+ import {default as GuildCommunity} from './GlobalConfigCommunity.js';
10
+ import {default as GuildTutor} from './GlobalConfigTutor.js';
11
+ import {default as GuildStaff} from './GlobalConfigStaff.js';
12
+ import { GuildBased } from '../NestedGlobalConfig.js';
13
+
14
+ export default class GlobalConfig {
15
+ main
16
+ community
17
+ tutor
18
+ staff
19
+
20
+ /**
21
+ * Loads the JSON file and returns a GlobalConfig instance.
22
+ * @param {string} path
23
+ * @param {string} environment
24
+ * @returns {GlobalConfig}
25
+ */
26
+ static async load(path) {
27
+ var json
28
+ try {
29
+ const raw = fs.readFileSync(path, { encoding: 'utf8', flag: 'r' });
30
+ json = JSON.parse(raw);
31
+ } catch (error) {
32
+ consola.error(`Failed to load GlobalConfig from path: ${path}`, error);
33
+ throw error;
34
+ }
35
+ return new GlobalConfig(json.guilds);
36
+ }
37
+
38
+ /**
39
+ * @param {Snowflake} guild_id
40
+ * @returns {InteractionScope} scope
41
+ */
42
+ get_scope(guild_id) {
43
+ switch(guild_id) {
44
+ case this.main:
45
+ return InteractionScope.Main;
46
+ case this.community:
47
+ return InteractionScope.Community;
48
+ case this.tutor:
49
+ return InteractionScope.Tutor;
50
+ case this.staff:
51
+ return InteractionScope.Staff;
52
+ default:
53
+ return InteractionScope.OtherGuild;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @param {InteractionScope} scope
59
+ * @returns {GuildBased} guild
60
+ */
61
+ get(scope){
62
+ switch(scope) {
63
+ case InteractionScope.Main:
64
+ return this.main;
65
+ case InteractionScope.Community:
66
+ return this.community;
67
+ case InteractionScope.Tutor:
68
+ return this.tutor;
69
+ case InteractionScope.Staff:
70
+ return this.staff;
71
+ default:
72
+ return null;
73
+ }
74
+ }
75
+
76
+ constructor(data) {
77
+ this.main = new GuildMain(data.main);
78
+ this.community = new GuildCommunity(data.community);
79
+ this.tutor = new GuildTutor(data.tutor);
80
+ this.staff = new GuildStaff(data.staff);
81
+ }
82
+ }
83
+
84
+
85
+
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import ConfigError from "./ConfigError.js";
6
+ import pkg from 'discord.js';
7
+ import { GuildBased, ChannelBased, RoleBased } from '../NestedGlobalConfig.js';
8
+ const { GuildBasedChannel } = pkg;
9
+
10
+ export default class Guild extends GuildBased {
11
+ /** @type {Categories} */
12
+ categories;
13
+ /** @type {Channels} */
14
+ channels;
15
+ /** @type {Logs} */
16
+ logs;
17
+ /** @type {Roles} */
18
+ roles;
19
+
20
+ constructor(data) {
21
+ if (!data)
22
+ throw new ConfigError('No data initialized for GlobalConfig');
23
+
24
+ super(data);
25
+ this.categories = new Categories(data.categories, data.id);
26
+ this.channels = new Channels(data.channels, data.id);
27
+ this.logs = new Logs(data.logs, data.id);
28
+ this.roles = new Roles(data.roles, data.id);
29
+ }
30
+ }
31
+
32
+ class Categories extends ChannelBased {}
33
+
34
+ class Channels extends ChannelBased {}
35
+
36
+ class Logs extends ChannelBased {}
37
+
38
+ class Roles extends RoleBased {}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import ConfigError from "./ConfigError.js";
6
+ import pkg from 'discord.js';
7
+ import { GuildBased, ChannelBased, RoleBased } from '../NestedGlobalConfig.js';
8
+ const { GuildBasedChannel } = pkg;
9
+
10
+ export default class Guild extends GuildBased {
11
+ /** @type {Categories} */
12
+ categories;
13
+ /** @type {Channels} */
14
+ channels;
15
+ /** @type {Logs} */
16
+ logs;
17
+ /** @type {Roles} */
18
+ roles;
19
+
20
+ constructor(data) {
21
+ if (!data)
22
+ throw new ConfigError('No data initialized for GlobalConfig');
23
+
24
+ super(data);
25
+ this.categories = new Categories(data.categories, data.id);
26
+ this.channels = new Channels(data.channels, data.id);
27
+ this.logs = new Logs(data.logs, data.id);
28
+ this.roles = new Roles(data.roles, data.id);
29
+ }
30
+ }
31
+
32
+ class Categories extends ChannelBased {
33
+ /** @type {Set<Snowflake>} */
34
+ custom_rooms;
35
+ /** @type {Set<Snowflake>} */
36
+ verified_com;
37
+
38
+ /** @type {GuildBasedChannel} */
39
+ chat;
40
+ /** @type {GuildBasedChannel} */
41
+ chill;
42
+ /** @type {GuildBasedChannel} */
43
+ events;
44
+ /** @type {GuildBasedChannel} */
45
+ music;
46
+ /** @type {GuildBasedChannel} */
47
+ timer_25;
48
+ /** @type {GuildBasedChannel} */
49
+ timer_50;
50
+ /** @type {GuildBasedChannel} */
51
+ screen_cam;
52
+ /** @type {GuildBasedChannel} */
53
+ staff;
54
+ /** @type {GuildBasedChannel} */
55
+ subjects;
56
+ /** @type {GuildBasedChannel} */
57
+ subjects_col;
58
+ /** @type {GuildBasedChannel} */
59
+ subjects_uni;
60
+ /** @type {GuildBasedChannel} */
61
+ to_do;
62
+
63
+ /** @type {Set<Snowflake>} */
64
+ custom_study_rooms;
65
+ /** @type {Set<Snowflake>} */
66
+ study_rooms;
67
+
68
+ constructor(data) {
69
+ super(data);
70
+ this.custom_study_rooms = new Set(data.custom_rooms.concat(data.verified_com));
71
+ this.study_rooms = new Set([...this.custom_study_rooms, data.music, data.timer_25, data.timer_50, data.screen_cam]);
72
+ }
73
+ }
74
+
75
+ class Channels extends ChannelBased {
76
+ /** @type {GuildBasedChannel} */
77
+ timer_control;
78
+ /** @type {GuildBasedChannel} */
79
+ accountability;
80
+ /** @type {GuildBasedChannel} */
81
+ break_afk;
82
+ /** @type {GuildBasedChannel} */
83
+ create_room;
84
+ /** @type {GuildBasedChannel} */
85
+ commands;
86
+ /** @type {GuildBasedChannel} */
87
+ general;
88
+ /** @type {GuildBasedChannel} */
89
+ international;
90
+ /** @type {GuildBasedChannel} */
91
+ introductions;
92
+ /** @type {GuildBasedChannel} */
93
+ mod_commands;
94
+ /** @type {GuildBasedChannel} */
95
+ support_commands;
96
+ /** @type {GuildBasedChannel} */
97
+ session_goals;
98
+ /** @type {GuildBasedChannel} */
99
+ silent_study;
100
+ /** @type {GuildBasedChannel} */
101
+ welcome;
102
+ }
103
+
104
+ class Logs extends ChannelBased {
105
+ /** @type {GuildBasedChannel} */
106
+ error;
107
+ /** @type {GuildBasedChannel} */
108
+ votekick;
109
+ /** @type {GuildBasedChannel} */
110
+ room_commands;
111
+ /** @type {GuildBasedChannel} */
112
+ room_admin;
113
+ /** @type {GuildBasedChannel} */
114
+ invites;
115
+ /** @type {GuildBasedChannel} */
116
+ command;
117
+ /** @type {GuildBasedChannel} */
118
+ communities;
119
+ }
120
+
121
+ class Roles extends RoleBased {
122
+ /** @type {Snowflake} */
123
+ cuckoo_ping;
124
+ /** @type {Snowflake} */
125
+ developer
126
+ /** @type {Snowflake} */
127
+ forest_ping;
128
+ /** @type {Snowflake} */
129
+ helper;
130
+ /** @type {Snowflake} */
131
+ member;
132
+ /** @type {Snowflake} */
133
+ music;
134
+ /** @type {Snowflake} */
135
+ muted;
136
+ /** @type {Snowflake} */
137
+ no_pc;
138
+ /** @type {Snowflake} */
139
+ screen_cam;
140
+ /** @type {Snowflake} */
141
+ studying;
142
+ /** @type {Snowflake} */
143
+ timer_25;
144
+ /** @type {Snowflake} */
145
+ timer_50;
146
+ /** @type {Snowflake} */
147
+ tutor;
148
+ /** @type {Snowflake} */
149
+ verified_com;
150
+ /** @type {Snowflake} */
151
+ water_ping;
152
+ /** @type {Snowflake} */
153
+ deepfocus;
154
+ /** @type {Snowflake} */
155
+ sr_staff;
156
+ /** @type {Snowflake} */
157
+ staff;
158
+ /** @type {Snowflake} */
159
+ jr_staff;
160
+ /** @type {Snowflake} */
161
+ st_team;
162
+ /** @type {Snowflake} */
163
+ coordinator;
164
+
165
+ /** @type {Set<Snowflake>} */
166
+ all_staff;
167
+
168
+
169
+ constructor(data) {
170
+ Object.assign(this, data);
171
+ this.all_staff = [this.jr_staff, this.sr_staff, this.st_team, this.coordinator];
172
+ }
173
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import ConfigError from "./ConfigError.js";
6
+ import pkg from 'discord.js';
7
+ import { GuildBased, ChannelBased, RoleBased } from '../NestedGlobalConfig.js';
8
+ const { GuildBasedChannel } = pkg;
9
+
10
+ export default class Guild extends GuildBased {
11
+ /** @type {Categories} */
12
+ categories;
13
+ /** @type {Channels} */
14
+ channels;
15
+ /** @type {Logs} */
16
+ logs;
17
+ /** @type {Roles} */
18
+ roles;
19
+
20
+ constructor(data) {
21
+ if (!data)
22
+ throw new ConfigError('No data initialized for GlobalConfig');
23
+
24
+ super(data);
25
+ this.categories = new Categories(data.categories, data.id);
26
+ this.channels = new Channels(data.channels, data.id);
27
+ this.logs = new Logs(data.logs, data.id);
28
+ this.roles = new Roles(data.roles, data.id);
29
+ }
30
+ }
31
+
32
+ class Categories extends ChannelBased {}
33
+
34
+ class Channels extends ChannelBased {}
35
+
36
+ class Logs extends ChannelBased {}
37
+
38
+ class Roles extends RoleBased {}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @typedef {string} Snowflake
3
+ */
4
+
5
+ import Fetchable from './Fetchable.js';
6
+
7
+ export class GuildBased extends Fetchable {
8
+ guild;
9
+ categories;
10
+ channels;
11
+ logs;
12
+ roles;
13
+
14
+ /**
15
+ * @param {Snowflake} id
16
+ * @returns {Proxy}
17
+ */
18
+ _createLazyObject(id) {
19
+ return super._createLazyObject(id, async (id) => await bot.guilds.fetch(id));
20
+ }
21
+
22
+ constructor(data){
23
+ this._guild = this._createLazyObject(data.id);
24
+ this._config_keys = Object.keys(data).filter(k => k !== 'id').push('guild');
25
+ }
26
+ }
27
+
28
+ export class ChannelBased extends Fetchable {
29
+ constructor(data) {
30
+ super(data);
31
+ }
32
+
33
+ /**
34
+ * @param {Snowflake} id
35
+ * @returns {Proxy}
36
+ */
37
+ _createLazyObject(id) {
38
+ return super._createLazyObject(id, async (id) => await bot.channels.fetch(id));
39
+ }
40
+ }
41
+
42
+ export class RoleBased extends Fetchable {
43
+ constructor(data) {
44
+ super(data);
45
+ }
46
+
47
+ /**
48
+ * @param {Snowflake} id
49
+ * @returns {Proxy}
50
+ */
51
+ _createLazyObject(id) {
52
+ return super._createLazyObject(id, async (id) => await bot.roles.fetch(id));
53
+ }
54
+ }
@@ -1,6 +1,6 @@
1
1
  import Interaction from "./Interaction.js";
2
2
  import { InteractionScope, InteractionType } from "../Utils/enums.js";
3
- import GlobalConfig from "../Configs/GlobalConfig.js";
3
+ import GlobalConfig from "../Configs/GlobalConfig/GlobalConfig.js";
4
4
  import LocalConfig from "../Configs/LocalConfig.js";
5
5
  import consola from "consola";
6
6
  import CommandError from "./CommandError.js";
@@ -80,7 +80,7 @@ export default class InteractionContainer {
80
80
 
81
81
  const scope =
82
82
  (interaction.channel.type === ChannelType.DM) ?
83
- InteractionScope.DM : this.#global_config.guilds.get_scope(interaction.guild.id);
83
+ InteractionScope.DM : this.#global_config.get_scope(interaction.guild.id);
84
84
 
85
85
  const customId = interaction.content.slice(this.#local_config.prefix?.length)
86
86
 
@@ -106,7 +106,7 @@ export default class InteractionContainer {
106
106
  call_interaction(interaction, on_error = async () => {}) {
107
107
  const scope =
108
108
  (interaction.channel.type === ChannelType.DM) ?
109
- InteractionScope.DM : this.#global_config.guilds.get_scope(interaction.guild.id);
109
+ InteractionScope.DM : this.#global_config.get_scope(interaction.guild.id);
110
110
 
111
111
  const customId = (interaction.commandName || interaction.customId)?.split(/\?(.+)/, 2)
112
112
 
@@ -1,4 +1,4 @@
1
- import GlobalConfig from "../Configs/GlobalConfig.js";
1
+ import GlobalConfig from "../Configs/GlobalConfig/GlobalConfig.js";
2
2
  import LocalConfig from "../Configs/LocalConfig.js";
3
3
  import { REST, Routes } from "discord.js";
4
4
 
@@ -10,6 +10,11 @@ export default class RestCommands {
10
10
  /** @type {LocalConfig} */
11
11
  #local_config;
12
12
 
13
+ /**
14
+ *
15
+ * @param {GlobalConfig} global_config
16
+ * @param {LocalConfig} local_config
17
+ */
13
18
  constructor(global_config, local_config) {
14
19
  this.#global_config = global_config;
15
20
  this.#local_config = local_config;
@@ -28,7 +33,7 @@ export default class RestCommands {
28
33
  const rest = new REST(this.#local_config.restOptions).setToken(secret_token);
29
34
 
30
35
  for(const [scope, commands] of this.#commands.entries()) {
31
- await rest.put(Routes.applicationGuildCommands(this.#local_config.clientId, this.#global_config.guilds.get_guild_id(scope)), {
36
+ await rest.put(Routes.applicationGuildCommands(this.#local_config.clientId, this.#global_config.get(scope)), {
32
37
  body: commands,
33
38
  });
34
39
  }
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export {default as LocalConfig} from "./Configs/LocalConfig.js";
2
- export {default as GlobalConfig} from "./Configs/GlobalConfig.js";
2
+ export {default as GlobalConfig} from "./Configs/GlobalConfig/GlobalConfig.js";
3
3
  export {default as SecretConfig} from "./Configs/SecretConfig.js";
4
4
 
5
5
  export {default as InteractionContainer} from "./Interactions/InteractionContainer.js";
@@ -1,332 +0,0 @@
1
- /**
2
- * @typedef {string} Snowflake
3
- */
4
-
5
- import fs from 'fs';
6
- import ConfigError from "./ConfigError.js";
7
- import consola from 'consola';
8
- import { InteractionScope } from "../Utils/enums.js";
9
- import { Client, Guild } from 'discord.js';
10
- import pkg from 'discord.js';
11
- const { GuildBasedChannel } = pkg;
12
-
13
- export default class GlobalConfig {
14
- /** @type {Guilds} */
15
- guilds;
16
-
17
- /** @type {Categories} */
18
- categories;
19
-
20
- /** @type {Channels} */
21
- channels;
22
-
23
- /** @type {Logs} */
24
- logs;
25
-
26
- /** @type {Roles} */
27
- roles;
28
-
29
- constructor(data) {
30
- if (!data)
31
- throw new ConfigError('No data initialized for GlobalConfig');
32
-
33
- this.guilds = new Guilds(data.guilds);
34
- this.categories = new Categories(data.categories);
35
- this.channels = new Channels(data.channels);
36
- this.logs = new Logs(data.logs);
37
- this.roles = new Roles(data.roles);
38
- }
39
-
40
- /**
41
- * Pre-fetches guilds and log channels
42
- * @param {Client} bot
43
- * @returns {Promise<GlobalConfig>}
44
- */
45
- async init(bot) {
46
- await this.guilds.init(bot);
47
- return this;
48
- }
49
-
50
- /**
51
- * Loads the JSON file and returns a GlobalConfig instance.
52
- * @param {string} path
53
- * @param {string} environment
54
- * @returns {GlobalConfig}
55
- */
56
- static async load(path, environment) {
57
- var json
58
- try {
59
- const raw = fs.readFileSync(path, { encoding: 'utf8', flag: 'r' });
60
- json = JSON.parse(raw);
61
- } catch (error) {
62
- consola.error(`Failed to load GlobalConfig from path: ${path}`, error);
63
- throw error;
64
- }
65
- if (environment == "production")
66
- return new GlobalConfig(json.production);
67
- else
68
- return new GlobalConfig(json.development);
69
- }
70
- }
71
-
72
-
73
- /* -----------------------
74
- * Nested Classes
75
- * ----------------------- */
76
-
77
- class Guilds {
78
- /** @type {Snowflake} */
79
- main;
80
- /** @type {Snowflake} */
81
- community;
82
- /** @type {Snowflake} */
83
- tutor;
84
- /** @type {Snowflake} */
85
- staff;
86
-
87
- /** @type {Guild} */
88
- main_guild;
89
- /** @type {Guild} */
90
- community_guild;
91
- /** @type {Guild} */
92
- tutor_guild;
93
- /** @type {Guild} */
94
- staff_guild;
95
-
96
- constructor(data) {
97
- Object.assign(this, data);
98
- }
99
-
100
- /**
101
- * Pre-fetches guilds
102
- * @param {Client} bot
103
- * @returns {Promise<void>}
104
- */
105
- async init(bot) {
106
- this.main_guild = await bot.guilds.fetch(this.main_guild);
107
- this.community_guild = await bot.guilds.fetch(this.community_guild);
108
- this.tutor_guild = await bot.guilds.fetch(this.tutor_guild);
109
- this.staff_guild = await bot.guilds.fetch(this.staff_guild);
110
- }
111
-
112
- /**
113
- * @param {Snowflake} guild_id
114
- * @returns {InteractionScope} scope
115
- */
116
- get_scope(guild_id) {
117
- switch(guild_id) {
118
- case this.main:
119
- return InteractionScope.Main;
120
- case this.community:
121
- return InteractionScope.Community;
122
- case this.tutor:
123
- return InteractionScope.Tutor;
124
- case this.staff:
125
- return InteractionScope.Staff;
126
- default:
127
- return InteractionScope.OtherGuild;
128
- }
129
- }
130
-
131
- /**
132
- * @param {InteractionScope} scope
133
- * @returns {Snowflake} guild_id
134
- */
135
- get_guild_id(scope) {
136
- switch(scope) {
137
- case InteractionScope.Main:
138
- return this.main;
139
- case InteractionScope.Community:
140
- return this.community;
141
- case InteractionScope.Tutor:
142
- return this.tutor;
143
- case InteractionScope.Staff:
144
- return this.staff;
145
- default:
146
- return null;
147
- }
148
- }
149
- }
150
-
151
- class Categories {
152
- /** @type {Snowflake} */
153
- chat;
154
- /** @type {[Snowflake]} */
155
- custom_rooms;
156
- /** @type {[Snowflake]} */
157
- verified_com;
158
- /** @type {Snowflake} */
159
- chill;
160
- /** @type {Snowflake} */
161
- events;
162
- /** @type {Snowflake} */
163
- music;
164
- /** @type {Snowflake} */
165
- timer_25;
166
- /** @type {Snowflake} */
167
- timer_50;
168
- /** @type {Snowflake} */
169
- screen_cam;
170
- /** @type {Snowflake} */
171
- staff;
172
- /** @type {Snowflake} */
173
- subjects;
174
- /** @type {Snowflake} */
175
- subjects_col;
176
- /** @type {Snowflake} */
177
- subjects_uni;
178
- /** @type {Snowflake} */
179
- to_do;
180
-
181
- /** @type {[Snowflake]} */
182
- custom_study_rooms;
183
- /** @type {[Snowflake]} */
184
- study_rooms;
185
-
186
- constructor(data) {
187
- Object.assign(this, data);
188
- this.custom_study_rooms = data.custom_rooms.concat(data.verified_com);
189
- this.study_rooms = this.custom_study_rooms.concat([data.music, data.timer_25, data.timer_50, data.screen_cam]);
190
- }
191
- }
192
-
193
- class Channels {
194
- /** @type {Snowflake} */
195
- timer_control;
196
- /** @type {Snowflake} */
197
- accountability;
198
- /** @type {Snowflake} */
199
- break_afk;
200
- /** @type {Snowflake} */
201
- create_room;
202
- /** @type {Snowflake} */
203
- commands;
204
- /** @type {Snowflake} */
205
- general;
206
- /** @type {Snowflake} */
207
- international;
208
- /** @type {Snowflake} */
209
- introductions;
210
- /** @type {Snowflake} */
211
- mod_commands;
212
- /** @type {Snowflake} */
213
- support_commands;
214
- /** @type {Snowflake} */
215
- session_goals;
216
- /** @type {Snowflake} */
217
- silent_study;
218
- /** @type {Snowflake} */
219
- welcome;
220
-
221
- constructor(data) {
222
- Object.assign(this, data);
223
- }
224
- }
225
-
226
- class Logs {
227
- /** @type {Snowflake} */
228
- error;
229
- /** @type {Snowflake} */
230
- votekick;
231
- /** @type {Snowflake} */
232
- room_commands;
233
- /** @type {Snowflake} */
234
- room_admin;
235
- /** @type {Snowflake} */
236
- invites;
237
- /** @type {Snowflake} */
238
- command;
239
- /** @type {Snowflake} */
240
- communities;
241
-
242
- /** @type {GuildBasedChannel} */
243
- error_channel;
244
- /** @type {GuildBasedChannel} */
245
- votekick_channel;
246
- /** @type {GuildBasedChannel} */
247
- room_commands_channel;
248
- /** @type {GuildBasedChannel} */
249
- room_admin_channel;
250
- /** @type {GuildBasedChannel} */
251
- invites_channel;
252
- /** @type {GuildBasedChannel} */
253
- command_channel;
254
- /** @type {GuildBasedChannel} */
255
- communities_channel;
256
-
257
- constructor(data) {
258
- Object.assign(this, data);
259
- }
260
-
261
- /**
262
- * Pre-fetches log channels
263
- * @param {Client} bot
264
- * @returns {Promise<void>}
265
- */
266
- async init(bot) {
267
- if(!this.main_guild)
268
- return;
269
-
270
- this.error_channel = await this.main_guild.channels.fetch(this.error_channel);
271
- this.votekick_channel = await this.main_guild.channels.fetch(this.votekick_channel);
272
- this.room_commands_channel = await this.main_guild.channels.fetch(this.room_commands_channel);
273
- this.room_admin_channel = await this.main_guild.channels.fetch(this.room_admin_channel);
274
- this.invites_channel = await this.main_guild.channels.fetch(this.invites_channel);
275
- this.command_channel = await this.main_guild.channels.fetch(this.command_channel);
276
- this.communities_channel = await this.main_guild.channels.fetch(this.communities_channel);
277
- }
278
- }
279
-
280
- class Roles {
281
- /** @type {Snowflake} */
282
- cuckoo_ping;
283
- /** @type {Snowflake} */
284
- developer
285
- /** @type {Snowflake} */
286
- forest_ping;
287
- /** @type {Snowflake} */
288
- helper;
289
- /** @type {Snowflake} */
290
- member;
291
- /** @type {Snowflake} */
292
- music;
293
- /** @type {Snowflake} */
294
- muted;
295
- /** @type {Snowflake} */
296
- no_pc;
297
- /** @type {Snowflake} */
298
- screen_cam;
299
- /** @type {Snowflake} */
300
- studying;
301
- /** @type {Snowflake} */
302
- timer_25;
303
- /** @type {Snowflake} */
304
- timer_50;
305
- /** @type {Snowflake} */
306
- tutor;
307
- /** @type {Snowflake} */
308
- verified_com;
309
- /** @type {Snowflake} */
310
- water_ping;
311
- /** @type {Snowflake} */
312
- deepfocus;
313
- /** @type {Snowflake} */
314
- sr_staff;
315
- /** @type {Snowflake} */
316
- staff;
317
- /** @type {Snowflake} */
318
- jr_staff;
319
- /** @type {Snowflake} */
320
- st_team;
321
- /** @type {Snowflake} */
322
- coordinator;
323
-
324
- /** @type {[Snowflake]} */
325
- all_staff;
326
-
327
-
328
- constructor(data) {
329
- Object.assign(this, data);
330
- this.all_staff = [this.jr_staff, this.sr_staff, this.st_team, this.coordinator];
331
- }
332
- }