import { Misc } from "./misc.js"; import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; /** * Class providing helper methods to get the list of users, and */ export class ChatUtility { static async init() { Hooks.on("renderChatMessage", async (app, html, msg) => await ChatUtility.onRenderChatMessage(app, html, msg)) Hooks.on("createChatMessage", async (chatMessage, options, id) => await ChatUtility.onCreateChatMessage(chatMessage, options, id)) } /* -------------------------------------------- */ static onSocketMessage(sockmsg) { switch (sockmsg.msg) { case "msg_gm_chat_message": return ChatUtility.handleGMChatMessage(sockmsg.data) case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.data) case "msg_user_ui_notifications": return ChatUtility.onNotifyUser(sockmsg.data) } } /* -------------------------------------------- */ static notifyUser(userId, level = 'info', message) { const socketData = { userId: userId, level: level, message: message }; if (game.user.id == userId) { ChatUtility.onNotifyUser(socketData); } else { game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_user_ui_notifications", data: socketData }); } } static onNotifyUser(socketData) { if (game.user.id == socketData.userId) { switch (socketData.level) { case 'warn': ui.notifications.warn(socketData.message); break; case 'error': ui.notifications.error(socketData.message); break; default: ui.notifications.info(socketData.message); break; } } } /* -------------------------------------------- */ static onRemoveMessages(socketData) { if (Misc.isUniqueConnectedGM()) { if (socketData.part) { const toDelete = game.messages.filter(it => it.content.includes(socketData.part)); toDelete.forEach(it => it.delete()); } if (socketData.messageId) { game.messages.get(socketData.messageId)?.delete(); } } } /* -------------------------------------------- */ static removeMessages(socketData) { if (Misc.isUniqueConnectedGM()) { ChatUtility.onRemoveMessages(socketData); } else { game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: socketData }); } } /* -------------------------------------------- */ static removeChatMessageContaining(part) { ChatUtility.removeMessages({ part: part }); } static removeChatMessageId(messageId) { if (messageId) { ChatUtility.removeMessages({ messageId: messageId }); } } /* -------------------------------------------- */ static async createChatWithRollMode(messageData, actor = undefined) { switch (game.settings.get("core", "rollMode")) { case "blindroll": // GM only if (!game.user.isGM) { ChatUtility.blindMessageToGM(messageData) messageData.whisper = [game.user]; messageData.content = "Message envoyé en aveugle au Gardien" } else { messageData.whisper = ChatUtility.getGMs() } break case "gmroll": messageData.whisper = ChatUtility.getOwners(actor) break case "selfroll": messageData.whisper = [game.user] break } messageData.alias = messageData.alias ?? actor?.name ?? game.user.name return await ChatMessage.create(messageData) } static getOwners(document) { return game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) } static getUserAndGMs() { return [game.user, ...ChatUtility.getGMs()] } /* -------------------------------------------- */ static getMultipleActorsOwners(...actors) { return Misc.concat(actors.map(it => it == undefined ? [] : ChatUtility.getOwners(it))) } /* -------------------------------------------- */ static getUsers(filter) { return game.users.filter(filter) } static getGMs() { return game.users.filter(user => user.isGM) } static applyRollMode(chatMessageData = {}, rollMode = game.settings.get("core", "rollMode")) { switch (rollMode) { case "blindroll": chatMessageData.blind = true chatMessageData.whisper = ChatUtility.getGMs() break case "gmroll": chatMessageData.whisper = ChatUtility.getGMs() chatMessageData.blind = false break case "roll": chatMessageData.whisper = ChatUtility.getUsers(user => user.active) chatMessageData.blind = false break case "selfroll": chatMessageData.whisper = [game.user] chatMessageData.blind = false break } return chatMessageData } /* -------------------------------------------- */ static blindMessageToGM(chatOptions) { const chatGM = foundry.utils.duplicate(chatOptions) chatGM.content = "Message aveugle de " + game.user.name + "
" + chatOptions.content console.log("blindMessageToGM", chatGM) game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_gm_chat_message", data: chatGM }) } /* -------------------------------------------- */ static handleGMChatMessage(socketData) { console.log("blindMessageToGM", socketData); if (Misc.firstConnectedGM()) { ChatMessage.create({ user: game.user.id, whisper: ChatUtility.getGMs(), content: socketData.content }) } } static async setMessageData(chatMessage, key, flag) { if (flag && chatMessage.isAuthor) { await chatMessage.setFlag(SYSTEM_RDD, key, flag) } } static getMessageData(chatMessage, key) { return chatMessage.getFlag(SYSTEM_RDD, key); } static getChatMessage(event) { const chatMessageId = $(event.currentTarget).closest('.chat-message').attr('data-message-id'); return game.messages.get(chatMessageId); } static async onRenderChatMessage(chatMessage, html, data) { const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp') if (rddTimestamp) { const timestamp = new RdDTimestamp(rddTimestamp); const timestampData = timestamp.toCalendrier(); const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData); html.find('header.message-header .message-sender').after(dateHeure) } } static async onCreateChatMessage(chatMessage, options, id) { if (chatMessage.isAuthor) { await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); } } }