another.im-ios/AnotherIM/xmpp/models/Stanza.swift
2024-12-17 09:20:04 +01:00

119 lines
2.9 KiB
Swift

import Foundation
enum StanzaType: Codable & Equatable {
enum IqType: String, Codable & Equatable {
case get
case set
case result
case error
}
enum MessageType: String, Codable & Equatable {
case chat
case groupchat
case headline
case normal
case error
case none
}
enum PresenceType: String, Codable & Equatable {
case subscribe
case unsubscribe
case subscribed
case unsubscribed
}
case iq(IqType)
case message(MessageType)
case presense(PresenceType)
// Should never appear
case unknown
}
struct Stanza {
let wrapped: XMLElement
init?(wrap: XMLElement) {
guard ["iq", "message", "presence"].contains(wrap.name) else { return nil }
wrapped = wrap
}
var type: StanzaType {
switch wrapped.name {
case "iq":
if let type = StanzaType.IqType(rawValue: wrapped.attributes["type"] ?? "") {
return .iq(type)
} else {
warn()
return .unknown
}
case "message":
let type = StanzaType.MessageType(rawValue: wrapped.attributes["type"] ?? "none") ?? .none
return .message(type)
case "presence":
if let type = StanzaType.PresenceType(rawValue: wrapped.attributes["type"] ?? "") {
return .presense(type)
} else {
warn()
return .unknown
}
default:
warn()
return .unknown
}
}
var id: String? {
wrapped.attributes["id"]
}
}
// MARK: Init IQ Stanza
extension Stanza {
static func iqGet(payload: XMLElement) -> Stanza? {
buildIq(direction: "get", from: nil, to: nil, payload: payload)
}
static func iqGet(from: String, payload: XMLElement) -> Stanza? {
buildIq(direction: "get", from: from, to: nil, payload: payload)
}
static func iqSet(payload: XMLElement) -> Stanza? {
buildIq(direction: "set", from: nil, to: nil, payload: payload)
}
static func iqSet(from: String, payload: XMLElement) -> Stanza? {
buildIq(direction: "set", from: from, to: nil, payload: payload)
}
// build iq stanza
private static func buildIq(direction: String, from: String?, to: String?, payload: XMLElement) -> Stanza? {
var attributes = ["id": XMLElement.randomId, "type": direction]
if let from {
attributes["from"] = from
}
if let to {
attributes["to"] = to
}
let req = XMLElement(
name: "iq",
xmlns: nil,
attributes: attributes,
content: nil,
nodes: [payload]
)
return Stanza(wrap: req)
}
}
private extension Stanza {
func warn() {
print("Something went wrong! with \(wrapped.stringRepresentation.prettyStr)")
}
}