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 extension Stanza { static func iqGet(jid: String? = nil, payload: XMLElement) -> Stanza? { var attributes = ["id": XMLElement.randomId, "type": "get"] if let jid { attributes["from"] = jid } let req = XMLElement( name: "iq", xmlns: nil, attributes: attributes, content: nil, nodes: [payload] ) return Stanza(wrap: req) } static func iqSet(jid: String? = nil, payload: XMLElement) -> Stanza? { var attributes = ["id": XMLElement.randomId, "type": "get"] if let jid { attributes["from"] = jid } let req = XMLElement( name: "iq", xmlns: nil, attributes: ["type": "set", "id": XMLElement.randomId], content: nil, nodes: [payload] ) return Stanza(wrap: req) } } private extension Stanza { func warn() { print("Something went wrong! with \(wrapped.stringRepresentation.prettyStr)") } }