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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@khurvity/khur-core

v0.2.0

Published

Core library for Discord Bots development with Discord.js library

Downloads

13

Readme

GitHub release (latest by date) GitHub Workflow Status GitHub Workflow Status GitHub

Khur Core

Set of base tools to work with the discord.js library.

This library contains some features to facilitate the event log and commands, besides using middlewares for the command handler (including the individual commands) to provide a better extension of functionality.

Note: As of version >= 0.2.0 it will not include the Discord.js package so it must be installed in your project separately.

Features

  • Command handler
  • Event handler
  • Translations by command or global
  • Custom middlewares
  • Support to:
    • Multi prefix
    • Command aliases (and dynamic alias)
  • Custom project structure
  • Simple command structure
  • TypeScript support

Installation

Node.js 14 or newer is required.

yarn add @khurvity/khur-core

Getting Started

At the moment of registering events, commands or any other feature, it is required to be done before configuring the library (Khur.config(...)).

Configuration

The Client class forms part of the library discord.js.

import { Khur, Client } from '@khurvity/khur-core';

Khur.config({
  appRoot: __dirname,
  defaultPrefix: '!',
  i18n: {
    supported: ['es', 'en'],
    globalTranslationsPath: 'PATH_TO_TRANSLATIONS_FOLDER',
  },
  bot: {
    client: {
      id: 'EXAMPLE_ID',
      secret: 'EXAMPLE_SECRET',
    },
    token: 'EXAMPLE_TOKEN',
    scopes: ['bot'],
    permissions: '8',
  },
  discordClient: new Client(), // Discord Client
});

The parameters that the Khur.config method receives are:

Khur.config(<KhurConfig>);

interface KhurConfig {
  appRoot: string;
  bot: BotCredentials;
  defaultPrefix: string;
  discordClient: Client;
  i18n: {
    globalTranslationsPath: string;
    supported: Array<string>;
  };
  onReady?(client: Client): Promise<void>;
}

interface BotCredentials {
  client: {
    id: string;
    secret: string;
  };
  token: string;
  scopes: Array<BotScopeOptions>; // type ['bot']
  permissions: string;
}

Register event

The event's name must be one available from the following documentation shown in the Client class.

Register.event(<event>, 'PATH_TO_EVENT_FILE');

Register command

The category and names properties are required.

Register.command('PATH_TO_COMMAND_FOLDER', {
  category: 'Test',
  names: ['test', 'alias1', 'alias2'],
});

The criteria received for the the method Register.command are the following:

Register.command(<string>, <CommandConfig>);

interface CommandConfig {
  allowDynamicAliases?: boolean;
  middlewares?: Array<typeof BaseMiddleware>;
  names: Array<string>;
  [key: string]: any;
}

Example usage

Keep in mind the following structure of files:

.
├── src
│   ├── app
│   │   ├── commands
│   │   │   └── Sample
│   │   │       └── index.ts <── Command
│   │   └── events
│   │       └── Message.ts <── EventMessage
│   └── index.ts <── MainFile
└──README.md

Configuration for ./src/app/events/Message.ts:

import {
  BaseEvent,
  CommandHandler,
  Khur,
  Message as MessageData,
} from '@khurvity/khur-core';

export default class Message extends BaseEvent {
  protected async handle(message: MessageData): Promise<void> {
    try {
      await CommandHandler.init(message, {
        prefix: Khur.getDefaultPrefix(),
      });
    } catch (error) {
      console.error(error);
    }
  }
}

Configuration for ./src/app/commands/Sample/index.ts:

import { BaseCommand } from '@khurvity/khur-core';

export default class Sample extends BaseCommand {
  public async handle(): Promise<void> {
    // this.deleteCommandUse(); // uncomment to remove usage of the command
    this.message.channel.send('Sample!');
  }
}

Note: An alias will be used for the importation of files.

Configuration for ./src/index.ts:

import { Register, Khur, Client } from '@khurvity/khur-core';

Register.event('message', '@app-event/Message');

