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

crystalapi.js

v1.0.0

Published

Official Discord API driver for Crystal Moderation.

Downloads

3

Readme

discord.js-light v3

All the power of discord.js, zero caching.

This library modifies discord.js's internal classes and functions in order to give you full control over its caching behaviour. Say goodbye to exorbitant memory usage!

npm GitHub Release Date npm (prod) dependency version node Discord

Why?

Discord.js has been THE javascript discord library for a long time now, and successfully powers thousands of bots, but as your bot grows larger, you will notice a substantial increase in resource usage, especially in memory consumption.

This is because discord.js caches as much as it can in order to avoid hitting the Discord API as well as to better provide many of its features. This can however make your bots feel bloated because the library is caching and processing data that your bot will likely never use.

This library solves the problem by giving developers full control over how and when discord.js should cache the data it receives from the API.

The Impact of Caching

Caching is the process of keeping a copy of something in memory. Most Discord libraries will keep data received from Discord in memory for any eventual needs. Caching Discord data gives you access to features such as looping through channels, finding something by name or by anything other than an ID, keeping a backup of old data accessible to update and delete events, perform permission checking and so on. Caching is very useful and makes a lot of features possible, but at a cost...

The following test is a ~3 hour run (each tick is 10 minutes), with ~3700 guilds total (4 internal shards), with all intents enabled (including presences), and with message caching disabled (messageCacheMaxSize:0). This test measures caching overhead by periodically checking process.memoryUsage().heapUsed in MB. Your actual memory usage still depends on your code and the node.js overhead so it will likely be higher.

The Impact of Caching

As you can see, excessive caching can be very costly in terms of memory requirements, especially at scale. By disabling all major caches we were able to reduce memory usage from ~500mb to less than 20mb. Unfortunately neither discord.js nor eris, the two most popular javascript libraries, provide a way to control or disable parts of their caching systems. The ability to selectively disable caches that your bot doesn't need can greatly reduce resource usage, so much that it becomes invaluable at scale.

More and more projects are being developed with such flexibility in mind, such as @klasa/core and detritus, and this library brings this much needed caching flexibility to discord.js with as little side effects as possible.

Features

  • Provides all of discord.js's events without any kind of automated caching
  • Most structures remain intact so your existing discord.js code should work without many changes
  • Custom partials system ensures events are always emitted regardless of caching state
  • Fully functional partials are given when the required data is not cached
  • Most things can be manually fetched and/or cached when needed
  • Drastically lower resource usage at scale

Usage

Installation

npm install discord.js-light

Optional packages (recommended to reduce bandwidth usage and improve websocket performance). These packages are plug and play, just install and they will be picked up automatically.

npm install zlib-sync
npm install bufferutil
npm install discord/erlpack
npm install utf-8-validate

Additionally, using an alternative memory allocator such as jemalloc can further reduce memory usage by avoiding fragmentation in exchange for slightly higher cpu usage.

Usage example

const Discord = require("discord.js-light");
const client = new Discord.Client({
    cacheGuilds: true,
    cacheChannels: false,
    cacheOverwrites: false,
    cacheRoles: false,
    cacheEmojis: false,
    cachePresences: false
});

client.on("ready", () => {
    console.log("client ready");
});

client.on("message", message => {
    if(message.content === "?!ping") {
        message.reply("pong");
    }
});

client.login("TOKEN").catch(console.error);

Generally, usage should be identical to discord.js and you can safely refer to its documentation as long as you respect the caching differences explained below.

Client Options

The following client options are available to control caching behavior:

| Option | Type | Default | Description | | ------------- | ------------- | ------------- | ------------- | | cacheGuilds | boolean | true | Enables caching of all Guilds at login | | cacheChannels | boolean | false | Enables caching of all Channels at login | | cacheOverwrites | boolean | false | Enables PermissionOverwrites in cached and fetched channels | | cacheRoles | boolean | false | Enables caching of all Roles at login | | cacheEmojis | boolean | false | Enables caching of all Emojis at login | | cachePresences | boolean | false | Enables caching of all Presences. If not enabled, Presences will be cached only for cached Users | | disabledEvents | array | [] | An array of Discord events to ignore. Use this in combination with intents for fine tuning of which events your bot should process |

This library implements its own partials system, therefore the partials client option is not available. All other discord.js client options continue to be available and should work normally.

Caching Behavior

Below is a quick summary and explanation on caches:

Guilds

This cache has a very low memory footprint and provides lots of useful information that most bots will want to use at some point. If disabled, the library will give up control of guilds and instead emit guildCreate events as per the Discord API, including the initial GUILD_CREATE packets as well as when guilds come back from being unavailable. This is so that you can implement your own guild tracking and/or caching. Guilds can also be fetched when needed but some properties may not be available this way.

Channels

