or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

app-commands.mdcommands-framework.mdcore-objects.mdevent-handling.mdindex.mduser-interface.mdutilities.mdvoice-audio.mdwebhooks.md

commands-framework.mddocs/

0

# Commands Framework

1

2

A comprehensive prefix-based command system built on top of the core Discord.py client. The commands framework provides command parsing, argument conversion, permission checks, cooldowns, error handling, and modular organization through cogs.

3

4

## Capabilities

5

6

### Bot Classes

7

8

Command bots extend the base client with command processing capabilities and customizable prefix handling.

9

10

```python { .api }

11

class Bot(commands.Bot):

12

"""

13

Bot client with command processing capabilities.

14

15

Parameters:

16

- command_prefix: String or callable returning command prefix(es)

17

- help_command: Help command instance (None to disable)

18

- description: Bot description for help

19

- intents: Gateway intents

20

- case_insensitive: Whether commands are case insensitive

21

- strip_after_prefix: Whether to strip whitespace after prefix

22

"""

23

def __init__(

24

self,

25

command_prefix: Union[str, List[str], Callable],

26

*,

27

help_command: Optional[HelpCommand] = ...,

28

description: str = None,

29

intents: Intents,

30

case_insensitive: bool = False,

31

strip_after_prefix: bool = False,

32

**options

33

): ...

34

35

# Command registration

36

def command(self, name: str = None, **attrs) -> Callable:

37

"""Decorator to register a command."""

38

39

def group(self, name: str = None, **attrs) -> Callable:

40

"""Decorator to register a command group."""

41

42

def check(self, predicate: Callable) -> Callable:

43

"""Decorator to add a global check."""

44

45

def before_invoke(self, coro: Callable) -> Callable:

46

"""Decorator for global before-invoke hook."""

47

48

def after_invoke(self, coro: Callable) -> Callable:

49

"""Decorator for global after-invoke hook."""

50

51

# Command management

52

def add_command(self, command: Command) -> None:

53

"""Add a command to the bot."""

54

55

def remove_command(self, name: str) -> Optional[Command]:

56

"""Remove a command from the bot."""

57

58

def get_command(self, name: str) -> Optional[Command]:

59

"""Get a command by name."""

60

61

# Cog management

62

async def add_cog(self, cog: Cog) -> None:

63

"""Add a cog to the bot."""

64

65

async def remove_cog(self, name: str) -> Optional[Cog]:

66

"""Remove a cog from the bot."""

67

68

def get_cog(self, name: str) -> Optional[Cog]:

69

"""Get a cog by name."""

70

71

# Command processing

72

async def get_prefix(self, message: Message) -> List[str]:

73

"""Get valid prefixes for a message."""

74

75

async def get_context(self, message: Message, *, cls: Type = Context) -> Context:

76

"""Get command context for a message."""

77

78

async def invoke(self, ctx: Context) -> None:

79

"""Invoke a command from context."""

80

81

async def process_commands(self, message: Message) -> None:

82

"""Process message for commands."""

83

84

# Properties

85

commands: Set[Command] # All registered commands

86

cogs: Dict[str, Cog] # All loaded cogs

87

extensions: Dict[str, types.ModuleType] # Loaded extensions

88

89

class AutoShardedBot(Bot):

90

"""

91

Bot with automatic sharding capabilities.

92

"""

93

def __init__(self, command_prefix, **kwargs): ...

94

95

shard_count: Optional[int] # Number of shards

96

shards: Dict[int, ShardInfo] # Shard information

97

98

# Prefix helpers

99

def when_mentioned(bot: Bot, message: Message) -> List[str]:

100

"""Return bot mention as prefix."""

101

102

def when_mentioned_or(*prefixes: str) -> Callable:

103

"""Return bot mention or specified prefixes."""

104

```

105

106

### Command Context

107

108

Context objects provide information about command invocation including the message, channel, guild, and author.

109

110

