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 { readable, writable } = new TransformStream()
|
||||
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 */
|
||||
|
|
|
@ -44,6 +44,20 @@ export class BaseChildManager<T, T2> {
|
|||
const arr = (await this.array()) ?? []
|
||||
const { readable, writable } = new TransformStream()
|
||||
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 { 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 getChannelByType from '../utils/getChannelByType.ts'
|
||||
import { BaseManager } from './base.ts'
|
||||
|
||||
export type AllMessageOptions = MessageOptions | Embed
|
||||
|
||||
export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
|
||||
constructor(client: Client) {
|
||||
super(client, 'channels', Channel)
|
||||
|
@ -66,4 +75,105 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
|
|||
.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
|
||||
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) */
|
||||
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
|
||||
return true
|
||||
|
|
|
@ -286,7 +286,8 @@ export class CommandClient extends Client implements CommandClientOptions {
|
|||
|
||||
if (
|
||||
(command.botPermissions !== undefined ||
|
||||
category?.permissions !== undefined) &&
|
||||
category?.botPermissions !== undefined ||
|
||||
allPermissions !== undefined) &&
|
||||
msg.guild !== undefined
|
||||
) {
|
||||
// TODO: Check Overwrites too
|
||||
|
@ -315,7 +316,8 @@ export class CommandClient extends Client implements CommandClientOptions {
|
|||
|
||||
if (
|
||||
(command.userPermissions !== undefined ||
|
||||
category?.userPermissions !== undefined) &&
|
||||
category?.userPermissions !== undefined ||
|
||||
allPermissions !== undefined) &&
|
||||
msg.guild !== undefined
|
||||
) {
|
||||
let permissions =
|
||||
|
@ -358,8 +360,11 @@ export class CommandClient extends Client implements CommandClientOptions {
|
|||
if (beforeExecute === false) return
|
||||
|
||||
const result = await command.execute(ctx)
|
||||
command.afterExecute(ctx, result)
|
||||
await command.afterExecute(ctx, result)
|
||||
} catch (e) {
|
||||
await command
|
||||
.onError(ctx, e)
|
||||
.catch((e: Error) => this.emit('commandError', ctx, e))
|
||||
this.emit('commandError', ctx, e)
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +380,7 @@ export function command(options?: CommandOptions) {
|
|||
})[name]
|
||||
|
||||
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()
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import {
|
|||
GuildTextChannelPayload,
|
||||
MessageOptions,
|
||||
MessagePayload,
|
||||
MessageReference,
|
||||
ModifyGuildTextChannelOption,
|
||||
ModifyGuildTextChannelPayload,
|
||||
Overwrite,
|
||||
|
@ -13,8 +12,6 @@ import {
|
|||
} from '../types/channel.ts'
|
||||
import {
|
||||
CHANNEL,
|
||||
CHANNEL_MESSAGE,
|
||||
CHANNEL_MESSAGES,
|
||||
MESSAGE_REACTION_ME,
|
||||
MESSAGE_REACTION_USER
|
||||
} from '../types/endpoint.ts'
|
||||
|
@ -62,42 +59,11 @@ export class TextChannel extends Channel {
|
|||
option?: AllMessageOptions,
|
||||
reply?: Message
|
||||
): Promise<Message> {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
return this.client.channels.sendMessage(
|
||||
this,
|
||||
content,
|
||||
Object.assign(option ?? {}, { reply })
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,32 +77,7 @@ export class TextChannel extends Channel {
|
|||
text?: string,
|
||||
option?: MessageOptions
|
||||
): Promise<Message> {
|
||||
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.')
|
||||
}
|
||||
|
||||
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
|
||||
return this.client.channels.editMessage(this, message, text, option)
|
||||
}
|
||||
|
||||
/** Add a reaction to a Message in this Channel */
|
||||
|
|
|
@ -243,6 +243,20 @@ client.on('messageCreate', async (msg: Message) => {
|
|||
buf += `\n${role.name}`
|
||||
}
|
||||
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 { MessageAttachment } from '../structures/message.ts'
|
||||
import type { Message, MessageAttachment } from '../structures/message.ts'
|
||||
import { EmojiPayload } from './emoji.ts'
|
||||
import { MemberPayload } from './guild.ts'
|
||||
import { UserPayload } from './user.ts'
|
||||
|
@ -156,16 +156,26 @@ export interface MessagePayload {
|
|||
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 {
|
||||
tts?: boolean
|
||||
embed?: Embed
|
||||
file?: MessageAttachment
|
||||
files?: MessageAttachment[]
|
||||
allowedMentions?: {
|
||||
parse?: 'everyone' | 'users' | 'roles'
|
||||
roles?: string[]
|
||||
users?: string[]
|
||||
}
|
||||
allowedMentions?: AllowedMentionsPayload
|
||||
reply?: Message | MessageReference | string
|
||||
}
|
||||
|
||||
export interface ChannelMention {
|
||||
|
|
Loading…
Reference in a new issue