This commit is contained in:
fmodf 2024-12-31 13:28:03 +01:00
parent fd1fb2860f
commit d733394196

View file

@ -1,6 +1,6 @@
import Foundation
// TODO: add versioning (XEP-0237) if needed
// TODO: add versioning (XEP-0237)
// TODO: implement error catching
final class RosterModule: XmppModule {
let id = "Roseter module"
@ -34,21 +34,28 @@ final class RosterModule: XmppModule {
}
case .addRosterItem(let jidStr, let args):
return update(jidStr: jidStr, args: args)
return await update(state: state, jidStr: jidStr, args: args)
case .updateRosterItem(let jidStr, let args):
return update(jidStr: jidStr, args: args)
return await update(state: state, jidStr: jidStr, args: args)
case .deleteRosterItem(let jidStr):
return delete(jidStr: jidStr)
return await delete(state: state, jidStr: jidStr)
case .stanzaInbound(let stanza):
if let query = stanza.wrapped.nodes.first(where: { $0.name == "query" }), query.xmlns == "jabber:iq:roster" {
if stanza.type == .iq(.set) {
switch stanza.type {
case .iq(.set):
return await processSet(state: state, stanza: stanza)
} else if stanza.type == .iq(.result) {
return processResult(state: state, stanza: stanza)
} else {
case .iq(.result):
return await processResult(state: state, stanza: stanza)
case .iq(.error):
// handle errors here
return nil
default:
return nil
}
} else {
@ -62,14 +69,23 @@ final class RosterModule: XmppModule {
}
private extension RosterModule {
private func update(jidStr: String, args: [String: String]) -> Event? {
print(jidStr, args)
private func update(state: ClientState, jidStr: String, args: [String: String]) async -> Event? {
print(state, jidStr, args)
return nil
}
private func delete(jidStr: String) -> Event? {
print(jidStr)
return nil
private func delete(state: ClientState, jidStr: String) async -> Event? {
var existItems: [RosterItem] = []
guard
let data = await storage?.getRoster(jid: state.jid),
let decoded = try? JSONDecoder().decode([XMLElement].self, from: data),
let jid = try? JID(jidStr)
else {
return nil
}
existItems = decoded.compactMap { RosterItem(wrap: $0, owner: state.jid) }
existItems = existItems.filter { $0.jid != jid }
return .rosterUpdated
}
private func processSet(state: ClientState, stanza: Stanza) async -> Event? {
@ -94,9 +110,12 @@ private extension RosterModule {
guard let itemJidStr = item.attributes["jid"], let itemJid = try? JID(itemJidStr) else { continue }
let subscription = item.attributes["subscription"]
switch subscription {
// TODO: scheck subscription type for removed contacts
// on different servers
case "remove":
existItems = existItems.filter { $0.jid == itemJid }
// by default just update roster (or add it if its new)
default:
if let rosterItem = RosterItem(wrap: item, owner: state.jid) {
existItems = existItems.filter { $0.jid == itemJid }
@ -128,78 +147,9 @@ private extension RosterModule {
return .stanzaOutbound(res)
}
private func processResult(state _: ClientState, stanza: Stanza) -> Event? {
private func processResult(state _: ClientState, stanza: Stanza) async -> Event? {
print("--WE HERE 2!")
print(stanza)
return nil
}
// <iq from=juliet@example.com/balcony
// id=a78b4q6ha463
// type=result/>
// private func processRoster(state: ClientState, stanza: Stanza) async -> Event? {
// // get inner query
// guard let query = stanza.wrapped.nodes.first(where: { $0.name == "query" })
// else { return nil }
//
// // get exists roster items
// var existItems: [RosterItem] = []
// if let data = await storage?.getRoster(jid: state.jid), let decoded = try? JSONDecoder().decode([XMLElement].self, from: data) {
// existItems = decoded.compactMap { RosterItem(wrap: $0, owner: state.jid) }
// }
//
// // process push (.set from server)
// if stanza.type == .iq(.set) {
// guard
// let item = query.nodes.first(where: { $0.name == "item" }),
// let new = RosterItem(wrap: item, owner: state.jid)
// else { return nil }
// existItems = existItems.filter { $0.jid != new.jid }
// existItems.append(new)
// guard let data = try? JSONEncoder().encode(existItems.map { $0.wrapped }) else { return nil }
// await storage?.setRoster(jid: state.jid, roster: data)
// return .rosterUpdated
//
// // process .result from server
// } else if stanza.type == .iq(.result) {
// // process full list
// if stanza.id == fullReqId {
// let items = query.nodes.filter { $0.name == "item" }
// guard let data = try? JSONEncoder().encode(items) else { return nil }
// await storage?.setRoster(jid: state.jid, roster: data)
//
// // process changed item
// } else {
// guard
// let item = query.nodes.first(where: { $0.name == "item" }),
// let new = RosterItem(wrap: item, owner: state.jid)
// else { return nil }
// existItems = existItems.filter { $0.jid != new.jid }
// if new.subsription != .remove, new.subsription != .none {
// existItems.append(new)
// guard let data = try? JSONEncoder().encode(existItems.map { $0.wrapped }) else { return nil }
// await storage?.setRoster(jid: state.jid, roster: data)
// } else {
// // do nothing, this item was removed
// }
// }
// return .rosterUpdated
// } else {
// return nil
// }
// }
// private func updRoster(state: ClientState, target: String, remove: Bool) -> Event? {
// var attributes = ["jid": target]
// if remove {
// attributes["subcription"] = "remove"
// }
// let item = XMLElement(name: "item", xmlns: "jabber:iq:roster", attributes: attributes, content: nil, nodes: [])
// let query = XMLElement(name: "query", xmlns: "jabber:iq:roster", attributes: [:], content: nil, nodes: [item])
// if let req = Stanza.iqSet(from: state.jid.full, payload: query) {
// return .stanzaOutbound(req)
// } else {
// return nil
// }
// }
}