public ChatMessageTable(MessageMessage msg, ChatTable chat) { switch (msg.TYPE) { case MessageMessage.TYPE_ERROR: id = generateErrorMessageId(msg.ID, chat.id); fromUser = msg.getFrom(); break; case MessageMessage.TYPE_GROUPCHAT: id = generateId(msg.ID, chat.id); fromUser = msg.FROM_NICK; break; default: id = generateId(msg.ID, chat.id); fromUser = Utils.getBareJidFromFullJid(msg.getFrom()); break; } stableId = msg.ID; chatId = chat.id; type = msg.TYPE; message = msg.MESSAGE; date = msg.delay; isDummyMessage = false; if (date.Equals(DateTime.MinValue)) { date = DateTime.Now; } state = msg.CC_TYPE == XMPP_API.Classes.Network.XML.CarbonCopyType.SENT ? MessageState.SEND : MessageState.UNREAD; isImage = isMessageAnImageUrl(msg.MESSAGE); isCC = msg.CC_TYPE != XMPP_API.Classes.Network.XML.CarbonCopyType.NONE; isEncrypted = msg is OmemoMessageMessage; isFavorite = false; }
public async Task <bool> OnNewChatMessage(MessageMessage msg, string deviceFullJid, Client client) { string fromFullJid = msg.getFrom(); string fromBareJid = Utils.getBareJidFromFullJid(fromFullJid); // Send the response: if (string.Equals(fromBareJid, deviceFullJid)) { MessageMessage response = new MessageMessage(client.dbAccount.fullJid.FullJid(), fromBareJid, msg.MESSAGE, MessageMessage.TYPE_CHAT, true); await client.xmppClient.SendAsync(response); await AddIoTDevice(fromBareJid, client); return(true); } return(false); }
private async void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events.NewChatMessageEventArgs args) { MessageMessage msg = args.getMessage(); // Handel MUC room subject messages: if (msg is MUCRoomSubjectMessage) { MUCHandler.INSTANCE.onMUCRoomSubjectMessage(msg as MUCRoomSubjectMessage); return; } string from = Utils.getBareJidFromFullJid(msg.getFrom()); string to = Utils.getBareJidFromFullJid(msg.getTo()); string id; if (msg.CC_TYPE == CarbonCopyType.SENT) { id = ChatTable.generateId(to, from); } else { id = ChatTable.generateId(from, to); } // Check if device id is valid and if, decrypt the OMEMO messages: if (msg is OmemoMessageMessage omemoMessage) { OmemoHelper helper = client.getOmemoHelper(); if (helper is null) { C_OmemoSessionBuildError(client, new OmemoSessionBuildErrorEventArgs(id, OmemoSessionBuildError.KEY_ERROR, new List <OmemoMessageMessage> { omemoMessage })); Logger.Error("Failed to decrypt OMEMO message - OmemoHelper is null"); return; } else if (!client.getXMPPAccount().checkOmemoKeys()) { C_OmemoSessionBuildError(client, new OmemoSessionBuildErrorEventArgs(id, OmemoSessionBuildError.KEY_ERROR, new List <OmemoMessageMessage> { omemoMessage })); Logger.Error("Failed to decrypt OMEMO message - keys are corrupted"); return; } else if (!await omemoMessage.decryptAsync(client.getOmemoHelper(), client.getXMPPAccount().omemoDeviceId)) { return; } } ChatTable chat = ChatDBManager.INSTANCE.getChat(id); bool chatChanged = false; // Spam detection: if (Settings.getSettingBoolean(SettingsConsts.SPAM_DETECTION_ENABLED)) { if (Settings.getSettingBoolean(SettingsConsts.SPAM_DETECTION_FOR_ALL_CHAT_MESSAGES) || chat is null) { if (SpamDBManager.INSTANCE.isSpam(msg.MESSAGE)) { Logger.Warn("Received spam message from " + from); return; } } } if (chat is null) { chatChanged = true; chat = new ChatTable(from, to) { lastActive = msg.getDelay(), chatType = string.Equals(msg.TYPE, MessageMessage.TYPE_GROUPCHAT) ? ChatType.MUC : ChatType.CHAT }; } ChatMessageTable message = new ChatMessageTable(msg, chat); // Handle MUC invite messages: if (msg is DirectMUCInvitationMessage) { DirectMUCInvitationMessage inviteMessage = msg as DirectMUCInvitationMessage; bool doesRoomExist = ChatDBManager.INSTANCE.doesMUCExist(ChatTable.generateId(inviteMessage.ROOM_JID, msg.getTo())); bool doesOutstandingInviteExist = ChatDBManager.INSTANCE.doesOutstandingMUCInviteExist(id, inviteMessage.ROOM_JID); if (doesRoomExist && doesOutstandingInviteExist) { return; } MUCDirectInvitationTable inviteTable = new MUCDirectInvitationTable(inviteMessage, message.id); ChatDBManager.INSTANCE.setMUCDirectInvitation(inviteTable); } bool isMUCMessage = string.Equals(MessageMessage.TYPE_GROUPCHAT, message.type); ChatMessageTable existingMessage = ChatDBManager.INSTANCE.getChatMessageById(message.id); bool doesMessageExist = existingMessage != null; if (isMUCMessage) { MUCChatInfoTable mucInfo = MUCDBManager.INSTANCE.getMUCInfo(chat.id); if (mucInfo != null) { if (Equals(message.fromUser, mucInfo.nickname)) { // Filter MUC messages that already exist: // ToDo: Allow MUC messages being edited and detect it if (doesMessageExist) { return; } else { message.state = MessageState.SEND; } } else { if (doesMessageExist) { message.state = existingMessage.state; } } } } if (chat.lastActive.CompareTo(msg.getDelay()) < 0) { chatChanged = true; chat.lastActive = msg.getDelay(); } if (chatChanged) { ChatDBManager.INSTANCE.setChat(chat, false, true); } // Send XEP-0184 (Message Delivery Receipts) reply: if (msg.RECIPT_REQUESTED && id != null && !Settings.getSettingBoolean(SettingsConsts.DONT_SEND_CHAT_MESSAGE_RECEIVED_MARKERS)) { await Task.Run(async() => { DeliveryReceiptMessage receiptMessage = new DeliveryReceiptMessage(client.getXMPPAccount().getFullJid(), from, msg.ID); await client.sendAsync(receiptMessage); }); } ChatDBManager.INSTANCE.setChatMessage(message, !doesMessageExist, doesMessageExist && !isMUCMessage); // Show toast: if (!doesMessageExist && !chat.muted) { await Task.Run(() => { try { switch (msg.TYPE) { case MessageMessage.TYPE_GROUPCHAT: case MessageMessage.TYPE_CHAT: if (!message.isCC) { if (message.isImage) { ToastHelper.showChatTextImageToast(message, chat); } else { ToastHelper.showChatTextToast(message, chat); } } break; default: break; } } catch (Exception e) { Logger.Error("Failed to send toast notification!", e); } }); } }
private void C_NewChatMessage(XMPPClient client, XMPP_API.Classes.Network.Events.NewChatMessageEventArgs args) { MessageMessage msg = args.getMessage(); // Handel MUC room subject messages: if (msg is MUCRoomSubjectMessage) { MUCHandler.INSTANCE.onMUCRoomSubjectMessage(msg as MUCRoomSubjectMessage); return; } string from = Utils.getBareJidFromFullJid(msg.getFrom()); // Check if device id is valid and if, decrypt the OMEMO messages: if (msg is OmemoMessageMessage omemoMessage) { // Decryption failed: if (!omemoMessage.decrypt(client.getOmemoHelper(), client.getXMPPAccount().omemoDeviceId)) { return; } } string to = Utils.getBareJidFromFullJid(msg.getTo()); string id; if (msg.CC_TYPE == CarbonCopyType.SENT) { id = ChatTable.generateId(to, from); } else { id = ChatTable.generateId(from, to); } ChatTable chat = ChatDBManager.INSTANCE.getChat(id); bool chatChanged = false; if (chat == null) { chatChanged = true; chat = new ChatTable() { id = id, chatJabberId = from, userAccountId = to, ask = null, inRoster = false, lastActive = msg.getDelay(), muted = false, presence = Presence.Unavailable, status = null, subscription = null, chatType = Equals(msg.TYPE, MessageMessage.TYPE_GROUPCHAT) ? ChatType.MUC : ChatType.CHAT, }; } ChatMessageTable message = new ChatMessageTable(msg, chat); // Handle MUC invite messages: if (msg is DirectMUCInvitationMessage) { DirectMUCInvitationMessage inviteMessage = msg as DirectMUCInvitationMessage; bool doesRoomExist = ChatDBManager.INSTANCE.doesMUCExist(ChatTable.generateId(inviteMessage.ROOM_JID, msg.getTo())); bool doesOutstandingInviteExist = ChatDBManager.INSTANCE.doesOutstandingMUCInviteExist(id, inviteMessage.ROOM_JID); if (doesRoomExist && doesOutstandingInviteExist) { return; } MUCDirectInvitationTable inviteTable = new MUCDirectInvitationTable(inviteMessage, message.id); ChatDBManager.INSTANCE.setMUCDirectInvitation(inviteTable); } bool isMUCMessage = string.Equals(MessageMessage.TYPE_GROUPCHAT, message.type); ChatMessageTable existingMessage = ChatDBManager.INSTANCE.getChatMessageById(message.id); bool doesMessageExist = existingMessage != null; if (isMUCMessage) { MUCChatInfoTable mucInfo = MUCDBManager.INSTANCE.getMUCInfo(chat.id); if (mucInfo != null) { if (Equals(message.fromUser, mucInfo.nickname)) { // Filter MUC messages that already exist: // ToDo: Allow MUC messages being edited and detect it if (doesMessageExist) { return; } else { message.state = MessageState.SEND; } } else { if (doesMessageExist) { message.state = existingMessage.state; } } } } if (chat.lastActive.CompareTo(msg.getDelay()) < 0) { chatChanged = true; chat.lastActive = msg.getDelay(); } if (chatChanged) { ChatDBManager.INSTANCE.setChat(chat, false, true); } // Send XEP-0184 (Message Delivery Receipts) reply: if (msg.RECIPT_REQUESTED && id != null && !Settings.getSettingBoolean(SettingsConsts.DONT_SEND_CHAT_MESSAGE_RECEIVED_MARKERS)) { Task.Run(async() => { DeliveryReceiptMessage receiptMessage = new DeliveryReceiptMessage(client.getXMPPAccount().getIdDomainAndResource(), from, msg.ID); await client.sendAsync(receiptMessage, true); }); } ChatDBManager.INSTANCE.setChatMessage(message, !doesMessageExist, doesMessageExist && !isMUCMessage); // Show toast: if (!doesMessageExist && !chat.muted) { Task.Run(() => { try { if (!msg.toasted) { switch (msg.TYPE) { case MessageMessage.TYPE_GROUPCHAT: case MessageMessage.TYPE_CHAT: if (!message.isCC) { if (message.isEncrypted) { ToastHelper.showChatTextEncryptedToast(message, chat); } else if (message.isImage) { ToastHelper.showChatTextImageToast(message, chat); } else { ToastHelper.showChatTextToast(message, chat); } } break; default: break; } msg.setToasted(); } } catch (Exception e) { Logger.Error("Failed to send toast notification!", e); } }); } }
public async Task HandleNewChatMessageAsync(MessageMessage msg) { // Handel MUC room subject messages: if (msg is MUCRoomSubjectMessage) { MucHandler.INSTANCE.OnMUCRoomSubjectMessage(msg as MUCRoomSubjectMessage); return; } string from = Utils.getBareJidFromFullJid(msg.getFrom()); string to = Utils.getBareJidFromFullJid(msg.getTo()); string chatBareJid = string.Equals(from, client.dbAccount.bareJid) ? to : from; SemaLock semaLock = DataCache.INSTANCE.NewChatSemaLock(); ChatModel chat = DataCache.INSTANCE.GetChat(client.dbAccount.bareJid, chatBareJid, semaLock); bool newChat = chat is null; bool chatChanged = false; // Spam detection: if (Settings.GetSettingBoolean(SettingsConsts.SPAM_DETECTION_ENABLED)) { if (Settings.GetSettingBoolean(SettingsConsts.SPAM_DETECTION_FOR_ALL_CHAT_MESSAGES) || newChat) { if (SpamHelper.INSTANCE.IsSpam(msg.MESSAGE)) { Logger.Warn("Received spam message from " + chatBareJid); return; } } } // Detect invalid chat messages: if (!string.Equals(msg.TYPE, MessageMessage.TYPE_CHAT) && !string.Equals(msg.TYPE, MessageMessage.TYPE_ERROR) && !string.Equals(msg.TYPE, MessageMessage.TYPE_GROUPCHAT)) { Logger.Warn($"Received an unknown message type ('{msg.TYPE}') form '{chatBareJid}'. Dropping it."); return; } // Add the new chat to the DB since it's expected to be there by for example our OMEMO encryption: if (newChat) { chat = new ChatModel(chatBareJid, client.dbAccount) { lastActive = msg.delay, chatType = string.Equals(msg.TYPE, MessageMessage.TYPE_GROUPCHAT) ? ChatType.MUC : ChatType.CHAT, isChatActive = false // Mark chat as inactive until we can be sure, it's a valid message }; DataCache.INSTANCE.AddChatUnsafe(chat, client); } else { // Mark chat as active: chat.isChatActive = true; chatChanged = true; } semaLock.Dispose(); // Check if device id is valid and if, decrypt the OMEMO messages: if (msg is OmemoEncryptedMessage omemoMessage) { OmemoHelper helper = client.xmppClient.getOmemoHelper(); if (helper is null) { OnOmemoSessionBuildError(client.xmppClient, new OmemoSessionBuildErrorEventArgs(chatBareJid, OmemoSessionBuildError.KEY_ERROR, new List <OmemoEncryptedMessage> { omemoMessage })); Logger.Error("Failed to decrypt OMEMO message - OmemoHelper is null"); return; } else if (!await DecryptOmemoEncryptedMessageAsync(omemoMessage, !newChat && chat.omemoInfo.trustedKeysOnly)) { if (newChat) { // We failed to decrypt, so this chat could be spam. Delete it again... DataCache.INSTANCE.DeleteChat(chat, false, false); Logger.Debug($"Deleting chat '{chat.bareJid}' again, since decrypting the initial OMEMO message failed."); } return; } else if (omemoMessage.IS_PURE_KEY_EXCHANGE_MESSAGE) { return; } } // Valid new chat, so we can change it to active now: chat.isChatActive = true; chatChanged = true; ChatMessageModel message = null; if (!newChat) { message = DataCache.INSTANCE.GetChatMessage(chat.id, msg.ID); } // Filter messages that already exist: // ToDo: Allow MUC messages being edited and detect it if (!(message is null)) { Logger.Debug("Duplicate message received from '" + chatBareJid + "'. Dropping it..."); return; } message = new ChatMessageModel(msg, chat); // Set the image path and file name: if (message.isImage) { await DataCache.PrepareImageModelPathAndNameAsync(message.image); } DataCache.INSTANCE.AddChatMessage(message, chat); // Handle MUC invite messages: if (msg is DirectMUCInvitationMessage inviteMessage) { if (!newChat) { Logger.Info("Ignoring received MUC direct invitation form '" + chatBareJid + "' since we already joined this MUC (" + inviteMessage.ROOM_JID + ")."); return; } // Ensure we add the message to the DB before we add the invite since the invite has the message as a foreign key: using (MainDbContext ctx = new MainDbContext()) { ctx.Add(new MucDirectInvitationModel(inviteMessage, message)); } } bool isMUCMessage = string.Equals(MessageMessage.TYPE_GROUPCHAT, message.type); if (chat.lastActive.CompareTo(msg.delay) < 0) { chatChanged = true; chat.lastActive = msg.delay; } // Send XEP-0184 (Message Delivery Receipts) reply: if (msg.RECIPT_REQUESTED && !Settings.GetSettingBoolean(SettingsConsts.DONT_SEND_CHAT_MESSAGE_RECEIVED_MARKERS)) { await Task.Run(async() => { DeliveryReceiptMessage receiptMessage = new DeliveryReceiptMessage(client.dbAccount.fullJid.FullJid(), from, msg.ID); await client.xmppClient.SendAsync(receiptMessage); }); } if (chatChanged) { chat.Update(); chatChanged = false; } // Show toast: if (!chat.muted) { await Task.Run(() => { try { switch (msg.TYPE) { case MessageMessage.TYPE_GROUPCHAT: case MessageMessage.TYPE_CHAT: if (!message.isCC) { // Create toast: if (message.isImage) { ToastHelper.ShowChatTextImageToast(message, chat); } else { ToastHelper.ShowChatTextToast(message, chat); } // Update badge notification count: ToastHelper.UpdateBadgeNumber(); } break; default: break; } } catch (Exception e) { Logger.Error("Failed to send toast notification!", e); } }); } }