```python { .api }

111

class Context:

112

"""

113

Command invocation context containing message and environment info.

114

"""

115

message: Message # Message that triggered the command

116

bot: Bot # Bot instance

117

args: List[Any] # Parsed command arguments

118

kwargs: Dict[str, Any] # Parsed keyword arguments

119

prefix: str # Prefix used to invoke command

120

command: Optional[Command] # Command being invoked

121

invoked_with: Optional[str] # String used to invoke command

122

invoked_parents: List[str] # Parent command names for subcommands

123

invoked_subcommand: Optional[Command] # Subcommand being invoked

124

subcommand_passed: Optional[str] # String passed for subcommand

125

command_failed: bool # Whether command failed

126

127

# Shortcuts to message properties

128

author: Union[User, Member] # Command author

129

guild: Optional[Guild] # Guild if invoked in guild

130

channel: Union[TextChannel, DMChannel, GroupChannel] # Channel

131

me: Union[ClientUser, Member] # Bot user/member

132

voice_client: Optional[VoiceClient] # Voice client if connected

133

134

# Utility methods

135

async def send(

136

self,

137

content: str = None,

138

*,

139

embed: Embed = None,

140

embeds: List[Embed] = None,

141

file: File = None,

142

files: List[File] = None,

143

view: View = None,

144

ephemeral: bool = False,

145

reference: MessageReference = None,

146

**kwargs

147

) -> Message:

148

"""Send a message to the context channel."""

149

150

async def reply(self, content: str = None, **kwargs) -> Message:

151

"""Reply to the context message."""

152

153

def typing(self) -> Typing:

154

"""Return typing context manager."""

155

156

async def invoke(self, command: Command, *args, **kwargs) -> Any:

157

"""Invoke another command."""

158

159

async def reinvoke(self, *, call_hooks: bool = False, restart: bool = True) -> None:

160

"""Re-invoke the current command."""

161

162

def valid(self) -> bool:

163

"""Check if context is valid for command invocation."""

164

165

@property

166

def clean_prefix(self) -> str:

167

"""Prefix with bot mention resolved to nickname."""

168

169

@property

170

def cog(self) -> Optional[Cog]:

171

"""Cog that contains the command."""

172

```

173

174

### Commands & Groups

175

176

Command objects represent individual bot commands with argument parsing, checks, and execution logic.

177

178

```python { .api }

179

class Command:

180

"""

181

Represents a bot command.

182

"""

183

def __init__(self, func: Callable, **kwargs): ...

184

185

name: str # Command name

186

callback: Callable # Command function

187

help: Optional[str] # Help text

188

brief: Optional[str] # Brief description

189

usage: Optional[str] # Usage string

190

aliases: List[str] # Command aliases

191

enabled: bool # Whether command is enabled

192

hidden: bool # Whether command is hidden from help

193

checks: List[Callable] # Command checks

194

description: str # Long description

195

signature: str # Command signature with parameters

196

qualified_name: str # Full command name including parents

197

parents: List[Group] # Parent command groups

198

cog: Optional[Cog] # Cog containing this command

199

params: Dict[str, inspect.Parameter] # Command parameters

200

201

async def __call__(self, context: Context, *args, **kwargs) -> Any:

202

"""Invoke the command."""

203

204

async def invoke(self, context: Context, *args, **kwargs) -> Any:

205

"""Invoke the command with context."""

206

207

async def reinvoke(self, context: Context, *, call_hooks: bool = False) -> None:

208

"""Re-invoke the command."""

209

210

def error(self, coro: Callable) -> Callable:

211

"""Decorator for command error handler."""

212

213

def before_invoke(self, coro: Callable) -> Callable:

214

"""Decorator for before-invoke hook."""

215

216

def after_invoke(self, coro: Callable) -> Callable:

217

"""Decorator for after-invoke hook."""

218

219

def add_check(self, func: Callable) -> None:

220

"""Add a check to the command."""

221

222

def remove_check(self, func: Callable) -> bool:

223

"""Remove a check from the command."""

224

225

def copy(self) -> Command:

226

"""Create a copy of the command."""

227

228

class Group(Command):

229

"""

230

Command that can contain subcommands.

231

"""

232

def __init__(self, **attrs): ...

233

234

commands: Set[Command] # Subcommands

235

invoke_without_subcommand: bool # Whether to invoke if no subcommand

236

case_insensitive: bool # Case insensitive subcommand matching

237

238

def command(self, *args, **kwargs) -> Callable:

239

"""Decorator to add a subcommand."""

240

241

def group(self, *args, **kwargs) -> Callable:

242

"""Decorator to add a subcommand group."""

243

244

def add_command(self, command: Command) -> None:

245

"""Add a subcommand."""

246

247

def remove_command(self, name: str) -> Optional[Command]:

248

"""Remove a subcommand."""

249

250

def get_command(self, name: str) -> Optional[Command]:

251

"""Get a subcommand by name."""

252

253

def walk_commands(self) -> Iterator[Command]:

254

"""Recursively walk all commands."""

255

256

# Command decorators

257

def command(name: str = None, **attrs) -> Callable:

258

"""Decorator to create a command."""

259

260

def group(name: str = None, **attrs) -> Callable:

261

"""Decorator to create a command group."""

262

```

