Merge pull request #115 from DjDeveloperr/catch
add ChannelsManager#{sendMessage, editMessage} and Command#onError
This commit is contained in:
commit
b532a99eb4
8 changed files with 189 additions and 78 deletions
|
@ -64,7 +64,21 @@ export class BaseManager<T, T2> {
|
||||||
const arr = (await this.array()) ?? []
|
const arr = (await this.array()) ?? []
|
||||||
const { readable, writable } = new TransformStream()
|
const { readable, writable } = new TransformStream()
|
||||||
arr.forEach((el) => writable.getWriter().write(el))
|
arr.forEach((el) => writable.getWriter().write(el))
|
||||||
yield* readable.getIterator()
|
yield* readable
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(...args: unknown[]): Promise<T2 | undefined> {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Try to get value from cache, if not found then fetch */
|
||||||
|
async resolve(key: string): Promise<T2 | undefined> {
|
||||||
|
const cacheValue = await this.get(key)
|
||||||
|
if (cacheValue !== undefined) return cacheValue
|
||||||
|
else {
|
||||||
|
const fetchValue = await this.fetch(key).catch(() => undefined)
|
||||||
|
if (fetchValue !== undefined) return fetchValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deletes everything from Cache */
|
/** Deletes everything from Cache */
|
||||||
|
|
|
@ -44,6 +44,20 @@ export class BaseChildManager<T, T2> {
|
||||||
const arr = (await this.array()) ?? []
|
const arr = (await this.array()) ?? []
|
||||||
const { readable, writable } = new TransformStream()
|
const { readable, writable } = new TransformStream()
|
||||||
arr.forEach((el: unknown) => writable.getWriter().write(el))
|
arr.forEach((el: unknown) => writable.getWriter().write(el))
|
||||||
yield* readable.getIterator()
|
yield* readable
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(...args: unknown[]): Promise<T2 | undefined> {
|
||||||
|
return this.parent.fetch(...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Try to get value from cache, if not found then fetch */
|
||||||
|
async resolve(key: string): Promise<T2 | undefined> {
|
||||||
|
const cacheValue = await this.get(key)
|
||||||
|
if (cacheValue !== undefined) return cacheValue
|
||||||
|
else {
|
||||||
|
const fetchValue = await this.fetch(key).catch(() => undefined)
|
||||||
|
if (fetchValue !== undefined) return fetchValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
import { Client } from '../models/client.ts'
|
import { Client } from '../models/client.ts'
|
||||||
import { Channel } from '../structures/channel.ts'
|
import { Channel } from '../structures/channel.ts'
|
||||||
import { ChannelPayload, GuildChannelPayload } from '../types/channel.ts'
|
import { Embed } from '../structures/embed.ts'
|
||||||
|
import { Message } from '../structures/message.ts'
|
||||||
|
import { TextChannel } from '../structures/textChannel.ts'
|
||||||
|
import {
|
||||||
|
ChannelPayload,
|
||||||
|
GuildChannelPayload,
|
||||||
|
MessageOptions
|
||||||
|
} from '../types/channel.ts'
|
||||||
import { CHANNEL } from '../types/endpoint.ts'
|
import { CHANNEL } from '../types/endpoint.ts'
|
||||||
import getChannelByType from '../utils/getChannelByType.ts'
|
import getChannelByType from '../utils/getChannelByType.ts'
|
||||||
import { BaseManager } from './base.ts'
|
import { BaseManager } from './base.ts'
|
||||||
|
|
||||||
|
export type AllMessageOptions = MessageOptions | Embed
|
||||||
|
|
||||||
export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
|
export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
super(client, 'channels', Channel)
|
super(client, 'channels', Channel)
|
||||||
|
@ -66,4 +75,105 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
|
||||||
.catch((e) => reject(e))
|
.catch((e) => reject(e))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sendMessage(
|
||||||
|
channel: string | TextChannel,
|
||||||
|
content?: string | AllMessageOptions,
|
||||||
|
option?: AllMessageOptions
|
||||||
|
): Promise<Message> {
|
||||||
|
const channelID = typeof channel === 'string' ? channel : channel.id
|
||||||
|
|
||||||
|
if (typeof content === 'object') {
|
||||||
|
option = content
|
||||||
|
content = undefined
|
||||||
|
}
|
||||||
|
if (content === undefined && option === undefined) {
|
||||||
|
throw new Error('Either text or option is necessary.')
|
||||||
|
}
|
||||||
|
if (option instanceof Embed) {
|
||||||
|
option = {
|
||||||
|
embed: option
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload: any = {
|
||||||
|
content: content,
|
||||||
|
embed: option?.embed,
|
||||||
|
file: option?.file,
|
||||||
|
files: option?.files,
|
||||||
|
tts: option?.tts,
|
||||||
|
allowed_mentions: option?.allowedMentions,
|
||||||
|
message_reference:
|
||||||
|
option?.reply === undefined
|
||||||
|
? undefined
|
||||||
|
: typeof option.reply === 'string'
|
||||||
|
? {
|
||||||
|
message_id: option.reply
|
||||||
|
}
|
||||||
|
: typeof option.reply === 'object'
|
||||||
|
? option.reply instanceof Message
|
||||||
|
? {
|
||||||
|
message_id: option.reply.id,
|
||||||
|
channel_id: option.reply.channel.id,
|
||||||
|
guild_id: option.reply.guild?.id
|
||||||
|
}
|
||||||
|
: option.reply
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const resp = await this.client.rest.api.channels[channelID].messages.post(
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
const chan =
|
||||||
|
typeof channel === 'string'
|
||||||
|
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
(await this.get<TextChannel>(channel))!
|
||||||
|
: channel
|
||||||
|
const res = new Message(this.client, resp, chan, this.client.user as any)
|
||||||
|
await res.mentions.fromPayload(resp)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
async editMessage(
|
||||||
|
channel: string | TextChannel,
|
||||||
|
message: Message | string,
|
||||||
|
text?: string | MessageOptions,
|
||||||
|
option?: MessageOptions
|
||||||
|
): Promise<Message> {
|
||||||
|
const channelID = typeof channel === 'string' ? channel : channel.id
|
||||||
|
|
||||||
|
if (text === undefined && option === undefined) {
|
||||||
|
throw new Error('Either text or option is necessary.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.client.user === undefined) {
|
||||||
|
throw new Error('Client user has not initialized.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof text === 'object') {
|
||||||
|
if (typeof option === 'object') Object.assign(option, text)
|
||||||
|
else option = text
|
||||||
|
text = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMsg = await this.client.rest.api.channels[channelID].messages[
|
||||||
|
typeof message === 'string' ? message : message.id
|
||||||
|
].patch({
|
||||||
|
content: text,
|
||||||
|
embed: option?.embed !== undefined ? option.embed.toJSON() : undefined,
|
||||||
|
// Cannot upload new files with Message
|
||||||
|
// file: option?.file,
|
||||||
|
tts: option?.tts,
|
||||||
|
allowed_mentions: option?.allowedMentions
|
||||||
|
})
|
||||||
|
|
||||||
|
const chan =
|
||||||
|
typeof channel === 'string'
|
||||||
|
? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
(await this.get<TextChannel>(channel))!
|
||||||
|
: channel
|
||||||
|
const res = new Message(this.client, newMsg, chan, this.client.user)
|
||||||
|
await res.mentions.fromPayload(newMsg)
|
||||||
|
return res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,9 @@ export class Command implements CommandOptions {
|
||||||
dmOnly?: boolean
|
dmOnly?: boolean
|
||||||
ownerOnly?: boolean
|
ownerOnly?: boolean
|
||||||
|
|
||||||
|
/** Method called when the command errors */
|
||||||
|
onError(ctx: CommandContext, error: Error): any {}
|
||||||
|
|
||||||
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
||||||
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
|
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -286,7 +286,8 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(command.botPermissions !== undefined ||
|
(command.botPermissions !== undefined ||
|
||||||
category?.permissions !== undefined) &&
|
category?.botPermissions !== undefined ||
|
||||||
|
allPermissions !== undefined) &&
|
||||||
msg.guild !== undefined
|
msg.guild !== undefined
|
||||||
) {
|
) {
|
||||||
// TODO: Check Overwrites too
|
// TODO: Check Overwrites too
|
||||||
|
@ -315,7 +316,8 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(command.userPermissions !== undefined ||
|
(command.userPermissions !== undefined ||
|
||||||
category?.userPermissions !== undefined) &&
|
category?.userPermissions !== undefined ||
|
||||||
|
allPermissions !== undefined) &&
|
||||||
msg.guild !== undefined
|
msg.guild !== undefined
|
||||||
) {
|
) {
|
||||||
let permissions =
|
let permissions =
|
||||||
|
@ -358,8 +360,11 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
if (beforeExecute === false) return
|
if (beforeExecute === false) return
|
||||||
|
|
||||||
const result = await command.execute(ctx)
|
const result = await command.execute(ctx)
|
||||||
command.afterExecute(ctx, result)
|
await command.afterExecute(ctx, result)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
await command
|
||||||
|
.onError(ctx, e)
|
||||||
|
.catch((e: Error) => this.emit('commandError', ctx, e))
|
||||||
this.emit('commandError', ctx, e)
|
this.emit('commandError', ctx, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +380,7 @@ export function command(options?: CommandOptions) {
|
||||||
})[name]
|
})[name]
|
||||||
|
|
||||||
if (typeof prop !== 'function')
|
if (typeof prop !== 'function')
|
||||||
throw new Error('@command decorator can only be used on functions')
|
throw new Error('@command decorator can only be used on class methods')
|
||||||
|
|
||||||
const command = new Command()
|
const command = new Command()
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
GuildTextChannelPayload,
|
GuildTextChannelPayload,
|
||||||
MessageOptions,
|
MessageOptions,
|
||||||
MessagePayload,
|
MessagePayload,
|
||||||
MessageReference,
|
|
||||||
ModifyGuildTextChannelOption,
|
ModifyGuildTextChannelOption,
|
||||||
ModifyGuildTextChannelPayload,
|
ModifyGuildTextChannelPayload,
|
||||||
Overwrite,
|
Overwrite,
|
||||||
|
@ -13,8 +12,6 @@ import {
|
||||||
} from '../types/channel.ts'
|
} from '../types/channel.ts'
|
||||||
import {
|
import {
|
||||||
CHANNEL,
|
CHANNEL,
|
||||||
CHANNEL_MESSAGE,
|
|
||||||
CHANNEL_MESSAGES,
|
|
||||||
MESSAGE_REACTION_ME,
|
MESSAGE_REACTION_ME,
|
||||||
MESSAGE_REACTION_USER
|
MESSAGE_REACTION_USER
|
||||||
} from '../types/endpoint.ts'
|
} from '../types/endpoint.ts'
|
||||||
|
@ -62,42 +59,11 @@ export class TextChannel extends Channel {
|
||||||
option?: AllMessageOptions,
|
option?: AllMessageOptions,
|
||||||
reply?: Message
|
reply?: Message
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
if (typeof content === 'object') {
|
return this.client.channels.sendMessage(
|
||||||
option = content
|
this,
|
||||||
content = undefined
|
content,
|
||||||
}
|
Object.assign(option ?? {}, { reply })
|
||||||
if (content === undefined && option === undefined) {
|
)
|
||||||
throw new Error('Either text or option is necessary.')
|
|
||||||
}
|
|
||||||
if (option instanceof Embed) {
|
|
||||||
option = {
|
|
||||||
embed: option
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload: any = {
|
|
||||||
content: content,
|
|
||||||
embed: option?.embed,
|
|
||||||
file: option?.file,
|
|
||||||
files: option?.files,
|
|
||||||
tts: option?.tts,
|
|
||||||
allowed_mentions: option?.allowedMentions
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reply !== undefined) {
|
|
||||||
const reference: MessageReference = {
|
|
||||||
message_id: reply.id,
|
|
||||||
channel_id: reply.channel.id,
|
|
||||||
guild_id: reply.guild?.id
|
|
||||||
}
|
|
||||||
payload.message_reference = reference
|
|
||||||
}
|
|
||||||
|
|
||||||
const resp = await this.client.rest.post(CHANNEL_MESSAGES(this.id), payload)
|
|
||||||
|
|
||||||
const res = new Message(this.client, resp, this, this.client.user as any)
|
|
||||||
await res.mentions.fromPayload(resp)
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,32 +77,7 @@ export class TextChannel extends Channel {
|
||||||
text?: string,
|
text?: string,
|
||||||
option?: MessageOptions
|
option?: MessageOptions
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
if (text === undefined && option === undefined) {
|
return this.client.channels.editMessage(this, message, text, option)
|
||||||
throw new Error('Either text or option is necessary.')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.client.user === undefined) {
|
|
||||||
throw new Error('Client user has not initialized.')
|
|
||||||
}
|
|
||||||
|
|
||||||
const newMsg = await this.client.rest.patch(
|
|
||||||
CHANNEL_MESSAGE(
|
|
||||||
this.id,
|
|
||||||
typeof message === 'string' ? message : message.id
|
|
||||||
),
|
|
||||||
{
|
|
||||||
content: text,
|
|
||||||
embed: option?.embed !== undefined ? option.embed.toJSON() : undefined,
|
|
||||||
// Cannot upload new files with Message
|
|
||||||
// file: option?.file,
|
|
||||||
tts: option?.tts,
|
|
||||||
allowed_mentions: option?.allowedMentions
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const res = new Message(this.client, newMsg, this, this.client.user)
|
|
||||||
await res.mentions.fromPayload(newMsg)
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add a reaction to a Message in this Channel */
|
/** Add a reaction to a Message in this Channel */
|
||||||
|
|
|
@ -243,6 +243,20 @@ client.on('messageCreate', async (msg: Message) => {
|
||||||
buf += `\n${role.name}`
|
buf += `\n${role.name}`
|
||||||
}
|
}
|
||||||
msg.reply(buf)
|
msg.reply(buf)
|
||||||
|
} else if (msg.content === '!timer') {
|
||||||
|
msg.channel.send('3...').then((msg) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
msg.edit('2...').then((msg) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
msg.edit('1...').then((msg) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
msg.edit('ok wut')
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Embed } from '../structures/embed.ts'
|
import { Embed } from '../structures/embed.ts'
|
||||||
import { MessageAttachment } from '../structures/message.ts'
|
import type { Message, MessageAttachment } from '../structures/message.ts'
|
||||||
import { EmojiPayload } from './emoji.ts'
|
import { EmojiPayload } from './emoji.ts'
|
||||||
import { MemberPayload } from './guild.ts'
|
import { MemberPayload } from './guild.ts'
|
||||||
import { UserPayload } from './user.ts'
|
import { UserPayload } from './user.ts'
|
||||||
|
@ -156,16 +156,26 @@ export interface MessagePayload {
|
||||||
stickers?: MessageStickerPayload[]
|
stickers?: MessageStickerPayload[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AllowedMentionType {
|
||||||
|
Roles = 'roles',
|
||||||
|
Users = 'users',
|
||||||
|
Everyone = 'everyone'
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AllowedMentionsPayload {
|
||||||
|
parse?: AllowedMentionType[]
|
||||||
|
users?: string[]
|
||||||
|
roles?: string[]
|
||||||
|
replied_user?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface MessageOptions {
|
export interface MessageOptions {
|
||||||
tts?: boolean
|
tts?: boolean
|
||||||
embed?: Embed
|
embed?: Embed
|
||||||
file?: MessageAttachment
|
file?: MessageAttachment
|
||||||
files?: MessageAttachment[]
|
files?: MessageAttachment[]
|
||||||
allowedMentions?: {
|
allowedMentions?: AllowedMentionsPayload
|
||||||
parse?: 'everyone' | 'users' | 'roles'
|
reply?: Message | MessageReference | string
|
||||||
roles?: string[]
|
|
||||||
users?: string[]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChannelMention {
|
export interface ChannelMention {
|
||||||
|
|
Loading…
Reference in a new issue