Skip to content

yansslo/effect-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Effect Bot

A Discord bot built with Effect and discord.js, running on Bun. A learning project for exploring Effect's approach to dependency injection, layered architecture, and typed error handling.

Prerequisites

Setup

  1. Install dependencies:

    bun install
  2. Copy the example env file and fill in your values:

    cp .env.example .env.local
    Variable Description
    NODE_ENV development or production
    BOT_TOKEN Your Discord bot token
    CLIENT_ID Your Discord application's client ID
    GUILD_ID The server to register commands in
  3. Deploy slash commands to your guild:

    bun run deploy:dev
  4. Start the bot:

    bun run dev

Project Structure

src/
├── index.ts              # Entry point — creates the client and wires up layers
├── config/
│   ├── index.ts          # Exports AppConfig (dev/prod) and Config namespace
│   └── bot.ts            # Bot service tag + config layers (token, clientId, guildId)
├── structures/
│   ├── command.ts        # Command interface and factory
│   └── event.ts          # Event interface and factory
├── layers/
│   ├── index.ts          # Merges AppConfig + registries into AppLayer
│   ├── command-registry.ts  # Auto-discovers commands from src/commands/
│   └── event-registry.ts    # Auto-discovers events from src/events/
├── commands/
│   └── ping.ts           # Example slash command
├── events/
│   ├── ready.ts          # Logs when the bot connects
│   └── interactionCreate.ts  # Routes interactions to commands
scripts/
└── deploy-commands.ts    # Registers slash commands with the Discord API

Adding a Command

Create a new file in src/commands/ — it will be auto-discovered at startup.

// src/commands/hello.ts
import { MessageFlags } from "discord.js";
import { Effect } from "effect";
import { Command } from "@/structures/command";

export const hello = Command.make({
  name: "hello",
  description: "Say hello",
  execute: (interaction) =>
    Effect.promise(() =>
      interaction.reply({ content: "Hello!", flags: MessageFlags.Ephemeral })
    ),
});

Then redeploy commands so Discord knows about it:

bun run deploy:dev

Adding an Event

Create a new file in src/events/ — also auto-discovered.

// src/events/messageCreate.ts
import { Effect } from "effect";
import { Event } from "@/structures/event";

export const messageCreate = Event.make({
  name: "messageCreate",
  handle: (message) => Effect.log(`Message from ${message.author.username}`),
});

Scripts

Script Description
bun run dev Start the bot
bun run deploy:dev Deploy slash commands (guild, development)
bun run deploy:prod Deploy slash commands (guild, production)
bun run check Lint/format check via ultracite
bun run fix Auto-fix lint/format issues

How It Works

The bot uses Effect's Layer system for dependency injection:

  • Config.Bot — provides bot credentials from environment variables
  • CommandRegistry — scans src/commands/ and builds a Map<string, Command>
  • EventRegistry — scans src/events/ and builds a Map<string, Event>
  • AppLayer — merges all the above into a single layer provided to the main program

At startup, the bot iterates over registered events and binds them to the Discord client. Commands are resolved from the registry when an interactionCreate event fires.

About

A Discord bot built with Effect and discord.js, running on Bun.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors