Skip to content

Commit

Permalink
feat: Add typing property to fire TextChannel.sendTyping() when a…
Browse files Browse the repository at this point in the history
… command is accepted (#258)

Co-authored-by: Antonio Román <kyradiscord@gmail.com>
Co-authored-by: Jeroen Claassens <support@favware.tech>
Co-authored-by: Tyler J Russell <xtylerjrx@gmail.com>
  • Loading branch information
4 people committed Sep 12, 2021
1 parent 4c3980d commit 71c1883
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/lib/SapphireClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ export interface SapphireClientOptions {
* @default true
*/
loadDefaultErrorListeners?: boolean;

/**
* Controls whether the bot will automatically appear to be typing when a command is accepted.
* @default false
*/
typing?: boolean;
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/lib/structures/Command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ export abstract class Command<T = Args> extends AliasPiece {
*/
public strategy: Lexure.UnorderedStrategy;

/**
* If {@link SapphireClient.typing} is true, it can be overridden for a specific command using this property, set via its options.
* Otherwise, this property will be ignored.
* @default true
*/
public typing: boolean;

/**
* The lexer to be used for command parsing
* @since 1.0.0
Expand All @@ -60,6 +67,7 @@ export abstract class Command<T = Args> extends AliasPiece {
this.detailedDescription = options.detailedDescription ?? '';
this.strategy = new FlagUnorderedStrategy(options);
this.fullCategory = options.fullCategory ?? this.location.directories;
this.typing = options.typing ?? true;

this.lexer.setQuotes(
options.quotes ?? [
Expand Down Expand Up @@ -466,6 +474,13 @@ export interface CommandOptions extends AliasPieceOptions, FlagStrategyOptions {
* @default null
*/
runIn?: CommandOptionsRunType | CommandOptionsRunTypeEnum | readonly (CommandOptionsRunType | CommandOptionsRunTypeEnum)[] | null;

/**
* If {@link SapphireClient.typing} is true, this option will override it.
* Otherwise, this option has no effect - you may call {@link Channel#sendTyping}` in the run method if you want specific commands to display the typing status.
* @default true
*/
typing?: boolean;
}

export interface CommandContext extends Record<PropertyKey, unknown> {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/types/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const Events = {
CommandFinish: 'commandFinish' as const,
CommandRun: 'commandRun' as const,
CommandSuccess: 'commandSuccess' as const,
CommandTypingError: 'commandTypingError' as const,
ListenerError: 'listenerError' as const,
MentionPrefixOnly: 'mentionPrefixOnly' as const,
NonPrefixedMessage: 'nonPrefixedMessage' as const,
Expand Down Expand Up @@ -128,6 +129,8 @@ export interface CommandSuccessPayload<T extends Args = Args> extends CommandRun
result: unknown;
}

export interface CommandTypingErrorPayload<T extends Args = Args> extends CommandRunPayload<T> {}

declare module 'discord.js' {
interface ClientEvents {
// #region Sapphire load cycle events
Expand All @@ -146,6 +149,7 @@ declare module 'discord.js' {
[Events.CommandSuccess]: [payload: CommandSuccessPayload];
[Events.CommandError]: [error: Error, payload: CommandErrorPayload];
[Events.CommandFinish]: [message: Message, command: Command, payload: CommandFinishPayload];
[Events.CommandTypingError]: [error: Error, payload: CommandTypingErrorPayload];
[Events.PluginLoaded]: [hook: PluginHook, name: string | undefined];
[Events.NonPrefixedMessage]: [message: Message];
// #endregion Sapphire load cycle events
Expand Down
22 changes: 22 additions & 0 deletions src/listeners/command-handler/CoreCommandTyping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Command } from '../../lib/structures/Command';
import type { Message } from 'discord.js';
import type { PieceContext } from '@sapphire/pieces';
import { Listener } from '../../lib/structures/Listener';
import { CommandRunPayload, Events } from '../../lib/types/Events';

export class CoreListener extends Listener<typeof Events.CommandRun> {
public constructor(context: PieceContext) {
super(context, { event: Events.CommandRun });
this.enabled = this.container.client.options.typing ?? false;
}

public async run(message: Message, command: Command, payload: CommandRunPayload) {
if (!command.typing) return;

try {
await message.channel.sendTyping();
} catch (error) {
message.client.emit(Events.CommandTypingError, error as Error, { ...payload, command, message });
}
}
}

0 comments on commit 71c1883

Please sign in to comment.