break up library, move bots to their own repositories
This commit is contained in:
193
packages/discord/wiki/discord.md
Normal file
193
packages/discord/wiki/discord.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# Discord
|
||||
|
||||
Star Kitten's discord functionality is built on top of [Project Dysnomia](https://github.com/projectdysnomia/dysnomia) to provide up to date and performance interactions with the Discord API.
|
||||
|
||||
## Create a bot
|
||||
|
||||
Running a bot with Star Kitten is as simple as calling startBot()!
|
||||
|
||||
_src/main.ts_
|
||||
|
||||
```ts
|
||||
import { startBot } from '@star-kitten/lib/discord';
|
||||
startBot({
|
||||
token: 'XXXXXX', // can be omitted if you set a DISCORD_BOT_TOKEN environment variable
|
||||
});
|
||||
```
|
||||
|
||||
You can configure the bot further through environment variables:
|
||||
|
||||
_I recommend using dotenvx to encrypt your .env files rather than using plaintext .env files_
|
||||
|
||||
```.env
|
||||
# Required
|
||||
DISCORD_BOT_TOKEN="XXXXXX" # https://discord.com/developers/applications
|
||||
|
||||
# Optional
|
||||
DEBUG="true" # Enable debug mode
|
||||
NODE_ENV="development"
|
||||
LOG_LEVEL="debug"
|
||||
RESET_COMMANDS="true" # "true" or NODE_ENV === "development" will have the bot delete and register all commands on every startup, useful for development
|
||||
STAR_KITTEN_KV_DB_PATH="./kv.db" # Allows the bot to remember commands between restarts for resume functionality and recovery from crashes. If not set, :memory: is used so commands created before any restart will no longer function
|
||||
|
||||
# if using EVE ESI functionality
|
||||
EVE_CLIENT_ID="XXXXX"
|
||||
EVE_CLIENT_SECRET="XXXX"
|
||||
EVE_CALLBACK_URL="http://my.callback.url"
|
||||
ESI_USER_AGENT="XXXX" # provided with each ESI request so CCP knows who to contact if there is any issue
|
||||
|
||||
JANICE_KEY="XXXXX" # If you have one for using janice to get pricing data or appraisals
|
||||
|
||||
# AI Features
|
||||
PERPLEXITY_API_KEY="XXXXX"
|
||||
```
|
||||
|
||||
Although, a bot without any commands isn't very useful, so on to Commands
|
||||
|
||||
## Commands
|
||||
|
||||
Star Kitten will automatically register commands for you at startup. By default, any file in your `./src` directory that matches the pattern `**/*.command.{js,ts,jsx,tsx}`, like `./src/ping.command.ts` or `./src/commands/time.command.tsx`.
|
||||
|
||||
### Command File
|
||||
|
||||
A command file's exports must match the [CommandHandler](../src/discord/commands/command-handler.ts#14) structure.
|
||||
|
||||
definition: Defines the command to Discord, providing the command name, description, parameters and more.
|
||||
|
||||
execute: Function that is ran when this command is executed. The execute method will get called for every interaction associated with that command, so ensure you properly handle different interaction types, like Autocomplete vs. ApplicationCommand.
|
||||
|
||||
Example:
|
||||
|
||||
```tsx
|
||||
import { Constants, type ChatInputApplicationCommandStructure } from '@projectdysnomia/dysnomia';
|
||||
import { type ExecutableInteraction, type CommandContext, isApplicationCommand, Locale } from '@star-kitten/lib/discord';
|
||||
|
||||
const definition: ChatInputApplicationCommandStructure = {
|
||||
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
|
||||
name: 'time',
|
||||
nameLocalizations: {
|
||||
[Locale.DE]: 'zeit',
|
||||
},
|
||||
description: 'Get the current EVE time',
|
||||
descriptionLocalizations: {
|
||||
[Locale.DE]: 'Holen Sie sich die aktuelle EVE-Zeit',
|
||||
},
|
||||
};
|
||||
|
||||
const eveTimeText = {
|
||||
[Locale.EN_US]: 'EVE Time',
|
||||
[Locale.DE]: 'EVE-Zeit',
|
||||
};
|
||||
|
||||
function renderTimeDisplay(locale: string = 'en-US') {
|
||||
const now = new Date();
|
||||
const eveTime = now.toISOString().split('T')[1].split('.')[0];
|
||||
const eveDate = now.toLocaleDateString(locale, {
|
||||
timeZone: 'UTC',
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: '2-digit',
|
||||
weekday: 'long',
|
||||
});
|
||||
return (
|
||||
<container>
|
||||
<textDisplay>
|
||||
{`### ${eveTimeText[locale] || eveTimeText[Locale.EN_US]}
|
||||
${eveTime}
|
||||
${eveDate}`}
|
||||
</textDisplay>
|
||||
</container>
|
||||
);
|
||||
}
|
||||
|
||||
async function execute(interaction: ExecutableInteraction, ctx: CommandContext) {
|
||||
if (!isApplicationCommand(interaction)) return;
|
||||
|
||||
interaction.createMessage({
|
||||
flags: Constants.MessageFlags.IS_COMPONENTS_V2,
|
||||
components: [renderTimeDisplay(interaction.locale)],
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
definition,
|
||||
execute,
|
||||
};
|
||||
```
|
||||
|
||||
## Components V2
|
||||
|
||||
Star Kitten commands should utilize components v2. We also have a JSX syntax for creating commands. Look at the examples below to compare using JSX vs plain JavaScript objecst to define your components.
|
||||
|
||||
### JSX Components
|
||||
|
||||
```tsx
|
||||
export function renderAppraisalModal(interaction: Interaction) {
|
||||
return (
|
||||
<modal customId="appraisalResult" title="Appraise Items">
|
||||
<label label="Select a market">
|
||||
<stringSelect customId="market" placeholder="Select a market" minValues={1} maxValues={1}>
|
||||
{markets.map((m) => (
|
||||
<option
|
||||
label={m.name}
|
||||
value={m.id.toString()}
|
||||
default={m.id === 2} // Jita
|
||||
/>
|
||||
))}
|
||||
</stringSelect>
|
||||
</label>
|
||||
<label label="Enter items to appraise">
|
||||
<textInput
|
||||
customId="input"
|
||||
isParagraph={true}
|
||||
placeholder={`e.g. Tritanium 22222
|
||||
Pyerite 8000
|
||||
Mexallon 2444`}
|
||||
/>
|
||||
</label>
|
||||
</modal>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Plain JS Object
|
||||
|
||||
```ts
|
||||
export function renderAppraisalModal(interaction: Interaction) {
|
||||
return {
|
||||
type: Constants.InteractionResponseTypes.MODAL,
|
||||
custom_id: 'appraisalResult',
|
||||
title: 'Appraise Items',
|
||||
components: [
|
||||
{
|
||||
type: Constants.ComponentTypes.LABEL,
|
||||
label: 'Select a market',
|
||||
component: {
|
||||
type: Constants.ComponentTypes.STRING_SELECT,
|
||||
custom_id: 'market',
|
||||
placeholder: 'Select a market',
|
||||
min_values: 1,
|
||||
max_values: 1,
|
||||
options: markets.map((m) => ({
|
||||
label: m.name,
|
||||
value: m.id.toString(),
|
||||
default: m.id === 2, // Jita
|
||||
})),
|
||||
},
|
||||
},
|
||||
{
|
||||
type: Constants.ComponentTypes.LABEL,
|
||||
label: 'Enter items to appraise',
|
||||
component: {
|
||||
type: Constants.ComponentTypes.TEXT_INPUT,
|
||||
custom_id: 'input',
|
||||
style: Constants.TextInputStyles.PARAGRAPH,
|
||||
placeholder: `e.g. Tritanium 22222
|
||||
Pyerite 8000
|
||||
Mexallon 2444`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user