- Implemented Last Message Sync

old/Message-History-Sync
Muhammad Khalid 3 years ago
parent be17e6bb46
commit 9b68d847e1

@ -24,7 +24,7 @@ import TigaseSwift
public class DBSchemaManager {
static let CURRENT_VERSION = 14;
static let CURRENT_VERSION = 15;
fileprivate let dbConnection: DBConnection;
@ -69,32 +69,6 @@ public class DBSchemaManager {
try dbConnection.execute("ALTER TABLE chat_history ADD COLUMN error TEXT;");
}
// let queryStmt = try dbConnection.prepareStatement("SELECT account, jid, encryption FROM chats WHERE encryption IS NOT NULL AND options IS NULL");
// let toConvert = try queryStmt.query { (cursor) -> (BareJID, BareJID, ChatEncryption)? in
// let account: BareJID = cursor["account"]!;
// let jid: BareJID = cursor["jid"]!;
// guard let encryptionStr: String = cursor["encryption"] else {
// return nil;
// }
// guard let encryption = ChatEncryption(rawValue: encryptionStr) else {
// return nil;
// }
//
// return (account, jid, encryption);
// }
// if !toConvert.isEmpty {
// let updateStmt = try dbConnection.prepareStatement("UPDATE chats SET options = ?, encryption = null WHERE account = ? AND jid = ?");
// try toConvert.forEach { (arg0) in
// let (account, jid, encryption) = arg0
// var options = ChatOptions();
// options.encryption = encryption;
// let data = try? JSONEncoder().encode(options);
// let dataStr = data != nil ? String(data: data!, encoding: .utf8)! : nil;
// _ = try updateStmt.update(dataStr, account, jid);
// }
// }
let toRemove: [(String,String,Int32)] = try dbConnection.prepareStatement("SELECT sess.account as account, sess.name as name, sess.device_id as deviceId FROM omemo_sessions sess WHERE NOT EXISTS (select 1 FROM omemo_identities i WHERE i.account = sess.account and i.name = sess.name and i.device_id = sess.device_id)").query([:] as [String: Any?], map: { (cursor:DBCursor) -> (String, String, Int32)? in
return (cursor["account"]!, cursor["name"]!, cursor["deviceId"]!);
});

@ -0,0 +1,13 @@
BEGIN;
CREATE TABLE IF NOT EXISTS last_message_sync (
id INTEGER PRIMARY KEY AUTOINCREMENT,
account TEXT NOT NULL COLLATE NOCASE,
jid TEXT NOT NULL COLLATE NOCASE,
received_id TEXT,
read_id TEXT
);
COMMIT;
PRAGMA user_version = 15;

@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
379D914A26E8A0E300B877CA /* db-schema-15.sql in Resources */ = {isa = PBXBuildFile; fileRef = 379D914926E8A0E300B877CA /* db-schema-15.sql */; };
379D914C26E8A29800B877CA /* DBLastMessageSyncStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 379D914B26E8A29800B877CA /* DBLastMessageSyncStore.swift */; };
E928AD4326D6A08A00F29F93 /* db-schema-14.sql in Resources */ = {isa = PBXBuildFile; fileRef = E928AD4226D6A08A00F29F93 /* db-schema-14.sql */; };
E95AA70226D38B6F00A38D44 /* DisplayNameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95AA70126D38B6E00A38D44 /* DisplayNameViewController.swift */; };
E963721026D786D000332482 /* BlockingCommandModuleExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E963720F26D786D000332482 /* BlockingCommandModuleExtension.swift */; };
@ -295,6 +297,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
379D914926E8A0E300B877CA /* db-schema-15.sql */ = {isa = PBXFileReference; lastKnownFileType = text; path = "db-schema-15.sql"; sourceTree = "<group>"; };
379D914B26E8A29800B877CA /* DBLastMessageSyncStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBLastMessageSyncStore.swift; sourceTree = "<group>"; };
E928AD4226D6A08A00F29F93 /* db-schema-14.sql */ = {isa = PBXFileReference; lastKnownFileType = text; path = "db-schema-14.sql"; sourceTree = "<group>"; };
E95AA70126D38B6E00A38D44 /* DisplayNameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayNameViewController.swift; sourceTree = "<group>"; };
E963720F26D786D000332482 /* BlockingCommandModuleExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockingCommandModuleExtension.swift; sourceTree = "<group>"; };
@ -659,6 +663,7 @@
FEE49DCF2426485500900BBB /* DBConnection_main.swift */,
FE3E387B242766A900D3A8E8 /* DBChannelStore.swift */,
FEBC12F324C70E2900689475 /* DBChatHistorySyncStore.swift */,
379D914B26E8A29800B877CA /* DBLastMessageSyncStore.swift */,
);
path = database;
sourceTree = "<group>";
@ -805,6 +810,7 @@
FE3BA0BF24B61583000C80D4 /* db-schema-12.sql */,
FEBC12F124C70DE000689475 /* db-schema-13.sql */,
E928AD4226D6A08A00F29F93 /* db-schema-14.sql */,
379D914926E8A0E300B877CA /* db-schema-15.sql */,
);
path = Shared;
sourceTree = "<group>";
@ -1183,6 +1189,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
379D914A26E8A0E300B877CA /* db-schema-15.sql in Resources */,
FE10BCF323FD4EF000E214F3 /* db-schema-10.sql in Resources */,
FE759FF22371F21C001E78D9 /* db-schema-6.sql in Resources */,
FE759FEF2371F21C001E78D9 /* db-schema-3.sql in Resources */,
@ -1415,6 +1422,7 @@
FE0E30F12535BB530030F8C5 /* BaseChatViewController+ShareFile.swift in Sources */,
FE507A251CDB7B3B001A015C /* AccountManager.swift in Sources */,
FEC79195241ABEF4007BE572 /* MessageState.swift in Sources */,
379D914C26E8A29800B877CA /* DBLastMessageSyncStore.swift in Sources */,
FE719E7C22730DC3007CEEC9 /* OMEMOIdentityTableViewCell.swift in Sources */,
FEDE93901D09BB8300CA60A9 /* VCardEditPhoneTableViewCell.swift in Sources */,
FE507A221CDB7B3B001A015C /* AvatarStatusView.swift in Sources */,

