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

@discordx/utilities

v7.0.3

Published

Utilities package for enhancing discordx functionality

Downloads

1,262

Readme

Content

📖 Introduction

Add useful features to discordx, If a feature isn't available, request it.

💻 Installation

Version 16.6.0 or newer of Node.js is required

npm install @discordx/utilities
yarn add @discordx/utilities

📟 @Category

Create group of commands

Example

@Discord()
@Category("Admin Commands")
class Example {
  // commands

  @Slash({ name: "my-command" })
  myCommand(interaction: CommandInteraction) {
    //....
  }
}
// Access data from anywhere
MetadataStorage.instance.applicationCommands.forEach(
  (cmd: DApplicationCommand & ICategory) => {
    if (cmd.category === "Admin Commands") {
      // access
    }
  },
);

📟 @Description

The description property can be set using this decorator

Example

@Discord()
class Example {
  @Slash({ name: "hello" })
  @Description("say hello to bot")
  handle(interaction: CommandInteraction) {
    //....
  }
}

Is equivalent to:

@Discord()
class Example {
  @Slash({ description: "say hello to bot", name: "hello" })
  handle(interaction: CommandInteraction) {
    //....
  }
}

⚔️ guards

Useful guards created by the discordx team to use in your bot!

IsGuildUser

A multi purpose guard for guild and user.

Example

import { IsGuardUserCallback, IsGuildUser } from "@discordx/utilities";
import { Events } from "discord.js";
import {
  ArgsOf,
  Discord,
  Guard,
  On,
  SimpleCommand,
  SimpleCommandMessage,
} from "discordx";

const OwnerOnly: IsGuardUserCallback = ({ client, user }) => {
  if (!user) {
    return false;
  }

  return client.application?.owner?.id === user.id;
};

@Discord()
@Guard(IsGuildUser(OwnerOnly))
class Example {
  @On({ event: Events.MessageCreate })
  message([message]: ArgsOf<"messageCreate">) {
    //...
  }

  @SimpleCommand({ name: "hello" })
  hello(command: SimpleCommandMessage) {
    //...
  }
}

NotBot

Ensure that the handler is only executed for users and not for bots.

Example

import { NotBot } from "@discordx/utilities";
import { Events } from "discord.js";
import {
  ArgsOf,
  Discord,
  Guard,
  On,
  SimpleCommand,
  SimpleCommandMessage,
} from "discordx";

@Discord()
@Guard(NotBot)
class Example {
  @On({ event: Events.MessageCreate })
  message([message]: ArgsOf<"messageCreate">) {
    //...
  }

  @SimpleCommand({ name: "hello" })
  hello(command: SimpleCommandMessage) {
    //...
  }
}

This will work on both Slash and Simple commands

PermissionGuard

When you are using global commands, but still wish to restrict commands to permissions from roles, then you can use this guard to easily supply an array of Permissions that a user must have in order to execute the command.

The guard can take an array of permissions or an async resolver to the permission array

Example

@Discord()
export class PermissionGuards {
  /**
   * Only allow users with the role "BAN_MEMBERS"
   *
   * @param interaction
   */
  @Slash({ name: "permission_ban_members" })
  @Guard(PermissionGuard(["BAN_MEMBERS"]))
  banMembers1(interaction: CommandInteraction): void {
    interaction.reply("It worked!");
  }

  /**
   * Only allow users with the role "BAN_MEMBERS" with a custom message
   *
   * @param interaction
   */
  @Slash({ name: "permission_ban_members" })
  @Guard(
    PermissionGuard(["BAN_MEMBERS"], {
      content: "You do not have the role `BAN_MEMBERS`",
    }),
  )
  banMembers2(interaction: CommandInteraction): void {
    interaction.reply("It worked!");
  }

  /**
   * get the permissions from an async resolver
   *
   * @param interaction
   */
  @Slash({ name: "permission_ban_members" })
  @Guard(
    PermissionGuard(PermissionGuards.resolvePermission, {
      content: "You do not have the role `BAN_MEMBERS`",
    }),
  )
  banMembers3(interaction: CommandInteraction): void {
    interaction.reply("It worked!");
  }

  private static resolvePermission(
    interaction: PermissionHandler,
  ): Promise<PermissionString[]> {
    if (interaction instanceof CommandInteraction) {
      // if guild id is 123
      if (interaction.guildId === "123") {
        return Promise.resolve(["ADD_REACTIONS"]);
      }
    }
    return Promise.resolve(["BAN_MEMBERS"]);
  }
}

