@open-discord-bots/framework 0.3.14 → 0.3.15

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.
Files changed (41) hide show
  1. package/dist/api/main.js +1 -1
  2. package/dist/api/modules/responder.js +50 -26
  3. package/package.json +1 -1
  4. package/src/api/index.ts +0 -31
  5. package/src/api/main.ts +0 -203
  6. package/src/api/modules/action.ts +0 -89
  7. package/src/api/modules/base.ts +0 -845
  8. package/src/api/modules/builder.ts +0 -1755
  9. package/src/api/modules/checker.ts +0 -1826
  10. package/src/api/modules/client.ts +0 -2345
  11. package/src/api/modules/code.ts +0 -84
  12. package/src/api/modules/component.ts +0 -2000
  13. package/src/api/modules/config.ts +0 -264
  14. package/src/api/modules/console.ts +0 -697
  15. package/src/api/modules/cooldown.ts +0 -369
  16. package/src/api/modules/database.ts +0 -321
  17. package/src/api/modules/event.ts +0 -123
  18. package/src/api/modules/flag.ts +0 -99
  19. package/src/api/modules/fuse.ts +0 -365
  20. package/src/api/modules/helpmenu.ts +0 -273
  21. package/src/api/modules/language.ts +0 -230
  22. package/src/api/modules/permission.ts +0 -363
  23. package/src/api/modules/plugin.ts +0 -294
  24. package/src/api/modules/post.ts +0 -137
  25. package/src/api/modules/progressbar.ts +0 -370
  26. package/src/api/modules/responder.ts +0 -1625
  27. package/src/api/modules/session.ts +0 -181
  28. package/src/api/modules/startscreen.ts +0 -345
  29. package/src/api/modules/state.ts +0 -298
  30. package/src/api/modules/statistic.ts +0 -380
  31. package/src/api/modules/verifybar.ts +0 -68
  32. package/src/api/modules/worker.ts +0 -119
  33. package/src/cli/editConfig.ts +0 -930
  34. package/src/cli/index.ts +0 -152
  35. package/src/index.ts +0 -8
  36. package/src/startup/compilation.ts +0 -204
  37. package/src/startup/dump.ts +0 -46
  38. package/src/startup/errorHandling.ts +0 -42
  39. package/src/startup/pluginLauncher.ts +0 -265
  40. package/src/utilities/index.ts +0 -229
  41. package/tools/cleanup.js +0 -2