263

264

### Cogs

265

266

Cogs provide modular organization for commands, event listeners, and shared functionality.

267

268

```python { .api }

269

class Cog:

270

"""

271

Base class for command cogs (modules).

272

"""

273

def __init_subclass__(cls, **kwargs): ...

274

275

qualified_name: str # Cog name

276

description: Optional[str] # Cog description

277

278

def get_commands(self) -> List[Command]:

279

"""Get all commands in this cog."""

280

281

def walk_commands(self) -> Iterator[Command]:

282

"""Recursively walk all commands in this cog."""

283

284

def get_listeners(self) -> List[Tuple[str, Callable]]:

285

"""Get all event listeners in this cog."""

286

287

# Lifecycle hooks

288

async def cog_load(self) -> None:

289

"""Called when cog is loaded."""

290

291

async def cog_unload(self) -> None:

292

"""Called when cog is unloaded."""

293

294

def cog_check(self, ctx: Context) -> bool:

295

"""Global check for all commands in this cog."""

296

297

async def cog_command_error(self, ctx: Context, error: Exception) -> None:

298

"""Error handler for all commands in this cog."""

299

300

async def cog_before_invoke(self, ctx: Context) -> None:

301

"""Before-invoke hook for all commands in this cog."""

302

303

async def cog_after_invoke(self, ctx: Context) -> None:

304

"""After-invoke hook for all commands in this cog."""

305

306

class GroupCog(Cog):

307

"""

308

Cog that acts as a command group.

309

"""

310

group_name: str # Name of the group

311

group_description: str # Description of the group

312

313

# Inherits Group functionality for subcommands

314

```

315

316

### Argument Conversion

317

318

Converters transform string arguments into Python objects with built-in support for Discord entities and custom conversion logic.

319

320

