2022-01-07 17:43:05 +01:00
|
|
|
export enum MessageType {
|
2022-01-07 18:28:34 +01:00
|
|
|
ACK = 0,
|
|
|
|
TEXT = 1,
|
2022-01-08 17:22:17 +01:00
|
|
|
ID_RESPONSE = 3,
|
2022-01-14 14:29:42 +01:00
|
|
|
TYPING = 4,
|
2022-01-17 16:16:46 +01:00
|
|
|
CURRENTLY_TYPING = 5,
|
2022-01-21 12:59:39 +01:00
|
|
|
CONNECTED_USERS = 6,
|
2022-01-07 17:43:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export type ServerMessage = {
|
2022-01-08 16:21:02 +01:00
|
|
|
__ctx?: string;
|
2022-01-07 18:28:34 +01:00
|
|
|
type: MessageType;
|
2022-01-07 17:43:05 +01:00
|
|
|
date: number;
|
|
|
|
};
|
2022-01-08 15:52:37 +01:00
|
|
|
export function isServerMessage(
|
|
|
|
obj: unknown,
|
|
|
|
type?: MessageType
|
|
|
|
): obj is ServerMessage {
|
2022-01-07 17:43:05 +01:00
|
|
|
if (typeof obj !== "object") return false;
|
|
|
|
if (obj === null) return false;
|
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "type") ||
|
2022-01-07 18:28:34 +01:00
|
|
|
typeof (obj as { type: unknown }).type !== "number" ||
|
2022-01-08 15:52:37 +01:00
|
|
|
(type === undefined &&
|
|
|
|
!Object.hasOwnProperty.call(
|
|
|
|
MessageType,
|
|
|
|
(obj as { type: number }).type
|
|
|
|
)) ||
|
|
|
|
(type !== undefined && (obj as { type: number }).type !== type)
|
2022-01-07 17:43:05 +01:00
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "date") ||
|
|
|
|
typeof (obj as { date: unknown }).date !== "number"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-01-08 16:21:02 +01:00
|
|
|
if (
|
|
|
|
Object.hasOwnProperty.call(obj, "__ctx") &&
|
|
|
|
typeof (obj as { __ctx: unknown }).__ctx !== "string" &&
|
|
|
|
typeof (obj as { __ctx: unknown }).__ctx !== "undefined"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-01-07 17:43:05 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type TextMessage = ServerMessage & {
|
|
|
|
type: MessageType.TEXT;
|
2022-01-08 17:12:38 +01:00
|
|
|
author: string;
|
2022-01-07 17:43:05 +01:00
|
|
|
content: string;
|
|
|
|
};
|
|
|
|
export function isTextMessage(obj: unknown): obj is TextMessage {
|
2022-01-08 15:52:37 +01:00
|
|
|
if (!isServerMessage(obj, MessageType.TEXT)) return false;
|
2022-01-07 17:43:05 +01:00
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "author") ||
|
2022-01-08 17:12:38 +01:00
|
|
|
typeof (obj as ServerMessage & { author: unknown }).author !== "string"
|
2022-01-07 17:43:05 +01:00
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "author") ||
|
|
|
|
typeof (obj as ServerMessage & { content: unknown }).content !== "string"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type AckMessage = ServerMessage & {
|
|
|
|
type: MessageType.ACK;
|
|
|
|
};
|
|
|
|
export function isAckMessage(obj: unknown): obj is AckMessage {
|
2022-01-08 15:52:37 +01:00
|
|
|
return isServerMessage(obj, MessageType.ACK);
|
2022-01-07 17:43:05 +01:00
|
|
|
}
|
2022-01-08 17:22:17 +01:00
|
|
|
|
|
|
|
export type IdResponseMessage = ServerMessage & {
|
|
|
|
type: MessageType.ID_RESPONSE;
|
|
|
|
authorId: string;
|
|
|
|
};
|
|
|
|
export function isIdResponseMessage(obj: unknown): obj is IdResponseMessage {
|
|
|
|
if (!isServerMessage(obj, MessageType.ID_RESPONSE)) return false;
|
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "authorId") ||
|
|
|
|
typeof (obj as ServerMessage & { authorId: unknown }).authorId !== "string"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-14 14:29:42 +01:00
|
|
|
|
|
|
|
export type TypingMessage = ServerMessage & {
|
|
|
|
type: MessageType.TYPING;
|
2022-01-17 16:16:46 +01:00
|
|
|
};
|
2022-01-14 14:29:42 +01:00
|
|
|
export function isTypingMessage(obj: unknown): obj is TypingMessage {
|
2022-01-14 14:32:30 +01:00
|
|
|
return isServerMessage(obj, MessageType.TYPING);
|
2022-01-14 14:29:42 +01:00
|
|
|
}
|
2022-01-17 16:16:46 +01:00
|
|
|
|
|
|
|
export type CurrentlyTypingMessage = ServerMessage & {
|
|
|
|
type: MessageType.CURRENTLY_TYPING;
|
|
|
|
currently: string[];
|
|
|
|
};
|
|
|
|
export function isCurrentlyTypingMessage(
|
|
|
|
obj: unknown
|
|
|
|
): obj is CurrentlyTypingMessage {
|
|
|
|
if (!isServerMessage(obj, MessageType.CURRENTLY_TYPING)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!Object.hasOwnProperty.call(obj, "currently") ||
|
|
|
|
typeof obj !== "object" ||
|
2022-01-21 12:59:39 +01:00
|
|
|
!Array.isArray((obj as ServerMessage & { currently: unknown }).currently) ||
|
|
|
|
!Array.prototype.every.call(
|
2022-01-17 16:16:46 +01:00
|
|
|
(obj as ServerMessage & { currently: unknown[] }).currently,
|
2022-01-21 12:59:39 +01:00
|
|
|
(element) => typeof element === "string"
|
2022-01-17 16:16:46 +01:00
|
|
|
)
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-21 12:59:39 +01:00
|
|
|
|
|
|
|
export type ConnectedUser = {
|
|
|
|
id: string;
|
|
|
|
desiredName?: string;
|
|
|
|
};
|
|
|
|
export function isConnectedUser(obj: unknown): obj is ConnectedUser {
|
|
|
|
if (typeof obj !== "object" || obj === null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!Object.prototype.hasOwnProperty.call(obj, "id") ||
|
|
|
|
typeof (obj as { id: unknown }).id !== "string"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
Object.prototype.hasOwnProperty.call(obj, "desiredName") &&
|
|
|
|
typeof (obj as { desiredName: unknown }).desiredName !== "string"
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type ConnectedUsersMessage = ServerMessage & {
|
|
|
|
type: MessageType.CONNECTED_USERS;
|
|
|
|
connected: ConnectedUser[];
|
|
|
|
};
|
|
|
|
export function isConnectedUsersMessage(
|
|
|
|
obj: unknown
|
|
|
|
): obj is ConnectedUsersMessage {
|
|
|
|
if (!isServerMessage(obj, MessageType.CONNECTED_USERS)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
typeof (obj as ServerMessage & { connected: unknown }).connected !==
|
|
|
|
"object" ||
|
|
|
|
!Array.isArray((obj as ServerMessage & { connected: unknown }).connected)
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
!Array.prototype.every.call(
|
|
|
|
(obj as ServerMessage & { connected: unknown[] }).connected,
|
|
|
|
(maybeUser) => isConnectedUser(maybeUser)
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|