// // MeteClientUser.swift // meterios // // (c) 2025 Martin "maride" Dessauer // import Foundation import CryptoKit /// **MeteClientUser** resembles a user retrieved from Space Market API, Version 1. Pure Swift, no platform-specific frameworks used. struct MeteClientUser: Decodable, Identifiable, Hashable { let id: UUID = UUID() // Careful: meterios-internal ID, not Mete/Backend user accoint ID! let meteID: Int let displayName: String let displayImageURL: URL? let balance: Float? private enum KeyMap : String, CodingKey { case id, name, email, balance } // Init function to be used with JSONDecoder, converting from SpaceMarket API's strange types to proper types init(from decoder : Decoder) throws { let container = try decoder.container(keyedBy: KeyMap.self) self.meteID = try container.decode(Int.self, forKey: .id) self.displayName = try container.decode(String.self, forKey: .name) self.displayImageURL = URL(string: String( format: "https://secure.gravatar.com/avatar/%@?s=300", Insecure.MD5.hash( // e-mails may be empty as they are not required during the registration process in Mete // however, Gravatar requires them for the profile picture functionality. // Default to the profile picture of md5("0"), which is simply the Gravatar logo on blue background data: (((try? container.decode(String.self, forKey: .email)) ?? "0").data(using: .utf8)!) ).compactMap { String(format: "%02x", $0) }.joined() )) self.balance = Float(try container.decode(String.self, forKey: .balance)) } // Init function, as straight-forward as it gets init(meteID: Int, displayName: String, displayImageURL: URL?, balance: Float) { self.meteID = meteID self.displayName = displayName self.displayImageURL = displayImageURL self.balance = balance } }