WallhavenAPI.swift

2.5 KB · raw

1import Foundation23enum WallhavenError: Error {4    case invalidURL5    case networkError(Error)6    case decodingError(Error)7    case noData8    case apiError(String)9}1011/// Sort order for Wallhaven search results. Maps to the `sorting` query12/// parameter on the public API. `random` returns a fresh batch per page.13enum WallhavenSorting: String {14    case dateAdded = "date_added"15    case toplist16    case random17}1819class WallhavenAPI {20    private let session: URLSession2122    init(session: URLSession = .shared) {23        self.session = session24    }2526    func searchWallpapers(27        query: String,28        categories: String = "111",29        purity: String = "100",30        sorting: WallhavenSorting = .dateAdded,31        resolutions: [String] = [],32        ratios: [String] = [],33        limit: Int = 24,34        page: Int = 135    ) async throws -> ([Wallpaper], Meta?) {36        var queryItems = [37            URLQueryItem(name: "q", value: query),38            URLQueryItem(name: "categories", value: categories),39            URLQueryItem(name: "purity", value: purity),40            URLQueryItem(name: "sorting", value: sorting.rawValue),41            URLQueryItem(name: "limit", value: String(limit)),42            URLQueryItem(name: "page", value: String(page))43        ]4445        if !resolutions.isEmpty {46            queryItems.append(URLQueryItem(name: "resolutions", value: resolutions.joined(separator: ",")))47        }4849        if !ratios.isEmpty {50            queryItems.append(URLQueryItem(name: "ratios", value: ratios.joined(separator: ",")))51        }5253        return try await performSearch(queryItems: queryItems)54    }5556    private func performSearch(queryItems: [URLQueryItem]) async throws -> ([Wallpaper], Meta?) {57        var urlComponents = URLComponents(url: Configuration.baseURL.appendingPathComponent("search"), resolvingAgainstBaseURL: true)!58        urlComponents.queryItems = queryItems5960        guard let url = urlComponents.url else {61            throw WallhavenError.invalidURL62        }6364        let (data, response) = try await session.data(from: url)6566        guard let httpResponse = response as? HTTPURLResponse,67              (200...299).contains(httpResponse.statusCode) else {68            throw WallhavenError.apiError("Server returned an error")69        }7071        do {72            let decodedResponse = try JSONDecoder().decode(WallhavenResponse.self, from: data)73            return (decodedResponse.data, decodedResponse.meta)74        } catch {75            throw WallhavenError.decodingError(error)76        }77    }78}