# Começando com o Core
> Entenda o papel do runtime, a estrutura do Template Bot e o caminho percorrido até o primeiro comando responder.

- Área: Base do Core
- URL humana: https://ninenity.vercel.app/doc/comecando
- URL Markdown: https://ninenity.vercel.app/doc/markdown/comecando
- Pacotes e conceitos: @ninenity/core, TypeScript, Discord.js

## O modelo mental

O Core não substitui o Discord.js. Ele organiza o ciclo de vida ao redor dele.

- **Você declara**: Cada arquivo registra um comando, evento, task ou interação no `Client`.
- **O Core carrega**: O auto-loader percorre `settings.baseDir`, importa os módulos e valida os registros.
- **O runtime executa**: Cooldown, fila, contexto de guild e respostas são preparados antes do seu `execute`.

> **Regra mais importante:** Um arquivo deve representar uma responsabilidade. Evite concentrar todos os comandos em `Bot.ts`; deixe o auto-loader fazer o trabalho.

## Estrutura do Template Bot

A estrutura já separa código carregado automaticamente de helpers importados explicitamente.

### estrutura do projeto

```text

src/
├─ Bot.ts                         # ponto de entrada
├─ Discord/
│  ├─ Commands/                  # slash, prefixo e menus de contexto
│  ├─ Events/                    # eventos do Discord.js
│  ├─ Interactions/              # modais, callbacks, prompts e paginações
│  └─ Tasks/                     # rotinas periódicas
├─ Shared/
│  ├─ Settings/Client.ts         # LibsClient, token e intents
│  ├─ Settings/Database.ts       # plugin opcional de banco
│  ├─ Emojis/                    # emojis do aplicativo
│  └─ Translate/                 # idiomas
└─ Utils/                        # regras e helpers importados por módulos
```


| Pasta | Carregamento | Use para |
| --- | --- | --- |
| `Discord/Commands` | Automático | Comandos slash, prefixados e menus de contexto |
| `Discord/Events` | Automático | Eventos emitidos pelo Discord.js |
| `Discord/Interactions` | Automático | Modais, prompts, paginações e callbacks registrados |
| `Discord/Tasks` | Automático | Rotinas globais ou executadas por servidor |
| `Shared` e `Utils` | Explícito | Configuração, serviços e regras reutilizáveis |

## Configure o Client

O `LibsClient` estende o cliente do Discord.js e adiciona os registradores do ecossistema.

### src/Shared/Settings/Client.ts

```text

import {
  GatewayIntentBits,
  LibsClient,
  type AppConfig
} from '@ninenity/core'

const Client = new LibsClient<AppConfig>({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildMembers
  ],
  token: process.env.BOT_TOKEN || process.env.DISCORD_TOKEN,
  config: {}
})

export default Client
```


> **Intents precisam combinar com o portal:** Ativar `MessageContent` ou `GuildMembers` no código não basta. Os intents privilegiados também precisam estar habilitados no Discord Developer Portal.

| Intent | Necessário quando |
| --- | --- |
| `Guilds` | Quase sempre: slash commands, canais, cargos e configuração por servidor |
| `GuildMessages` | O bot observa mensagens ou usa comandos prefixados |
| `MessageContent` | O conteúdo textual das mensagens precisa ser lido |
| `GuildMembers` | Entradas, saídas, cargos ou dados completos de membros são usados |

## Inicialize o runtime

`Ninenity.init()` prepara plugins e auto-loader antes de `Client.login()` abrir a conexão com o Discord.

### src/Bot.ts

```text

import 'dotenv/config'
import { Ninenity } from '@ninenity/core'
import Client from './Shared/Settings/Client'
import { databasePlugin } from './Shared/Settings/Database'

Ninenity.init({
  bots: [Client],
  plugins: databasePlugin ? { database: databasePlugin } : undefined,
  settings: { baseDir: __dirname }
})

Client.login()
```


1. **Variáveis são carregadas** — O import de `dotenv/config` disponibiliza o token e integrações antes de criar o Client.
2. **O runtime recebe os bots** — `bots` aceita mais de um Client, mas cada bot mantém seus próprios registradores e timers.
3. **Módulos são encontrados** — `baseDir` aponta para `src` em desenvolvimento e para `dist` após o build.
4. **O login começa** — Depois dos registros, `Client.login()` conecta e conclui as etapas de bootstrap.

## Crie o primeiro módulo

O arquivo só precisa importar o Client compartilhado e fazer seu registro no escopo do módulo.

### src/Discord/Commands/Ping.ts

```text

import {
  SlashCommandBuilder,
  type SlashInputCommandInteraction
} from '@ninenity/core'
import Client from '../../Shared/Settings/Client'

Client.slash({
  data: new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Mostra a latência atual.'),
  cooldown: '3s',
  execute: async (interaction: SlashInputCommandInteraction) => {
    await interaction.reply('Pong!')
  }
})
```


Você não importa `Ping.ts` em `Bot.ts`. O auto-loader encontra o arquivo, executa o módulo uma vez e o `Client.slash()` guarda a definição para deploy e execução.

> **Como saber se funcionou:** Ao iniciar, confirme que o boot termina, o comando aparece entre os registros e o Client fica online. Se o comando não aparecer no Discord, consulte **Solução de problemas**.

## Variáveis de ambiente

Comece com o mínimo e adicione integrações somente quando forem usadas.

### .env

```dotenv

BOT_TOKEN=seu_token_do_discord

# Opcionais: integração com API e HUB
API_KEY=
API_SECRET=

# Opcional: banco de dados
DATABASE_URL=
```


- Nunca envie `.env` para o Git; mantenha apenas um `.env.example` sem secrets.
- Use um token de bot, não o client secret da aplicação.
- A ausência de `API_KEY` e `API_SECRET` desativa a hidratação remota, mas não impede o bot de conectar ao Discord.
- Mantenha `src` e `dist` com a mesma árvore para o auto-loader funcionar após o build.
