summary refs log tree commit diff
path: root/gateway/src
diff options
context:
space:
mode:
Diffstat (limited to 'gateway/src')
-rw-r--r--gateway/src/Server.ts13
-rw-r--r--gateway/src/listener/listener.ts29
-rw-r--r--gateway/src/opcodes/Identify.ts62
-rw-r--r--gateway/src/opcodes/LazyRequest.ts70
-rw-r--r--gateway/src/schema/Activity.ts43
5 files changed, 119 insertions, 98 deletions
diff --git a/gateway/src/Server.ts b/gateway/src/Server.ts

index a50c24a6..944174c7 100644 --- a/gateway/src/Server.ts +++ b/gateway/src/Server.ts
@@ -1,7 +1,7 @@ import "missing-native-js-functions"; import dotenv from "dotenv"; dotenv.config(); -import { Config, db, initEvent, RabbitMQ } from "@fosscord/util"; +import { closeDatabase, Config, initDatabase, initEvent, RabbitMQ } from "@fosscord/util"; import { Server as WebSocketServer } from "ws"; import { Connection } from "./events/Connection"; import http from "http"; @@ -38,15 +38,8 @@ export class Server { this.ws.on("error", console.error); } - async setupSchema() { - // TODO: adjust expireAfterSeconds -> lower - await Promise.all([db.collection("events").createIndex({ created_at: 1 }, { expireAfterSeconds: 60 })]); - } - async start(): Promise<void> { - // @ts-ignore - await (db as Promise<Connection>); - await this.setupSchema(); + await initDatabase(); await Config.init(); await initEvent(); if (!this.server.listening) { @@ -56,7 +49,7 @@ export class Server { } async stop() { - await db.close(); + closeDatabase(); this.server.close(); } } diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts
index 51082586..75ca1680 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts
@@ -1,22 +1,21 @@ import { - db, - Event, - UserModel, + User, getPermission, Permissions, - ChannelModel, + Channel, RabbitMQ, - EVENT, listenEvent, EventOpts, ListenEventOpts, + Member, } from "@fosscord/util"; import { OPCODES } from "../util/Constants"; import { Send } from "../util/Send"; import WebSocket from "../util/WebSocket"; import "missing-native-js-functions"; -import { ConsumeMessage } from "amqplib"; -import { Channel } from "amqplib"; +import { Channel as AMQChannel } from "amqplib"; +import { In, Like } from "../../../util/node_modules/typeorm"; +import { Recipient } from "../../../util/dist/entities/Recipient"; // TODO: close connection on Invalidated Token // TODO: check intent @@ -27,15 +26,15 @@ import { Channel } from "amqplib"; // TODO: use already queried guilds/channels of Identify and don't fetch them again export async function setupListener(this: WebSocket) { - const user = await UserModel.findOne({ id: this.user_id }, { guilds: true }).exec(); - const channels = await ChannelModel.find( - { $or: [{ recipient_ids: this.user_id }, { guild_id: { $in: user.guilds } }] }, - { id: true, permission_overwrites: true } - ).exec(); - const dm_channels = channels.filter((x) => !x.guild_id); + const members = await Member.find({ where: { id: this.user_id } }); + const guild_ids = members.map((x) => x.guild_id); + const user = await User.findOneOrFail({ id: this.user_id }); + const recipients = await Recipient.find({ where: { id: this.user_id }, relations: ["channel"] }); + const channels = await Channel.find({ guild_id: In(guild_ids) }); + const dm_channels = recipients.map((x) => x.channel); const guild_channels = channels.filter((x) => x.guild_id); - const opts: { acknowledge: boolean; channel?: Channel } = { acknowledge: true }; + const opts: { acknowledge: boolean; channel?: AMQChannel } = { acknowledge: true }; const consumer = consume.bind(this); if (RabbitMQ.connection) { @@ -50,7 +49,7 @@ export async function setupListener(this: WebSocket) { this.events[channel.id] = await listenEvent(channel.id, consumer, opts); } - for (const guild of user.guilds) { + for (const guild of guild_ids) { // contains guild and dm channels getPermission(this.user_id, guild) diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts
index 91f7f675..958f1b73 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts
@@ -1,17 +1,16 @@ import { CLOSECODES, Payload, OPCODES } from "../util/Constants"; import WebSocket from "../util/WebSocket"; import { - ChannelModel, + Channel, checkToken, - GuildModel, + Guild, Intents, - MemberDocument, - MemberModel, + Member, ReadyEventData, - UserModel, - toObject, + User, EVENTEnum, Config, + dbConnection, } from "@fosscord/util"; import { setupListener } from "../listener/listener"; import { IdentifySchema } from "../schema/Identify"; @@ -19,6 +18,8 @@ import { Send } from "../util/Send"; // import experiments from "./experiments.json"; const experiments: any = []; import { check } from "./instanceOf"; +import { Like } from "../../../util/node_modules/typeorm"; +import { Recipient } from "../../../util/dist/entities/Recipient"; // TODO: bot sharding // TODO: check priviliged intents @@ -54,17 +55,22 @@ export async function onIdentify(this: WebSocket, data: Payload) { } } - const members = toObject(await MemberModel.find({ id: this.user_id }).exec()); + const members = await Member.find({ + where: { id: this.user_id }, + relations: ["guild", "guild.channels", "guild.emojis", "guild.roles", "guild.stickers", "user", "roles"], + }); const merged_members = members.map((x: any) => { - const y = { ...x, user_id: x.id }; - delete y.settings; - delete y.id; - return [y]; - }) as MemberDocument[][]; + return [x]; + }) as Member[][]; + const guilds = members.map((x) => ({ ...x.guild, joined_at: x.joined_at })); const user_guild_settings_entries = members.map((x) => x.settings); - const channels = await ChannelModel.find({ recipient_ids: this.user_id }).exec(); - const user = await UserModel.findOne({ id: this.user_id }).exec(); + const recipients = await Recipient.find({ + where: { id: this.user_id }, + relations: ["channel", "channel.recipients"], + }); + const channels = recipients.map((x) => x.channel); + const user = await User.findOneOrFail({ id: this.user_id }); if (!user) return this.close(CLOSECODES.Authentication_failed); const public_user = { @@ -74,12 +80,9 @@ export async function onIdentify(this: WebSocket, data: Payload) { public_flags: user.public_flags, avatar: user.avatar, bot: user.bot, + bio: user.bio, }; - const guilds = await GuildModel.find({ id: { $in: user.guilds } }) - .populate({ path: "joined_at", match: { id: this.user_id } }) - .exec(); - const privateUser = { avatar: user.avatar, mobile: user.mobile, @@ -99,14 +102,15 @@ export async function onIdentify(this: WebSocket, data: Payload) { bot: user.bot, accent_color: user.accent_color || 0, banner: user.banner, + bio: user.bio, }; const d: ReadyEventData = { v: 8, user: privateUser, - user_settings: user.user_settings, + user_settings: user.settings, // @ts-ignore - guilds: toObject(guilds).map((x) => { + guilds: guilds.map((x) => { // @ts-ignore x.guild_hashes = { channels: { omitted: false, hash: "y4PV2fZ0gmo" }, @@ -118,7 +122,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { }), guild_experiments: [], // TODO geo_ordered_rtc_regions: [], // TODO - relationships: user.user_data.relationships, + relationships: user.relationships, read_state: { // TODO entries: [], @@ -130,12 +134,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { partial: false, // TODO partial version: 642, }, - // @ts-ignore - private_channels: toObject(channels).map((x: ChannelDocument) => { - x.recipient_ids = x.recipients.map((y: any) => y.id); - delete x.recipients; - return x; - }), + private_channels: channels, session_id: "", // TODO analytics_token: "", // TODO connected_accounts: [], // TODO @@ -144,17 +143,12 @@ export async function onIdentify(this: WebSocket, data: Payload) { consented: false, // TODO }, }, - country_code: user.user_settings.locale, + country_code: user.settings.locale, friend_suggestion_count: 0, // TODO // @ts-ignore experiments: experiments, // TODO guild_join_requests: [], // TODO what is this? - users: [ - public_user, - ...toObject(channels) - .map((x: any) => x.recipients) - .flat(), - ].unique(), // TODO + users: [public_user].unique(), // TODO merged_members: merged_members, // shard // TODO: only for bots sharding // application // TODO for applications diff --git a/gateway/src/opcodes/LazyRequest.ts b/gateway/src/opcodes/LazyRequest.ts
index 63075e5a..9f514f5f 100644 --- a/gateway/src/opcodes/LazyRequest.ts +++ b/gateway/src/opcodes/LazyRequest.ts
@@ -18,45 +18,43 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) { permissions.hasThrow("VIEW_CHANNEL"); // MongoDB query to retrieve all hoisted roles and join them with the members and users collection - const roles = toObject( - await db - .collection("roles") - .aggregate([ - { - $match: { - guild_id, - // hoist: true // TODO: also match @everyone role - }, + const roles = await db + .collection("roles") + .aggregate([ + { + $match: { + guild_id, + // hoist: true // TODO: also match @everyone role }, - { $sort: { position: 1 } }, - { - $lookup: { - from: "members", - let: { id: "$id" }, - pipeline: [ - { $match: { $expr: { $in: ["$$id", "$roles"] } } }, - { $limit: 100 }, - { - $lookup: { - from: "users", - let: { user_id: "$id" }, - pipeline: [ - { $match: { $expr: { $eq: ["$id", "$$user_id"] } } }, - { $project: PublicUserProjection }, - ], - as: "user", - }, - }, - { - $unwind: "$user", + }, + { $sort: { position: 1 } }, + { + $lookup: { + from: "members", + let: { id: "$id" }, + pipeline: [ + { $match: { $expr: { $in: ["$$id", "$roles"] } } }, + { $limit: 100 }, + { + $lookup: { + from: "users", + let: { user_id: "$id" }, + pipeline: [ + { $match: { $expr: { $eq: ["$id", "$$user_id"] } } }, + { $project: PublicUserProjection }, + ], + as: "user", }, - ], - as: "members", - }, + }, + { + $unwind: "$user", + }, + ], + as: "members", }, - ]) - .toArray() - ); + }, + ]) + .toArray(); const groups = roles.map((x) => ({ id: x.id === guild_id ? "online" : x.id, count: x.members.length })); const member_count = roles.reduce((a, b) => b.members.length + a, 0); diff --git a/gateway/src/schema/Activity.ts b/gateway/src/schema/Activity.ts
index d7e0a30b..f1665efd 100644 --- a/gateway/src/schema/Activity.ts +++ b/gateway/src/schema/Activity.ts
@@ -1,10 +1,47 @@ -import { ActivityBodySchema } from "@fosscord/util"; import { EmojiSchema } from "./Emoji"; export const ActivitySchema = { afk: Boolean, status: String, - $activities: [ActivityBodySchema], + $activities: [ + { + name: String, + type: Number, + $url: String, + $created_at: Date, + $timestamps: [ + { + $start: Number, + $end: Number, + }, + ], + $application_id: String, + $details: String, + $state: String, + $emoji: { + $name: String, + $id: String, + $amimated: Boolean, + }, + $party: { + $id: String, + $size: [Number, Number], + }, + $assets: { + $large_image: String, + $large_text: String, + $small_image: String, + $small_text: String, + }, + $secrets: { + $join: String, + $spectate: String, + $match: String, + }, + $instance: Boolean, + $flags: String, + }, + ], $since: Number, // unix time (in milliseconds) of when the client went idle, or null if the client is not idle }; @@ -42,7 +79,7 @@ export interface ActivitySchema { match?: string; // the secret for a specific instanced match }; instance?: boolean; - flags: bigint; // activity flags OR d together, describes what the payload includes + flags: string; // activity flags OR d together, describes what the payload includes } ]; since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle