npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pekno/simple-discordbot

v0.0.5

Published

<div align="center">

Readme

SimpleDiscordBot

GitHub License TypeScript npm version

SimpleDiscordBot is a TypeScript library designed to simplify the creation of Discord bots using discord.js. It provides a structured approach to handling bot interactions, command registration, and localization.

🚀 Why This Package?

This package was created to reduce code duplication across my Discord bot projects. After noticing a lot of shared logic between my bots, I decided to extract the core functionalities into a reusable NPM package. This makes bot development faster, cleaner, and easier to maintain.

[!TIP] You can checkout my bots that use this libray, League of Legends Gamble Bot & SUNO Discord Bot


📦 Installation

npm install @pekno/simple-discordbot

🛠️ Configuration

To initialize SimpleDiscordBot, provide a configuration object containing your bot credentials, intents, and localization settings.

Example: Instantiating the Bot

import { SimpleDiscordBot } from "simple-discordbot";
import { GatewayIntentBits } from "discord.js";

class MyService {
  // Your custom service logic here
}

const myService = new MyService();

const simpleBot = new SimpleDiscordBot<MyService>(
  {
    discord_token: CONFIG.DISCORD_TOKEN ?? "",
    discord_id: CONFIG.DISCORD_ID ?? "",
    intents: [GatewayIntentBits.Guilds],
    locale: CONFIG.LOCALE,
    available_locale: localList,
    locale_directory: localesPath,
  },
  myService
);

Configuration Options:

| Option | Type | Description | |-------------------|----------------------|----------------------------------| | discord_token | string | Your bot's authentication token. | | discord_id | string | Your bot's application ID. | | intents | GatewayIntentBits[] | List of intents required. | | locale | string | Default bot locale. | | available_locale| string[] | Supported locales. | | locale_directory| string | Path to locale JSON files. |


🔥 Creating Commands

Command Parameters

| Parameter | Type | Description | |------------------|------------------------------------------------|--------------------------------------------------| | name | string | Command name. | | clickAlias | string | Alias for triggering the command via interactions. | | description | string | Command description. | | options | CommandOption[] | List of available options for the command. | | execute | (interaction, client, service, extraInfo?, modalPayload?) => Promise<void> | Function to execute when the command is triggered. | | registerPredicate | () => boolean | Function to determine if the command should be registered (usefull for command only based on available features). |

[!TIP] execute's' extraInfo is an object containing all data passed through customId, for example if you fill a button with command;A:=1;B:=2;C:=3, extraInfo will be equal {A: "1", B: "2", C: "3"}. execute's' modalPayload is an object containing data from modals.

Basic Command Example

import { Command, CommandList } from "simple-discordbot";
import { ChatInputCommandInteraction, Client } from "discord.js";

const simpleCommandsList = new CommandList<MyService>();

simpleCommandsList.push(
  new Command({
    name: "start",
    description: "Starts an action",
    execute: async (
      interaction: ChatInputCommandInteraction,
      client: Client,
      myService: MyService
    ) => {
      await interaction.deferReply();
      // Use myService inside command execution
      await interaction.editReply("Command executed successfully.");
    },
  })
);

Command with Options

The CommandOption class now provides factory methods for easier creation of different option types:

import { Command, CommandList, CommandOption } from "simple-discordbot";
import { ChatInputCommandInteraction, Client } from "discord.js";

simpleCommandsList.push(
  new Command({
    name: "add",
    description: "Adds an item",
    options: [
      // Using the string factory method
      CommandOption.string(
        "item_name",
        "The name of the item",
        true, // required
        false // autocomplete
      ),
      // Using the integer factory method
      CommandOption.integer(
        "quantity",
        "The quantity to add",
        false // optional
      ),
      // Using the boolean factory method
      CommandOption.boolean(
        "notify",
        "Whether to send a notification",
        false // optional
      )
    ],
    execute: async (
      interaction: ChatInputCommandInteraction,
      client: Client,
      myService: MyService
    ) => {
      await interaction.deferReply();
      const itemName = interaction.options.getString("item_name");
      const quantity = interaction.options.getInteger("quantity") ?? 1;
      const notify = interaction.options.getBoolean("notify") ?? false;
      
      await interaction.editReply(`Added ${quantity} of ${itemName}. Notification: ${notify ? 'Yes' : 'No'}`);
    },
  })
);

You can still use the traditional constructor approach if needed:

new CommandOption({
  name: "item_name",
  description: "The name of the item",
  type: ApplicationCommandOptionType.String,
  required: true,
})

Modal Submission Example

import { ModalSubmitCommand } from "simple-discordbot";
import { ModalSubmitInteraction, Client } from "discord.js";

simpleCommandsList.push(
  new ModalSubmitCommand({
    name: "submit_feedback_modal",
    execute: async (
      interaction: ModalSubmitInteraction,
      client: Client,
      myService: MyService,
      extraInfo: any,
      modalPayload: ModalSubmitFields
    ) => {
      const { userId } = extraInfo as { userId: string };
      const feedback = modalPayload?.getField('feedback')?.value;
      await interaction.deferReply({ ephemeral: true });
      if (!feedback) throw new Error("Feedback cannot be empty.");
      console.log(`User ${userId} submitted feedback: ${feedback}`);
      interaction.editReply({ content: "Thank you for your feedback!" });
    },
  })
);

🚀 Running the Bot

Once your bot and commands are set up, start your bot with:

const client = await simpleBot.start(simpleCommandsList);

[!TIP] Calling start will return the Client object used by the bot, if you ever need it somewhere else.

🔥 Using the API Client with Circuit Breaker

Creating API Classes

You can extend MainApi to create custom API clients with built-in request queuing, rate limiting, and circuit breaker functionality.

class MyFirstApi extends MainApi {
    //...
}
const requestPerMinutes = 30;
const myFirstApi = new MyFirstApi(
    { 'My-Header-Token': "value" },
    requestPerMinutes
);
class MySecondApi extends MainApi {
    //...
}
const mySecondApi = new MySecondApi();

Making API Requests

The MainApi class now provides methods for all common HTTP verbs. All requests are queued and processed according to rate limits.

// GET request
const getData = async (endpoint: string): Promise<any> => {
  try {
    const response = await this.get(`https://api.example.com/${endpoint}`);
    return response.data;
  } catch (error: any) {
    if (error.response?.status === 404) return null;
    throw error;
  }
};

// POST request
const createData = async (endpoint: string, data: any): Promise<any> => {
  try {
    const response = await this.post(`https://api.example.com/${endpoint}`, data);
    return response.data;
  } catch (error: any) {
    throw error;
  }
};

// Other available methods: put(), delete(), patch()

Circuit Breaker Protection

The API client includes a circuit breaker that prevents cascading failures when external services are experiencing issues:

  • Closed State: Normal operation, requests flow through
  • Open State: After multiple failures, requests are blocked to prevent overloading the failing service
  • Half-Open State: After a timeout period, allows a test request to check if the service has recovered

Resource Management

When you're done with an API instance, properly dispose of it to prevent memory leaks:

// Clean up resources when done
myApi.dispose();

📜 License

This project is licensed under MIT.


📚 Additional Notes

  • This package relies on discord.js, make sure to install it.
  • The library includes i18n support, allowing easy localization.
  • The command structure is fully typed, making development safer.
  • All classes and methods are thoroughly documented with JSDoc comments.

🔗 Contributing & Source Code

Contributions and feedback are always welcome! If you have any suggestions or issues, feel free to open an issue or submit a pull request.

Happy coding! 🎉