```python { .api }

321

class Converter:

322

"""

323

Base class for argument converters.

324

"""

325

async def convert(self, ctx: Context, argument: str) -> Any:

326

"""Convert string argument to desired type."""

327

raise NotImplementedError

328

329

# Built-in converters

330

class MemberConverter(Converter):

331

"""Convert to Member object via ID, mention, or name."""

332

async def convert(self, ctx: Context, argument: str) -> Member: ...

333

334

class UserConverter(Converter):

335

"""Convert to User object via ID, mention, or name."""

336

async def convert(self, ctx: Context, argument: str) -> User: ...

337

338

class TextChannelConverter(Converter):

339

"""Convert to TextChannel via ID, mention, or name."""

340

async def convert(self, ctx: Context, argument: str) -> TextChannel: ...

341

342

class VoiceChannelConverter(Converter):

343

"""Convert to VoiceChannel via ID, mention, or name."""

344

async def convert(self, ctx: Context, argument: str) -> VoiceChannel: ...

345

346

class CategoryChannelConverter(Converter):

347

"""Convert to CategoryChannel via ID or name."""

348

async def convert(self, ctx: Context, argument: str) -> CategoryChannel: ...

349

350

class RoleConverter(Converter):

351

"""Convert to Role via ID, mention, or name."""

352

async def convert(self, ctx: Context, argument: str) -> Role: ...

353

354

class GuildConverter(Converter):

355

"""Convert to Guild via ID or name."""

356

async def convert(self, ctx: Context, argument: str) -> Guild: ...

357

358

class EmojiConverter(Converter):

359

"""Convert to Emoji via ID, mention, or name."""

360

async def convert(self, ctx: Context, argument: str) -> Emoji: ...

361

362

class PartialEmojiConverter(Converter):

363

"""Convert to PartialEmoji via ID, mention, name, or unicode."""

364

async def convert(self, ctx: Context, argument: str) -> PartialEmoji: ...

365

366

class MessageConverter(Converter):

367

"""Convert to Message via ID or message link."""

368

async def convert(self, ctx: Context, argument: str) -> Message: ...

369

370

class InviteConverter(Converter):

371

"""Convert to Invite via invite code or URL."""

372

async def convert(self, ctx: Context, argument: str) -> Invite: ...

373

374

class ColourConverter(Converter):

375

"""Convert to Colour via hex, RGB, or name."""

376

async def convert(self, ctx: Context, argument: str) -> Colour: ...

377

378

ColorConverter = ColourConverter # Alias

379

380

class clean_content(Converter):

381

"""

382

Convert message content with mentions resolved.

383

384

Parameters:

385

- fix_channel_mentions: Whether to fix channel mentions

386

- use_nicknames: Whether to use nicknames for users

387

- escape_markdown: Whether to escape markdown

388

- remove_markdown: Whether to remove markdown

389

"""

390

def __init__(

391

self,

392

*,

393

fix_channel_mentions: bool = False,

394

use_nicknames: bool = True,

395

escape_markdown: bool = False,

396

remove_markdown: bool = False

397

): ...

398

399

class Greedy:

400

"""

401

Converter that consumes multiple arguments.

402

403

Usage: async def command(ctx, users: commands.Greedy[Member]):

404

"""

405

def __init__(self, converter: Type): ...

406

407

class Range:

408

"""

409

Converter that validates numeric ranges.

410

411

Parameters:

412

- min: Minimum value (inclusive)

413

- max: Maximum value (inclusive)

414

415

Usage: async def command(ctx, number: commands.Range[int, 1, 10]):

416

"""

417

def __init__(self, annotation: Type, min: Any = None, max: Any = None): ...

418

419

# Converter utilities

420

async def run_converters(ctx: Context, converter: Type, argument: str, param: inspect.Parameter) -> Any:

421

"""Run converter on argument."""

422

```

423

424

### Command Checks

425

426

Checks provide permission and condition validation before command execution.

427

428

