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 { MessagesManager } from './src/managers/messages.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 { ImageURL } from './src/structures/cdn.ts'
export { Channel } from './src/structures/channel.ts'

View file

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

View file

@ -1,6 +1,11 @@
import { Client } from '../models/client.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> {
client: Client
/** Cache Name or Key used to differentiate caches */
@ -14,30 +19,36 @@ export class BaseManager<T, T2> {
this.DataType = DataType
}
/** Get raw value from a cache (payload) */
async _get(key: string): Promise<T | undefined> {
return this.client.cache.get(this.cacheName, key)
}
/** Get a value from Cache */
async get(key: string): Promise<T2 | undefined> {
const raw = await this._get(key)
if (raw === undefined) return
return new this.DataType(this.client, raw)
}
/** Set a value to Cache */
async set(key: string, value: T): Promise<any> {
return this.client.cache.set(this.cacheName, key, value)
}
/** Delete a key from Cache */
async delete(key: string): Promise<boolean> {
return this.client.cache.delete(this.cacheName, key)
}
/** Get an Array of values from Cache */
async array(): Promise<undefined | T2[]> {
let arr = await (this.client.cache.array(this.cacheName) as T[])
if (arr === undefined) arr = []
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>> {
const arr = await this.array()
if (arr === undefined) return new Collection()
@ -49,6 +60,7 @@ export class BaseManager<T, T2> {
return collection
}
/** Delete everything from Cache */
flush(): any {
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 { BaseManager } from './base.ts'
/** Child Managers validate data from their parents i.e. from Managers */
export class BaseChildManager<T, T2> {
client: Client
/** Parent Manager */
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()
const collection = new Collection()
for (const elem of arr) {
// @ts-expect-error
collection.set(elem.id, elem)
// any is required here. Else you would need ts-ignore or expect-error.
collection.set((elem as any).id, elem)
}
return collection
}

View file

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

View file

@ -20,6 +20,7 @@ export class EmojisManager extends BaseManager<EmojiPayload, 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> {
return await new Promise((resolve, reject) => {
this.client.rest

View file

@ -1,5 +1,10 @@
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 {
client: Client
cacheName: string = 'discord_gateway_cache'

View file

@ -1,8 +1,8 @@
import { Client } from '../models/client.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
constructor(client: Client, reaction: MessageReaction) {

View file

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

View file

@ -4,7 +4,7 @@ import { Gateway } from '../gateway/index.ts'
import { RESTManager } from './rest.ts'
import EventEmitter from 'https://deno.land/std@0.74.0/node/events.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 { ChannelsManager } from '../managers/channels.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? */
fetchUncachedReactions: boolean = false
users: UserManager = new UserManager(this)
users: UsersManager = new UsersManager(this)
guilds: GuildManager = new GuildManager(this)
channels: ChannelsManager = new ChannelsManager(this)
emojis: EmojisManager = new EmojisManager(this)

View file

@ -1,63 +1,9 @@
import { Client } from '../models/client.ts'
interface IInit {
useCache?: boolean
endpoint: (...restURLfuncArgs: string[]) => string
restURLfuncArgs: string[]
}
export class Base {
client: Client
static cacheName?: string
propertyConverterOverride: { [k: string]: string } = {}
static useCache?: boolean = true
static restFunc?: (...restURLfuncArgs: string[]) => string
constructor(client: Client, _data?: any) {
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'
/** Function to get Image URL from a resource on Discord CDN */
export const ImageURL = (
url: string,
format: ImageFormats,
size?: ImageSize | 128
format: ImageFormats | undefined = 'png',
size: ImageSize | undefined = 128
): string => {
size = size === undefined ? 128 : size
if (url.includes('a_')) {
return `${url}.gif?size=${size}`
} else return `${url}.${format}?size=${size}`
return `${url}.${format === undefined ? 'gif' : 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)
this.type = data.type
this.id = data.id
// TODO: Cache in Gateway Event Code
// this.client.channels.set(this.id, data)
}
protected readFromData(data: ChannelPayload): void {
super.readFromData(data)
this.type = data.type ?? this.type
this.id = data.id ?? this.id
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,12 @@
export class Snowflake {
snowflake: bigint
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 {

View file

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

View file

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { Client } from '../models/client.ts'
/** Gets Discord Build info for self-bot support */
export const getBuildInfo = (
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> {
/** Set a key to value in Collection */
set(key: K, value: V): this {
return super.set(key, value)
}
/** Get Array of values in Collection */
array(): V[] {
return [...this.values()]
}
/** Get first value in Collection */
first(): V {
return this.values().next().value
}
/** Get last value in Collection */
last(): V {
return [...this.values()][this.size - 1]
}
/** Get a random value from Collection */
random(): V {
const arr = [...this.values()]
return arr[Math.floor(Math.random() * arr.length)]
}
/** Find a value from Collection using callback */
find(callback: (value: V, key: K) => boolean): V | undefined {
for (const key of this.keys()) {
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> {
const relevant = new Collection<K, V>()
this.forEach((value, key) => {
@ -36,6 +44,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return relevant
}
/** Map the collection */
map<T>(callback: (value: V, key: K) => T): T[] {
const results = []
for (const key of this.keys()) {
@ -45,6 +54,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return results
}
/** Check if any of the values/keys in Collection satisfy callback */
some(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) {
const value = this.get(key) as V
@ -53,6 +63,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return false
}
/** Check if every value/key in Collection satisfy callback */
every(callback: (value: V, key: K) => boolean): boolean {
for (const key of this.keys()) {
const value = this.get(key) as V
@ -61,6 +72,7 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return true
}
/** Reduce the Collection to a single value */
reduce<T>(
callback: (accumulator: T, value: V, key: K) => T,
initialValue?: T
@ -75,10 +87,12 @@ export class Collection<K = string, V = any> extends Map<K, V> {
return accumulator
}
/** Create a Collection from an Object */
static fromObject<V>(object: { [key: string]: V }): Collection<string, V> {
return new Collection<string, V>(Object.entries(object))
}
/** Convert Collection to an object */
toObject(): { [name: string]: V } {
return Object.fromEntries(this)
}

View file

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

View file

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

View file

@ -2,7 +2,7 @@ import { GatewayIntents } from '../types/gateway.ts'
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 {
static NonPriviliged: number[] = [
GatewayIntents.GUILD_MESSAGES,
@ -38,6 +38,7 @@ export class Intents {
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(
priviliged?: PriviligedIntents[],
disable?: number[]

View file

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