# Quick Start

This quick start guide will take you from an empty project to a basic bot in no time. For info about getting started with Pages, head over to the special quick start guide for Pages after you finish the basic setup.

### Installation

Slashasaurus does not provide a version of discord.js itself, so you'll need to install both.

```bash
yarn install discord.js@latest slashasaurus@latest
```

### The Main File

Setting up a slashasaurus bot is very similar to setting up a discord.js bot. In your main file, create a new SlashasaurusClient, this wraps the discord.js client and adds all the extra features that slashasaurus provides. The constructor takes two arguments, the first is the options to be passed on to the discord.js client ([you can find the options here](https://discord.js.org/#/docs/discord.js/stable/typedef/ClientOptions)), the second is the options for slashasaurus ([you can find the options here](/slashasaurus/interfaces/slashasaurusclientoptions.md#options)).

{% code title="index.ts" %}

```typescript
import { Intents } from 'discord.js';
import path from 'path';
import { SlashasaurusClient } from 'slashasaurus';

const client = new SlashasaurusClient(
  {
    intents: [Intents.FLAGS.GUILDS],
    restRequestTimeout: 30 * 1000,
  },
  {
    devServerId: '939038490023301150',
  }
);

client.once('ready', () => {
  logger.info(`Client ready and logged in as ${client.user?.tag}`);
});

client.login(process.env.TOKEN);
```

{% endcode %}

### Creating Your First Command

Now that we have the basics set up, we're ready to make our first command. When using slashasaurus, commands are stored in a special way in the file system. Let's make a folder to store them in called `commands`.

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

The first command we're gonna add is going to be a slash command. For this we'll need to make another folder named `chat` inside our commands folder, this will store all of our slash commands.

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

Let's make a basic `/ping` command to get familiar with the basics of slash commands in Slashasaurus. Inside of `commands/chat` , make a new file called `ping.ts`. In the file we'll create a new SlashCommand and export it as default.

{% code title="ping.ts" %}

```typescript
import { SlashCommand } from 'slashasaurus';

export default new SlashCommand(
  {
    name: 'ping',
    description: 'Pings the bot to make sure everything is working',
    options: [],
  },
  {
    run: (interaction) => {
      interaction.reply({
        content: `Pong!`,
        ephemeral: true,
      });
    },
  }
);
```

{% endcode %}

Let's break down what we have above. The first argument of SlashCommand is the basic info about the command: the name, description, and options. The second argument contains our run handler, with a pretty simple reply. That's it, the command is all ready to go! Just one more quick thing before you can start the bot. We need to tell slashasaurus where this command is. Let's head back to our main file and get that set up.

We can run `client.registerCommandsFrom` to load all the commands from our commands folder. Simply pass it the path to the commands folder and where you want to register the commands. In development, you'll want to pass "dev" as the second argument, this will register the commands to your dev server directly, making them available immediately. In production you'll want to register your commands to "global", this will make them available in all guilds, but can take up to an hour for changes to appear (don't worry, if a command changes the options, you won't receive any incorrect ones).

{% hint style="info" %}
If you plan on sharding your bot, you'll want to avoid registering the commands multiple times at startup, so instead you can pass "none" and the command handlers will be registered, but the command data won't be sent to discord.
{% endhint %}

```typescript
import { Intents } from 'discord.js';
import path from 'path';
import { SlashasaurusClient } from 'slashasaurus';

const client = new SlashasaurusClient(
  {
    intents: [Intents.FLAGS.GUILDS],
    restRequestTimeout: 30 * 1000,
  },
  {
    devServerId: '939038490023301150',
  }
);

client.once('ready', () => {
  logger.info(`Client ready and logged in as ${client.user?.tag}`);
  // Register our commands from our folder
  client.registerCommandsFrom(
    path.join(__dirname, '/commands'),
    process.env.NODE_ENV === 'development' ? 'dev' : 'global'
  );
});

client.login(process.env.TOKEN);
```

That's it, build and run your code to see your new command!

### A Command With Options

Now let's look at how a command with options works, there's one special thing to watch out for while working with options. Let's make a command called `/hello` that will ask the user for their name and greet them.

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│        ├─ hello.ts
│        └─ ping.ts
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

We'll name our option "name" (crazy, right?). Take a close look at the options here though, there's something special in there.

```typescript
import { SlashCommand } from 'slashasaurus';

export default new SlashCommand(
  {
    name: 'hello',
    description: 'Makes the bot greet you',
    options: [
      {
        type: 'STRING',
        name: 'name',
        description: 'Your name',
        required: true,
      },
    ] as const,
  },
  {
    run: (interaction, client, options) => {
      interaction.reply({
        content: `Hello, ${options.name}. Nice to meet you!`,
        ephemeral: true,
      });
    },
  }
);
```

You might be thinking `as const`? What is that? The `as const` here tells TypeScript that your options array will always remain constant and allows it to make some more inferrences about the types of each member of the array. This powers something special in slashasaurus. If you typed this into your editor yourself you may have noticed that as you were typing `options.name` your editor automatically suggested `name` and it's typed as a string. This works with any slash command option type.

### A Command With Choices

Lets take a look at building out a command with a string argument with a provided set of `choices` for the user.

Create a file called `survey.ts` in the same place as last time.

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│        ├─ hello.ts
│        ├─ ping.ts
│        └─ survey.ts
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

In there we'll make our new command:

{% code title="survey.ts" %}

```typescript
import { SlashCommand } from 'slashasaurus';

export default new SlashCommand(
  {
    name: 'survey',
    description: 'Give a response for our survey',
    options: [
      {
        type: 'STRING',
        name: 'language',
        description: 'What language do you use?',
        required: true,
        choices: [
          {
            name: 'JavaScript',
            value: 'js',
          },
          {
            name: 'TypeScript',
            value: 'ts',
          },
        ] as const,
      },
    ] as const,
  },
  {
    run: (interaction, client, options) => {
      if (options.language === 'js') {
        interaction.reply({
          content: `We've recorded your response. (also try TypeScript)`,
          ephemeral: true,
        });
      } else {
        interaction.reply({
          content: `We've recorded your response. (also try JavaScript)`,
          ephemeral: true,
        });
      }
    },
  }
);
```

{% endcode %}

Again you'll see the `as const` after the array of choices. This does the same thing with the types to help keep the autocomplete helpful. When you look at the type of `options.language` you'll see it's `"js" | "ts"` this means that you'll know exactly what the options are that the user has, instead of needing to remember them or scroll back and check. If you happen to notice that it's just typed as `string` this likely means you forgot the second `as const`.

### A Command With Autocomplete

Before we move on we should take a look at autocomplete options.

Make a new file `longsurvey.ts`:

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│        ├─ hello.ts
│        ├─ ping.ts
│        ├─ longsurvey.ts
│        └─ survey.ts
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

In here we'll make our command:

{% code title="longsurvey.ts" %}

```typescript
import { SlashCommand } from 'slashasaurus';

