// // MeteClient.swift // meterios // // (c) 2025 Martin "maride" Dessauer // import Foundation enum MeteClientError: Error { case StatusCodeLooksBad(explanation: String) } /// **MeteClient** is the client-side implementation of the Space Market API. Pure Swift, no platform-specific frameworks used. class MeteClient { private let address: String private let userID: Int init(address: String, userID: Int) { self.address = address self.userID = userID } func CanConnect() async throws -> Bool { // Send HTTP request to the drinks endpoint let url = URL(string: "https://\(address)/api/v1/users/stats.json") let (_, response) = try await URLSession.shared.data(from: url!) let statusCode = (response as? HTTPURLResponse)?.statusCode return statusCode == 200 } // GetDrinks returns the list of drinks available at the backend func GetDrinks() async throws -> Array { // Send HTTP request to the drinks endpoint let url = URL(string: "https://\(address)/api/v1/drinks") let (data, _) = try await URLSession.shared.data(from: url!) // Decode JSON to array of drinks let decoder = JSONDecoder() let drinks = try decoder.decode([MeteClientDrink].self, from: data) return drinks } // GetUser returns the user object for the given ID func GetUser() async throws -> MeteClientUser { // Send HTTP request to the user endpoint let url = URL(string: "https://\(address)/api/v1/users/\(userID).json") let (data, _) = try await URLSession.shared.data(from: url!) // Decode JSON to array of drinks let decoder = JSONDecoder() let user = try decoder.decode(MeteClientUser.self, from: data) return user } // GetUsers returns all users registered at the backend func GetUsers() async throws -> Array { // Send HTTP request to the user endpoint let url = URL(string: "https://\(address)/api/v1/users.json") let (data, _) = try await URLSession.shared.data(from: url!) // Decode JSON to array of drinks let decoder = JSONDecoder() let users = try decoder.decode([MeteClientUser].self, from: data) return users } // BookDrink subtracts the recommended price off the balance from the user given by ID func BookDrink(_ drinkID: Int) async throws { // Send HTTP request to the user endpoint let url = URL(string: "https://\(address)/api/v1/users/\(userID)/buy.json?drink=\(drinkID)") let (_, response) = try await URLSession.shared.data(from: url!) // Check status code let statusCode = (response as? HTTPURLResponse)?.statusCode if statusCode != 204 { throw MeteClientError.StatusCodeLooksBad(explanation: "Failed to book drink \(drinkID) for user \(userID)@\(address): HTTP status code \(statusCode ?? 0) received for \(url!)") } } }