Channels have a pretty large impact on memory usage and most common bot features should work normally without them. You only need this cache if you track channel updates or if you want to find channels by anything other than an ID, and even then there might be more efficient solutions. Channels can always be fetched when needed.

Overwrites

PermissionOverwrites may have a moderate impact on memory usage when channels are cached, and are required for checking permissions on specific channels. Enabling this cache without enabling cacheChannels will eliminate its memory footprint but requires you to cache or fetch the channel before being able to check permissions on it. PermissionOverwrites are included when fetching channels if the withOverwrites option is enabled.

Roles

Roles may have a moderate memory footprint but are required for general permission checking. You can still access Member Roles without enabling this cache, but they will be partials instead, which only contain an ID and nothing else. Roles can also be fetched when needed.

Emojis

Emojis usually have a low memory footprint but are only really needed if you want to list emojis often, find emojis by name or keep track of emoji updates, otherwise they can always be fetched when needed.

Presences

Presences have a large impact on memory usage and are not needed most of the time. Presences are only cached if the User they belong to is cached but enabling this cache will enable caching of all Presences, including those belonging to uncached Users and Members. You only need this if you want to track people's statuses and activities in real time. Presences are included when fetching members if the withPresences option is enabled. Presences require the GUILD_PRESENCES intent.

Users and Members

Besides the bot user, all other Users and Members are never automatically cached. Having an incomplete user cache is not very useful most of the time, so we prefer an all-or-nothing approach. The fetchAllMembers client option can be used to cache all Users and Members, otherwise they must be manually fetched if required. Events that include some User and/or Member data usually do not require fetching as the event itself already contains enough information to provide a complete User and/or Member object.

VoiceStates

Voice States will be cached if the GUILD_VOICE_STATES intent is enabled (required for voice features to work), otherwise they will not be cached.

Messages

Messages are cached only if the Channel they belong to is cached. Message caching can further be controlled via discord.js's messageCacheMaxSize, messageCacheLifetime and messageSweepInterval client options as usual. Additionally, the messageEditHistoryMaxSize client option is set to 1 by default (instead of infinity).

Events

Most events should be identical to the originals aside from the caching behavior plus they always emit regardless of caching state. When required data is missing, a partial structure where only an id is guaranteed will be given (the .partial property is not guaranteed to exist on all partials).

Events that emit past versions of a structure, such as update and delete events, will emit either null or partial if not cached instead of not being emitted at all.

| Event | Emits | Notes | | ------------- | ------------- | ------------- | | message | Message | Includes some User and Member data | | messageUpdate | Message?, Message | Old Message is NULL if not cached. New Message includes some User and Member data | | messageDelete | Message | Partial Message if not cached | | messageDeleteBulk | Collection | Collection of deleted Messages or Partial Messages as above | | messageReactionAdd | Reaction, User | Includes some User and Member data (partial if DMs) | | messageReactionRemove | Reaction, User | Partial User if not cached | | messageReactionRemoveAll | Message | Partial Message if not cached | | messageReactionRemoveEmoji | Reaction | - | | channelCreate | Channel | - | | channelUpdate | Channel?, Channel | Old Channel is NULL if not cached | | channelDelete | Channel | - | | channelPinsUpdate | Channel, Date | Partial Channel if not cached | | roleCreate | Role | - | | roleUpdate | Role?, Role | Old Role is NULL if not cached | | roleDelete | Role | Partial Role if not cached | | inviteCreate | Invite | Includes some User data | | inviteDelete | Invite | - | | emojiCreate | Emoji | Only emits if Emojis are cached | | emojiUpdate | Emoji, Emoji | Only emits if Emojis are cached | | emojiDelete | Emoji | Only emits if Emojis are cached | | guildEmojisUpdate | Collection | Non-standard event. Emitted instead of Emoji events when Emojis are not cached. Provides a Collection of updated Emojis | | guildBanAdd | Guild, User | Partial Guild if not cached | | guildBanRemove | Guild, User | Partial Guild if not cached | | guildCreate | Guild | Does not include disabled data | | guildUpdate | Guild?, Guild | Old Guild is NULL if not cached | | guildDelete | Guild | Partial Guild if not cached | | guildUnavailable | Guild | Partial Guild if not cached | | guildMemberAdd | Member | Includes some User data | | guildMemberUpdate | Member?, Member | Old Member is NULL if not cached. new Member includes some User data | | guildMemberRemove | Member | Partial Member if not cached | | guildIntegrationsUpdate | Guild | Partial Guild if not cached | | presenceUpdate | Presence?, Presence | Old Presence is NULL if not cached. New Presence includes some Member data | | typingStart | Channel, User | Partial Channel. Includes some User and Member data (partial if DMs) | | userUpdate | User?, User | Old User is NULL if not cached | | voiceStateUpdate | VoiceState?, VoiceState? | NULL when data does not include a Channel ID (indicates disconnection). Includes some User and Member data | | webhookUpdate | Channel | Partial Channel if not cached | | shardConnect | Number, Collection | Non-standard event. Emitted when a shard connects to Discord. Provides a Shard ID and a Collection of Partial Guilds assigned to this shard | | rest | Object | Non-standard event. Emitted when the library makes an API request to Discord. Provides an object containing the request method, path and optionally a response buffer (buffer is only included if the client option restEventIncludeBuffer is set to true) |