@@ -1,298 +0,0 @@
1
- ///////////////////////////////////////
2
- //STATE MODULE
3
- ///////////////////////////////////////
4
- import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData, ODNoGeneric, ODValidJsonType } from "./base.js"
5
- import { ODClientManager } from "./client.js"
6
- import { ODDebugger } from "./console.js"
7
- import { ODDatabase, ODDatabaseIdConstraint } from "./database.js"
8
- import * as discord from "discord.js"
9
-
10
- /**## ODStateKey `type`
11
- * The key template for message states.
12
- */
13
- export type ODStateKey<WithGuildKey extends boolean,WithUserKey extends boolean> = {
14
- /**A valid discord channel ID or instance. */
15
- channel:discord.Channel|string,
16
- /**A valid discord message ID or instance. */
17
- message:discord.Message|string,
18
- }
19
- & (WithGuildKey extends true ? {
20
- /**A valid discord server/guild ID or instance. */
21
- guild:discord.Guild|string,
22
- } : {})
23
- & (WithUserKey extends true ? {
24
- /**A valid discord user ID or instance. */
25
- user:discord.User|discord.GuildMember|string
26
- } : {})
27
-
28
- /**## ODStateData `type`
29
- * The raw data template for message states used for storing in the database.
30
- */
31
- export interface ODStateData<StateData extends any> {
32
- /**The linked Guild ID of this message state. */
33
- guildId:string|null,
34
- /**The linked Channel ID of this message state. */
35
- channelId:string,
36
- /**The linked Message ID of this message state. */
37
- messageId:string,
38
- /**The linked User ID of this message state. */
39
- userId:string|null,
40
- /**The creation date of this state (UNIX TIMESTAMP). */
41
- createdDate:number,
42
- /**The modified date of this state (UNIX TIMESTAMP). */
43
- modifiedDate:number,
44
- /**Optional date after which this state should be regarded as expired (UNIX TIMESTAMP). */
45
- deleteAfterDate:number|null,
46
- /**The state data. */
47
- data:StateData
48
- }
49
-
50
- /**## ODStateSettings `type`
51
- * Configurable settings for an ODState.
52
- */
53
- export interface ODStateSettings {
54
- /**(Default: `false`) Completely disable autodelete of message states. (unless manually activated using other settings) */
55
- disableAutodelete:boolean,
56
- /**(Default: `true`) Delete state on channel deletion. */
57
- autodeleteOnChannelDelete:boolean,
58
- /**(Default: `true`) Delete state on message deletion. */
59
- autodeleteOnMessageDelete:boolean,
60
- /**(Default: `true`) Delete state when the user leaves the guild/server. */
61
- autodeleteOnUserLeave:boolean,
62
- /**(Default: `false`) Delete state on bot restart. */
63
- autodeleteOnRestart:boolean,
64
- /**(Default: `true`) Delete state after 1 hour of an ephemeral message being sent. */
65
- autodeleteOnEphemeral:boolean,
66
- /**(Default: `null`) Delete state when unmodified/inactive for more than.... */
67
- autodeleteAfterTimeout:null|{time:number,unit:"seconds"|"minutes"|"hours"|"days"},
68
- }
69
-
70
- /**## ODState `class`
71
- * An Open Discord state is a system for storing additional chunks of metadata for Discord messages.
72
- * A system for tracking messages or linking metadata, states or progress to Discord messages (ID-based).
73
- *
74
- * Features automatic garbage collection to clear expired states.
75
- */
76
- export class ODState<StateData extends any,WithGuildKey extends boolean,WithUserKey extends boolean> extends ODManagerData {
77
- /**Alias to Open Discord message states database. */
78
- protected database: ODDatabase<ODDatabaseIdConstraint>
79
- /**Alias to Open Discord client manager. */
80
- protected client: ODClientManager
81
- /**Alias to Open Discord debugger. */
82
- protected debug: ODDebugger|null = null
83
- /**The settings of this state. */
84
- settings: ODStateSettings
85
-
86
- constructor(id:ODValidId,client:ODClientManager,database:ODDatabase<ODDatabaseIdConstraint>,settings:Partial<ODStateSettings>){
87
- super(id)
88
- this.client = client
89
- this.database = database
90
- this.settings = {
91
- disableAutodelete:false,
92
- autodeleteOnChannelDelete:true,
93
- autodeleteOnMessageDelete:true,
94
- autodeleteOnUserLeave:true,
95
- autodeleteOnRestart:false,
96
- autodeleteOnEphemeral:true,
97
- autodeleteAfterTimeout:null,
98
- ...settings
99
- }
100
- }
101
-
102
- /**Use the Open Discord debugger in this manager for logs. */
103
- useDebug(debug?:ODDebugger|null){
104
- this.debug = debug ?? null
105
- }
106
- /**Init the state and start autodeleting. The client must already be logged-in for this to work. */
107
- async init(){
108
- if (!this.client.loggedIn) throw new ODSystemError("ODState('"+this.id.value+"').init() => The client must be logged in for states to initialize.")
109
-
110
- //autodelete on restart
111
- if (!this.settings.disableAutodelete && this.settings.autodeleteOnRestart) this.clearAllMsgStates()
112
-
113
- //autodelete on channelDelete
114
- this.client.client.on("channelDelete",async (deletedChannel) => {
115
- if (this.settings.disableAutodelete || !this.settings.autodeleteOnChannelDelete) return
116
-
117
- for (const {key,value} of await this.listMsgStates()){
118
- if (value.channelId === deletedChannel.id) await this.deleteMsgStateWithRawKey(key)
119
- }
120
- })
121
- //autodelete on messageDelete
122
- this.client.client.on("messageDelete",async (deletedMsg) => {
123
- if (this.settings.disableAutodelete || !this.settings.autodeleteOnMessageDelete) return
124
-
125
- for (const {key,value} of await this.listMsgStates()){
126
- if (value.messageId === deletedMsg.id) await this.deleteMsgStateWithRawKey(key)
127
- }
128
- })
129
- //autodelete on userLeave
130
- this.client.client.on("guildMemberRemove",async (member) => {
131
- if (this.settings.disableAutodelete || !this.settings.autodeleteOnUserLeave) return
132
- if (member.guild.id !== this.client.mainServer?.id) return
133
-
134
- for (const {key,value} of await this.listMsgStates()){
135
- if (value.userId === member.id) await this.deleteMsgStateWithRawKey(key)
136
- }
137
- })
138
-
139
- //autodelete when expired (ephemeral/timeout) every 30 seconds
140
- this.purgeExpiredStates()
141
- setInterval(() => {
142
- this.purgeExpiredStates()
143
- },30*1000)
144
-
145
- //create a list of all channels, messages & users that still exist (and are part of states)
146
- const existingChannelIds: string[] = []
147
- const existingMessageIds: string[] = []
148
- const existingUserIds: string[] = []
149
-
150
- for (const {key,value} of await this.listMsgStates()){
151
- if (!existingChannelIds.includes(value.channelId)){
152
- //check if channel still exists
153
- const channel = await this.client.fetchChannel(value.channelId)
154
- if (channel) existingChannelIds.push(channel.id)
155
- }
156
- if (!existingMessageIds.includes(value.messageId)){
157
- //check if message still exists
158
- const message = await this.client.fetchChannelMessage(value.channelId,value.messageId)
159
- if (message) existingMessageIds.push(message.id)
160
- }
161
- if (value.userId && this.client.mainServer && !existingUserIds.includes(value.userId)){
162
- //check if user still exists
163
- const user = await this.client.fetchGuildMember(this.client.mainServer.id,value.userId)
164
- if (user) existingUserIds.push(user.id)
165
- }
166
- }
167
-
168
- //delete all states where a channel, message or user is missing (when the bot was offline)
169
- for (const {key,value} of await this.listMsgStates()){
170
- if (value.channelId && !existingChannelIds.includes(value.channelId)) await this.deleteMsgStateWithRawKey(key)
171
- if (value.messageId && !existingMessageIds.includes(value.messageId)) await this.deleteMsgStateWithRawKey(key)
172
- if (value.userId && !existingUserIds.includes(value.userId)) await this.deleteMsgStateWithRawKey(key)
173
- }
174
- }
175
- /**Purge all expired message states that reached a timeout or ephemeral. */
176
- protected async purgeExpiredStates(){
177
- for (const {key,value} of await this.listMsgStates()){
178
- if (value.deleteAfterDate && value.deleteAfterDate < Date.now()) await this.deleteMsgStateWithRawKey(key)
179
- }
180
- }
181
- /**Transform the object-based message state key contents to a string. */
182
- protected transformKey(key:ODStateKey<WithGuildKey,WithUserKey>){
183
- const newGuild = (!("guild" in key) || !key.guild) ? "NULL" : (typeof key.guild === "string" ? key.guild : key.guild.id)
184
- const newChannel = (!key.channel) ? "NULL" : (typeof key.channel === "string" ? key.channel : key.channel.id)
185
- const newMessage = (!key.message) ? "NULL" : (typeof key.message === "string" ? key.message : key.message.id)
186
- const newUser = (!("user" in key) || !key.user) ? "NULL" : (typeof key.user === "string" ? key.user : key.user.id)
187
-
188
- return `G:${newGuild},C:${newChannel},M:${newMessage},U:${newUser}`
189
- }
190
- /**Transform the message state data contents for storage in the database. */
191
- protected transformData(key:ODStateKey<WithGuildKey,WithUserKey>,data:StateData,isEphemeral:boolean,keepCreatedDate?:number): ODStateData<StateData> {
192
- const guildId = (!("guild" in key) || !key.guild) ? null : (typeof key.guild === "string" ? key.guild : key.guild.id)
193
- const channelId = (typeof key.channel === "string" ? key.channel : key.channel.id)
194
- const messageId = (typeof key.message === "string" ? key.message : key.message.id)
195
- const userId = (!("user" in key) || !key.user) ? null : (typeof key.user === "string" ? key.user : key.user.id)
196
- const createdDate = keepCreatedDate ?? Date.now()
197
- const modifiedDate = Date.now()
198
-
199
- const unmodifiedTimeoutDate = this.timeoutToUnixTime()
200
- const ephemeralTimeoutDate = (isEphemeral) ? Date.now()+(3600*1000) : null //delete ephemeral state after 1 hour
201
- const deleteAfterDate = (unmodifiedTimeoutDate) ? unmodifiedTimeoutDate : ephemeralTimeoutDate
202
-
203
- return {guildId,channelId,messageId,userId,createdDate,modifiedDate,deleteAfterDate,data}
204
- }
205
- /**Calculate milliseconds from a time + unit. */
206
- protected timeoutToUnixTime(){
207
- const timeout = this.settings.autodeleteAfterTimeout
208
- if (!timeout) return null
209
- if (timeout.unit == "seconds") return Date.now() + (timeout.time * 1000)
210
- else if (timeout.unit == "minutes") return Date.now() + (timeout.time * 1000 * 60)
211
- else if (timeout.unit == "hours") return Date.now() + (timeout.time * 1000 * 3600)
212
- else if (timeout.unit == "days") return Date.now() + (timeout.time * 1000 * 3600 * 24)
213
- else return null
214
- }
215
- /**Set a message state using guild, channel & message id as key. Returns `true` when overwritten. */
216
- async setMsgState(key:ODStateKey<WithGuildKey,WithUserKey>,data:StateData,isEphemeral:boolean): Promise<boolean> {
217
- const rawKey = this.transformKey(key)
218
-
219
- const existingData = await this.getMsgState(key)
220
- const contents = this.transformData(key,data,isEphemeral,existingData?.createdDate)
221
- return await this.database.set(this.id.value,rawKey,contents)
222
- }
223
- /**Get a message state using guild, channel & message id as key. */
224
- async getMsgState(key:ODStateKey<WithGuildKey,WithUserKey>): Promise<ODStateData<StateData>|null> {
225
- const rawKey = this.transformKey(key)
226
- const rawData = await this.database.get(this.id.value,rawKey)
227
- if (typeof rawData !== "object") return null
228
- else return rawData as ODStateData<StateData>
229
- }
230
- /**Delete a message state using guild, channel & message id as key. Returns `true` when deleted. */
231
- async deleteMsgState(key:ODStateKey<WithGuildKey,WithUserKey>): Promise<boolean> {
232
- const rawKey = this.transformKey(key)
233
- return await this.database.delete(this.id.value,rawKey)
234
- }
235
- /**List all message states of this `ODState`. */
236
- async listMsgStates(): Promise<{key:string,value:ODStateData<StateData>}[]> {
237
- return ((await this.database.getCategory(this.id.value)) ?? []) as {key:string,value:ODStateData<StateData>}[]
238
- }
239
- /**Delete all message states from this ODState. */
240
- async clearAllMsgStates(): Promise<void> {
241
- for (const state of await this.database.getAll()){
242
- await this.database.delete(state.category,state.key)
243
- }
244
- }
245
- /**Delete a message state using the raw key. Returns `true` when deleted. */
246
- protected async deleteMsgStateWithRawKey(rawKey:string): Promise<boolean> {
247
- return await this.database.delete(this.id.value,rawKey)
248
- }
249
- }
250
-
251
- /**## ODStateManagerIdConstraint `type`
252
- * The constraint/layout for id mappings/interfaces of the `ODStateManager` class.
253
- */
254
- export type ODStateManagerIdConstraint = Record<string,ODState<any,boolean,boolean>>
255
-
256
- /**## ODStateManager `class`
257
- * The Open Discord state manager is a system for tracking messages or linking metadata, states or progress to Discord messages (ID-based).
258
- *
259
- * Features automatic garbage collection to clear expired states.
260
- */
261
- export class ODStateManager<IdList extends ODStateManagerIdConstraint = ODStateManagerIdConstraint> extends ODManager<ODState<any,boolean,boolean>> {
262
- constructor(debug:ODDebugger){
263
- super(debug,"state")
264
- }
265
-
266
- /**Init all states. */
267
- async init(){
268
- for (const state of this.getAll()){
269
- await state.init()
270
- }
271
- }
272
-
273
- add(data:ODState<any,boolean,boolean>, overwrite?:boolean): boolean {
274
- data.useDebug(this.debug)
275
- return super.add(data,overwrite)
276
- }
277
-
278
- get<StateId extends keyof ODNoGeneric<IdList>>(id:StateId): IdList[StateId]
279
- get(id:ODValidId): ODState<any,boolean,boolean>|null
280
-
281
- get(id:ODValidId): ODState<any,boolean,boolean>|null {
282
- return super.get(id)
283
- }
284
-
285
- remove<StateId extends keyof ODNoGeneric<IdList>>(id:StateId): IdList[StateId]
286
- remove(id:ODValidId): ODState<any,boolean,boolean>|null
287
-
288
- remove(id:ODValidId): ODState<any,boolean,boolean>|null {
289
- return super.remove(id)
290
- }
291
-
292
- exists(id:keyof ODNoGeneric<IdList>): boolean
293
- exists(id:ODValidId): boolean
294
-
295
- exists(id:ODValidId): boolean {
296
- return super.exists(id)
297
- }
298
- }
@@ -1,380 +0,0 @@
1
- ///////////////////////////////////////
2
- //STATISTIC MODULE
3
- ///////////////////////////////////////
4
- import { ODId, ODManager, ODManagerData, ODNoGeneric, ODSystemError, ODValidId } from "./base.js"
5
- import { ODDebugger } from "./console.js"
6
- import { ODDatabase, ODDatabaseIdConstraint, ODJsonDatabaseStructure } from "./database.js"
7
- import * as discord from "discord.js"
8
-
9
- /**## ODValidStatisticValue `type`
10
- * These are the only allowed types for a statistic value to improve compatibility with different database systems.
11
- */
12
- export type ODValidStatisticValue = string|number|boolean
13
-
14
- /**## ODStatisticManagerInitCallback `type`
15
- * This callback can be used to execute something when the statistics have been initiated.
16
- *
17
- * By default this is used to clear statistics from users that left the server or tickets which don't exist anymore.
18
- */
19
- export type ODStatisticManagerInitCallback = (database:ODJsonDatabaseStructure, deletables:ODJsonDatabaseStructure) => void|Promise<void>
20
-
21
- /**## ODStatisticScopeSetMode `type`
22
- * This type contains all valid methods for changing the value of a statistic.
23
- */
24
- export type ODStatisticScopeSetMode = "set"|"increase"|"decrease"
25
-
26
- /**## ODStatisticManagerIdConstraint `type`
27
- * The constraint/layout for id mappings/interfaces of the `ODStatisticManager` class.
28
- */
29
- export type ODStatisticManagerIdConstraint = Record<string,ODStatisticScope>
30
-
31
- /**## ODStatisticManager `class`
32
- * This is an Open Discord statistics manager.
33
- *
34
- * This class is responsible for managing all statistics of the bot.
35
- * Statistic are categorized in "scopes" which can be accessed in this manager.
36
- *
37
- * Statistic can be accessed in the individual scopes.
38
- */
39
- export class ODStatisticManager<IdList extends ODStatisticManagerIdConstraint = ODStatisticManagerIdConstraint> extends ODManager<ODStatisticScope> {
40
- /**Alias to Open Discord statistics database. */
41
- database: ODDatabase<ODDatabaseIdConstraint>|null = null
42
- /**All the listeners for the init event. */
43
- protected initListeners: ODStatisticManagerInitCallback[] = []
44
-
45
- constructor(debug:ODDebugger){
46
- super(debug,"statistic scope")
47
- }
48
-
49
- /**Select the database to use to read/write all statistics from/to. */
50
- useDatabase(database:ODDatabase<ODDatabaseIdConstraint>){
51
- this.database = database
52
- }
53
- add(data:ODStatisticScope, overwrite?:boolean): boolean {
54
- data.useDebug(this.debug,"stat")
55
- if (this.database) data.useDatabase(this.database)
56
- return super.add(data,overwrite)
57
- }
58
- /**Init all statistics and run `onInit()` listeners. */
59
- async init(){
60
- if (!this.database) throw new ODSystemError("Unable to initialize statistics scopes due to missing database!")
61
-
62
- //get all valid categories
63
- const validCategories: string[] = []
64
- for (const scope of this.getAll()){
65
- validCategories.push(...scope.init())
66
- }
67
-
68
- //filter out the deletable statistics
69
- const deletableStats: ODJsonDatabaseStructure = []
70
- const data = await this.database.getAll()
71
- data.forEach((data) => {
72
- if (!validCategories.includes(data.category)) deletableStats.push(data)
73
- })
74
-
75
- //do additional deletion
76
- for (const cb of this.initListeners){
77
- await cb(data,deletableStats)
78
- }
79
-
80
- //delete all deletable statistics
81
- for (const data of deletableStats){
82
- if (!this.database) return
83
- await this.database.delete(data.category,data.key)
84
- }
85
- }
86
- /**Reset all statistics. (clears the entire database) */
87
- async reset(){
88
- if (!this.database) return
89
- const data = await this.database.getAll()
90
- for (const d of data){
91
- await this.database.delete(d.category,d.key)
92
- }
93
- }
94
- /**Run a function when the statistics are initialized. This can be used to clear statistics from users that left the server or tickets which don't exist anymore. */
95
- onInit(callback:ODStatisticManagerInitCallback){
96
- this.initListeners.push(callback)
97
- }
98
-
99
- get<ScopeId extends keyof ODNoGeneric<IdList>>(id:ScopeId): IdList[ScopeId]
100
- get(id:ODValidId): ODStatisticScope|null
101
-
102
- get(id:ODValidId): ODStatisticScope|null {
103
- return super.get(id)
104
- }
105
-
106
- remove<ScopeId extends keyof ODNoGeneric<IdList>>(id:ScopeId): IdList[ScopeId]
107
- remove(id:ODValidId): ODStatisticScope|null
108
-
109
- remove(id:ODValidId): ODStatisticScope|null {
110
- return super.remove(id)
111
- }
112
-
113
- exists(id:keyof ODNoGeneric<IdList>): boolean
114
- exists(id:ODValidId): boolean
115
-
116
- exists(id:ODValidId): boolean {
117
- return super.exists(id)
118
- }
119
- }
120
- /**## ODStatisticScopeIdConstraint `type`
121
- * The constraint/layout for id mappings/interfaces of the `ODStatisticScope` class.
122
- */
123
- export type ODStatisticScopeIdConstraint = Record<string,ODStatistic>
124
-
125
- /**## ODStatisticScope `class`
126
- * This is an Open Discord statistic scope.
127
- *
128
- * A scope can contain multiple statistics. Every scope is seperated from other scopes.
129
- * Here, you can read & write the values of all statistics.
130
- *
131
- * The built-in Open Discord scopes are: `global`, `user`, `ticket`
132
- */
133
- export class ODStatisticScope<IdList extends ODStatisticScopeIdConstraint = ODStatisticScopeIdConstraint> extends ODManager<ODStatistic> {
134
- /**The id of this statistics scope. */
135
- id: ODId
136
- /**Is this scope already initialized? */
137
- ready: boolean = false
138
- /**Alias to Open Discord statistics database. */
139
- database: ODDatabase<ODDatabaseIdConstraint>|null = null
140
- /**The name of this scope (used in embed title) */
141
- name:string
142
-
143
- constructor(id:ODValidId, name:string){
144
- super()
145
- this.id = new ODId(id)
146
- this.name = name
147
- }
148
-
149
- /**Select the database to use to read/write all statistics from/to. (Automatically assigned when used in `ODStatisticManager`) */
150
- useDatabase(database:ODDatabase<ODDatabaseIdConstraint>){
151
- this.database = database
152
- }
153
- /**Get the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the statistics are related to. */
154
- getStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId, scopeId:string): Promise<ODValidStatisticValue|null>
155
- getStat(id:ODValidId, scopeId:string): Promise<ODValidStatisticValue|null>
156
- async getStat(id:ODValidId, scopeId:string): Promise<ODValidStatisticValue|null> {
157
- if (!this.database) return null
158
- const newId = new ODId(id)
159
- const data = await this.database.get(this.id.value+"_"+newId.value,scopeId)
160
-
161
- if (typeof data == "undefined"){
162
- //set statistics to default value & return
163
- return this.resetStat(id,scopeId)
164
- }else if (typeof data == "string" || typeof data == "boolean" || typeof data == "number"){
165
- //return value received from database
166
- return data
167
- }
168
- //return null on error
169
- return null
170
- }
171
- /**Get the value of a statistic for all `scopeId`'s. The `scopeId` is the unique id of the user, channel, role, etc that the statistics are related to. */
172
- getAllStats<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId): Promise<{id:string,value:ODValidStatisticValue}[]>
173
- getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatisticValue}[]>
174
- async getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatisticValue}[]> {
175
- if (!this.database) return []
176
- const newId = new ODId(id)
177
- const data = await this.database.getCategory(this.id.value+"_"+newId.value) ?? []
178
- const output: {id:string,value:ODValidStatisticValue}[] = []
179
-
180
- for (const stat of data){
181
- if (typeof stat.value == "string" || typeof stat.value == "boolean" || typeof stat.value == "number"){
182
- //return value received from database
183
- output.push({id:stat.key,value:stat.value})
184
- }
185
- }
186
-
187
- //return null on error
188
- return output
189
- }
190
- /**Set, increase or decrease the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the statistics are related to. */
191
- setStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId, scopeId:string, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean>
192
- setStat(id:ODValidId, scopeId:string, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean>
193
- async setStat(id:ODValidId, scopeId:string, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean> {
194
- if (!this.database) return false
195
- const stat = this.get(id)
196
- if (!stat) return false
197
- if (mode == "set" || typeof value != "number"){
198
- await this.database.set(this.id.value+"_"+stat.id.value,scopeId,value)
199
- }else if (mode == "increase"){
200
- const currentValue = await this.getStat(id,scopeId)
201
- if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0+value)
202
- else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value)
203
- }else if (mode == "decrease"){
204
- const currentValue = await this.getStat(id,scopeId)
205
- if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0-value)
206
- else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value)
207
- }
208
- return true
209
- }
210
- /**Reset the value of a statistic to the initial value. The `scopeId` is the unique id of the user, channel, role, etc that the statistics are related to. */
211
- resetStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:ODValidId, scopeId:string): Promise<ODValidStatisticValue|null>
212
- resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatisticValue|null>
213
- async resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatisticValue|null> {
214
- if (!this.database) return null
215
- const stat = this.get(id)
216
- if (!stat) return null
217
- if (stat.value != null) await this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value)
218
- return stat.value
219
- }
220
- /**Initialize this statistic scope & return a list of all statistic ids in the following format: `<scopeid>_<statid>` */
221
- init(): string[] {
222
- //get all valid statistics categories
223
- this.ready = true
224
- return this.getAll().map((stat) => this.id.value+"_"+stat.id.value)
225
- }
226
- /**Render all statistics in this scope for usage in a discord message/embed. */
227
- async render(scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User): Promise<string> {
228
- //sort from high priority to low
229
- const derefArray = [...this.getAll()]
230
- derefArray.sort((a,b) => {
231
- return b.priority-a.priority
232
- })
233
- const result: string[] = []
234
-
235
- for (const stat of derefArray){
236
- try {
237
- if (stat instanceof ODDynamicStatistic){
238
- //dynamic render (without value)
239
- result.push(await stat.render("",scopeId,guild,channel,user))
240
- }else{
241
- //normal render (with value)
242
- const value = await this.getStat(stat.id,scopeId)
243
- if (value != null) result.push(await stat.render(value,scopeId,guild,channel,user))
244
- }
245
-
246
- }catch(err){
247
- process.emit("uncaughtException",err)
248
- }
249
- }
250
-
251
- return result.filter((stat) => stat !== "").join("\n")
252
- }
253
-
254
- get<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId): IdList[StatisticId]
255
- get(id:ODValidId): ODStatistic|null
256
-
257
- get(id:ODValidId): ODStatistic|null {
258
- return super.get(id)
259
- }
260
-
261
- remove<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId): IdList[StatisticId]
262
- remove(id:ODValidId): ODStatistic|null
263
-
264
- remove(id:ODValidId): ODStatistic|null {
265
- return super.remove(id)
266
- }
267
-
268
- exists(id:keyof ODNoGeneric<IdList>): boolean
269
- exists(id:ODValidId): boolean
270
-
271
- exists(id:ODValidId): boolean {
272
- return super.exists(id)
273
- }
274
- }
275
-
276
- /**## ODStatisticGlobalScope `class`
277
- * This is an Open Discord statistic global scope.
278
- *
279
- * A scope can contain multiple statistics. Every scope is seperated from other scopes.
280
- * Here, you can read & write the values of all statistics.
281
- *
282
- * This scope is made specifically for the global statistics of Open Discord.
283
- */
284
- export class ODStatisticGlobalScope<IdList extends ODStatisticScopeIdConstraint = ODStatisticScopeIdConstraint> extends ODStatisticScope<IdList> {
285
- getStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId): Promise<ODValidStatisticValue|null>
286
- getStat(id:ODValidId): Promise<ODValidStatisticValue|null>
287
- getStat(id:ODValidId): Promise<ODValidStatisticValue|null> {
288
- return super.getStat(id,"GLOBAL")
289
- }
290
-
291
- getAllStats<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId): Promise<{id:string,value:ODValidStatisticValue}[]>
292
- getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatisticValue}[]>
293
- getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatisticValue}[]> {
294
- return super.getAllStats(id)
295
- }
296
-
297
- setStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:StatisticId, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean>
298
- setStat(id:ODValidId, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean>
299
- setStat(id:ODValidId, value:ODValidStatisticValue, mode:ODStatisticScopeSetMode): Promise<boolean> {
300
- return super.setStat(id,"GLOBAL",value,mode)
301
- }
302
-
303
- resetStat<StatisticId extends keyof ODNoGeneric<IdList>>(id:ODValidId): Promise<ODValidStatisticValue|null>
304
- resetStat(id:ODValidId): Promise<ODValidStatisticValue|null>
305
- resetStat(id:ODValidId): Promise<ODValidStatisticValue|null> {
306
- return super.resetStat(id,"GLOBAL")
307
- }
308
-
309
- render(scopeId:"GLOBAL", guild:discord.Guild, channel:discord.TextBasedChannel, user: discord.User): Promise<string> {
310
- return super.render("GLOBAL",guild,channel,user)
311
- }
312
- }
313
-
314
- /**## ODStatisticRenderer `type`
315
- * This callback will render a single statistic for a discord embed/message.
316
- */
317
- export type ODStatisticRenderer = (value:ODValidStatisticValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
318
-
319
- /**## ODStatistic `class`
320
- * This is an Open Discord statistic.
321
- *
322
- * This single statistic doesn't do anything except defining the rules of this statistic.
323
- * Use it in a statistics scope to register a new statistic. A statistic can also include a priority to choose the render priority.
324
- *
325
- * It's recommended to use the `ODBaseStatistic` & `ODDynamicStatistic` classes instead of this one!
326
- */
327
- export class ODStatistic extends ODManagerData {
328
- /**The priority of this statistic. */
329
- priority: number
330
- /**The render function of this statistic. */
331
- render: ODStatisticRenderer
332
- /**The value of this statistic. */
333
- value: ODValidStatisticValue|null
334
-
335
- constructor(id:ODValidId, priority:number, render:ODStatisticRenderer, value?:ODValidStatisticValue){
336
- super(id)
337
- this.priority = priority
338
- this.render = render
339
- this.value = value ?? null
340
- }
341
- }
342
-
343
- /**## ODBaseStatistic `class`
344
- * This is an Open Discord basic statistic.
345
- *
346
- * This single statistic will store a number, boolean or string in the database.
347
- * Use it to create a simple statistic for any statistics scope.
348
- */
349
- export class ODBaseStatistic extends ODStatistic {
350
- /**The name of this statistic. Rendered in discord embeds/messages. */
351
- name: string
352
-
353
- constructor(id:ODValidId, priority:number, name:string, value:ODValidStatisticValue){
354
- super(id,priority,(value) => {
355
- return ""+name+": `"+value.toString()+"`"
356
- },value)
357
- this.name = name
358
- }
359
- }
360
-
361
- /**## ODDynamicStatisticRenderer `type`
362
- * This callback will render a single dynamic statistic for a discord embed/message.
363
- */
364
- export type ODDynamicStatisticRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
365
-
366
- /**## ODDynamicStatistic `class`
367
- * This is an Open Discord dynamic statistic.
368
- *
369
- * A dynamic statistic does not store anything in the database! Instead, it will execute a function to return a custom result.
370
- * This can be used to show statistics which are not stored in the database.
371
- *
372
- * This is used in Open Discord for the live ticket status, participants & system status.
373
- */
374
- export class ODDynamicStatistic extends ODStatistic {
375
- constructor(id:ODValidId, priority:number, render:ODDynamicStatisticRenderer){
376
- super(id,priority,(value,scopeId,guild,channel,user) => {
377
- return render(scopeId,guild,channel,user)
378
- })
379
- }
380
- }