feat(jsdoc): added some
This commit is contained in:
parent
5428aae1b7
commit
62ed3ac9f7
7 changed files with 80 additions and 10 deletions
|
@ -5,19 +5,30 @@ import {
|
||||||
RedisConnectOptions
|
RedisConnectOptions
|
||||||
} from 'https://denopkg.com/keroxp/deno-redis/mod.ts'
|
} from 'https://denopkg.com/keroxp/deno-redis/mod.ts'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ICacheAdapter is the interface to be implemented by Cache Adapters for them to be usable with Harmony.
|
||||||
|
*
|
||||||
|
* Methods can return Promises too.
|
||||||
|
*/
|
||||||
export interface ICacheAdapter {
|
export interface ICacheAdapter {
|
||||||
|
/** Get a key from a Cache */
|
||||||
get: (cacheName: string, key: string) => Promise<any> | any
|
get: (cacheName: string, key: string) => Promise<any> | any
|
||||||
|
/** Set a key to value in a Cache Name with optional expire value in MS */
|
||||||
set: (
|
set: (
|
||||||
cacheName: string,
|
cacheName: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: any,
|
value: any,
|
||||||
expire?: number
|
expire?: number
|
||||||
) => Promise<any> | any
|
) => Promise<any> | any
|
||||||
|
/** Delete a key from a Cache */
|
||||||
delete: (cacheName: string, key: string) => Promise<boolean> | boolean
|
delete: (cacheName: string, key: string) => Promise<boolean> | boolean
|
||||||
|
/** Get array of all values in a Cache */
|
||||||
array: (cacheName: string) => undefined | any[] | Promise<any[] | undefined>
|
array: (cacheName: string) => undefined | any[] | Promise<any[] | undefined>
|
||||||
|
/** Entirely delete a Cache */
|
||||||
deleteCache: (cacheName: string) => any
|
deleteCache: (cacheName: string) => any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Default Cache Adapter for in-memory caching. */
|
||||||
export class DefaultCacheAdapter implements ICacheAdapter {
|
export class DefaultCacheAdapter implements ICacheAdapter {
|
||||||
data: {
|
data: {
|
||||||
[name: string]: Collection<string, any>
|
[name: string]: Collection<string, any>
|
||||||
|
@ -65,6 +76,7 @@ export class DefaultCacheAdapter implements ICacheAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Redis Cache Adatper for using Redis as a cache-provider. */
|
||||||
export class RedisCacheAdapter implements ICacheAdapter {
|
export class RedisCacheAdapter implements ICacheAdapter {
|
||||||
_redis: Promise<Redis>
|
_redis: Promise<Redis>
|
||||||
redis?: Redis
|
redis?: Redis
|
||||||
|
|
|
@ -105,7 +105,12 @@ export class Client extends EventEmitter {
|
||||||
this.fetchUncachedReactions = true
|
this.fetchUncachedReactions = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set Cache Adapter */
|
/**
|
||||||
|
* Set Cache Adapter
|
||||||
|
*
|
||||||
|
* Should NOT set after bot is already logged in or using current cache.
|
||||||
|
* Please look into using `cache` option.
|
||||||
|
*/
|
||||||
setAdapter(adapter: ICacheAdapter): Client {
|
setAdapter(adapter: ICacheAdapter): Client {
|
||||||
this.cache = adapter
|
this.cache = adapter
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -403,12 +403,14 @@ export class CategoriesManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parsed Command object */
|
||||||
export interface ParsedCommand {
|
export interface ParsedCommand {
|
||||||
name: string
|
name: string
|
||||||
args: string[]
|
args: string[]
|
||||||
argString: string
|
argString: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parses a Command to later look for. */
|
||||||
export const parseCommand = (
|
export const parseCommand = (
|
||||||
client: CommandClient,
|
client: CommandClient,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
|
|
|
@ -11,19 +11,33 @@ import { ExtensionsManager } from './extensions.ts'
|
||||||
|
|
||||||
type PrefixReturnType = string | string[] | Promise<string | string[]>
|
type PrefixReturnType = string | string[] | Promise<string | string[]>
|
||||||
|
|
||||||
|
/** Command Client options extending Client Options to provide a lot of Commands-related customizations */
|
||||||
export interface CommandClientOptions extends ClientOptions {
|
export interface CommandClientOptions extends ClientOptions {
|
||||||
|
/** Global prefix(s) of the bot. */
|
||||||
prefix: string | string[]
|
prefix: string | string[]
|
||||||
|
/** Whether to enable mention prefix or not. */
|
||||||
mentionPrefix?: boolean
|
mentionPrefix?: boolean
|
||||||
|
/** Method to get a Guild's custom prefix(s). */
|
||||||
getGuildPrefix?: (guildID: string) => PrefixReturnType
|
getGuildPrefix?: (guildID: string) => PrefixReturnType
|
||||||
|
/** Method to get a User's custom prefix(s). */
|
||||||
getUserPrefix?: (userID: string) => PrefixReturnType
|
getUserPrefix?: (userID: string) => PrefixReturnType
|
||||||
|
/** Method to check if certain Guild is blacklisted from using Commands. */
|
||||||
isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
||||||
|
/** Method to check if certain User is blacklisted from using Commands. */
|
||||||
isUserBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
isUserBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
||||||
|
/** Method to check if certain Channel is blacklisted from using Commands. */
|
||||||
isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
||||||
|
/** Allow spaces after prefix? Recommended with Mention Prefix ON. */
|
||||||
spacesAfterPrefix?: boolean
|
spacesAfterPrefix?: boolean
|
||||||
|
/** Better Arguments regex to split at every whitespace. */
|
||||||
betterArgs?: boolean
|
betterArgs?: boolean
|
||||||
|
/** List of Bot's Owner IDs whom can access `ownerOnly` commands. */
|
||||||
owners?: string[]
|
owners?: string[]
|
||||||
|
/** Whether to allow Bots to use Commands or not, not allowed by default. */
|
||||||
allowBots?: boolean
|
allowBots?: boolean
|
||||||
|
/** Whether to allow Commands in DMs or not, allowed by default. */
|
||||||
allowDMs?: boolean
|
allowDMs?: boolean
|
||||||
|
/** Whether Commands should be case-sensitive or not, not by default. */
|
||||||
caseSensitive?: boolean
|
caseSensitive?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +102,7 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Process a Message to Execute Command. */
|
||||||
async processMessage(msg: Message): Promise<any> {
|
async processMessage(msg: Message): Promise<any> {
|
||||||
if (!this.allowBots && msg.author.bot === true) return
|
if (!this.allowBots && msg.author.bot === true) return
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { CommandClient } from './commandClient.ts'
|
||||||
|
|
||||||
export type ExtensionEventCallback = (ext: Extension, ...args: any[]) => any
|
export type ExtensionEventCallback = (ext: Extension, ...args: any[]) => any
|
||||||
|
|
||||||
|
/** Extension Commands Manager */
|
||||||
export class ExtensionCommands {
|
export class ExtensionCommands {
|
||||||
extension: Extension
|
extension: Extension
|
||||||
|
|
||||||
|
@ -11,12 +12,14 @@ export class ExtensionCommands {
|
||||||
this.extension = ext
|
this.extension = ext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get a list of Extension's Commands */
|
||||||
get list(): Collection<string, Command> {
|
get list(): Collection<string, Command> {
|
||||||
return this.extension.client.commands.list.filter(
|
return this.extension.client.commands.list.filter(
|
||||||
(c) => c.extension?.name === this.extension.name
|
(c) => c.extension?.name === this.extension.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get an Extension Command */
|
||||||
get(cmd: string): Command | undefined {
|
get(cmd: string): Command | undefined {
|
||||||
const find = this.extension.client.commands.find(cmd)
|
const find = this.extension.client.commands.find(cmd)
|
||||||
// linter sucks
|
// linter sucks
|
||||||
|
@ -26,12 +29,14 @@ export class ExtensionCommands {
|
||||||
else return find
|
else return find
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Add an Extension Command */
|
||||||
add(Cmd: Command | typeof Command): boolean {
|
add(Cmd: Command | typeof Command): boolean {
|
||||||
const cmd = Cmd instanceof Command ? Cmd : new Cmd()
|
const cmd = Cmd instanceof Command ? Cmd : new Cmd()
|
||||||
cmd.extension = this.extension
|
cmd.extension = this.extension
|
||||||
return this.extension.client.commands.add(cmd)
|
return this.extension.client.commands.add(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Delete an Extension Command */
|
||||||
delete(cmd: Command | string): boolean {
|
delete(cmd: Command | string): boolean {
|
||||||
const find = this.extension.client.commands.find(
|
const find = this.extension.client.commands.find(
|
||||||
typeof cmd === 'string' ? cmd : cmd.name
|
typeof cmd === 'string' ? cmd : cmd.name
|
||||||
|
@ -45,6 +50,7 @@ export class ExtensionCommands {
|
||||||
else return this.extension.client.commands.delete(find)
|
else return this.extension.client.commands.delete(find)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Delete all Commands of an Extension */
|
||||||
deleteAll(): void {
|
deleteAll(): void {
|
||||||
for (const [cmd] of this.list) {
|
for (const [cmd] of this.list) {
|
||||||
this.delete(cmd)
|
this.delete(cmd)
|
||||||
|
@ -52,17 +58,23 @@ export class ExtensionCommands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Customizable, isolated and pluggable Extensions are a great way of writing certain Modules independent of others */
|
||||||
export class Extension {
|
export class Extension {
|
||||||
client: CommandClient
|
client: CommandClient
|
||||||
|
/** Name of the Extension */
|
||||||
name: string = ''
|
name: string = ''
|
||||||
|
/** Description of the Extension */
|
||||||
description?: string
|
description?: string
|
||||||
|
/** Extensions's Commands Manager */
|
||||||
commands: ExtensionCommands = new ExtensionCommands(this)
|
commands: ExtensionCommands = new ExtensionCommands(this)
|
||||||
|
/** Events registered by this Extension */
|
||||||
events: { [name: string]: (...args: any[]) => {} } = {}
|
events: { [name: string]: (...args: any[]) => {} } = {}
|
||||||
|
|
||||||
constructor(client: CommandClient) {
|
constructor(client: CommandClient) {
|
||||||
this.client = client
|
this.client = client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Listen for an Event through Extension. */
|
||||||
listen(event: string, cb: ExtensionEventCallback): boolean {
|
listen(event: string, cb: ExtensionEventCallback): boolean {
|
||||||
if (this.events[event] !== undefined) return false
|
if (this.events[event] !== undefined) return false
|
||||||
else {
|
else {
|
||||||
|
@ -76,10 +88,13 @@ export class Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Method called upon loading of an Extension */
|
||||||
load(): any {}
|
load(): any {}
|
||||||
|
/** Method called upon unloading of an Extension */
|
||||||
unload(): any {}
|
unload(): any {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Extensions Manager for CommandClient */
|
||||||
export class ExtensionsManager {
|
export class ExtensionsManager {
|
||||||
client: CommandClient
|
client: CommandClient
|
||||||
list: Collection<string, Extension> = new Collection()
|
list: Collection<string, Extension> = new Collection()
|
||||||
|
@ -88,14 +103,17 @@ export class ExtensionsManager {
|
||||||
this.client = client
|
this.client = client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get an Extension by name */
|
||||||
get(ext: string): Extension | undefined {
|
get(ext: string): Extension | undefined {
|
||||||
return this.list.get(ext)
|
return this.list.get(ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check whether an Extension exists or not */
|
||||||
exists(ext: string): boolean {
|
exists(ext: string): boolean {
|
||||||
return this.get(ext) !== undefined
|
return this.get(ext) !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Load an Extension onto Command Client */
|
||||||
load(ext: Extension | typeof Extension): void {
|
load(ext: Extension | typeof Extension): void {
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
if (!(ext instanceof Extension)) ext = new ext(this.client)
|
if (!(ext instanceof Extension)) ext = new ext(this.client)
|
||||||
|
@ -105,6 +123,7 @@ export class ExtensionsManager {
|
||||||
ext.load()
|
ext.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Unload an Extension from Command Client */
|
||||||
unload(ext: Extension | string): boolean {
|
unload(ext: Extension | string): boolean {
|
||||||
const name = typeof ext === 'string' ? ext : ext.name
|
const name = typeof ext === 'string' ? ext : ext.name
|
||||||
const extension = this.get(name)
|
const extension = this.get(name)
|
||||||
|
|
|
@ -65,7 +65,7 @@ export class RESTManager {
|
||||||
this.handleRateLimits()
|
this.handleRateLimits()
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkQueues(): Promise<void> {
|
private async checkQueues(): Promise<void> {
|
||||||
Object.entries(this.queues).forEach(([key, value]) => {
|
Object.entries(this.queues).forEach(([key, value]) => {
|
||||||
if (value.length === 0) {
|
if (value.length === 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
|
@ -74,7 +74,7 @@ export class RESTManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
queue(request: QueuedItem): void {
|
private queue(request: QueuedItem): void {
|
||||||
const route = request.url.substring(
|
const route = request.url.substring(
|
||||||
// eslint seriously?
|
// eslint seriously?
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
|
@ -91,7 +91,7 @@ export class RESTManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async processQueue(): Promise<void> {
|
private async processQueue(): Promise<void> {
|
||||||
if (Object.keys(this.queues).length !== 0 && !this.globalRateLimit) {
|
if (Object.keys(this.queues).length !== 0 && !this.globalRateLimit) {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
Object.values(this.queues).map(async (pathQueue) => {
|
Object.values(this.queues).map(async (pathQueue) => {
|
||||||
|
@ -139,7 +139,7 @@ export class RESTManager {
|
||||||
} else this.processing = false
|
} else this.processing = false
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare(body: any, method: RequestMethods): { [key: string]: any } {
|
private prepare(body: any, method: RequestMethods): { [key: string]: any } {
|
||||||
const headers: RequestHeaders = {
|
const headers: RequestHeaders = {
|
||||||
'User-Agent': `DiscordBot (harmony, https://github.com/harmony-org/harmony)`
|
'User-Agent': `DiscordBot (harmony, https://github.com/harmony-org/harmony)`
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ export class RESTManager {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
async isRateLimited(url: string): Promise<number | false> {
|
private async isRateLimited(url: string): Promise<number | false> {
|
||||||
const global = this.rateLimits.get('global')
|
const global = this.rateLimits.get('global')
|
||||||
const rateLimited = this.rateLimits.get(url)
|
const rateLimited = this.rateLimits.get(url)
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
|
@ -207,7 +207,10 @@ export class RESTManager {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
processHeaders(url: string, headers: Headers): string | null | undefined {
|
private processHeaders(
|
||||||
|
url: string,
|
||||||
|
headers: Headers
|
||||||
|
): string | null | undefined {
|
||||||
let rateLimited = false
|
let rateLimited = false
|
||||||
|
|
||||||
const global = headers.get('x-ratelimit-global')
|
const global = headers.get('x-ratelimit-global')
|
||||||
|
@ -257,7 +260,7 @@ export class RESTManager {
|
||||||
return rateLimited ? bucket : undefined
|
return rateLimited ? bucket : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleStatusCode(
|
private async handleStatusCode(
|
||||||
response: Response,
|
response: Response,
|
||||||
body: any,
|
body: any,
|
||||||
data: { [key: string]: any }
|
data: { [key: string]: any }
|
||||||
|
@ -304,6 +307,15 @@ export class RESTManager {
|
||||||
} else throw new DiscordAPIError('Request - Unknown Error')
|
} else throw new DiscordAPIError('Request - Unknown Error')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a Request to Discord API
|
||||||
|
* @param method HTTP Method to use
|
||||||
|
* @param url URL of the Request
|
||||||
|
* @param body Body to send with Request
|
||||||
|
* @param maxRetries Number of Max Retries to perform
|
||||||
|
* @param bucket BucketID of the Request
|
||||||
|
* @param rawResponse Whether to get Raw Response or body itself
|
||||||
|
*/
|
||||||
async make(
|
async make(
|
||||||
method: RequestMethods,
|
method: RequestMethods,
|
||||||
url: string,
|
url: string,
|
||||||
|
@ -389,7 +401,7 @@ export class RESTManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleRateLimits(): Promise<void> {
|
private async handleRateLimits(): Promise<void> {
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
this.rateLimits.forEach((value, key) => {
|
this.rateLimits.forEach((value, key) => {
|
||||||
if (value.resetAt > now) return
|
if (value.resetAt > now) return
|
||||||
|
@ -398,6 +410,7 @@ export class RESTManager {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make a GET Request to API */
|
||||||
async get(
|
async get(
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
|
@ -408,6 +421,7 @@ export class RESTManager {
|
||||||
return await this.make('get', url, body, maxRetries, bucket, rawResponse)
|
return await this.make('get', url, body, maxRetries, bucket, rawResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make a POST Request to API */
|
||||||
async post(
|
async post(
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
|
@ -418,6 +432,7 @@ export class RESTManager {
|
||||||
return await this.make('post', url, body, maxRetries, bucket, rawResponse)
|
return await this.make('post', url, body, maxRetries, bucket, rawResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make a DELETE Request to API */
|
||||||
async delete(
|
async delete(
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
|
@ -428,6 +443,7 @@ export class RESTManager {
|
||||||
return await this.make('delete', url, body, maxRetries, bucket, rawResponse)
|
return await this.make('delete', url, body, maxRetries, bucket, rawResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make a PATCH Request to API */
|
||||||
async patch(
|
async patch(
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
|
@ -438,6 +454,7 @@ export class RESTManager {
|
||||||
return await this.make('patch', url, body, maxRetries, bucket, rawResponse)
|
return await this.make('patch', url, body, maxRetries, bucket, rawResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make a PUT Request to API */
|
||||||
async put(
|
async put(
|
||||||
url: string,
|
url: string,
|
||||||
body?: unknown,
|
body?: unknown,
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class VoiceClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(): Promise<VoiceClient> {
|
async connect(): Promise<VoiceClient> {
|
||||||
// TODO(DjDeveloperr): Actually understand what the hell docs say
|
// TODO(DjDeveloperr): understand docs
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue