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.
Setting up a minimal Identify Payload
When a bot first connects to @discordās gateway it recieves 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.send({
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 use the send function which is just a helper function provided by Shards to send payloads over the websocket.
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 }
]
}
}
}