From 7df723e62da5256a5cc4d091a9b334ceefaad5ac Mon Sep 17 00:00:00 2001 From: fmodf Date: Sun, 18 Aug 2024 16:43:13 +0200 Subject: [PATCH] wip --- .../AppData/Client/Client+MartinDisco.swift | 24 +++++++++++++++++++ .../Client/Client+MartinMessages.swift | 9 +++++++ .../AppData/Client/Client.swift | 14 ++++++++++- .../AppData/Model/ServerFeature.swift | 21 ++++++++++++++++ .../AppData/Store/ConversationStore.swift | 3 +++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 ConversationsClassic/AppData/Client/Client+MartinDisco.swift create mode 100644 ConversationsClassic/AppData/Model/ServerFeature.swift diff --git a/ConversationsClassic/AppData/Client/Client+MartinDisco.swift b/ConversationsClassic/AppData/Client/Client+MartinDisco.swift new file mode 100644 index 0000000..68d2101 --- /dev/null +++ b/ConversationsClassic/AppData/Client/Client+MartinDisco.swift @@ -0,0 +1,24 @@ + +import Combine +import Foundation +import GRDB +import Martin + +final class ClientMartinDiscoManager { + private(set) var features: [ServerFeature] = [] + private var cancellables: Set = [] + + init(_ xmppConnection: XMPPClient) { + // subscribe to client server features + xmppConnection.module(DiscoveryModule.self).$serverDiscoResult + .sink { [weak self] disco in + let allFeatures = ServerFeature.allFeatures + let features = disco.features + .compactMap { featureId in + allFeatures.first(where: { $0.xmppId == featureId }) + } + self?.features = features + } + .store(in: &cancellables) + } +} diff --git a/ConversationsClassic/AppData/Client/Client+MartinMessages.swift b/ConversationsClassic/AppData/Client/Client+MartinMessages.swift index 00426f3..47edc50 100644 --- a/ConversationsClassic/AppData/Client/Client+MartinMessages.swift +++ b/ConversationsClassic/AppData/Client/Client+MartinMessages.swift @@ -21,6 +21,15 @@ final class ClientMartinMessagesManager { } .store(in: &cancellables) + // subscribe to archived messages + xmppConnection.module(.mam).archivedMessagesPublisher + .sink(receiveValue: { [weak self] archived in + let message = archived.message + message.attribute("archived_date", newValue: "\(archived.timestamp.timeIntervalSince1970)") + self?.handleMessage(message) + }) + .store(in: &cancellables) + // enable carbons if available xmppConnection.module(.messageCarbons).$isAvailable.filter { $0 } .sink(receiveValue: { [weak xmppConnection] _ in diff --git a/ConversationsClassic/AppData/Client/Client.swift b/ConversationsClassic/AppData/Client/Client.swift index 7260017..1772053 100644 --- a/ConversationsClassic/AppData/Client/Client.swift +++ b/ConversationsClassic/AppData/Client/Client.swift @@ -25,12 +25,14 @@ final class Client: ObservableObject { private var rosterManager = ClientMartinRosterManager() private var chatsManager = ClientMartinChatsManager() private var messageManager: ClientMartinMessagesManager + private var discoManager: ClientMartinDiscoManager init(credentials: Credentials) { self.credentials = credentials state = credentials.isActive ? .enabled(.disconnected) : .disabled connection = Self.prepareConnection(credentials, rosterManager, chatsManager) messageManager = ClientMartinMessagesManager(connection) + discoManager = ClientMartinDiscoManager(connection) connectionCancellable = connection.$state .sink { [weak self] state in guard let self = self else { return } @@ -134,6 +136,16 @@ extension Client { throw URLError(.badServerResponse) } } + + func requestArchivedMessages(for roster: Roster) async { + if !discoManager.features.map({ $0.xep }).contains("XEP-0313") { + return + } + let module = connection.module(MessageArchiveManagementModule.self) + let endDate = Date() + let startDate = Calendar.current.date(byAdding: .day, value: -Const.mamRequestDaysLength, to: endDate) ?? Date() + let response = try? await module.queryItems(componentJid: JID(credentials.bareJid), with: JID(roster.bareJid), start: startDate, end: endDate, queryId: UUID().uuidString) + } } extension Client { @@ -163,7 +175,7 @@ private extension Client { client.modulesManager.register(PubSubModule()) client.modulesManager.register(MessageModule(chatManager: chat)) - // client.modulesManager.register(MessageArchiveManagementModule()) + client.modulesManager.register(MessageArchiveManagementModule()) client.modulesManager.register(MessageCarbonsModule()) diff --git a/ConversationsClassic/AppData/Model/ServerFeature.swift b/ConversationsClassic/AppData/Model/ServerFeature.swift new file mode 100644 index 0000000..bc04363 --- /dev/null +++ b/ConversationsClassic/AppData/Model/ServerFeature.swift @@ -0,0 +1,21 @@ +import Foundation + +struct ServerFeature: Identifiable & Codable { + let xep: String + let name: String + let xmppId: String? + let description: String? + + var id: String { xep } + + static var allFeatures: [ServerFeature] { + guard + let url = Bundle.main.url(forResource: "server_features", withExtension: "plist"), + let data = try? Data(contentsOf: url), + let loaded = try? PropertyListDecoder().decode([ServerFeature].self, from: data) + else { + return [] + } + return loaded + } +} diff --git a/ConversationsClassic/AppData/Store/ConversationStore.swift b/ConversationsClassic/AppData/Store/ConversationStore.swift index d8a4b56..ef0b3a0 100644 --- a/ConversationsClassic/AppData/Store/ConversationStore.swift +++ b/ConversationsClassic/AppData/Store/ConversationStore.swift @@ -18,6 +18,9 @@ final class ConversationStore: ObservableObject { self.client = client self.roster = roster subscribe() + Task { + await client.requestArchivedMessages(for: roster) + } } }