```python { .api }

429

# Check decorators

430

def check(predicate: Callable[[Context], bool]) -> Callable:

431

"""Add a check to a command."""

432

433

def check_any(*checks: Callable) -> Callable:

434

"""Require any of the provided checks to pass."""

435

436

# Permission checks

437

def has_role(item: Union[int, str]) -> Callable:

438

"""Check if user has a specific role."""

439

440

def has_any_role(*items: Union[int, str]) -> Callable:

441

"""Check if user has any of the specified roles."""

442

443

def has_permissions(**perms: bool) -> Callable:

444

"""Check if user has specific permissions."""

445

446

def has_guild_permissions(**perms: bool) -> Callable:

447

"""Check if user has specific guild permissions."""

448

449

def bot_has_role(item: Union[int, str]) -> Callable:

450

"""Check if bot has a specific role."""

451

452

def bot_has_any_role(*items: Union[int, str]) -> Callable:

453

"""Check if bot has any of the specified roles."""

454

455

def bot_has_permissions(**perms: bool) -> Callable:

456

"""Check if bot has specific permissions."""

457

458

def bot_has_guild_permissions(**perms: bool) -> Callable:

459

"""Check if bot has specific guild permissions."""

460

461

# Context checks

462

def dm_only() -> Callable:

463

"""Command can only be used in DMs."""

464

465

def guild_only() -> Callable:

466

"""Command can only be used in guilds."""

467

468

def is_owner() -> Callable:

469

"""Check if user is bot owner."""

470

471

def is_nsfw() -> Callable:

472

"""Check if channel is NSFW."""

473

474

# Hook decorators

475

def before_invoke(coro: Callable) -> Callable:

476

"""Register before-invoke hook."""

477

478

def after_invoke(coro: Callable) -> Callable:

479

"""Register after-invoke hook."""

480

```

481

482

### Cooldowns & Rate Limiting

483

484

Cooldown system prevents command spam and implements various rate limiting strategies.

485

486

```python { .api }

487

class BucketType(Enum):

488

"""Cooldown bucket types."""

489

default = 0 # Global cooldown

490

user = 1 # Per-user cooldown

491

guild = 2 # Per-guild cooldown

492

channel = 3 # Per-channel cooldown

493

member = 4 # Per-member (user+guild) cooldown

494

category = 5 # Per-category cooldown

495

role = 6 # Per-role cooldown

496

497

class Cooldown:

498

"""

499

Represents a command cooldown.

500

501

Parameters:

502

- rate: Number of times command can be used

503

- per: Time period in seconds

504

"""

505

def __init__(self, rate: int, per: float): ...

506

507

rate: int # Number of uses allowed

508

per: float # Time period in seconds

509

510

def get_tokens(self, current: float = None) -> int:

511

"""Get available tokens."""

512

513

def update_rate_limit(self, current: float = None) -> Optional[float]:

514

"""Update rate limit and return retry after time."""

515

516

def reset(self) -> None:

517

"""Reset the cooldown."""

518

519

def copy(self) -> Cooldown:

520

"""Create a copy of the cooldown."""

521

522

class CooldownMapping:

523

"""Maps cooldown buckets to cooldown instances."""

524

def __init__(self, original: Cooldown, type: BucketType): ...

525

526

def copy(self) -> CooldownMapping:

527

"""Create a copy of the mapping."""

528

529

def get_bucket(self, message: Message, current: float = None) -> Cooldown:

530

"""Get cooldown bucket for message."""

531

532

def update_rate_limit(self, message: Message, current: float = None) -> Optional[float]:

533

"""Update rate limit for message."""

534

535

class DynamicCooldownMapping(CooldownMapping):

536

"""Cooldown mapping with dynamic cooldown function."""

537

def __init__(self, cooldown_func: Callable[[Message], Cooldown], type: BucketType): ...

538

539

class MaxConcurrency:

540

"""

541

Limit concurrent command executions.

542

543

Parameters:

544

- number: Maximum concurrent executions

545

- per: Bucket type for concurrency limit

546

- wait: Whether to wait for slot availability

547

"""

548

def __init__(self, number: int, *, per: BucketType, wait: bool = False): ...

549

550

# Cooldown decorators

551

def cooldown(rate: int, per: float, type: BucketType = BucketType.default) -> Callable:

552

"""Add a cooldown to a command."""

553

554

def dynamic_cooldown(cooldown: Callable[[Message], Cooldown], type: BucketType = BucketType.default) -> Callable:

555

"""Add a dynamic cooldown to a command."""

556

557

def max_concurrency(number: int, *, per: BucketType = BucketType.default, wait: bool = False) -> Callable:

558

"""Limit concurrent command executions."""

559

```

