# Context menu commands

Add a right-click command on a user or a message, and read what someone ran it on. Covers the base class each kind has, reaching the member, serving several commands from one handler, and the separate names each kind keeps.

Discord shows a context menu command when someone right-clicks. It takes a name and a kind, and the click itself is its only input.

```ts title="src/commands/ViewProfile.ts"
import {
    BuilderComponent,
    RegisterCommand
} from '@seedcord/gateway';
import { ApplicationCommandType } from 'discord.js';

@RegisterCommand('global')
export class ViewProfile extends BuilderComponent<'context_menu'> {
    constructor() {
        super('context_menu');

        this.instance
            .setName('View Profile')
            .setType(ApplicationCommandType.User);
    }
}
```

That name is the route you write on the handler, including its spaces and capitals.

```ts title="src/handlers/ViewProfile.ts"
@UserContextMenuRoute('View Profile')
export class ViewProfile extends UserContextMenuHandler<'View Profile'> {
    public async execute(): Promise<void> {
        const user = this.target;

        await this.reply(`Profile for ${user.tag}.`);
    }
}
```

## Each kind has its own base class

`ApplicationCommandType.User` puts the command on a right-clicked person. `ApplicationCommandType.Message` puts it on a right-clicked message. Pick the base and the decorator that match the kind you set.

{/* prettier-ignore-start */}

| the command sets                 | the handler extends                                                                                           | the decorator                                                                                           |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `ApplicationCommandType.User`    | [`UserContextMenuHandler`](https://docs.seedcord.org/packages/gateway/latest/user-context-menu-handler)       | [`@UserContextMenuRoute`](https://docs.seedcord.org/packages/core/latest/user-context-menu-route)       |
| `ApplicationCommandType.Message` | [`MessageContextMenuHandler`](https://docs.seedcord.org/packages/gateway/latest/message-context-menu-handler) | [`@MessageContextMenuRoute`](https://docs.seedcord.org/packages/core/latest/message-context-menu-route) |

{/* prettier-ignore-end */}

> **Gateway and http differ**
>
> The clicked thing arrives as a discord.js object on gateway and as a `discord-api-types` payload on http.
>
> {/* prettier-ignore-start */}
>
> |                       | gateway               | http                                            |
> | --------------------- | --------------------- | ----------------------------------------------- |
> | user `this.target`    | `User`                | `APIUser`                                       |
> | message `this.target` | `Message`             | `APIMessage`                                    |
> | `this.targetMember`   | `GuildMember \| null` | `APIInteractionDataResolvedGuildMember \| null` |
>
> {/* prettier-ignore-end */}
>
> Both transports give `this.target` an `id`. A user target carries `username` too, and a message target reaches its author through `author`.
>
> `this.targetMember` differs further. Gateway gives it `id` and `displayName`. Http holds the guild fields alone there, since Discord sends that person's user object once under `resolved.users`.

A message command reads the message it was run on.

```ts title="src/handlers/ReportMessage.ts"
@MessageContextMenuRoute('Report Message')
export class ReportMessage extends MessageContextMenuHandler<'Report Message'> {
    public async execute(): Promise<void> {
        const message = this.target;

        await this.reply(
            `Reported ${message.id} from <@${message.author.id}>.`
        );
    }
}
```

## Reaching the member

A user command also carries the clicked person's server member, which is `null` when the command runs outside a server.

```ts
const member = this.targetMember;
```

## Several commands in one handler

You put both commands on one class. Its decorator takes every name and its generic repeats them. Each arm then receives the clicked user and their server member, narrowed to that one command.

```ts title="src/handlers/Moderation.ts"
@UserContextMenuRoute('View Profile', 'Warn')
export class Moderation extends UserContextMenuHandler<
    'View Profile' | 'Warn'
> {
    public async execute(): Promise<void> {
        await this.match({
            'View Profile': (user) =>
                this.reply(`Profile for ${user.tag}.`),
            Warn: (user, member) =>
                this.reply(
                    `Warned ${member?.displayName ?? user.tag}.`
                )
        });
    }
}
```

Leaving `Warn` out of the arms is a compile error, the same as it is on a slash handler.

`this.commandName` gives you the name that fired, typed to the union, for when you want it without branching.

Message commands work the same way, and each of your arms receives the clicked message.

## Each kind keeps its own names

Discord lets a user command and a message command share a name, so the two registries stay separate. A name in one is invisible to the other.

```ts
class Wrong extends MessageContextMenuHandler<'View Profile'> {
    public async execute(): Promise<void> {}
}
```
