| 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` class | Defines the `ImageSearchManager` class. |