560

561

### Error Handling

562

563

Comprehensive error handling for commands with specific exception types for different failure scenarios.

564

565

```python { .api }

566

# Base command errors

567

class CommandError(DiscordException):

568

"""Base exception for command errors."""

569

pass

570

571

class UserInputError(CommandError):

572

"""Base exception for user input errors."""

573

pass

574

575

class CommandNotFound(CommandError):

576

"""Command was not found."""

577

pass

578

579

class DisabledCommand(CommandError):

580

"""Command is disabled."""

581

pass

582

583

class CommandInvokeError(CommandError):

584

"""Exception occurred during command execution."""

585

def __init__(self, e: Exception): ...

586

original: Exception

587

588

# Argument errors

589

class MissingRequiredArgument(UserInputError):

590

"""Required argument is missing."""

591

def __init__(self, param: inspect.Parameter): ...

592

param: inspect.Parameter

593

594

class TooManyArguments(UserInputError):

595

"""Too many arguments provided."""

596

pass

597

598

class BadArgument(UserInputError):

599

"""Argument could not be converted."""

600

pass

601

602

class BadUnionArgument(UserInputError):

603

"""Union argument could not be converted."""

604

def __init__(self, param: inspect.Parameter, converters: List[Type], errors: List[CommandError]): ...

605

param: inspect.Parameter

606

converters: List[Type]

607

errors: List[CommandError]

608

609

class BadLiteralArgument(UserInputError):

610

"""Literal argument is not one of the valid choices."""

611

def __init__(self, param: inspect.Parameter, literals: List[Any], errors: List[CommandError]): ...

612

613

# Check failures

614

class CheckFailure(CommandError):

615

"""Command check failed."""

616

pass

617

618

class CheckAnyFailure(CheckFailure):

619

"""All checks in check_any failed."""

620

def __init__(self, checks: List[Callable], errors: List[CommandError]): ...

621

checks: List[Callable]

622

errors: List[CommandError]

623

624

class PrivateMessageOnly(CheckFailure):

625

"""Command can only be used in private messages."""

626

pass

627

628

class NoPrivateMessage(CheckFailure):

629

"""Command cannot be used in private messages."""

630

pass

631

632

class NotOwner(CheckFailure):

633

"""User is not the bot owner."""

634

pass

635

636

class MissingRole(CheckFailure):

637

"""User is missing required role."""

638

def __init__(self, missing_role: Union[str, int]): ...

639

missing_role: Union[str, int]

640

641

class BotMissingRole(CheckFailure):

642

"""Bot is missing required role."""

643

def __init__(self, missing_role: Union[str, int]): ...

644

missing_role: Union[str, int]

645

646

class MissingAnyRole(CheckFailure):

647

"""User is missing any of the required roles."""

648

def __init__(self, missing_roles: List[Union[str, int]]): ...

649

missing_roles: List[Union[str, int]]

650

651

class BotMissingAnyRole(CheckFailure):

652

"""Bot is missing any of the required roles."""

653

def __init__(self, missing_roles: List[Union[str, int]]): ...

654

missing_roles: List[Union[str, int]]

655

656

class MissingPermissions(CheckFailure):

657

"""User is missing required permissions."""

658

def __init__(self, missing_permissions: List[str]): ...

659

missing_permissions: List[str]

660

661

class BotMissingPermissions(CheckFailure):

662

"""Bot is missing required permissions."""

663

def __init__(self, missing_permissions: List[str]): ...

664

missing_permissions: List[str]

665

666

class NSFWChannelRequired(CheckFailure):

667

"""Command requires NSFW channel."""

668

def __init__(self, channel: GuildChannel): ...

669

channel: GuildChannel

670

671

# Cooldown errors

672

class CommandOnCooldown(CommandError):

673

"""Command is on cooldown."""

674

def __init__(self, cooldown: Cooldown, retry_after: float, type: BucketType): ...

675

cooldown: Cooldown

676

retry_after: float

677

type: BucketType

678

679

class MaxConcurrencyReached(CommandError):

680

"""Maximum concurrent executions reached."""

681

def __init__(self, number: int, per: BucketType): ...

682

number: int

683

per: BucketType

684

685

# Conversion errors

686

class MemberNotFound(BadArgument):

687

"""Member could not be found."""

688

def __init__(self, argument: str): ...

689

argument: str

690

691

class UserNotFound(BadArgument):

692

"""User could not be found."""

693

def __init__(self, argument: str): ...

694

argument: str

695

696

class MessageNotFound(BadArgument):

697

"""Message could not be found."""

698

def __init__(self, argument: str): ...

699

argument: str

700

701

class ChannelNotFound(BadArgument):

702

"""Channel could not be found."""

703

def __init__(self, argument: str): ...

704

argument: str

705

706

class ChannelNotReadable(BadArgument):

707

"""Channel is not readable by the bot."""

708

def __init__(self, argument: Union[GuildChannel, str]): ...

709

argument: Union[GuildChannel, str]

710

711

class RoleNotFound(BadArgument):

712

"""Role could not be found."""

713

def __init__(self, argument: str): ...

714

argument: str

715

716

class EmojiNotFound(BadArgument):

717

"""Emoji could not be found."""

718

def __init__(self, argument: str): ...

719

argument: str

720

721

class GuildNotFound(BadArgument):

722

"""Guild could not be found."""

723

def __init__(self, argument: str): ...

724

argument: str

725

726

class BadInviteArgument(BadArgument):

727

"""Invalid invite argument."""

728

pass

729

730

class BadColourArgument(BadArgument):

731

"""Invalid colour argument."""

732

def __init__(self, argument: str): ...

733

argument: str

734

735

BadColorArgument = BadColourArgument # Alias

736

```

