A wheels-attached, pure-TypeScript library for the Discord API.
Detritus is distributed via npm. A high-level wrapper over the Discord API is provided
in this package, detritus-client. Low-level wrappers over Discord's REST API and Gateway
are provided through detritus-client-rest and
detritus-client-socket.
$ npm i detritus-client$ yarn add detritus-client
Detritus is operated through the Clients classes:
ShardClientprovides a base client for connecting to the Discord API and receiving events.ClusterClientprovides a client that createsShardClientclasses inside of it for easier shardingCommandClientwraps over theClusterClientorShardClientto provide support for bot commands.InteractionCommandClientwraps over theClusterClientorShardClientto provide support for interaction commands.ClusterManagerprovides a manager that'll spawn in multipleClusterClientprocesses for big shardings
More Examples are provided under the examples/
directory.
const { CommandClient } = require('detritus-client'); // Note: it is not advised to hard-code your bot token directly into the bot source. // // Tokens should be considered secrets and stored in a configuration file that is not // part of your version control system, or an environment variable. // By default, the CommandClient will use the ClusterClient // The ShardClient/ClusterClient will be under CommandClient.client as soon as you create the object const token = ''; const commandClient = new CommandClient(token, { // Prefix `..`, if you want multiple prefixes pass in `prefixes: ['..', '...']` prefix: '..', }); // Simple ping/pong command commandClient.add({ // name describes the command trigger; in this case, ..ping name: 'ping', run: (context, args) => { // Commands should return a promise to ensure that errors are handled return context.reply('pong!'); }, }); // Command demonstrating command pipelines commandClient.add({ name: 'owner', // onBefore should return a boolean to indicate whether or not the command should proceed onBefore: (context) => context.client.isOwner(context.userId), onCancel: (context) => context.reply('This command is only available to the bot owner.'), run: async (context) => { // Commands may also run asynchronously. await context.reply('You are the owner of the bot!'); }, }); // Spawn the client in an async context // // Note: Due to how Node handles tasks, the script will block until the Detritus client // is killed. (async () => { const client = await commandClient.run(); console.log(`Client has loaded with a shard count of ${client.shardCount}`); })();
const { Constants, InteractionCommandClient } = require('detritus-client'); const { ApplicationCommandTypes, InteractionCallbackTypes, MessageFlags } = Constants; // Note: it is not advised to hard-code your bot token directly into the bot source. // // Tokens should be considered secrets and stored in a configuration file that is not // part of your version control system, or an environment variable. // By default, the InteractionCommandClient will use the ClusterClient // The ShardClient/ClusterClient will be under InteractionCommandClient.client as soon as you create the object const token = ''; const interactionClient = new InteractionCommandClient(token); // Simple ping/pong command interactionClient.add({ description: 'Ping!', name: 'ping', run: (context, args) => { // Commands should return a promise to ensure that errors are handled return context.respond(InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, 'pong!'); }, }); // Command demonstrating command pipelines interactionClient.add({ description: 'Are you the owner or part of the team for this application?', name: 'owner', // onBefore should return a boolean to indicate whether or not the command should proceed onBefore: (context) => context.client.isOwner(context.userId), // we want the error to only show to the user to not clunk up the chat onCancel: (context) => { return context.respond(InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, { content: 'This command is only available to the bot owner.'), flags: MessageFlags.EPHEMERAL, }); }, run: async (context) => { // Commands may also run asynchronously. await context.respond(InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, 'You are the owner of the bot!'); }, }); // Context Menu User Command interactionClient.add({ name: 'Poke', type: ApplicationCommandTypes.USER, run: async (context, args) => { await context.respond(InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, { content: `You poked ${args.member || args.user}`, flags: MessageFlags.EPHEMERAL, }); }, }); // Context Menu Message Command (tells you when the message was created) interactionClient.add({ name: 'Creation Date', guildIds: [], // you can make it a guild command type: ApplicationCommandTypes.MESSAGE, run: async (context, args) => { const { message } = args; await context.respond(InteractionCallbackTypes.CHANNEL_MESSAGE_WITH_SOURCE, { content: `${message.id} was made at ${message.createdAt}`, flags: MessageFlags.EPHEMERAL, }); }, }); // Spawn the client in an async context // // Note: Due to how Node handles tasks, the script will block until the Detritus client // is killed. (async () => { // Interaction Client will compare the local commands w/ commands stored on discord // If any of them differ, it will call `.bulkOverwriteApplicationCommands()` with the local commands // Guild-specific Interaction commands are not supported right now const client = await interactionClient.run(); console.log(`Client has loaded with a shard count of ${client.shardCount}`); })();
const { ShardClient } = require('detritus-client'); // Note: it is not advised to hard-code your bot token directly into the bot source. // // Tokens should be considered secrets and stored in a configuration file that is not // part of your version control system, or an environment variable. const token = ''; const client = new ShardClient(token, { gateway: { // This will tell our client to fill our Members cache on any of our guilds that are larger than the large threshold you pass in (default 250) loadAllMembers: true, }, }); // listen to our client's eventemitter client.on('guildCreate', async ({fromUnavailable, guild}) => { if (fromUnavailable) { console.log(`Guild ${guild.name} has just came back from being unavailable`); } else { console.log(`Joined Guild ${guild.name}, bringing us up to ${client.guilds.length} guilds.`); } }); // listen to our client's eventemitter client.on('messageCreate', async ({message}) => { if (message.content === '!ping') { const reply = await message.reply('pong!, deleting message in 5 seconds...'); setTimeout(async () => { await reply.delete(); }, 5000); } }); (async () => { await client.run(); console.log('Successfully connected to Discord!'); console.log(`Currently have ${client.guilds.length} guilds in cache.`); // set our presence, we can pass this into the client's options too under `gateway.presence` client.gateway.setPresence({ activity: { // What comes after our activity type, x. name: 'with Detritus', // Type 0 sets our message to `Playing x` type: 0, }, // do-not-disturb us status: 'dnd', }); })();
const { ClusterClient } = require('detritus-client'); // Note: it is not advised to hard-code your bot token directly into the bot source. // // Tokens should be considered secrets and stored in a configuration file that is not // part of your version control system, or an environment variable. const token = ''; const cluster = new ClusterClient(token, { gateway: { // Pass in a presence we will send with the identify payload presence: { activity: { // What comes after our activity type, x. name: 'with Detritus ClusterClient', // Type 0 sets our message to `Playing x` type: 0, }, // do-not-disturb us status: 'dnd', }, }, }); // listen to our client's eventemitter // `shard` (which is the ShardClient the event originated from) is added onto EVERY event that you listen to on the cluster client cluster.on('guildCreate', async ({fromUnavailable, guild, shard}) => { if (fromUnavailable) { console.log(`Shard #${shard.shardId}:`, `Guild ${guild.name} has just came back from being unavailable`); } else { console.log(`Shard #${shard.shardId}:`, `Joined Guild ${guild.name}, bringing us up to ${client.guilds.length} guilds.`); } }); // listen to our client's eventemitter // `shard` (which is the ShardClient the event originated from) is added onto EVERY event that you listen to on the cluster client cluster.on('messageCreate', async ({message, shard}) => { if (message.content === '!ping') { const reply = await message.reply(`pong on shard #${shard.shardId}!, deleting message in 5 seconds...`); setTimeout(async () => { await reply.delete(); }, 5000); } }); (async () => { // shards are made after the cluster is ran, found in `ClusterClient.shards`. await cluster.run(); console.log(`Successfully launched shards ${cluster.shardStart} to ${cluster.shardEnd} with a shardCount of ${cluster.shardCount}`); })();
Detritus is licensed under the BSD-2 license; see the LICENSE.
To contribute, please first open an issue describing your requested changes, and then open a pull request.