The code is a Discord bot implementation that initializes variables and functions for handling WebSocket connections, sending heartbeats, and processing gateway messages. The gatewayMessage
function is the main entry point for processing messages from the WebSocket server, and it updates the sequence number, logs messages, and performs different actions based on the op
value of the gateway message.
npm run import -- "discord gateway"
const {TOKEN, DEFAULT_APPLICATION} = importer.import("discord configuration")
const systemUsage = importer.import("system usage report")
const INSTANCES = {}
const SESSIONS = {}
var indentifyTimer
var privateChannels = {}
var interactions = {}
const interactionsCommands = {}
var cancelConnection // if gateway doesn't respond properly, close web socket
var heartbeat
var resources
var seq = 0
function sendHeartbeat(ws, reconnect) {
if(!ws) return
console.log('Sending heartbeat')
ws.send(JSON.stringify({
op: 1,
d: seq
}))
cancelConnection = setTimeout(gatewayClose.bind(null, ws, reconnect), 4000)
}
function gatewayMessage(ws, reconnectGateway, interactionResponse, message) {
var msgBuff = new Buffer.from(message)
var gateway = JSON.parse(msgBuff.toString('utf-8'))
if(gateway.s) seq = gateway.s
if(gateway.d && gateway.d.seq) seq = gateway.d.seq
console.log('Gateway message', gateway)
if(gateway.op == 10) {
ws.identified = true
heartbeat = setInterval(sendHeartbeat.bind(null, ws, reconnectGateway), gateway.d.heartbeat_interval)
resources = setInterval(systemUsage, 1000)
ws.send(JSON.stringify({
op: 2,
intents: [
'DIRECT_MESSAGES', 'DIRECT_MESSAGE_REACTIONS',
'GUILD_MESSAGES', 'GUILD_MESSAGE_REACTIONS',
'GUILDS', 'THREAD_UPDATE', 'THREAD_CREATE',
'THREAD_DELETE', 'THREAD_LIST_SYNC', 'THREAD_MEMBER_UPDATE',
'THREAD_MEMBERS_UPDATE', 'MESSAGE_CREATE', 'MESSAGE_UPDATE',
'GUILD_PRESENCES',
],
d: {
token: TOKEN,
properties: {
"$os": "linux",
"$browser": "nodejs",
"$device": "quake3"
}
}
}))
return
} else if (gateway.op === 7) { // should reconnect
console.log('Reconnecting...')
gatewayClose(ws, reconnectGateway)
return
} else if (gateway.op === 0 || gateway.op === 9) {
if(gateway.t == 'MESSAGE_CREATE') {
// guild ID can only be null if it is a personal message
if(typeof gateway.d.guild_id == 'undefined') {
privateChannels[gateway.d.channel_id] = Date.now()
if(gateway.d.author.id != DEFAULT_APPLICATION) {
interactionsCommands['promptPrivate'](gateway.d)
}
} else if(gateway.d.content.includes('@' + DEFAULT_APPLICATION)
&& typeof interactionsCommands['promptMention'] != 'undefined'
) {
interactionsCommands['promptMention'](gateway.d)
}
}
if(gateway.t == 'INTERACTION_CREATE') {
if(typeof interactions[gateway.d.channel_id] == 'undefined')
interactions[gateway.d.channel_id] = []
interactions[gateway.d.channel_id].push(gateway.d)
if(typeof interactionsCommands[gateway.d.data.name] != 'undefined') {
Promise.resolve(interactionsCommands[gateway.d.data.name](gateway.d))
}
interactionResponse(gateway.d.id, gateway.d.token)
}
if(gateway.t == 'EMBEDDED_ACTIVITY_UPDATE_V2') {
if(typeof INSTANCES[gateway.d['instance_id']] == 'undefined') {
INSTANCES[gateway.d['instance_id']] = []
}
INSTANCES[gateway.d['instance_id']] = INSTANCES[gateway.d['instance_id']].filter(i => gateway.d.participants.includes(i[0]))
if(typeof interactionsCommands['startActivity'] != 'undefined'
&& typeof interactionsCommands['endActivity'] != 'undefined'
) {
if(gateway.d.participants.length) {
Promise.resolve(interactionsCommands['startActivity'](gateway.d))
} else {
Promise.resolve(interactionsCommands['endActivity'](gateway.d))
}
}
}
return
} else if (gateway.op === 11) {
clearTimeout(cancelConnection)
return
}
console.log('Unrecognized gateway', gateway)
}
function gatewayClose(ws, reconnect) {
console.log('Discord disconnected')
if(indentifyTimer)
clearInterval(indentifyTimer)
if(heartbeat)
clearInterval(heartbeat)
if(resources)
clearInterval(resources)
if(ws.readyState == 1)
ws.close()
if(reconnect) {
setTimeout(reconnect, 1000)
}
if(typeof interactionsCommands['endActivity'] != 'undefined') {
Promise.resolve(interactionsCommands['endActivity']())
}
ws.identified = false
return
}
module.exports = {
gatewayClose,
gatewayMessage,
privateChannels,
interactions,
interactionsCommands,
INSTANCES,
SESSIONS,
}
const {
TOKEN,
DEFAULT_APPLICATION,
} = importer.import('discord configuration');
const {
getSystemUsage,
} = importer.import('system usage report');
const INSTANCES = {};
const SESSIONS = {};
const privateChannels = {};
const interactions = {};
const interactionsCommands = {};
let indentifyTimer;
let cancelConnection;
let heartbeat;
let resources;
let seq = 0;
/**
* Sends a heartbeat to Discord
* @param {Object} ws WebSocket object
* @param {Boolean} reconnect Whether to reconnect after sending heartbeat
*/
function sendHeartbeat(ws, reconnect) {
if (!ws) return;
console.log('Sending heartbeat');
ws.send(JSON.stringify({
op: 1,
d: seq,
}));
cancelConnection = setTimeout(() => gatewayClose(ws, reconnect), 4000);
}
/**
* Handles a message received from Discord
* @param {Object} ws WebSocket object
* @param {Boolean} reconnectGateway Whether to reconnect to the gateway
* @param {Function} interactionResponse Function to respond to interactions
* @param {Object} message Message received from Discord
*/
function gatewayMessage(ws, reconnectGateway, interactionResponse, message) {
const msgBuffer = Buffer.from(message);
const gateway = JSON.parse(msgBuffer.toString('utf-8'));
if (gateway.s) seq = gateway.s;
if (gateway.d && gateway.d.seq) seq = gateway.d.seq;
console.log('Gateway message', gateway);
switch (gateway.op) {
case 10:
ws.identified = true;
heartbeat = setInterval(() => sendHeartbeat(ws, reconnectGateway), gateway.d.heartbeat_interval);
resources = setInterval(getSystemUsage, 1000);
ws.send(JSON.stringify({
op: 2,
intents: [
'DIRECT_MESSAGES',
'DIRECT_MESSAGE_REACTIONS',
'GUILD_MESSAGES',
'GUILD_MESSAGE_REACTIONS',
'GUILDS',
'THREAD_UPDATE',
'THREAD_CREATE',
'THREAD_DELETE',
'THREAD_LIST_SYNC',
'THREAD_MEMBER_UPDATE',
'THREAD_MEMBERS_UPDATE',
'MESSAGE_CREATE',
'MESSAGE_UPDATE',
'GUILD_PRESENCES',
],
d: {
token: TOKEN,
properties: {
'$os': 'linux',
'$browser': 'nodejs',
'$device': 'quake3',
},
},
}));
break;
case 7:
console.log('Reconnecting...');
gatewayClose(ws, reconnectGateway);
break;
case 0:
case 9:
if (gateway.t === 'MESSAGE_CREATE') {
const { guild_id, channel_id, author, content } = gateway.d;
if (typeof guild_id === 'undefined') {
privateChannels[channel_id] = Date.now();
if (author.id!== DEFAULT_APPLICATION && interactionsCommands.promptPrivate) {
interactionsCommands.promptPrivate(gateway.d);
}
} else if (content.includes(`@${DEFAULT_APPLICATION}`) && interactionsCommands.promptMention) {
interactionsCommands.promptMention(gateway.d);
}
}
if (gateway.t === 'INTERACTION_CREATE') {
const { channel_id, data } = gateway.d;
if (!interactions[channel_id]) interactions[channel_id] = [];
interactions[channel_id].push(gateway.d);
if (interactionsCommands[data.name]) {
Promise.resolve(interactionsCommands[data.name](gateway.d));
}
interactionResponse(gateway.d.id, gateway.d.token);
}
if (gateway.t === 'EMBEDDED_ACTIVITY_UPDATE_V2') {
const { instance_id, participants } = gateway.d;
if (!INSTANCES[instance_id]) INSTANCES[instance_id] = [];
INSTANCES[instance_id] = INSTANCES[instance_id].filter(i => participants.includes(i[0]));
if (interactionsCommands.startActivity && interactionsCommands.endActivity) {
if (participants.length) {
Promise.resolve(interactionsCommands.startActivity(gateway.d));
} else {
Promise.resolve(interactionsCommands.endActivity(gateway.d));
}
}
}
break;
case 11:
clearTimeout(cancelConnection);
break;
default:
console.log('Unrecognized gateway', gateway);
break;
}
}
/**
* Closes the Discord gateway
* @param {Object} ws WebSocket object
* @param {Boolean} reconnect Whether to reconnect after closing the gateway
*/
function gatewayClose(ws, reconnect) {
console.log('Discord disconnected');
clearInterval(indentifyTimer);
clearInterval(heartbeat);
clearInterval(resources);
if (ws.readyState === 1) ws.close();
if (reconnect) {
setTimeout(reconnect, 1000);
}
if (interactionsCommands.endActivity) {
Promise.resolve(interactionsCommands.endActivity());
}
ws.identified = false;
return;
}
module.exports = {
gatewayClose,
gatewayMessage,
privateChannels,
interactions,
interactionsCommands,
INSTANCES,
SESSIONS,
};
Breakdown of the Code
const {TOKEN, DEFAULT_APPLICATION} = importer.import('discord configuration')
const systemUsage = importer.import('system usage report')
TOKEN
and DEFAULT_APPLICATION
. It also imports a function systemUsage
from a module named'system usage report'.const INSTANCES = {}
const SESSIONS = {}
var indentifyTimer
var privateChannels = {}
var interactions = {}
const interactionsCommands = {}
var cancelConnection // if gateway doesn't respond properly, close web socket
var heartbeat
var resources
var seq = 0
INSTANCES
and SESSIONS
.indentifyTimer
(with a typo: it should be identifyTimer
).privateChannels
.interactions
.interactionsCommands
.cancelConnection
(used to close the WebSocket connection if the gateway doesn't respond).heartbeat
(used to track the heartbeat interval).resources
(used to track the system usage report).seq
(initially set to 0, used to track the sequence number).function sendHeartbeat(ws, reconnect) {
if(!ws) return
console.log('Sending heartbeat')
ws.send(JSON.stringify({
op: 1,
d: seq
}))
cancelConnection = setTimeout(gatewayClose.bind(null, ws, reconnect), 4000)
}
seq
).ws
parameter is falsy, the function returns immediately.cancelConnection
) to close the WebSocket connection after 4 seconds if the gateway doesn't respond.function gatewayMessage(ws, reconnectGateway, interactionResponse, message) {
var msgBuff = new Buffer.from(message)
var gateway = JSON.parse(msgBuff.toString('utf-8'))
if(gateway.s) seq = gateway.s
if(gateway.d && gateway.d.seq) seq = gateway.d.seq
console.log('Gateway message', gateway)
if(gateway.op == 10) {
ws.identified = true
heartbeat = setInterval(sendHeartbeat.bind(null, ws, reconnectGateway), gateway.d.heartbeat_interval)
resources = setInterval(systemUsage, 1000)
ws.send(JSON.stringify({
op: 2,
intents: [
'DIRECT_MESSAGES', 'DIRECT_MESSAGE_REACTIONS',
'GUILD_MESSAGES', 'GUILD_MESSAGE_REACTIONS',
'GUILDS', 'THREAD_UPDATE', 'THREAD_CREATE',
'THREAD_DELETE', 'THREAD_LIST_SYNC', 'THREAD_MEMBER_UPDATE',
'THREAD_MEMBERS_UPDATE', 'MESSAGE_CREATE', 'MESSAGE_UPDATE',
'GUILD_PRESENCES',
],
d: {
token: TOKEN,
properties: {
"$os": "linux",
"$browser": "nodejs",
"$device": "quake3"
}
}
}))
return
} else if (gateway.op === 7) { // should reconnect
console.log('Reconnecting...')
gatewayClose(ws, reconnectGateway)
return
} else if (gateway.op === 0 || gateway.op === 9) {
if(gateway.t == 'MESSAGE_CREATE') {
// guild ID can only be null if it is a personal message
if(typeof gateway.d.guild_id == 'undefined') {
return
}
}
}
}
seq
) if the gateway message contains it.op
value of the gateway message, the function performs different actions:
op
is 10, the function sets the WebSocket connection to identified and starts sending heartbeat packets at regular intervals. It also sets up an interval to send the system usage report every second.op
is 7, the function logs a message indicating that the gateway is reconnecting and calls the gatewayClose
function.op
is 0 or 9 and the message type is 'MESSAGE_CREATE', the function checks if the guild ID is null (indicating a personal message). If the guild ID is not null, the function does nothing.