737

738

### Help System

739

740

Customizable help command system with built-in implementations and support for custom help formats.

741

742

```python { .api }

743

class HelpCommand:

744

"""

745

Base help command implementation.

746

"""

747

def __init__(self, **options): ...

748

749

context: Optional[Context] # Current command context

750

verify_checks: bool # Whether to verify command checks

751

command_attrs: Dict[str, Any] # Attributes for help command

752

753

def copy(self) -> HelpCommand:

754

"""Create a copy of the help command."""

755

756

async def prepare_help_command(self, ctx: Context, command: Optional[Command] = None) -> None:

757

"""Prepare help command for execution."""

758

759

async def command_callback(self, ctx: Context, *, command: str = None) -> None:

760

"""Help command callback."""

761

762

def get_bot_mapping(self) -> Dict[Optional[Cog], List[Command]]:

763

"""Get mapping of cogs to commands."""

764

765

def filter_commands(self, commands: List[Command], *, sort: bool = False, key: Callable = None) -> List[Command]:

766

"""Filter commands based on checks."""

767

768

def get_max_size(self, commands: List[Command]) -> int:

769

"""Get maximum command name size."""

770

771

def get_command_signature(self, command: Command) -> str:

772

"""Get command signature string."""

773

774

def get_opening_note(self) -> str:

775

"""Get opening note for help."""

776

777

def get_ending_note(self) -> str:

778

"""Get ending note for help."""

779

780

def add_indented_commands(self, commands: List[Command], *, heading: str, max_size: int = None) -> None:

781

"""Add indented command list."""

782

783

# Subclass hooks

784

async def send_bot_help(self, mapping: Dict[Optional[Cog], List[Command]]) -> None:

785

"""Send bot help (all commands)."""

786

787

async def send_cog_help(self, cog: Cog) -> None:

788

"""Send help for a specific cog."""

789

790

async def send_group_help(self, group: Group) -> None:

791

"""Send help for a command group."""

792

793

async def send_command_help(self, command: Command) -> None:

794

"""Send help for a specific command."""

795

796

async def send_error_message(self, error: str) -> None:

797

"""Send error message."""

798

799

async def on_help_command_error(self, ctx: Context, error: CommandError) -> None:

800

"""Handle help command errors."""

801

802

def command_not_found(self, string: str) -> str:

803

"""Return message for command not found."""

804

805

def subcommand_not_found(self, command: Command, string: str) -> str:

806

"""Return message for subcommand not found."""

807

808

class DefaultHelpCommand(HelpCommand):

809

"""

810

Default help command implementation with embed formatting.

811

"""

812

def __init__(self, **options): ...

813

814

# Formatting options

815

no_category: str # Name for uncategorized commands

816

paginator: Paginator # Text paginator

817

sort_commands: bool # Whether to sort commands

818

dm_help: Optional[bool] # Whether to DM help

819

dm_help_threshold: Optional[int] # Member count threshold for DM

820

821

class MinimalHelpCommand(HelpCommand):

822

"""

823

Minimal help command implementation.

824

"""

825

def __init__(self, **options): ...

826

827

# Simplified help output

828

sort_commands: bool

829

commands_heading: str

830

aliases_heading: str

831

dm_help: Optional[bool]

832

dm_help_threshold: Optional[int]

833

no_category: str

834

835

class Paginator:

836

"""

837

Text paginator for breaking long help output into pages.

838

"""

839

def __init__(self, prefix: str = '```', suffix: str = '```', max_size: int = 2000, linesep: str = '\n'): ...

840

841

prefix: str # Page prefix

842

suffix: str # Page suffix

843

max_size: int # Maximum page size

844

linesep: str # Line separator

845

846

def add_line(self, line: str = '', *, empty: bool = False) -> None:

847

"""Add a line to the paginator."""

848

849

def close_page(self) -> None:

850

"""Close current page."""

851

852

@property

853

def pages(self) -> List[str]:

854

"""Get all pages."""

855

```

