diff --git a/src/controllers/UserWebSocketController.ts b/src/controllers/UserWebSocketController.ts index c7854aa..4ca57e4 100644 --- a/src/controllers/UserWebSocketController.ts +++ b/src/controllers/UserWebSocketController.ts @@ -9,6 +9,7 @@ import { RequestHandler } from '../entities/RequestHandler'; import { time } from '../utils/DateUtils'; import { randomStr } from '../utils/CryptUtils'; import { EventsHelper } from '../helpers/EventsHelper'; +import { NotificationsHelper } from '../helpers/NotificationsHelper'; interface PendingRequests { time: number, @@ -18,11 +19,18 @@ interface PendingRequests { } interface ActiveClient { + socketID: string, clientID: number, userID: number, ws: ws } +interface WsMessage { + id: string, + title: string, + data: any +} + // Tokens are valid only 10 seconds after they are generated const TOKENS_DURATION = 10 const TOKEN_LENGTH = 20 @@ -105,6 +113,7 @@ export class UserWebSocketController { // Add the client to the list of active clients const client: ActiveClient = { + socketID: randomStr(30), clientID: entry.clientID, userID: entry.userID, ws: ws @@ -150,7 +159,59 @@ export class UserWebSocketController { for(const entry of this.active_clients.filter((f) => f.clientID == clientID && f.userID == userID)) entry.ws.close(); } + + /** + * Send a message to a socket + * + * @param userID Target user ID + * @param socketID Target socket ID (if null the message is sent to + * all the active sockets of the user) + * @param message The message to send + */ + public static Send(userID: number, socketID: string, message: WsMessage) { + for(const entry of this.active_clients.filter( + (e) => e.userID == userID + && (socketID.length == 0 || e.socketID == socketID))) + { + if(entry.ws.readyState == ws.OPEN) + entry.ws.send(JSON.stringify(message)); + } + } + + /** + * Check out whether a user has an active websocket or not + * + * @param userID Target user ID + */ + public static IsConnected(userID: number) : boolean { + return this.active_clients.find((e) => e.userID == userID) != undefined; + } + + /** + * Send updated notifications number to some users + * + * @param usersID Target users ID + */ + public static async SendNewNotificationsNumber(usersID: number[]) { + + // Process each user + for(const userID of usersID) { + if(!this.IsConnected(userID)) + continue; + + // Notify user + this.Send(userID, "", { + title: "number_notifs", + id: "", + data: await NotificationsHelper.CountUnread(userID) + }); + } + + } } // When user sign out -EventsHelper.Listen("destroyed_login_tokens", (e) => UserWebSocketController.CloseClientSockets(e.client.id, e.userID)); \ No newline at end of file +EventsHelper.Listen("destroyed_login_tokens", (e) => UserWebSocketController.CloseClientSockets(e.client.id, e.userID)); + +// When we get a new number of notifications +EventsHelper.Listen("updated_number_notifications", async (e) => await UserWebSocketController.SendNewNotificationsNumber(e.usersID)); \ No newline at end of file diff --git a/src/helpers/EventsHelper.ts b/src/helpers/EventsHelper.ts index 528ceb0..de0d3fe 100644 --- a/src/helpers/EventsHelper.ts +++ b/src/helpers/EventsHelper.ts @@ -13,11 +13,17 @@ export interface DestroyedLoginTokensEvent { client: APIClient } +// When some user might have an updated number of notifications +export interface UpdatedNotificationsNumberEvent { + usersID: number[] +} + /** * Global map of all possible events */ export interface EventsMap { - "destroyed_login_tokens": DestroyedLoginTokensEvent + "destroyed_login_tokens": DestroyedLoginTokensEvent, + "updated_number_notifications": UpdatedNotificationsNumberEvent, } export class EventsHelper { diff --git a/src/helpers/NotificationsHelper.ts b/src/helpers/NotificationsHelper.ts index 8232c27..d6cded1 100644 --- a/src/helpers/NotificationsHelper.ts +++ b/src/helpers/NotificationsHelper.ts @@ -6,6 +6,7 @@ import { PostPageKind, PostVisibilityLevel } from "../entities/Post"; import { FriendsHelper } from "./FriendsHelper"; import { GroupsHelper } from "./GroupsHelper"; import { GroupMembershipLevels } from "../entities/GroupMember"; +import { EventsHelper } from "./EventsHelper"; /** * Notifications helper @@ -308,6 +309,9 @@ export class NotificationsHelper { NOTIFICATIONS_TABLE, this.NotifToDB(n, true) ) + + // Trigger notify system + await EventsHelper.Emit("updated_number_notifications", {usersID: [n.destUserID]}); } /**