Register.command('@app-command/Sample', {
  category: 'Test',
  names: ['sample', 'alias1', 'alias2'],
});

// It is recommended to use this method if you want to run some features before starting the Bot
Khur.beforeInit(async (): Promise<void> => {
  console.log('Hi!');
});

Khur.config({
  appRoot: __dirname,
  defaultPrefix: '!',
  i18n: {
    supported: ['es', 'en'],
    globalTranslationsPath: '@app-translation',
  },
  bot: {
    client: {
      id: 'EXAMPLE_ID',
      secret: 'EXAMPLE_SECRET',
    },
    token: 'EXAMPLE_TOKEN',
    scopes: ['bot'],
    permissions: '8', // Administrator
  },
  discordClient: new Client(),
});

To execute this code and test on your Discord server, the command !sample should reply with a message saying Sample!

Structure of classes

The classes for @khurvity/khur-core contain utility properties and methods, which are shown below:

Class: Bot

Property | Type | Description --- | --- | --- prefix | string | Bot prefix

Method | Return | Description --- | --- | --- getStatus() | boolean | static Getting bot status setStatus(status: boolean) | void | static Change bot status getClient() | Client | static Getting client instance setClient(Client) | void | static Set client instance getPrefix() | string | Getting bot prefix

Class: Commands

Method | Return | Description --- | --- | --- all() | Array | static Retrieve command list get(key: string) | CommandData | undefined | static If it exists, retrieve the information from a command rawList() | Array | static Retrieve command list (classes version) has(key: string) | boolean | static Check if a command has been registered

Class: Events

Method | Return | Description --- | --- | --- all() | Array | static Retrieve event list get(key: string) | EventData | undefined | static If it exists, retrieve the information from a event has(key: string) | boolean | static Check if a event has been registered

Class: Khur

Method | Return | Description --- | --- | --- config(data: KhurConfig) | Promise | static Initialize all application configuration getAppRoot() | string | static Getting application path getDefaultPrefix() | string | static Getting default prefix beforeInit(initCallback: () => Promise) | Promise | static Set initialize function

Class: Register

Method | Return | Description --- | --- | --- group(params: RegisterGroupParams, callback: (params: RegisterGroupParams) => void) | void | static Callback function to group commands command(path: string, newConfig: CommandConfig) | void | static Register new command event(name: string, path: string) | void | static Register new event. More details

Class: Request

Property | Type | Description --- | --- | --- bot | Bot | Instance: Bot message | Message | Discord message prefix | string | Current prefix

Method | Return | Description --- | --- | --- data(message?: string) | RequestData | Extract and parse message content isCommand(prefix: string, message: string) | boolean | static Verify that it is a possible command

Class: Translation

const translation = new Translation(current: null | string = null, commandPath?: string);

// translation.globals('<filename>.<property>.<property>', { name: 'John' });
translation.globals('info.author', { name: 'John' });

// PATH_TO/info.ts
export const author = 'Hello! My name is {{name}}';

Property | Type | Description --- | --- | --- current | string | Current translation language

Method | Return | Description --- | --- | --- getSupported() | Array | static Getting list of supported languages setSupported(supported: Array) | void | static Set list of supported languages getCurrent() | string | Getting current language globals(key: string, replace: TranslationReplaceParams = {}) | any | Use globals translations locals(key: string, replace: TranslationReplaceParams = {}) | any | Use locals translations checkLocaleFormat(locale: string) | boolean | static Check if language key to use has a valid format

Class: CommandHandler

Method | Return | Description --- | --- | --- init(message: Message, config?: CommandHandlerConfig) | Promise | static Initialize handler

Structure of features (utilities)

import {
  checkMentions,
  extractMentions,
  extractParams,
  getAuthorAvatar,
  getBotAvatar,
  getGuildBanner,
  getGuildIcon,
} from '@khurvity/khur-core';

