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…
	
	Add table
		Add a link
		
	
		Reference in a new issue