A middleware based @discord Gateway API.
denska allows you to create a @discord bot using a middleware system like that used by koa. When a payload is sent from @discord to a shard it gets added to a context and sent through the middleware stack.
Unlike other libraries (which are also awesome and more beginner friendly), denska doesnât handle anything out of the box. Instead, functionality is added through middleware provided by the user and another libraries.
After giving the bellow example a go, take a look at denska-core. It handles common middleware tasks that youâll face using denska, plus extra things.
Setting up a minimal Identify Payload
When a bot first connects to @discordâs gateway it receives a hello payload which we then have to respond to with an identify payload. Letâs get a very minimal setup for this made, in a more full setup weâd also add heartbeating.
So first letâs import everything we need from denska and create a Shard. Weâll go over what each thing is when we use it.
import {
Shard, ShardContext,
PayloadOpcode
} from "https://deno.land/x/denska/mod.ts";
const shard = new Shard({ url: "wss://gateway.discord.gg" });A Shard is a single instance of a connection to the @discord gateway. We may later want to create multiple Shards to handle more data over separate instances.
Next weâll create our first middleware function and begin by check that the data payload we got is a hello payload.
shard.use<ShardContext>(async (ctx, next) => {
if(ctx.raw && ctx.raw.op === PayloadOpcode.Hello) {Here we use the use function to add a middleware function onto the stack. We then take in a ctx of type ShardContext (which is used by typescript to check the data in ctx) and a next function which calls the next middleware function in the stack.
Now that we know that we have a hello payload, letâs respond with an identify payload.
shard.ws.send(JSON.stringify({
op: PayloadOpcode.Identify,
d: {
token: "<bot_token>",
intents: 1 << 9, // the GUILD_MESSAGES intent
// these are good properties to use
properties: {
$os: "linux",
$browser: "denska",
$device: "denska"
}
}
}));Here we access the WebSocket inside the Shard using ws and use the send function to send a JSON.stringifyed payload.
Then we can call the next function to pass the ctx through if itâs not a hello payload and close the use function.
} // if
else await next();
}); // useWeâll lastly create another middleware function with use to console.log the ctx.
shard.use(async (ctx, next) => {
console.log(ctx);
});I didnât use the ShardContext here since we donât care about knowing whatâs in ctx, all we want to do is console.log it.
If we run this and forget to put our botâs token in the token part of the identify payload, weâll get close data from @discord.
{ close: { code: 4004, name: "AuthenticationFailed" } }Otherwise weâll see a dispatch payload with the READY event and data relating to our bot.
{
raw: {
t: "READY",
s: 1,
op: 0,
d: {
v: 8,
user_settings: {},
user: {
verified: true,
username: "Denska Test",
mfa_enabled: true,
id: "797163722002661456",
flags: 0,
email: null,
discriminator: "4976",
bot: true,
avatar: null
},
session_id: "070652aba963996f096f5d2a8ac042ee",
relationships: [],
private_channels: [],
presences: [],
guilds: [ [Object] ],
guild_join_requests: [],
geo_ordered_rtc_regions: [ "europe", "russia", "us-east", "us-central", "india" ],
application: { id: "797163722002661456", flags: 0 }
]
}
}
}