const foods = ['cheese', 'apples', 'oranges', 'burgers', 'bacon', 'fish'];

export default new SlashCommand(
  {
    name: 'longsurvey',
    description: 'Give a response for our other survey',
    options: [
      {
        type: 'STRING',
        name: 'food',
        description: 'Which of these foods is your favorite?',
        required: true,
        autocomplete: true,
      },
    ] as const,
  },
  {
    run: (interaction, client, options) => {
      interaction.reply({
        content: `We've recorded your response of ${options.food}.`,
        ephemeral: true,
      });
    },
    autocomplete: (interaction, focusedName, focusedValue, client, options) => {
      if (focusedName === 'food') {
        interaction.respond(
          foods.filter((food) => food.startsWith(focusedValue))
        );
      }
    },
  }
);
```

{% endcode %}

Here we have our second handler, `autocomplete`. This handler is given the autocomplete interaction, the name of the field that's being filled out, the value the user has entered so far, the client, and finally the options again. The `focusedName` will only ever be one of the options with autocomplete set to true, so in this case it's type is `"food"`, but if we had another it would be a union of the two, for instance: `"food" | "other"`.

{% hint style="info" %}
Optionally, you can specify `onAutocomplete` inside your `food` option, this function will receive `interaction`, `value`, and `client`. If you pass this handler, all autocomplete interactions related to this arg will call that function *instead* of the `autocomplete` inside your handlers. This is extra useful when you have a specific autocomplete that's used across multiple commands, for instance autocompleting the name of something in a search, etc.
{% endhint %}

{% hint style="info" %}
You can also pass a custom `transformer` to your autocomplete option. This will take the value of the autocomplete and transform it before it gets sent to your run handler. For instance if you have an option to autocomplete a date, you can convert it to a Date inside the transformer and the run handler will receive the Date in place of the original value.
{% endhint %}

### A Command With Subcommands

Lastly, lets take a look at how we make subcommands. Lets make a `/role add` and a `/role remove`.

First, make a new folder called `role` where you other commands are, then add an `add.ts` and a `remove.ts` inside.

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│        ├─ hello.ts
│        ├─ ping.ts
│        ├─ longsurvey.ts
│        ├─ role
│        │  ├─ add.ts
│        │  └─ remove.ts
│        │
│        └─ survey.ts
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

With this one I won't show the exact commands since that isn't necessary to illusatrate the point. Here you'll see that making subcommands is almost the same as making top level commands. Just place them inside the folder and the top level command will use the folder name as its name. If you want to specify a description for the top level command you can create a file inside the folder named `_meta.ts`. You can export a `description` and `defaultPermissions` to set those on that command. For instance we can make the `_meta.ts` file:

```
my-bot
├─ src
│  ├─ index.ts
│  └─ commands
│     └─ chat
│        ├─ hello.ts
│        ├─ ping.ts
│        ├─ longsurvey.ts
│        ├─ role
│        │  ├─ _meta.ts
│        │  ├─ add.ts
│        │  └─ remove.ts
│        │
│        └─ survey.ts
│
├─ tsconfig.json
├─ README.md
└─ package.json
```

and put:

{% code title="\_meta.ts" %}

```typescript
export const description = 'Commands for managing your roles';
```

{% endcode %}

Now our top level `/role` command will have that description.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://rodentman87.gitbook.io/slashasaurus/quick-start.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