Function | Return | Description --- | --- | --- checkMentions(content: string) | RequestValidations | Check for mentions extractMentions(content: string) | RequestMentions | Extract mentions from message content extractParams(content: string) | RequestParams | Extract params from message content getAuthorAvatar(request: Message | User) | string | Getting user avatar getBotAvatar() | string | Getting Bot avatar getGuildBanner(request: Guild | Message) | string | Getting guild banner getGuildIcon(request: Guild | Message) | string | Getting guild icon

API Reference

  • In the main file, the last thing to be running must be Khur.config due to it being in charge of starting the settings of the Bot.
  • Middlewares Array<Middleware>: if the returned value is false, the command won't be executed.
  • The commands/events will always be extended to its base class such as BaseCommand and BaseEvent respectively, in addition to being exported by default export default class ....

Khur.beforeInit

Do execute each feature before starting the Bot. This must be run before Khur.config(...)

Khur.beforeInit(async (): Promise<void> => {
  console.log('{beforeInit} -> Hi!');
})

Khur.config

Register each setting to start the client and internal components:

Khur.config(<KhurConfig>)

Interface: KhurConfig

Property | type | Description --- | --- | --- appRoot | string | Main directory of the project bot | BotCredentials | Credentials of your application. See Discord Developers bot.client.id | string | Client ID bot.client.secret | string | Client Secret bot.token | string | Bot Token defaultPrefix | string | Bot prefix discordClient | Client | Client instance i18n | | Translation config | i18n.globalTranslationsPath | string | Path to global translations folder i18n.supported | Array | Languages supported onReady?(client: Client) | Promise | Callback. Bot is ready

Register.event

To register an event. See the documentation (Client) to know about the list of available events.

Register.event(<event>, 'PATH_TO_EVENT_FILE');

Register.group

To group the record of commands.

Register.group(<RegisterGroupParams>, callback: (params: RegisterGroupParams) => void);

Interface: RegisterGroupParams

Property | Type | Description --- | --- | --- prefix? | string | Prefix (any context) [key: string] | any | Custom value

Register.group({
  prefix: '@app-command/Information',
}, (params: RegisterGroupParams): void => {
  Register.command(`${params.prefix}/Help`, {
    category: 'Information',
    names: ['help', 'h'],
  });

  Register.command(`${params.prefix}/Support`, {
    category: 'Information',
    names: ['support'],
  });
});

Register.command

Register command. The properties of these settings can be accessed through the middlewares (including the command) to add validations.

Register.command('PATH_TO_COMMAND_FOLDER', <CommandConfig>);

Interface: CommandConfig

Property | Type | Description --- | --- | --- allowDynamicAliases? | boolean | Allow dynamic alias middlewares? | Array | Middleware to use names | Array | required Aliases [key: string] | any | Custom value

// Using alias (directory)
Register.command('@app-command/Sample', {
  allowDynamicAliases: true,
  category: 'Test',
  cooldown: 5, // Seconds
  middlewares: [OnlyGuild], // Details below
  names: ['sample', 'non'], // Two aliases
  nsfw: {
    current: true, // This command has NSFW content
  },
});

Note: Dynamic aliases are detected with after the ":" or "-" character, for example: name:dynamicalias, name:non, name-dynamicalias, name-non, etc.

  • If allowDynamicAliases = true the aliases should coincide with sample:dynamic, sample:bye, non:sample, non:test, sample-dynamic, sample-bye.
  • Middleware OnlyGuild indicates that the command could be executed if it is in a server.

CommandHandler.init

Use the command handler.

await CommandHandler.init(<EventMessage>, <CommandHandlerConfig>);

Interface: CommandHandlerConfig

Property | Type | Description --- | --- | --- currentTranslation? | string | Key of current translation (es, en, es-ES, en-US, etc) middlewares? | Array | Middlewares to evaluate before command prefix | string | required Current prefix or custom by Guild

try {
  await CommandHandler.init(message, {
    // currentTranslation: 'en', // Or dynamic (by database)
    prefix: Khur.getDefaultPrefix(), // Or dynamic (by database)
    // middlewares: [],
  });
} catch (error) {
  console.error(error);
}

Credits

This project generate a build using TSDX a zero-config CLI for TypeScript package development.