@ -450,7 +450,6 @@ public class DBChatHistoryStore {
let uuid = UUID();
previewsInProgress[masterId] = uuid;
previewGenerationDispatcher.async {
print("generating previews for master id:", masterId, "uuid:", uuid);
// if we may have previews, we should add them here..
if let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) {
let matches = detector.matches(in: data, range: NSMakeRange(0, data.utf16.count));
@ -464,7 +463,6 @@ public class DBChatHistoryStore {
}) else {
return;
}
print("adding previews for master id:", masterId, "uuid:", uuid);
matches.forEach { match in
if let url = match.url, let scheme = url.scheme, ["https", "http"].contains(scheme) {
if (data as NSString).range(of: "http", options: .caseInsensitive, range: match.range).location == match.range.location {

@ -0,0 +1,79 @@
//
// DBLastMessageSyncStore.swift
// Snikket
//
// Created by Hammad Ashraf on 08/09/2021.
// Copyright © 2021 Snikket. All rights reserved.
//
import Foundation
import TigaseSwift
import Shared
// Table last_message_sync :-
// account TEXT
// jid TEXT
// received_id TEXT
// read_id TEXT
class DBLastMessageSyncStore {
static let instance = DBLastMessageSyncStore()
fileprivate let dispatcher: QueueDispatcher;
private let insertLastMessage: DBStatement
private let getLastMessage: DBStatement
private let updateLastMessage: DBStatement
private init() {
insertLastMessage = try! DBConnection.main.prepareStatement("INSERT INTO last_message_sync (account, jid, received_id, read_id) VALUES (:account, :jid, :received_id, :read_id)")
updateLastMessage = try! DBConnection.main.prepareStatement("UPDATE last_message_sync SET received_id = :received_id, read_id = :read_id WHERE account = :account AND jid = :jid")
getLastMessage = try! DBConnection.main.prepareStatement("SELECT account, jid, received_id, read_id FROM last_message_sync WHERE account = :account AND jid = :jid")
dispatcher = QueueDispatcher(label: "last_message_sync")
}
func insertmessage(account: BareJID, jid: BareJID, receivedId: String?, readId: String?) {
let params: [String:Any?] = ["account":account, "jid":jid, "received_id": receivedId, "read_id":readId]
dispatcher.async {
_ = try! self.insertLastMessage.insert(params)
}
}
func updateMessage(account: BareJID, jid: BareJID, receivedId: String?, readId: String?) {
let params: [String:Any?] = ["account":account, "jid":jid, "received_id": receivedId, "read_id":readId]
dispatcher.async {
_ = try! self.updateLastMessage.update(params)
}
}
func getLastMessage(account: BareJID, jid: BareJID) -> LastMessageSync? {
let params: [String:Any?] = ["account":account, "jid":jid]
let message = try! self.getLastMessage.queryFirstMatching(params) { (cursor) -> LastMessageSync? in
return LastMessageSync(account: account, jid: jid, receivedId: cursor["received_id"], readId: cursor["read_id"])
}
return message
}
func updateOrInsertLastMessage(account: BareJID, jid: BareJID, receivedId: String?, readId: String?) {
dispatcher.async {
let lastMessage = self.getLastMessage(account: account, jid: jid)
if lastMessage != nil, receivedId != nil {
self.updateMessage(account: account, jid: jid, receivedId: receivedId, readId: readId)
}
else if lastMessage == nil {
self.insertmessage(account: account, jid: jid, receivedId: receivedId, readId: readId)
}
}
}
}
struct LastMessageSync {
var account : BareJID
var jid : BareJID
var receivedId : String?
var readId : String?
}

@ -362,6 +362,30 @@ class MessageEventHandler: XmppServiceEventHandler {
syncMessages(for: account, since: syncMessagesSince);
}
}
static func syncMessagesAfterID(for account: BareJID, version: MessageArchiveManagementModule.Version?, componentJID: JID, afterId: String) {
guard let client = XmppService.instance.getClient(for: account), let mamModule: MessageArchiveManagementModule = client.modulesManager.getModule(MessageArchiveManagementModule.ID) else { return }
let queryId = UUID().uuidString
let query = JabberDataElement(type: .submit)
let formTypeField = HiddenField(name: "FORM_TYPE")
formTypeField.value = version?.rawValue
query.addField(formTypeField)
let withField = JidSingleField(name: "with")
withField.value = componentJID
query.addField(withField)
let startField = TextSingleField(name: "after-id")
startField.value = afterId
query.addField(startField)
mamModule.queryItems(version: version, componentJid: componentJID, node: nil, query: query, queryId: queryId, rsm: RSM.Query(after:afterId ,max: 150)) { responseStanza in
return
}
}
static func syncMessages(for account: BareJID, version: MessageArchiveManagementModule.Version? = nil, componentJID: JID? = nil, since: Date, rsmQuery: RSM.Query? = nil) {
let period = DBChatHistorySyncStore.Period(account: account, component: componentJID?.bareJid, from: since, after: nil);

@ -54,13 +54,21 @@ class MucEventHandler: XmppServiceEventHandler {
room.supportedFeatures = [];
break;
}
let account = e.sessionObject.userBareJid!;
if let timestamp = room.lastMessageDate, !mamVersions.isEmpty {
let account = e.sessionObject.userBareJid!;
room.onRoomJoined = { room in
MessageEventHandler.syncMessages(for: account, version: mamVersions.contains(.MAM2) ? .MAM2 : .MAM1, componentJID: room.jid, since: timestamp);
}
_ = room.rejoin(skipHistoryFetch: true);
NotificationCenter.default.post(name: MucEventHandler.ROOM_STATUS_CHANGED, object: room);
} else if let lastMessageRecieved = DBLastMessageSyncStore.instance.getLastMessage(account: account, jid: room.roomJid), let afterId = lastMessageRecieved.receivedId {
room.onRoomJoined = { room in
MessageEventHandler.syncMessagesAfterID(for: account, version: mamVersions.contains(.MAM2) ? .MAM2 : .MAM1, componentJID: room.jid, afterId: afterId)
}
room.lastMessageDate = Date()
_ = room.rejoin(skipHistoryFetch: true);
NotificationCenter.default.post(name: MucEventHandler.ROOM_STATUS_CHANGED, object: room);
} else {
_ = room.rejoin();
NotificationCenter.default.post(name: MucEventHandler.ROOM_STATUS_CHANGED, object: room);
@ -101,7 +109,9 @@ class MucEventHandler: XmppServiceEventHandler {
}
}
DBChatHistoryStore.instance.append(for: room.account, message: e.message, source: .stream);
DBChatHistoryStore.instance.append(for: room.account, message: e.message, source: .stream)
DBLastMessageSyncStore.instance.updateOrInsertLastMessage(account: room.account, jid: room.roomJid, receivedId: e.message.id, readId: nil)
case let e as MucModule.AbstractOccupantEvent:
if let room = e.room as? DBRoom, room.isOMEMOCapable, let jid = e.occupant.jid {
if (e.occupant.affiliation == .none || e.occupant.affiliation == .outcast) {

Loading…
Cancel
Save