diff --git a/src/controllers/CommentsController.ts b/src/controllers/CommentsController.ts index 93ec850..f70432c 100644 --- a/src/controllers/CommentsController.ts +++ b/src/controllers/CommentsController.ts @@ -6,6 +6,7 @@ import { time } from "../utils/DateUtils"; import { CommentsHelper } from "../helpers/CommentsHelper"; import { NotifEventType } from "../entities/Notification"; import { NotificationsHelper } from "../helpers/NotificationsHelper"; +import { AbstractUserConnectionContainer } from "../entities/UserConnectionContainer"; /** * Comments controller @@ -145,7 +146,7 @@ export class CommentsController { * @param h Request handler * @param c Comment */ - public static async CommentToAPI(h: RequestHandler, c: Comment) : Promise { + public static async CommentToAPI(h: AbstractUserConnectionContainer, c: Comment) : Promise { return { ID: c.id, userID: c.userID, diff --git a/src/controllers/UserWebSocketActions.ts b/src/controllers/UserWebSocketActions.ts index 1c22d85..3ae7990 100644 --- a/src/controllers/UserWebSocketActions.ts +++ b/src/controllers/UserWebSocketActions.ts @@ -13,6 +13,9 @@ import { EventsHelper } from "../helpers/EventsHelper"; import { ConversationMessage } from "../entities/ConversationMessage"; import { ConversationsController } from "./ConversationsController"; import { PostAccessLevel } from "../entities/Post"; +import { Comment } from "../entities/Comment"; +import { CommentsController } from "./CommentsController"; +import { AbritraryUserConnection } from "../entities/UserConnectionContainer"; export class UserWebSocketActions { @@ -122,7 +125,7 @@ export class UserWebSocketActions { for(const client of UserWebSocketController.active_clients.filter( (e) => e.registeredConversations.has(msg.convID))) { - UserWebSocketController.Send(client.userID, client.socketID, new WsMessage({ + UserWebSocketController.SendToClient(client, new WsMessage({ id: "", title: "new_conv_message", data: ConversationsController.ConversationMessageToAPI(msg) @@ -132,6 +135,24 @@ export class UserWebSocketActions { } } + + /** + * Propagate the creation of a new comment + * + * @param c New comment + */ + public static async CreatedNewComment(c: Comment) { + + for(const client of UserWebSocketController.active_clients.filter((e) => e.registeredPosts.has(c.postID))) { + + UserWebSocketController.SendToClient(client, new WsMessage({ + id: "", + title: "new_comment", + data: await CommentsController.CommentToAPI(new AbritraryUserConnection(client.userID), c) + })) + + } + } } @@ -142,4 +163,7 @@ EventsHelper.Listen("updated_number_notifications", async (e) => await UserWebSo EventsHelper.Listen("updated_number_unread_conversations", async (e) => await UserWebSocketActions.SendNewUnreadConversationsCount(e.usersID)); // When a new message is sent -EventsHelper.Listen("sent_conversation_message", async (e) => await UserWebSocketActions.SentNewConversationMessage(e.msg)); \ No newline at end of file +EventsHelper.Listen("sent_conversation_message", async (e) => await UserWebSocketActions.SentNewConversationMessage(e.msg)); + +// When a comment is created +EventsHelper.Listen("comment_created", async (e) => await UserWebSocketActions.CreatedNewComment(e.comment)) \ No newline at end of file diff --git a/src/controllers/UserWebSocketController.ts b/src/controllers/UserWebSocketController.ts index f15b830..0bf4066 100644 --- a/src/controllers/UserWebSocketController.ts +++ b/src/controllers/UserWebSocketController.ts @@ -221,11 +221,21 @@ export class UserWebSocketController { (e) => e.userID == userID && (socketID.length == 0 || e.socketID == socketID))) { - if(entry.ws.readyState == ws.OPEN) - entry.ws.send(JSON.stringify(message)); + this.SendToClient(entry, message); } } + /** + * Send a message to a specific client + * + * @param client Target client + * @param message The message to send + */ + public static SendToClient(client: ActiveClient, message: WsMessage) { + if(client.ws.readyState == ws.OPEN) + client.ws.send(JSON.stringify(message)); + } + /** * Check out whether a user has an active websocket or not * diff --git a/src/entities/BaseRequestsHandler.ts b/src/entities/BaseRequestsHandler.ts index b960c08..faba6bd 100644 --- a/src/entities/BaseRequestsHandler.ts +++ b/src/entities/BaseRequestsHandler.ts @@ -15,8 +15,9 @@ import { PostAccessLevel } from "./Post"; import { CommentsHelper } from "../helpers/CommentsHelper"; import { checkVirtualDirectory } from "../utils/VirtualDirsUtils"; import { ConversationsHelper } from "../helpers/ConversationsHelper"; +import { AbstractUserConnectionContainer } from "./UserConnectionContainer"; -export abstract class BaseRequestsHandler { +export abstract class BaseRequestsHandler implements AbstractUserConnectionContainer { protected abstract get userID() : number; diff --git a/src/entities/UserConnectionContainer.ts b/src/entities/UserConnectionContainer.ts new file mode 100644 index 0000000..b5b61ae --- /dev/null +++ b/src/entities/UserConnectionContainer.ts @@ -0,0 +1,29 @@ +/** + * Simple user connection container + * + * @author Pierre Hubert + */ + +export abstract class AbstractUserConnectionContainer { + public abstract getUserId() : number; + public abstract get signedIn() : boolean; +} + +/** + * Fake user connnection checker used for notifications in WebSockets + */ +export class AbritraryUserConnection implements AbstractUserConnectionContainer { + + constructor(private userID: number) {} + + public getUserId(): number { + if(!this.signedIn) + throw new Error("User is not signed in!"); + + return this.userID; + } + public get signedIn(): boolean { + return this.userID > 0; + } + +} \ No newline at end of file diff --git a/src/helpers/CommentsHelper.ts b/src/helpers/CommentsHelper.ts index 5a5c584..3b43b09 100644 --- a/src/helpers/CommentsHelper.ts +++ b/src/helpers/CommentsHelper.ts @@ -3,6 +3,7 @@ import { DatabaseHelper } from "./DatabaseHelper"; import { unlinkSync, existsSync } from "fs"; import { LikesHelper, LikesType } from "./LikesHelper"; import { mysql_date, time } from "../utils/DateUtils"; +import { EventsHelper } from "./EventsHelper"; /** * Comments helper @@ -20,7 +21,7 @@ export class CommentsHelper { * @param comment Information about the comment to create */ public static async Create(comment: Comment) : Promise { - return await DatabaseHelper.InsertRow(COMMENTS_TABLE, { + const commentID = await DatabaseHelper.InsertRow(COMMENTS_TABLE, { ID_texte: comment.postID, ID_personne: comment.userID, date_envoi: mysql_date(), @@ -28,6 +29,14 @@ export class CommentsHelper { commentaire: comment.content, image_commentaire: comment.hasImage ? comment.imagePath : "" }); + + // Propagate event + comment.id = commentID; + await EventsHelper.Emit("comment_created", { + comment: comment + }); + + return commentID } /** diff --git a/src/helpers/EventsHelper.ts b/src/helpers/EventsHelper.ts index ee0c555..4d25b8a 100644 --- a/src/helpers/EventsHelper.ts +++ b/src/helpers/EventsHelper.ts @@ -1,5 +1,6 @@ import { APIClient } from "../entities/APIClient"; import { ConversationMessage } from "../entities/ConversationMessage"; +import { Comment } from "../entities/Comment"; /** * Events manager @@ -28,6 +29,11 @@ export interface SentNewConversationMessageEvent { msg: ConversationMessage } +// When a comment is created +export interface CommentCreatedEvent { + comment: Comment +} + /** * Global map of all possible events */ @@ -35,7 +41,8 @@ export interface EventsMap { "destroyed_login_tokens": DestroyedLoginTokensEvent, "updated_number_notifications": UpdatedNotificationsNumberEvent, "updated_number_unread_conversations": UpdateNumberUnreadConversationsEvent, - "sent_conversation_message": SentNewConversationMessageEvent + "sent_conversation_message": SentNewConversationMessageEvent, + "comment_created": CommentCreatedEvent } export class EventsHelper {