Events that include some User and/or Member data will contain full or mostly full User and/or Member objects even if not cached, for example message.author will always contain a full User object, including most of its properties, even if said user is not cached.

Structures not marked as partial only guarantee the contents of its top-level properties. Linked structures such as message.channel or reaction.message may still be partials if not previously cached or fetched. This is especially true for Guild objects, which do not include Roles, Emojis, Channels, Members, Presences or VoiceStates unless previously cached, fetched, enabled or other conditions met.

Events not listed above should continue to work normally as per the discord.js documentation.

Fetch Methods

Fetch methods are used to obtain data from the Discord API when needed and optionally cached for reuse. Once data is cached, it will remain in the cache until manually removed. Cached data will be automatically updated as new Discord events are received.

Some fetch methods are already included by default in discord.js, others were added or tweaked as below:

client.channels.fetch()

.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (Channel)

Fetches a single channel from the /channels/:id endpoint. This method is identical to the original except that it includes an additional withOverwrites option.

  • id or options.id (string) - id of the channel to fetch.
  • cache or options.cache (boolean) - whether to cache the result if not cached. defaults to true.
  • options.withOverwrites (boolean) - whether to include permissionOverwrites. always true if cacheOverwrites is enabled. defaults to false.
  • options.force (boolean) - whether to force fetch the channel from the api even if its already cached. defaults to false.

client.guilds.fetch()

.fetch()
.fetch(cache)
.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (Guild | Collection of Guilds)

Fetches a single guild from the /guilds/:id endpoint, or multiple guilds from the /users/@me/guilds endpoint. When fetching multiple guilds, some guild information may be stripped away by Discord. Additionally fetching multiple guilds is extremely slow, taking roughly 20 seconds per 1000 guilds. If you need to fetch thousands of guilds, it's much faster to create a new connection to the gateway. Fetching multiple guilds also bypasses the guild cache, whereas fetching a specific guild id will always check the cache first.

  • id or options.id (string) - id of the guild to fetch. if not provided, fetches all guilds instead.
  • cache or options.cache (boolean) - whether to cache the results. defaults to true.
  • options.limit (number) - max amount of results (0 for no limit). defaults to 0.
  • options.before (string) - a guild id to search only guilds with a smaller id (0 for any). defaults to 0.
  • options.after (string) - a guild id to search only guilds with a bigger id (0 for any). defaults to 0.
  • options.force (boolean) - whether to force fetch the guild from the api even if already cached. defaults to false.

guild.channels.fetch()

.fetch()
.fetch(cache)
.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (Channel | Collection of Channels)

Fetches channels from the /guilds/:id/channels endpoint. This endpoint bypasses the VIEW_CHANNEL permission. Fetching all channels also bypasses the channel cache, whereas fetching a specific channel id always checks the cache first.

  • id or options.id (string) - id of the channel to fetch. if not provided, fetches all guild channels instead.
  • cache or options.cache (boolean) - whether to cache the results. defaults to true.
  • options.withOverwrites (boolean) - whether to include permissionOverwrites. always true if cacheOverwrites is enabled. defaults to false.
  • options.force (boolean) - whether to force fetch the channel from the api even if its already cached. defaults to false.

guild.members.fetch()

.fetch()
.fetch(cache)
.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (GuildMember | Collection of GuildMembers)

Fetches guild members from the gateway or from the /guilds/:id/members endpoint. This method is identical to the original but includes a few additional options.

  • id or options.user (string) - id of the member to fetch. if not provided, fetches all guild members instead.
  • id or options.user (array) - array of member ids to fetch (gateway only, requires the GUILD_MEMBERS intent).
  • cache or options.cache (boolean) - whether to cache all results. defaults to true.
  • options.rest (boolean) - whether to use the rest endpoint instead of the gateway. defaults to true when fetching a single id, otherwise defaults to false.
  • options.query (string) - query to search for members by username (gateway only). set to "" for all members (setting to "" requires the GUILD_MEMBERS intent). defaults to "";
  • options.limit (number) - max amount of results (0 for no limit. setting to 0 requires the GUILD_MEMBERS intent). defaults to 0.
  • options.after (string) - a user id to search only users with a bigger id (rest only).
  • options.withPresences (boolean) - whether to include presence data (gateway only, requires the GUILD_PRESENCES intent). this option also requires the cachePresences client option to be enabled, or that the cache option is enabled, or that the relevant users are already cached.
  • options.time (number) - max amount of time to wait for a response in milliseconds (gateway only). defaults to 60000.
  • options.force (boolean) - whether to force fetch members even if already cached. defaults to false.

