feat(jsdoc): pretty much done

This commit is contained in:
DjDeveloperr 2020-12-03 09:36:41 +05:30
parent 62ed3ac9f7
commit d1aba4a981
27 changed files with 65 additions and 84 deletions

2
mod.ts
View file

@ -22,7 +22,7 @@ export { MessageReactionsManager } from './src/managers/messageReactions.ts'
export { ReactionUsersManager } from './src/managers/reactionUsers.ts' export { ReactionUsersManager } from './src/managers/reactionUsers.ts'
export { MessagesManager } from './src/managers/messages.ts' export { MessagesManager } from './src/managers/messages.ts'
export { RolesManager } from './src/managers/roles.ts' export { RolesManager } from './src/managers/roles.ts'
export { UserManager } from './src/managers/users.ts' export { UsersManager } from './src/managers/users.ts'
export { Application } from './src/structures/application.ts' export { Application } from './src/structures/application.ts'
export { ImageURL } from './src/structures/cdn.ts' export { ImageURL } from './src/structures/cdn.ts'
export { Channel } from './src/structures/channel.ts' export { Channel } from './src/structures/channel.ts'

View file

@ -26,6 +26,7 @@ export interface RequestMembersOptions {
/** /**
* Handles Discord gateway connection. * Handles Discord gateway connection.
*
* You should not use this and rather use Client class. * You should not use this and rather use Client class.
*/ */
class Gateway { class Gateway {

View file

@ -1,6 +1,11 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Collection } from '../utils/collection.ts' import { Collection } from '../utils/collection.ts'
/**
* Managers handle caching data. And also some REST Methods as required.
*
* You should not be making Managers yourself.
*/
export class BaseManager<T, T2> { export class BaseManager<T, T2> {
client: Client client: Client
/** Cache Name or Key used to differentiate caches */ /** Cache Name or Key used to differentiate caches */
@ -14,30 +19,36 @@ export class BaseManager<T, T2> {
this.DataType = DataType this.DataType = DataType
} }
/** Get raw value from a cache (payload) */
async _get(key: string): Promise<T | undefined> { async _get(key: string): Promise<T | undefined> {
return this.client.cache.get(this.cacheName, key) return this.client.cache.get(this.cacheName, key)
} }
/** Get a value from Cache */
async get(key: string): Promise<T2 | undefined> { async get(key: string): Promise<T2 | undefined> {
const raw = await this._get(key) const raw = await this._get(key)
if (raw === undefined) return if (raw === undefined) return
return new this.DataType(this.client, raw) return new this.DataType(this.client, raw)
} }
/** Set a value to Cache */
async set(key: string, value: T): Promise<any> { async set(key: string, value: T): Promise<any> {
return this.client.cache.set(this.cacheName, key, value) return this.client.cache.set(this.cacheName, key, value)
} }
/** Delete a key from Cache */
async delete(key: string): Promise<boolean> { async delete(key: string): Promise<boolean> {
return this.client.cache.delete(this.cacheName, key) return this.client.cache.delete(this.cacheName, key)
} }
/** Get an Array of values from Cache */
async array(): Promise<undefined | T2[]> { async array(): Promise<undefined | T2[]> {
let arr = await (this.client.cache.array(this.cacheName) as T[]) let arr = await (this.client.cache.array(this.cacheName) as T[])
if (arr === undefined) arr = [] if (arr === undefined) arr = []
return arr.map((e) => new this.DataType(this.client, e)) as any return arr.map((e) => new this.DataType(this.client, e)) as any
} }
/** Get a Collection of values from Cache */
async collection(): Promise<Collection<string, T2>> { async collection(): Promise<Collection<string, T2>> {
const arr = await this.array() const arr = await this.array()
if (arr === undefined) return new Collection() if (arr === undefined) return new Collection()
@ -49,6 +60,7 @@ export class BaseManager<T, T2> {
return collection return collection
} }
/** Delete everything from Cache */
flush(): any { flush(): any {
return this.client.cache.deleteCache(this.cacheName) return this.client.cache.deleteCache(this.cacheName)
} }

View file

@ -2,8 +2,10 @@ import { Client } from '../models/client.ts'
import { Collection } from '../utils/collection.ts' import { Collection } from '../utils/collection.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
/** Child Managers validate data from their parents i.e. from Managers */
export class BaseChildManager<T, T2> { export class BaseChildManager<T, T2> {
client: Client client: Client
/** Parent Manager */
parent: BaseManager<T, T2> parent: BaseManager<T, T2>
constructor(client: Client, parent: BaseManager<T, T2>) { constructor(client: Client, parent: BaseManager<T, T2>) {
@ -32,8 +34,8 @@ export class BaseChildManager<T, T2> {
if (arr === undefined) return new Collection() if (arr === undefined) return new Collection()
const collection = new Collection() const collection = new Collection()
for (const elem of arr) { for (const elem of arr) {
// @ts-expect-error // any is required here. Else you would need ts-ignore or expect-error.
collection.set(elem.id, elem) collection.set((elem as any).id, elem)
} }
return collection return collection
} }

View file

@ -43,6 +43,7 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
return result return result
} }
/** Fetch a Channel by ID, cache it, resolve it */
async fetch<T = Channel>(id: string): Promise<T> { async fetch<T = Channel>(id: string): Promise<T> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest

View file

@ -20,6 +20,7 @@ export class EmojisManager extends BaseManager<EmojiPayload, Emoji> {
return emoji return emoji
} }
/** Fetch an Emoji by Guild ID and Emoji ID, cache it and resolve it */
async fetch(guildID: string, id: string): Promise<Emoji> { async fetch(guildID: string, id: string): Promise<Emoji> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest

View file

@ -1,5 +1,10 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
/**
* Cache Manager used for Caching values related to Gateway connection
*
* In case of Redis, this will persistently cache session ID and seq for fast resumes.
*/
export class GatewayCache { export class GatewayCache {
client: Client client: Client
cacheName: string = 'discord_gateway_cache' cacheName: string = 'discord_gateway_cache'

View file

@ -1,8 +1,8 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { MessageReaction } from '../structures/messageReaction.ts' import { MessageReaction } from '../structures/messageReaction.ts'
import { UserManager } from './users.ts' import { UsersManager } from './users.ts'
export class ReactionUsersManager extends UserManager { export class ReactionUsersManager extends UsersManager {
reaction: MessageReaction reaction: MessageReaction
constructor(client: Client, reaction: MessageReaction) { constructor(client: Client, reaction: MessageReaction) {

View file

@ -4,7 +4,7 @@ import { USER } from '../types/endpoint.ts'
import { UserPayload } from '../types/user.ts' import { UserPayload } from '../types/user.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class UserManager extends BaseManager<UserPayload, User> { export class UsersManager extends BaseManager<UserPayload, User> {
constructor(client: Client) { constructor(client: Client) {
super(client, 'users', User) super(client, 'users', User)
} }

View file

@ -4,7 +4,7 @@ import { Gateway } from '../gateway/index.ts'
import { RESTManager } from './rest.ts' import { RESTManager } from './rest.ts'
import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts' import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts'
import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts' import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts'
import { UserManager } from '../managers/users.ts' import { UsersManager } from '../managers/users.ts'
import { GuildManager } from '../managers/guilds.ts' import { GuildManager } from '../managers/guilds.ts'
import { ChannelsManager } from '../managers/channels.ts' import { ChannelsManager } from '../managers/channels.ts'
import { ClientPresence } from '../structures/presence.ts' import { ClientPresence } from '../structures/presence.ts'
@ -72,7 +72,7 @@ export class Client extends EventEmitter {
/** Whether to fetch Uncached Message of Reaction or not? */ /** Whether to fetch Uncached Message of Reaction or not? */
fetchUncachedReactions: boolean = false fetchUncachedReactions: boolean = false
users: UserManager = new UserManager(this) users: UsersManager = new UsersManager(this)
guilds: GuildManager = new GuildManager(this) guilds: GuildManager = new GuildManager(this)
channels: ChannelsManager = new ChannelsManager(this) channels: ChannelsManager = new ChannelsManager(this)
emojis: EmojisManager = new EmojisManager(this) emojis: EmojisManager = new EmojisManager(this)

View file

@ -1,63 +1,9 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
interface IInit {
useCache?: boolean
endpoint: (...restURLfuncArgs: string[]) => string
restURLfuncArgs: string[]
}
export class Base { export class Base {
client: Client client: Client
static cacheName?: string
propertyConverterOverride: { [k: string]: string } = {}
static useCache?: boolean = true
static restFunc?: (...restURLfuncArgs: string[]) => string
constructor(client: Client, _data?: any) { constructor(client: Client, _data?: any) {
this.client = client this.client = client
} }
static async autoInit(
client: Client,
{ useCache, endpoint, restURLfuncArgs }: IInit
): Promise<any> {
this.useCache = useCache
const cacheID = restURLfuncArgs.join(':')
if (this.useCache !== undefined) {
const cached = await client.cache.get(
this.cacheName ?? this.name,
cacheID
)
if (cached !== undefined) {
return cached
}
}
const jsonParsed = await client.rest.get(endpoint(...restURLfuncArgs))
return new this(client, jsonParsed)
}
async refreshFromAPI(
client: Client,
{ endpoint, restURLfuncArgs }: IInit
): Promise<this> {
const oldOne = Object.assign(Object.create(this), this)
const jsonParsed = await client.rest.get(endpoint(...restURLfuncArgs))
this.readFromData(jsonParsed)
return oldOne
}
refreshFromData(data: { [k: string]: any }): this {
const oldOne = Object.assign(Object.create(this), this)
this.readFromData(data)
return oldOne
}
protected readFromData(data: { [k: string]: any }): void {}
// toJSON() {}
} }

View file

@ -1,11 +1,13 @@
import { ImageFormats, ImageSize } from '../types/cdn.ts' import { ImageFormats, ImageSize } from '../types/cdn.ts'
/** Function to get Image URL from a resource on Discord CDN */
export const ImageURL = ( export const ImageURL = (
url: string, url: string,
format: ImageFormats, format: ImageFormats | undefined = 'png',
size?: ImageSize | 128 size: ImageSize | undefined = 128
): string => { ): string => {
size = size === undefined ? 128 : size
if (url.includes('a_')) { if (url.includes('a_')) {
return `${url}.gif?size=${size}` return `${url}.${format === undefined ? 'gif' : format}?size=${size}`
} else return `${url}.${format}?size=${size}` } else return `${url}.${format === 'gif' ? 'png' : format}?size=${size}`
} }

View file

@ -14,12 +14,9 @@ export class Channel extends Base {
super(client, data) super(client, data)
this.type = data.type this.type = data.type
this.id = data.id this.id = data.id
// TODO: Cache in Gateway Event Code
// this.client.channels.set(this.id, data)
} }
protected readFromData(data: ChannelPayload): void { protected readFromData(data: ChannelPayload): void {
super.readFromData(data)
this.type = data.type ?? this.type this.type = data.type ?? this.type
this.id = data.id ?? this.id this.id = data.id ?? this.id
} }

View file

@ -39,7 +39,6 @@ export class Emoji extends Base {
} }
protected readFromData(data: EmojiPayload): void { protected readFromData(data: EmojiPayload): void {
super.readFromData(data)
this.id = data.id ?? this.id this.id = data.id ?? this.id
this.name = data.name ?? this.name this.name = data.name ?? this.name
this.roles = data.roles ?? this.roles this.roles = data.roles ?? this.roles
@ -47,11 +46,6 @@ export class Emoji extends Base {
this.managed = data.managed ?? this.managed this.managed = data.managed ?? this.managed
this.animated = data.animated ?? this.animated this.animated = data.animated ?? this.animated
this.available = data.available ?? this.available this.available = data.available ?? this.available
if (data.user !== undefined && data.user.id !== this.user?.id) { if (data.user !== undefined) this.user = new User(this.client, data.user)
User.autoInit(this.client, {
endpoint: USER,
restURLfuncArgs: [data.user.id]
}).then((user) => (this.user = user))
}
} }
} }

View file

@ -220,7 +220,6 @@ export class Guild extends Base {
} }
protected readFromData(data: GuildPayload): void { protected readFromData(data: GuildPayload): void {
super.readFromData(data)
this.id = data.id ?? this.id this.id = data.id ?? this.id
this.unavailable = data.unavailable ?? this.unavailable this.unavailable = data.unavailable ?? this.unavailable

View file

@ -32,7 +32,6 @@ export class Invite extends Base {
} }
protected readFromData(data: InvitePayload): void { protected readFromData(data: InvitePayload): void {
super.readFromData(data)
this.code = data.code ?? this.code this.code = data.code ?? this.code
this.guild = data.guild ?? this.guild this.guild = data.guild ?? this.guild
this.channel = data.channel ?? this.channel this.channel = data.channel ?? this.channel

View file

@ -57,7 +57,6 @@ export class Member extends Base {
} }
protected readFromData(data: MemberPayload): void { protected readFromData(data: MemberPayload): void {
super.readFromData(data.user)
this.nick = data.nick ?? this.nick this.nick = data.nick ?? this.nick
this.joinedAt = data.joined_at ?? this.joinedAt this.joinedAt = data.joined_at ?? this.joinedAt
this.premiumSince = data.premium_since ?? this.premiumSince this.premiumSince = data.premium_since ?? this.premiumSince

View file

@ -82,7 +82,6 @@ export class Message extends Base {
} }
protected readFromData(data: MessagePayload): void { protected readFromData(data: MessagePayload): void {
super.readFromData(data)
this.channelID = data.channel_id ?? this.channelID this.channelID = data.channel_id ?? this.channelID
this.guildID = data.guild_id ?? this.guildID this.guildID = data.guild_id ?? this.guildID
this.content = data.content ?? this.content this.content = data.content ?? this.content

View file

@ -34,7 +34,6 @@ export class Role extends Base {
} }
protected readFromData(data: RolePayload): void { protected readFromData(data: RolePayload): void {
super.readFromData(data)
this.name = data.name ?? this.name this.name = data.name ?? this.name
this.color = data.color ?? this.color this.color = data.color ?? this.color
this.hoist = data.hoist ?? this.hoist this.hoist = data.hoist ?? this.hoist

View file

@ -1,7 +1,12 @@
export class Snowflake { export class Snowflake {
snowflake: bigint id: string
constructor(id: string) { constructor(id: string) {
this.snowflake = BigInt.asUintN(64, BigInt(id)) this.id = id
}
get snowflake(): bigint {
return BigInt.asUintN(64, BigInt(this.id))
} }
get timestamp(): string { get timestamp(): string {

View file

@ -1,6 +1,7 @@
// Ported from https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js // Ported from https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
export type BitFieldResolvable = number | BitField | string | BitField[] export type BitFieldResolvable = number | BitField | string | BitField[]
/** Bit Field utility to work with Bits and Flags */
export class BitField { export class BitField {
flags: { [name: string]: number } = {} flags: { [name: string]: number } = {}
bitfield: number bitfield: number

View file

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/naming-convention */
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
/** Gets Discord Build info for self-bot support */
export const getBuildInfo = ( export const getBuildInfo = (
client: Client client: Client
): { ): {

View file

@ -1,25 +1,32 @@
/** Enhanced Map with various utility functions */
export class Collection<K = string, V = any> extends Map<K, V> { export class Collection<K = string, V = any> extends Map<K, V> {
/** Set a key to value in Collection */
set(key: K, value: V): this { set(key: K, value: V): this {
return super.set(key, value) return super.set(key, value)
} }
/** Get Array of values in Collection */
array(): V[] { array(): V[] {
return [...this.values()] return [...this.values()]
} }
/** Get first value in Collection */
first(): V { first(): V {
return this.values().next().value return this.values().next().value
} }
/** Get last value in Collection */
last(): V { last(): V {
return [...this.values()][this.size - 1] return [...this.values()][this.size - 1]
} }
/** Get a random value from Collection */
random(): V { random(): V {
const arr = [...this.values()] const arr = [...this.values()]
return arr[Math.floor(Math.random() * arr.length)] return arr[Math.floor(Math.random() * arr.length)]
} }
/** Find a value from Collection using callback */
find(callback: (value: V, key: K) => boolean): V | undefined { find(callback: (value: V, key: K) => boolean): V | undefined {
for (const key of this.keys()) { for (const key of this.keys()) {
const value = this.get(key) as V const value = this.get(key) as V
@ -28,6 +35,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
} }
} }
/** Filter out the Collection using callback */
filter(callback: (value: V, key: K) => boolean): Collection<K, V> { filter(callback: (value: V, key: K) => boolean): Collection<K, V> {
const relevant = new Collection<K, V>() const relevant = new Collection<K, V>()
this.forEach((value, key) => { this.forEach((value, key) => {
@ -36,6 +44,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return relevant return relevant
} }
/** Map the collection */
map<T>(callback: (value: V, key: K) => T): T[] { map<T>(callback: (value: V, key: K) => T): T[] {
const results = [] const results = []
for (const key of this.keys()) { for (const key of this.keys()) {
@ -45,6 +54,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return results return results
} }
/** Check if any of the values/keys in Collection satisfy callback */
some(callback: (value: V, key: K) => boolean): boolean { some(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) { for (const key of this.keys()) {
const value = this.get(key) as V const value = this.get(key) as V
@ -53,6 +63,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return false return false
} }
/** Check if every value/key in Collection satisfy callback */
every(callback: (value: V, key: K) => boolean): boolean { every(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) { for (const key of this.keys()) {
const value = this.get(key) as V const value = this.get(key) as V
@ -61,6 +72,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return true return true
} }
/** Reduce the Collection to a single value */
reduce<T>( reduce<T>(
callback: (accumulator: T, value: V, key: K) => T, callback: (accumulator: T, value: V, key: K) => T,
initialValue?: T initialValue?: T
@ -75,10 +87,12 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return accumulator return accumulator
} }
/** Create a Collection from an Object */
static fromObject<V>(object: { [key: string]: V }): Collection<string, V> { static fromObject<V>(object: { [key: string]: V }): Collection<string, V> {
return new Collection<string, V>(Object.entries(object)) return new Collection<string, V>(Object.entries(object))
} }
/** Convert Collection to an object */
toObject(): { [name: string]: V } { toObject(): { [name: string]: V } {
return Object.fromEntries(this) return Object.fromEntries(this)
} }

View file

@ -1,3 +1,4 @@
/** Delay by `ms` miliseconds */
export const delay = async (ms: number): Promise<true> => export const delay = async (ms: number): Promise<true> =>
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
setTimeout(() => resolve(true), ms) setTimeout(() => resolve(true), ms)

View file

@ -45,6 +45,7 @@ export type EveryChannelPayloadTypes =
| GuildVoiceChannelPayload | GuildVoiceChannelPayload
| EveryTextChannelPayloadTypes | EveryTextChannelPayloadTypes
/** Get appropriate Channel structure by its type */
const getChannelByType = ( const getChannelByType = (
client: Client, client: Client,
data: EveryChannelPayloadTypes, data: EveryChannelPayloadTypes,

View file

@ -2,7 +2,7 @@ import { GatewayIntents } from '../types/gateway.ts'
export type PriviligedIntents = 'GUILD_MEMBERS' | 'GUILD_PRESENCES' export type PriviligedIntents = 'GUILD_MEMBERS' | 'GUILD_PRESENCES'
// eslint-disable-next-line @typescript-eslint/no-extraneous-class /** Utility class for handling Gateway Intents */
export class Intents { export class Intents {
static NonPriviliged: number[] = [ static NonPriviliged: number[] = [
GatewayIntents.GUILD_MESSAGES, GatewayIntents.GUILD_MESSAGES,
@ -38,6 +38,7 @@ export class Intents {
static None: number[] = [...Intents.NonPriviliged] static None: number[] = [...Intents.NonPriviliged]
/** Create an Array of Intents easily passing Intents you're priviliged for and disable the ones you don't need */
static create( static create(
priviliged?: PriviligedIntents[], priviliged?: PriviligedIntents[],
disable?: number[] disable?: number[]

View file

@ -8,6 +8,7 @@ export type PermissionResolvable =
| Permissions | Permissions
| PermissionResolvable[] | PermissionResolvable[]
/** Manages Discord's Bit-based Permissions */
export class Permissions extends BitField { export class Permissions extends BitField {
static DEFAULT = 104324673 static DEFAULT = 104324673
static ALL = Object.values(PermissionFlags).reduce((all, p) => all | p, 0) static ALL = Object.values(PermissionFlags).reduce((all, p) => all | p, 0)