0.5.3 • Published 8 months ago

breezer.js v0.5.3

Weekly downloads
-
License
ISC
Repository
-
Last release
8 months ago

BREEZER JS

An elegant framework for discord.js :)

Still under development (v0), only msgCreate is supported for now...

Features:

  • Typescript support
  • Simple and intuitive
  • State management more coming soon

Getting Started

Installation

npm i breezer.js
npm i discord.js@v13

Project setup

MyBot:
 --index.js
 --commands:
    --ping.js
    --calc.js
    --mul.js

A Basic Example

index.js :

import { Bot } from 'breezer.js'

const bot = new Bot({
    token: "<BOT_TOKEN>",
    prefix: "+",
    commandsFolder: "commands",
    // intents: []
});

bot.go(() => console.log('Logged In'));

It is as easy as its looks. commandsFolder folder is where all your commands will be stored. Everything else looks quite easy to follow up. Fill up some details and you're ready to go() !

Note: There is also an optional property to have custom intents (Breezer automatically sets the most common ones by default).

commands/ping.js :

import { Command } from 'breezer.js'

export default class extends Command<[]> {
    constructor() {
        super({
            structure: [],
            name: 'ping', // same as the file name
            strict: true // optional (def:false)
        });
    }

    async execute() {
        this.msg.reply({
            content: 'Pong!',
            allowedMentions: {
                repliedUser: false
            }
        });
    }
}

Every command is a class, child of the Command class. Generic of class Command<[]>: Defines the type of the structure of your cmd. - helps in inferring the types of different fields returned by this.extract() (explained later) structure - defines a structure for your command. Helpful when extracting the fields of you commands. This property will be better understood in the next command. Here there are no fields for this cmd => no structure.

*Reason why we define the structure twice is because, Generic helps in inferring the type properly and the property structure helps in actual conversion of field (say to number) and raising errors in strict mode.

strict - set it to true if you want to recieve errors/warnings when:

  • user does not follow the defined structure of the cmd
  • a deleted msg listens for certain state(s)
  • an expired msg listens for state(s).

This feature should only be turned on during development.

name - optional: will help in debugging in strict mode execute - logics for your command will be defined here.

commands/calc.js:

import { Command } from 'breezer.js'

export default class extends Command<[string]> {
    constructor() {
        super({
            structure: ['string'],
            name: 'calc'
        });
    }

    async execute() {
        // operation: string
        const [operation] = this.extract();
        let value;
        try {
            value = eval(operation);
        } catch (_) {
            value = 'Invalid Operation'
        }

        this.msg.channel.send(value.toString());
    }
}

Here structure has string as its first and only option. Now the user can easily extract the first option using this.extract.

Context: This string will be an expression 1*3 Warning: Never use eval like this, who knows what the operation is.

Structure can have these values:

"string", "string|null", "number", "number|null"

The nullable properties keep you safe in strict mode and while extracting.

Example of a structure:

["string", "number", "number", "string|null"]

Here a command will accept 4 options. If a user does not follow this structure in strict mode, it'll raise an error and you bot will stop. You can also easily extract these options:

// inside execute()
const [opt1, opt2, opt3, opt4] = this.extract();

NOTE: There can be only one nullable option, that too at the end.

commands/mul.js:

import { Command, StateManager } from 'breezer.js';
import { MessageEmbed } from 'discord.js';

const state = new StateManager({
    count: 1
});
export default class extends Command<[number]> {
    constructor() {
        super({
            name: 'mul',
            structure: ["number"],
            states: state.clone(),
            strict: true,
            till: 1
        });
    }
    async execute() {
        // by: number
        const [by] = this.extract();

        await this.send({
            embeds: [
                new MessageEmbed({
                    title: `${by} x $count$ = << ${by} * $count$ >>`
                })
            ]
        });
        
        setInterval(() => {
            this.states.set('count', p => p + 1);
        }, 1000);
    }
}

States are special values that when referred in message payload in a special way as string, update their reference in the original message as their value change.

We mention them inside strings using the $ reference, like this: $statename$.

We can also do operations on states, only when they lie inside << ... >>

// js methods
{
  content: "Answer is: << ['first', 'third'].includes('$answer$') >>"
}
// ternary operations
{
  content: "Count is: << $count$ > 5 : 'Big' :'Small' >>"
}
// arithmetic operations
{
  content: "Answer = << $num1$ + (($num2$ - 3) * 5)/10 >>"
  // yes, you can have 2 state in an operation!
}

Inside the constructor: states: this will be the instance of class StateManager. You can clone it to it independent or you can just refer the original object. till: msg listen to its state(s) for a certain time, define that time in minutes in this property. (default: 15min). Or set it to forever, it will always listen for the state(s).

This is what that example cmd (mul) looks in action:

state

HANDLERS

These are some extra functions available in the library to make stuff easier.

buttonSignal()

This handler is a syntactic-sugar for createMessageComponentCollector. This can be used in situations when one wants to collect button interactions when some specific users click the button.

import { buttonSignal } from 'breezer.js'

// inisde execute()
const sentMsg = this.msg.reply({
    components: [row]
});

buttonSignal(
    ['userid1', 'userid2'], // users
    sentMsg, // msg
    { max: 3, time: 2000 } // props (opt)

).on('collect', async btn => {
    await btn.deferUpdate();
    ...
}).on('end', async collection => {
    ...
});

/** 
 This signal will listen for 
    * max 3 clicks, for
    * 2 seconds, from
    * user with id 1 and 2 only, on
    * every button in the "row"
 */

So buttonSignal accepts 3 arguments

  • users: array containing the user id who can click the button (empty-array: anyone click the button)
  • msg: the message that contains the buttons
  • props: an optional parameter specifying these 3 properties-
    • customId: the only button from the row that you'll listen to (its id)
    • max: maximum valid clicks
    • time: the time interval (in ms) for which the button will be valid and clicks will matter

This function returns the normal discord's interaction listener listening for collect and end.

HasPerm Methods

A method and a function to check if the bot or any user has certain perm in the channel linked to a cmd's msg.

Inside a Command class (checks only for the bot)

this.botHasPerm( perm: PermissionResolvable ): boolean

Anywhere (checks for any user)

import { userHasPerm } from 'breezer.js';
userHasPerm( perm, userId: string, msg: Message ): Promise<boolean>
0.4.9

8 months ago

0.4.8

10 months ago

0.4.5

10 months ago

0.5.3

8 months ago

0.4.4

10 months ago

0.4.7

10 months ago

0.4.6

10 months ago

0.5.0

8 months ago

0.5.2

8 months ago

0.5.1

8 months ago

0.4.3

11 months ago

0.4.2

11 months ago

0.4.1

11 months ago

0.4.0

11 months ago

0.3.7

12 months ago

0.3.6

1 year ago

0.3.5

1 year ago

0.3.1

1 year ago

0.3.4

1 year ago

0.3.3

1 year ago

0.3.0

1 year ago

0.2.7

1 year ago

0.2.6

1 year ago

0.2.5

1 year ago

0.2.4

1 year ago

0.2.3

1 year ago

0.2.2

1 year ago

0.2.1

1 year ago

0.2.0

1 year ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago