← Back to index

ImageSearchManager

Spots
CodeWhat It DoesHow It Does It
â–ļ IMPORTS
import FoundationFramework importsImports Foundation.
class ImageSearchManager { private static let serperApiKey = Secrets.serperAPIKey static func searchImageURLs(for showName: String, year: Int, cuisine: String = "", maxResults: Int = 20, page: Int = 1) async -> [String] { let venuePart = cuisine.trimmingCharacters(in: .whitespacesAndNewlines) let query = venuePart.isEmpty ? "\(showName) \(year)" : "\(showName) \(year) \"\(venuePart)\"" print("🔍 ImageSearch query: \(query) page:\(page)") guard let url = URL(string: "https://google.serper.dev/images") else { return [] } var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 15) request.httpMethod = "POST" request.setValue(serperApiKey, forHTTPHeaderField: "X-API-KEY") request.setValue("application/json", forHTTPHeaderField: "Content-Type") var body: [String: Any] = ["q": query, "num": maxResults] if page > 1 { body["page"] = page } guard let httpBody = try? JSONSerialization.data(withJSONObject: body) else { return [] } request.httpBody = httpBody guard let (data, response) = try? await URLSession.shared.data(for: request) else { print("âš ī¸ Serper: network request failed") return [] } if let http = response as? HTTPURLResponse { print("â„šī¸ Serper: HTTP \(http.statusCode)") guard http.statusCode == 200 else { if let body = String(data: data, encoding: .utf8) { print("âš ī¸ Serper error: \(body.prefix(300))") } return [] } } guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let images = json["images"] as? [[String: Any]] else { print("âš ī¸ Serper: failed to parse response") return [] } let urls = images.compactMap { $0["imageUrl"] as? String } print("â„šī¸ Serper: found \(urls.count) image(s)") return Array(urls.prefix(maxResults)) } }`ImageSearchManager` classDefines the `ImageSearchManager` class.