diff --git a/src/Server.ts b/src/Server.ts
index df5ec905..ea1e39b0 100644
--- a/src/Server.ts
+++ b/src/Server.ts
@@ -9,7 +9,15 @@ import Config from "./util/Config";
export class Server {
public ws: WebSocketServer;
constructor() {
- this.ws = new WebSocketServer({ port: 8080, maxPayload: 4096 });
+ this.ws = new WebSocketServer({
+ port: 8080,
+ maxPayload: 4096,
+ // perMessageDeflate: {
+ // zlibDeflateOptions: {
+ // chunkSize: 65536,
+ // },
+ // },
+ });
this.ws.on("connection", Connection);
}
diff --git a/src/listener/listener.ts b/src/listener/listener.ts
index b6ae0ac6..5f3ee93b 100644
--- a/src/listener/listener.ts
+++ b/src/listener/listener.ts
@@ -1,14 +1,15 @@
import { db, Event, MongooseCache, UserModel, getPermission, Permissions } from "fosscord-server-util";
+import { OPCODES } from "../util/Constants";
+import { Send } from "../util/Send";
import WebSocket from "../util/WebSocket";
-// TODO: bot sharding
// TODO: close connection on Invalidated Token
// TODO: check intent
// TODO: Guild Member Update is sent for current-user updates regardless of whether the GUILD_MEMBERS intent is set.
// ? How to resubscribe MongooseCache for new dm channel events? Maybe directly send them to the user_id regardless of the channel_id? -> max overhead of creating 10 events in database for dm user group. Or a new field in event -> recipient_ids?
export async function setupListener(this: WebSocket) {
- const user = await UserModel.findOne({ id: this.user_id }).exec();
+ const user = await UserModel.findOne({ id: this.user_id }).lean().exec();
const eventStream = new MongooseCache(
db.collection("events"),
@@ -23,6 +24,7 @@ export async function setupListener(this: WebSocket) {
export async function dispatch(this: WebSocket, document: Event) {
var permission = new Permissions("ADMINISTRATOR"); // default permission for dms
+ console.log("event", document);
if (document.guild_id) {
if (!this.intents.has("GUILDS")) return;
@@ -30,8 +32,6 @@ export async function dispatch(this: WebSocket, document: Event) {
permission = await getPermission(this.user_id, document.guild_id, channel_id);
}
- console.log("event", document);
-
// check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents
switch (document.event) {
case "GUILD_CREATE":
@@ -93,7 +93,7 @@ export async function dispatch(this: WebSocket, document: Event) {
if (!this.intents.has("GUILD_MESSAGE_TYPING") && document.guild_id) return;
if (!this.intents.has("DIRECT_MESSAGE_TYPING") && !document.guild_id) return;
break;
- case "READY":
+ case "READY": // will be sent by the gateway
case "USER_UPDATE":
case "APPLICATION_COMMAND_CREATE":
case "APPLICATION_COMMAND_DELETE":
@@ -149,7 +149,7 @@ export async function dispatch(this: WebSocket, document: Event) {
case "CHANNEL_DELETE":
case "CHANNEL_UPDATE":
case "GUILD_EMOJI_UPDATE":
- case "READY":
+ case "READY": // will be sent by the gateway
case "USER_UPDATE":
case "APPLICATION_COMMAND_CREATE":
case "APPLICATION_COMMAND_DELETE":
@@ -160,5 +160,10 @@ export async function dispatch(this: WebSocket, document: Event) {
break;
}
- return this.emit(document.event, document.data);
+ return Send(this, {
+ op: OPCODES.Dispatch,
+ t: document.event,
+ d: document.data,
+ s: this.sequence++,
+ });
}
diff --git a/src/opcodes/Identify.ts b/src/opcodes/Identify.ts
index fdde79fc..61238e62 100644
--- a/src/opcodes/Identify.ts
+++ b/src/opcodes/Identify.ts
@@ -48,6 +48,8 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const channels = await ChannelModel.find({ recipients: this.user_id }).lean().exec();
const user = await UserModel.findOne({ id: this.user_id }).lean().exec();
+ if (!user) return this.close(CLOSECODES.Authentication_failed);
+
const public_user = {
username: user.username,
discriminator: user.discriminator,
diff --git a/src/schema/Activity.ts b/src/schema/Activity.ts
index 00772743..45bd6fef 100644
--- a/src/schema/Activity.ts
+++ b/src/schema/Activity.ts
@@ -1,42 +1,10 @@
+import { Activity } from "fosscord-server-util";
import { EmojiSchema } from "./Emoji";
export const ActivitySchema = {
afk: Boolean,
status: String,
- $activities: [
- {
- name: String, // the activity's name
- type: Number, // activity type // TODO: check if its between range 0-5
- $url: String, // stream url, is validated when type is 1
- $created_at: Number, // unix timestamp of when the activity was added to the user's session
- $timestamps: {
- // unix timestamps for start and/or end of the game
- start: Number,
- end: Number,
- },
- $application_id: BigInt, // application id for the game
- $details: String,
- $State: String,
- $emoji: EmojiSchema,
- $party: {
- $id: String,
- $size: [Number], // used to show the party's current and maximum size // TODO: array length 2
- },
- $assets: {
- $large_image: String, // the id for a large asset of the activity, usually a snowflake
- $large_text: String, // text displayed when hovering over the large image of the activity
- $small_image: String, // the id for a small asset of the activity, usually a snowflake
- $small_text: String, // text displayed when hovering over the small image of the activity
- },
- $secrets: {
- $join: String, // the secret for joining a party
- $spectate: String, // the secret for spectating a game
- $match: String, // the secret for a specific instanced match
- },
- $instance: Boolean,
- flags: BigInt, // activity flags OR d together, describes what the payload includes
- },
- ],
+ $activities: [Activity],
$since: Number, // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
};
@@ -56,7 +24,7 @@ export interface ActivitySchema {
};
application_id?: bigint; // application id for the game
details?: string;
- State?: string;
+ state?: string;
emoji?: EmojiSchema;
party?: {
id?: string;
diff --git a/src/schema/Identify.ts b/src/schema/Identify.ts
index cfc3702a..0c458f14 100644
--- a/src/schema/Identify.ts
+++ b/src/schema/Identify.ts
@@ -2,32 +2,72 @@ import { ActivitySchema } from "./Activity";
export const IdentifySchema = {
token: String,
- intents: BigInt, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+ $intents: BigInt, // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
$properties: {
- // bruh discord really uses $ in the property key, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
+ // bruh discord really uses $ in the property key for bots, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
+ $os: String,
+ $browser: String,
+ $device: String,
$$os: String,
$$browser: String,
$$device: String,
+ $browser_user_agent: String,
+ $browser_version: String,
+ $os_version: String,
+ $referrer: String,
+ $referring_domain: String,
+ $referrer_current: String,
+ $referring_domain_current: String,
+ $release_channel: String,
+ $client_build_number: Number,
+ $client_event_source: String,
},
$presence: ActivitySchema,
$compress: Boolean,
$large_threshold: Number,
$shard: [Number],
$guild_subscriptions: Boolean,
+ $capabilities: Number,
+ $client_state: {
+ $guild_hashes: Object,
+ $highest_last_message_id: BigInt,
+ $read_state_version: Number,
+ $user_guild_settings_version: Number,
+ },
};
export interface IdentifySchema {
token: string;
properties: {
// bruh discord really uses $ in the property key, so we need to double prefix it, because instanceOf treats $ (prefix) as a optional key
- $$os: string;
- $$browser: string;
- $$device: string;
+ os?: string;
+ browser?: string;
+ device?: string;
+ $os?: string;
+ $browser?: string;
+ $device?: string;
+ browser_user_agent?: string;
+ browser_version?: string;
+ os_version?: string;
+ referrer?: string;
+ referring_domain?: string;
+ referrer_current?: string;
+ referring_domain_current?: string;
+ release_channel?: "stable" | "dev" | "ptb" | "canary";
+ client_build_number?: number;
+ client_event_source?: any;
};
- intents: bigint; // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
+ intents?: bigint; // discord uses a Integer for bitfields we use bigints tho. | instanceOf will automatically convert the Number to a BigInt
presence?: ActivitySchema;
compress?: boolean;
large_threshold?: number;
shard?: [number];
guild_subscriptions?: boolean;
+ capabilities?: number;
+ client_state?: {
+ guild_hashes?: any;
+ highest_last_message_id?: bigint;
+ read_state_version?: number;
+ user_guild_settings_version?: number;
+ };
}
diff --git a/src/util/setHeartbeat.ts b/src/util/setHeartbeat.ts
index 1fe657a8..a59dd251 100644
--- a/src/util/setHeartbeat.ts
+++ b/src/util/setHeartbeat.ts
@@ -6,5 +6,5 @@ export function setHeartbeat(socket: WebSocket) {
socket.heartbeatTimeout = setTimeout(() => {
return socket.close(4009);
- }, 1000 * 30);
+ }, 1000 * 45);
}
|