Skip to content

Latest commit

 

History

History
221 lines (191 loc) · 5.96 KB

File metadata and controls

221 lines (191 loc) · 5.96 KB

StelliaJS

About

StelliaJS is built using Discord JS V14 and TypeScript. It allows you to quickly set up a new bot with a simple and complete architecture. A CLI is available to help you set up a project with StelliaJS : link to the CLI

Architecture

Recommended architecture for StelliaJS project.

.
├── src/
│   ├── commands/
│   │   ├── contextMenus/
│   │   │   └── mute.ts
│   │   └── slash/
│   │       ├── moderation // You can create folders, everything is loaded recursively
│   │       │   ├── ban.ts
│   │       │   └── mute.ts
│   │       └── ping.ts
│   ├── environments/
│   │   ├── environment.development.ts
│   │   ├── environment.model.ts
│   │   └── environment.ts
│   ├── events/
│   │   ├── ready.ts
│   │   └── interactionCreate.ts
│   ├── interactions/
│   │   ├── autoCompletes/
│   │   │   └── song.ts
│   │   ├── buttons/
│   │   │   └── colorChoice.ts
│   │   ├── modals/
│   │   │   └── form.ts
│   │   └── selectMenus/
│   │       └── settings.ts
│   ├── environment.d.ts
│   └── index.ts
├── .env
├── package.json
├── pnpm-lock.yaml
├── stellia.json
└── tsconfig.json

Examples

Simple client with environment

Client initialization

import { StelliaClient } from "@stelliajs/framework";
import { GatewayIntentBits, Partials } from "discord.js";

(async () => {
	const client = new StelliaClient(
		{
			intents: [
				GatewayIntentBits.Guilds,
				GatewayIntentBits.GuildMessages,
				GatewayIntentBits.MessageContent,
				GatewayIntentBits.GuildMembers
			],
			partials: [Partials.Message, Partials.GuildMember]
		},
		{
			managers: {
				autoCompletes: {
					directoryPath: "./interactions/autoCompletes"
				},
				buttons: {
					directoryPath: "./interactions/buttons"
				},
				commands: {
					directoryPath: "./commands/slash"
				},
				contextMenus: {
					directoryPath: "./commands/contextMenus"
				},
				events: {
					directoryPath: "./events"
				},
				modals: {
					directoryPath: "./interactions/modals"
				},
				selectMenus: {
					directoryPath: "./interactions/selectMenus"
				}
			},
			environment: {
				areGuildsConfigurationEnabled: true
			}
		}
	);

	await client.connect(process.env.TOKEN);
})();

// If you need internationalisation:
import { initTranslations } from "@stelliajs/framework";

await use(Backend).init(
	{
		lng: StelliaLocale.English, // StelliaLocale is an enum with all the supported languages by Discord
		backend: {
			// With namespace: path.join(import.meta.dirname, "../locales/{{lng}}/{{ns}}.json")
			loadPath: path.join(import.meta.dirname, "../locales/{{lng}}.json")
		},
		fallbackLng: StelliaLocale.English,
		supportedLngs: Object.values(AmariLocale),
		preload: Object.values(AmariLocale)
		// ns: ["common", "commands", "errors"]
	},
	(error) => {
		if (error) {
			console.error(error);
		}
	}
);
initTranslations(i18next);

Environment model

import { BaseGeneralConfiguration, BaseGuildConfiguration, GuildConfiguration, GuildsConfiguration } from "@stelliajs/framework";
import { Snowflake } from "discord.js";

interface MyBotGeneralConfiguration extends BaseGeneralConfiguration {
	botName: string;
}
interface MyBotSpecificGuildConfiguration extends BaseGuildConfiguration {
	channels: {
		logs: Snowflake;
		welcome: Snowflake;
	};
}

export interface MyBotGuildConfiguration extends GuildConfiguration {
	general: MyBotGeneralConfiguration;
	guild: MyBotSpecificGuildConfiguration;
}

export interface MyBotGuildsConfiguration extends GuildsConfiguration {
	general: MyBotGeneralConfiguration;
	guilds: {
		[guildId: Snowflake]: MyBotSpecificGuildConfiguration;
	};
}

Interactions/Events with environment

Ready event

import { type EventStructure, type StelliaClient } from "@stelliajs/framework";
import { Events } from "discord.js";
import { type MyBotGuildsConfiguration } from "@environments/environment.model.ts";

export default {
	data: {
		name: Events.ClientReady,
		once: true
	},
	async execute(client: StelliaClient<true>, guildsConfiguration: MyBotGuildsConfiguration) {
		// <true> ensures that the client is Ready
		console.log(`Logged in as ${client.user.tag}`);
		await client.initializeCommands(); // Used to initialise registered commands
	}
} satisfies EventStructure;

InteractionCreate event

import { type StelliaClient, type EventStructure } from "@stelliajs/framework";
import { Events, type Interaction } from "discord.js";
import { type MyBotGuildConfiguration } from "@environments/environment.model.ts";

export default {
	data: {
		name: Events.InteractionCreate,
		once: false
	},
	async execute(client: StelliaClient<true>, guildConfiguration: MyBotGuildConfiguration, interaction: Interaction) {
		if (interaction.inCachedGuild()) {
			await client.handleInteraction(interaction); // Automatic interaction handling
		}
	}
} satisfies EventStructure;

Command interaction

import { type CommandStructure, type StelliaClient } from "@stelliajs/framework";
import { type ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import { type MyBotGuildConfiguration } from "@environments/environment.model.ts";

export default {
	data: {
		command: new SlashCommandBuilder().setName("ping"),
		reply: {
			autoDefer: true, // Defer the reply to avoid the interaction failing after 3 seconds
			ephemeral: true // The reply will be visible only by the user who triggered the interaction
		}
	},
	async execute(client: StelliaClient, guildConfiguration: MyBotGuildConfiguration, interaction: ChatInputCommandInteraction<"cached">) {
		// All interactions are cached
		await interaction.editReply("Pong!");
	}
} satisfies CommandStructure;

Help

If you need help with the framework you can open an issue.