856

857

## Usage Examples

858

859

### Basic Command Bot

860

861

```python

862

import discord

863

from discord.ext import commands

864

865

bot = commands.Bot(command_prefix='!', intents=discord.Intents.default())

866

867

@bot.event

868

async def on_ready():

869

print(f'Bot is ready! Logged in as {bot.user}')

870

871

@bot.command()

872

async def ping(ctx):

873

await ctx.send('Pong!')

874

875

@bot.command()

876

async def echo(ctx, *, message):

877

await ctx.send(message)

878

879

bot.run('YOUR_TOKEN')

880

```

881

882

### Command with Checks and Cooldowns

883

884

```python

885

@bot.command()

886

@commands.has_permissions(manage_messages=True)

887

@commands.cooldown(1, 30, commands.BucketType.guild)

888

async def purge(ctx, amount: int):

889

if amount > 100:

890

await ctx.send("Cannot delete more than 100 messages at once.")

891

return

892

893

deleted = await ctx.channel.purge(limit=amount + 1) # +1 for command message

894

await ctx.send(f"Deleted {len(deleted) - 1} messages.", delete_after=5)

895

```

896

897

### Using Cogs

898

899

```python

900

class ModerationCog(commands.Cog, name="Moderation"):

901

def __init__(self, bot):

902

self.bot = bot

903

904

@commands.command()

905

@commands.has_permissions(kick_members=True)

906

async def kick(self, ctx, member: discord.Member, *, reason=None):

907

await member.kick(reason=reason)

908

await ctx.send(f'{member} has been kicked.')

909

910

@commands.command()

911

@commands.has_permissions(ban_members=True)

912

async def ban(self, ctx, member: discord.Member, *, reason=None):

913

await member.ban(reason=reason)

914

await ctx.send(f'{member} has been banned.')

915

916

async def setup(bot):

917

await bot.add_cog(ModerationCog(bot))

918

```