diff --git a/assets/openapi.json b/assets/openapi.json
index aa965def..769daa67 100644
--- a/assets/openapi.json
+++ b/assets/openapi.json
@@ -256,6 +256,9 @@
},
"since": {
"type": "integer"
+ },
+ "client_status": {
+ "$ref": "#/components/schemas/ClientStatus"
}
},
"required": [
@@ -3764,7 +3767,9 @@
"additionalProperties": false
},
"intents": {
- "type": "number"
+ "type": "number",
+ "properties": {},
+ "additionalProperties": false
},
"presence": {
"$ref": "#/components/schemas/ActivitySchema"
@@ -3783,7 +3788,9 @@
"maxItems": 2,
"type": "array",
"items": {
- "type": "number"
+ "type": "number",
+ "properties": {},
+ "additionalProperties": false
}
},
"guild_subscriptions": {
@@ -7796,6 +7803,26 @@
5
]
},
+ "ClientStatus": {
+ "type": "object",
+ "properties": {
+ "desktop": {
+ "type": "string"
+ },
+ "mobile": {
+ "type": "string"
+ },
+ "web": {
+ "type": "string"
+ },
+ "embedded": {
+ "type": "string"
+ },
+ "vr": {
+ "type": "string"
+ }
+ }
+ },
"ChannelPermissionOverwriteType": {
"type": "number",
"enum": [
@@ -9468,7 +9495,7 @@
"$ref": "#/components/schemas/ClientStatus"
},
"status": {
- "$ref": "#/components/schemas/Status"
+ "$ref": "#/components/schemas/PrivateStatus"
},
"is_admin_session": {
"type": "boolean"
@@ -9506,25 +9533,15 @@
"user_id"
]
},
- "ClientStatus": {
- "type": "object",
- "properties": {
- "desktop": {
- "type": "string"
- },
- "mobile": {
- "type": "string"
- },
- "web": {
- "type": "string"
- },
- "embedded": {
- "type": "string"
- },
- "vr": {
- "type": "string"
- }
- }
+ "PrivateStatus": {
+ "enum": [
+ "dnd",
+ "idle",
+ "invisible",
+ "offline",
+ "online"
+ ],
+ "type": "string"
},
"ExtendedLocationInfo": {
"type": "object",
@@ -13402,7 +13419,7 @@
"length": {
"type": "integer"
},
- "__@unscopables@698": {
+ "__@unscopables@749": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
@@ -13528,17 +13545,17 @@
"with": {
"type": "boolean"
},
- "__@iterator@696": {
+ "__@iterator@747": {
"type": "boolean"
},
- "__@unscopables@698": {
+ "__@unscopables@749": {
"type": "boolean"
}
}
}
},
"required": [
- "__@unscopables@698",
+ "__@unscopables@749",
"length"
]
},
diff --git a/assets/schemas.json b/assets/schemas.json
index e28447eb..0ec5ee02 100644
--- a/assets/schemas.json
+++ b/assets/schemas.json
@@ -241,6 +241,9 @@
},
"since": {
"type": "integer"
+ },
+ "client_status": {
+ "$ref": "#/definitions/ClientStatus"
}
},
"additionalProperties": false,
@@ -3990,7 +3993,9 @@
"additionalProperties": false
},
"intents": {
- "type": "bigint"
+ "type": "number",
+ "properties": {},
+ "additionalProperties": false
},
"presence": {
"$ref": "#/definitions/ActivitySchema"
@@ -4009,7 +4014,9 @@
"maxItems": 2,
"type": "array",
"items": {
- "type": "bigint"
+ "type": "number",
+ "properties": {},
+ "additionalProperties": false
}
},
"guild_subscriptions": {
@@ -8297,6 +8304,28 @@
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
+ "ClientStatus": {
+ "type": "object",
+ "properties": {
+ "desktop": {
+ "type": "string"
+ },
+ "mobile": {
+ "type": "string"
+ },
+ "web": {
+ "type": "string"
+ },
+ "embedded": {
+ "type": "string"
+ },
+ "vr": {
+ "type": "string"
+ }
+ },
+ "additionalProperties": false,
+ "$schema": "http://json-schema.org/draft-07/schema#"
+ },
"ChannelPermissionOverwriteType": {
"type": "number",
"enum": [
@@ -10073,7 +10102,7 @@
"$ref": "#/definitions/ClientStatus"
},
"status": {
- "$ref": "#/definitions/Status"
+ "$ref": "#/definitions/PrivateStatus"
},
"is_admin_session": {
"type": "boolean"
@@ -10113,26 +10142,15 @@
],
"$schema": "http://json-schema.org/draft-07/schema#"
},
- "ClientStatus": {
- "type": "object",
- "properties": {
- "desktop": {
- "type": "string"
- },
- "mobile": {
- "type": "string"
- },
- "web": {
- "type": "string"
- },
- "embedded": {
- "type": "string"
- },
- "vr": {
- "type": "string"
- }
- },
- "additionalProperties": false,
+ "PrivateStatus": {
+ "enum": [
+ "dnd",
+ "idle",
+ "invisible",
+ "offline",
+ "online"
+ ],
+ "type": "string",
"$schema": "http://json-schema.org/draft-07/schema#"
},
"ExtendedLocationInfo": {
@@ -14319,7 +14337,7 @@
"length": {
"type": "integer"
},
- "__@unscopables@698": {
+ "__@unscopables@749": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
@@ -14445,17 +14463,17 @@
"with": {
"type": "boolean"
},
- "__@iterator@696": {
+ "__@iterator@747": {
"type": "boolean"
},
- "__@unscopables@698": {
+ "__@unscopables@749": {
"type": "boolean"
}
}
}
},
"required": [
- "__@unscopables@698",
+ "__@unscopables@749",
"length"
]
},
diff --git a/src/gateway/opcodes/PresenceUpdate.ts b/src/gateway/opcodes/PresenceUpdate.ts
index ca52af2a..f4d9ffcf 100644
--- a/src/gateway/opcodes/PresenceUpdate.ts
+++ b/src/gateway/opcodes/PresenceUpdate.ts
@@ -17,7 +17,7 @@
*/
import { WebSocket, Payload } from "@spacebar/gateway";
-import { emitEvent, PresenceUpdateEvent, Session, User } from "@spacebar/util";
+import { emitEvent, PresenceUpdateEvent, PrivateStatus, PublicStatus, PublicStatusOrder, Session, User } from "@spacebar/util";
import { check } from "./instanceOf";
import { ActivitySchema } from "@spacebar/schemas";
@@ -26,7 +26,12 @@ export async function onPresenceUpdate(this: WebSocket, { d }: Payload) {
check.call(this, ActivitySchema, d);
const presence = d as ActivitySchema;
- await Session.update({ session_id: this.session_id }, { status: presence.status, activities: presence.activities });
+ if (d.status === "unknown") {
+ const sessions = await Session.find({ where: { user_id: this.user_id } });
+ d.status = sessions.sort((a, b) => PublicStatusOrder[a.getPublicStatus()] - PublicStatusOrder[b.getPublicStatus()])[0].getPublicStatus();
+ }
+
+ await Session.update({ session_id: this.session_id }, { status: presence.status as PrivateStatus, activities: presence.activities });
const session = await Session.findOneOrFail({
select: { client_status: true },
diff --git a/src/schemas/uncategorised/ActivitySchema.ts b/src/schemas/uncategorised/ActivitySchema.ts
index 572c28c0..f0dfaf89 100644
--- a/src/schemas/uncategorised/ActivitySchema.ts
+++ b/src/schemas/uncategorised/ActivitySchema.ts
@@ -17,7 +17,7 @@
*/
// TODO: remove entity imports
-import { Activity, Status } from "@spacebar/util";
+import { Activity, ClientStatus, Status } from "@spacebar/util";
export const ActivitySchema = {
$afk: Boolean,
@@ -78,4 +78,5 @@ export interface ActivitySchema {
status: Status;
activities?: Activity[];
since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
+ client_status?: ClientStatus;
}
diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts
index 058961f6..1cb77ebe 100644
--- a/src/util/entities/Session.ts
+++ b/src/util/entities/Session.ts
@@ -20,7 +20,7 @@ import crypto from "node:crypto";
import { User } from "./User";
import { BaseClassWithoutId } from "./BaseClass";
import { Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
-import { Activity, ClientStatus, GatewaySession, GatewaySessionClientInfo, Status } from "../interfaces";
+import { Activity, ClientStatus, GatewaySession, GatewaySessionClientInfo, PrivateStatus } from "../interfaces";
import { randomUpperString } from "@spacebar/api";
import { DateBuilder, IpDataClient, TimeSpan } from "../util";
@@ -57,7 +57,7 @@ export class Session extends BaseClassWithoutId {
client_status: ClientStatus;
@Column({ nullable: false, type: String })
- status: Status;
+ status: PrivateStatus;
@Column({ default: false })
is_admin_session: boolean;
diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts
index 96d04a55..087f0a59 100644
--- a/src/util/interfaces/Event.ts
+++ b/src/util/interfaces/Event.ts
@@ -35,6 +35,7 @@ import {
GuildOrUnavailable,
Snowflake,
ThreadMember,
+ PrivateStatus,
} from "@spacebar/util";
import { JsonValue } from "@protobuf-ts/runtime";
import {
@@ -603,7 +604,7 @@ export interface GatewaySession {
activities: Activity[];
hidden_activities: Activity[];
client_info: GatewaySessionClientInfo;
- status: Status;
+ status: PrivateStatus;
active?: boolean; // How is this even defined?
}
diff --git a/src/util/interfaces/Status.ts b/src/util/interfaces/Status.ts
index 8edd379c..93e1b74f 100644
--- a/src/util/interfaces/Status.ts
+++ b/src/util/interfaces/Status.ts
@@ -16,6 +16,20 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+export enum PublicStatusOrder {
+ online = 0,
+ idle = 1,
+ dnd = 2,
+ offline = 3,
+}
+
+console.log(PublicStatusOrder);
+
+export type PublicStatus = keyof typeof PublicStatusOrder;
+export type PrivateStatus = PublicStatus | "invisible";
+export type SetPrivateStatus = PrivateStatus | "unknown";
+
+// @deprecated Use PublicStatus, PrivateStatus or SetPrivateStatus instead
export type Status =
| "idle"
| "dnd"
|