Skip to content

Commit 71c1883

Browse files
bitomickyranetfavnaNytelife26
authored
feat: Add typing property to fire TextChannel.sendTyping() when a command is accepted (#258)
Co-authored-by: Antonio Román <[email protected]> Co-authored-by: Jeroen Claassens <[email protected]> Co-authored-by: Tyler J Russell <[email protected]>
1 parent 4c3980d commit 71c1883

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

src/lib/SapphireClient.ts

+6
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ export interface SapphireClientOptions {
108108
* @default true
109109
*/
110110
loadDefaultErrorListeners?: boolean;
111+
112+
/**
113+
* Controls whether the bot will automatically appear to be typing when a command is accepted.
114+
* @default false
115+
*/
116+
typing?: boolean;
111117
}
112118

113119
/**

src/lib/structures/Command.ts

+15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ export abstract class Command<T = Args> extends AliasPiece {
4242
*/
4343
public strategy: Lexure.UnorderedStrategy;
4444

45+
/**
46+
* If {@link SapphireClient.typing} is true, it can be overridden for a specific command using this property, set via its options.
47+
* Otherwise, this property will be ignored.
48+
* @default true
49+
*/
50+
public typing: boolean;
51+
4552
/**
4653
* The lexer to be used for command parsing
4754
* @since 1.0.0
@@ -60,6 +67,7 @@ export abstract class Command<T = Args> extends AliasPiece {
6067
this.detailedDescription = options.detailedDescription ?? '';
6168
this.strategy = new FlagUnorderedStrategy(options);
6269
this.fullCategory = options.fullCategory ?? this.location.directories;
70+
this.typing = options.typing ?? true;
6371

6472
this.lexer.setQuotes(
6573
options.quotes ?? [
@@ -466,6 +474,13 @@ export interface CommandOptions extends AliasPieceOptions, FlagStrategyOptions {
466474
* @default null
467475
*/
468476
runIn?: CommandOptionsRunType | CommandOptionsRunTypeEnum | readonly (CommandOptionsRunType | CommandOptionsRunTypeEnum)[] | null;
477+
478+
/**
479+
* If {@link SapphireClient.typing} is true, this option will override it.
480+
* 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.
481+
* @default true
482+
*/
483+
typing?: boolean;
469484
}
470485

471486
export interface CommandContext extends Record<PropertyKey, unknown> {

src/lib/types/Events.ts

+4
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export const Events = {
6565
CommandFinish: 'commandFinish' as const,
6666
CommandRun: 'commandRun' as const,
6767
CommandSuccess: 'commandSuccess' as const,
68+
CommandTypingError: 'commandTypingError' as const,
6869
ListenerError: 'listenerError' as const,
6970
MentionPrefixOnly: 'mentionPrefixOnly' as const,
7071
NonPrefixedMessage: 'nonPrefixedMessage' as const,
@@ -128,6 +129,8 @@ export interface CommandSuccessPayload<T extends Args = Args> extends CommandRun
128129
result: unknown;
129130
}
130131

132+
export interface CommandTypingErrorPayload<T extends Args = Args> extends CommandRunPayload<T> {}
133+
131134
declare module 'discord.js' {
132135
interface ClientEvents {
133136
// #region Sapphire load cycle events
@@ -146,6 +149,7 @@ declare module 'discord.js' {
146149
[Events.CommandSuccess]: [payload: CommandSuccessPayload];
147150
[Events.CommandError]: [error: Error, payload: CommandErrorPayload];
148151
[Events.CommandFinish]: [message: Message, command: Command, payload: CommandFinishPayload];
152+
[Events.CommandTypingError]: [error: Error, payload: CommandTypingErrorPayload];
149153
[Events.PluginLoaded]: [hook: PluginHook, name: string | undefined];
150154
[Events.NonPrefixedMessage]: [message: Message];
151155
// #endregion Sapphire load cycle events
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { Command } from '../../lib/structures/Command';
2+
import type { Message } from 'discord.js';
3+
import type { PieceContext } from '@sapphire/pieces';
4+
import { Listener } from '../../lib/structures/Listener';
5+
import { CommandRunPayload, Events } from '../../lib/types/Events';
6+
7+
export class CoreListener extends Listener<typeof Events.CommandRun> {
8+
public constructor(context: PieceContext) {
9+
super(context, { event: Events.CommandRun });
10+
this.enabled = this.container.client.options.typing ?? false;
11+
}
12+
13+
public async run(message: Message, command: Command, payload: CommandRunPayload) {
14+
if (!command.typing) return;
15+
16+
try {
17+
await message.channel.sendTyping();
18+
} catch (error) {
19+
message.client.emit(Events.CommandTypingError, error as Error, { ...payload, command, message });
20+
}
21+
}
22+
}

0 commit comments

Comments
 (0)