guild.emojis.fetch()

.fetch()
.fetch(cache)
.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (Emoji | Collection of Emojis)

Fetches guild emojis from the /guilds/:id/emojis endpoint.

  • id or options.id (string) - the id of the emoji to fetch. if not provided, fetches all guild emojis instead.
  • cache or cache.id (boolean) - whether to cache the results. defaults to true.
  • options.force (boolean) - whether to force fetch the emoji even if already cached. defaults to false.

guild.roles.fetch()

.fetch()
.fetch(cache)
.fetch(id)
.fetch(id,cache)
.fetch(id,options)
.fetch(options)

returns - Promise (Role | Collection of Roles)

Fetches guild roles from the /guilds/:id/roles endpoint.

  • id or options.id (string) - the id of the role to fetch. if not provided, fetches all guild roles instead.
  • cache or options.cache (boolean) - whether to cache the results. defaults to true
  • options.force (boolean) - whether to force fetch the role even if already cached. defaults to false.

reaction.users.fetch()

.fetch(options)

returns - Promise (Collection of Users)

Fetches users from the /channels/:id/messages/:id/reactions/:emoji. This endpoint is identical to the original except that it includes a cache option.

  • options.limit (number) - max amount of results (0 for no limit). defaults to 0.
  • options.before (string) - a user id to search only users with a smaller id (0 for any). defaults to 0.
  • options.after (string) - a user id to search only users with a bigger id (0 for any). defaults to 0.
  • options.cache (boolean) - whether to cache the results. defaults to true.

Forge Methods

Forge methods are a set of non-standard methods used to interact with the Discord API without requiring a cache. They provide a way to create Partial instances on demand, which is especially useful when sharding. For example, sending a message to a specific channel ID:

// fetch method, requires an API round trip if channel is not available
let channel = await client.channels.fetch(id, false);
await channel.send("message");

// using broadcastEval if channel is available in another shard
await client.broadcastEval(`
    let channel = client.channels.cache.get("${id}");
    if(channel) { channel.send("message"); }
`);

// forge method, works from any shard and regardless of caching
await client.channels.forge(id).send("message");

Forge methods avoid unnecessary round trips and give you access to all the api methods of each class, however there isn't any form of data validation, it's up to you to provide valid IDs.

The following forge methods are available:

client.users.forge(id)

Creates a User instance from a user ID.

client.guilds.forge(id)

Creates a Guild instance from a guild ID.

client.channels.forge(id,type)

Creates a Channel instance from a channel ID and channel type. Defaults to DMChannel.

guild.channels.forge(id,type)

Creates a Channel instance from a channel ID and channel type. Defaults to TextChannel.

guild.members.forge(id)

Creates a GuildMember instance from a user ID and the current guild.

guild.emojis.forge(id)

Creates an Emoji instance from an emoji ID.

guild.roles.forge(id)

Creates a Role instance from a role ID.

guild.presences.forge(id)

Creates a Presence instance from a user ID.

channel.messages.forge(id)

Creates a Message instance from a message ID.

message.reactions.forge(emoji or id)

Creates a MessageReaction instance from an emoji id or emoji unicode and the current message.

Sweep Methods

This library includes two additional utility methods to help with manual cache control. Furthermore all discord.js Collections include .sweep() and .clear() methods which can be used to manually clear caches.

client.sweepUsers()

client.sweepUsers(lifetime)

returns - Void

Sweeps all cached Users and Members whose last message is older than the supplied time.

  • lifetime (number) - User's last message's age in seconds. Defaults to 86400 (24 hours).

client.sweepChannels()

client.sweepChannels(lifetime)

returns - Void

Sweeps all cached Channels whose last message is older than the supplied time.

  • lifetime (number) - Channel's last message's age in seconds. Defaults to 86400 (24 hours).

Notes

This project has come a long way and gone through a lot of testing, however it is still somewhat experimental. There might be silly bugs or broken features in untested scenarios. You are encouraged to make your own tests with your specific use cases and post any issues, questions, suggestions, feature requests or contributions you may find.

You can also find me in discord (Tim#2373)

Bots using discord.js-light

Astrobot

Message Viewer

Helper

Art Prompts

Xeno

Tamaki

Animal Bot

Denky

Game Tracker

D-Safe

Aeon

Filo

T_Moderator_Bot

T_Music_Bot

CalcBot

Infinity

Scathach

Music Boat

Melody

Hydra bot

Multipurpose+

CleverChat

Dio

(using discord.js-light? let me know if you're interested in having your bot listed here)