Rate limit

This guard will rate limit a user for a specified amount of time. When set, a user can only call a command x amount of times after that, a cooldown is applied disallowing any more calls to the command until the cooldown is over.

This cooldown starts from the moment the user sends the last message.

If your cooldown is 10 seconds, and you allow 3 calls of your command, the user will have 10 seconds to call it 3 times, with the timer resetting after each call.

Example

@Discord()
class RateLimitExample {
  /**
   * 1 command every 30 seconds with default message
   */
  @Slash({ name: "rate_limit_1" })
  @Guard(RateLimit(TIME_UNIT.seconds, 30))
  rateLimit1(interaction: CommandInteraction): void {
    interaction.reply("It worked!");
  }

  /**
   * Allow 3 command before rate limit of 30 seconds (from last message)
   */
  @Slash({ name: "rate_limit_2" })
  @Guard(
    RateLimit(TIME_UNIT.seconds, 30, {
      message: "Please wait `30` seconds!",
      rateValue: 3,
    }),
  )
  rateLimit2(interaction: CommandInteraction): void {
    interaction.reply("It worked!");
  }

  /**
   * Rate limit simple command
   *
   * @param message
   */
  @SimpleCommand({ name: "rateLimit" })
  @Guard(RateLimit(TIME_UNIT.seconds, 10))
  private async rateLimitSimpleCommand({
    message,
  }: SimpleCommandMessage): Promise<void> {
    message.reply("It worked!");
  }
}

🧰 Useful

Here are some helpful functions for accelerating your development.

EnumChoice

enum RPS {
  Rock = "0",
  Paper = "1",
  scissors = "2",
}

@SlashChoice(...EnumChoice(RPS))

TimeFormat

Discord Timestamps

Discord timestamps can be useful for specifying a date/time across multiple users time zones. They work with the Unix Timestamp format and can be posted by regular users as well as bots and applications.

The Epoch Unix Time Stamp Converter is a good way to quickly generate a timestamp. For the examples below I will be using the Time Stamp of 1543392060, which represents November 28th, 2018 at 09:01:00 hours for my local time zone (GMT+0100 Central European Standard Time).

Formatting

| Syntax | Output | Output (12-hour clock) | Output (24-hour clock) | | ----------------------------- | ------------------ | ------------------------------------ | --------------------------------- | | TimeFormat.Default | <t:1543392060> | November 28, 2018 9:01 AM | 28 November 2018 09:01 | | TimeFormat.ShortTime | <t:1543392060:t> | 9:01 AM | 09:01 | | TimeFormat.LongTime | <t:1543392060:T> | 9:01:00 AM | 09:01:00 | | TimeFormat.ShortDate | <t:1543392060:d> | 11/28/2018 | 28/11/2018 | | TimeFormat.LongDate | <t:1543392060:D> | November 28, 2018 | 28 November 2018 | | TimeFormat.ShortDateTime | <t:1543392060:f> | November 28, 2018 9:01 AM | 28 November 2018 09:01 | | TimeFormat.LongDateTime | <t:1543392060:F> | Wednesday, November 28, 2018 9:01 AM | Wednesday, 28 November 2018 09:01 | | TimeFormat.RelativeTime | <t:1543392060:R> | 3 years ago | 3 years ago | | TimeFormat.StaticRelativeTime | 3 years ago | 3 years ago | 3 years ago |

Whether your output is 12-hour or 24-hour depends on your Discord language setting. For example, if you have your Discord language set to English, US 🇺🇸, you will get a 12-hour output. If your Discord language is set to English, UK 🇬🇧, you will get a 24-hour output.

Source: https://gist.github.com/LeviSnoot/d9147767abeef2f770e9ddcd91eb85aa

Example

import { dayjs, TimeFormat } from "@discordx/utilities";

const message = `I will be there in ${TimeFormat.StaticRelativeTime("31/12/2025", false)}`;
const message = `I will be there by ${TimeFormat.LongDate(
  dayjs({
    day: 31,
    month: 12,
    year: 2025,
  }),
  false,
)}`;

📜 Documentation

☎️ Need help?

💖 Thank you

You can support discordx by giving it a GitHub star.