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)") } }