TM-SGNL-iOS/SignalServiceKit/Network/API/Giphy/GiphyAPI.swift
TeleMessage developers dde0620daf initial commit
2025-05-03 12:28:28 -07:00

99 lines
3.6 KiB
Swift

//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
@objc
public class GiphyAPI: NSObject {
// MARK: - Properties
private static let kGiphyBaseURL = URL(string: "https://api.giphy.com/")!
private static func buildURLSession() -> OWSURLSessionProtocol {
let configuration = ContentProxy.sessionConfiguration()
// Don't use any caching to protect privacy of these requests.
configuration.urlCache = nil
configuration.requestCachePolicy = .reloadIgnoringCacheData
return OWSURLSession(
baseUrl: kGiphyBaseURL,
securityPolicy: OWSURLSession.defaultSecurityPolicy,
configuration: configuration
)
}
// MARK: Search
// This is the Signal iOS API key.
private static let kGiphyApiKey = "ZsUpUm2L6cVbvei347EQNp7HrROjbOdc"
private static let kGiphyPageSize = 100
public static func trending() -> Promise<[GiphyImageInfo]> {
return fetch(urlPath: "/v1/gifs/trending", queryItems: [])
}
public static func search(query: String) -> Promise<[GiphyImageInfo]> {
return fetch(urlPath: "/v1/gifs/search", queryItems: [
URLQueryItem(name: "q", value: query),
URLQueryItem(name: "offset", value: "0")
])
}
private static func fetch(urlPath: String, queryItems: [URLQueryItem]) -> Promise<[GiphyImageInfo]> {
var urlComponents = URLComponents()
urlComponents.path = urlPath
let baseQueryItems: [URLQueryItem] = [
URLQueryItem(name: "api_key", value: kGiphyApiKey),
URLQueryItem(name: "limit", value: "\(kGiphyPageSize)")
]
urlComponents.queryItems = baseQueryItems + queryItems
guard let urlString = urlComponents.string else {
return Promise(error: OWSAssertionError("Could not encode query."))
}
let urlSession = buildURLSession()
return Promise.wrapAsync {
var request = try urlSession.endpoint.buildRequest(urlString, method: .get)
guard ContentProxy.configureProxiedRequest(request: &request) else {
throw OWSAssertionError("Invalid URL")
}
return try await urlSession.performRequest(request: request, ignoreAppExpiry: false)
}.map(on: DispatchQueue.global()) { (response: HTTPResponse) -> [GiphyImageInfo] in
guard let json = response.responseBodyJson else {
throw OWSAssertionError("Missing or invalid JSON")
}
Logger.info("Request succeeded.")
guard let imageInfos = self.parseGiphyImages(responseJson: json) else {
throw OWSAssertionError("unable to parse trending images")
}
return imageInfos
}.recover(on: DispatchQueue.global()) { error -> Promise<[GiphyImageInfo]> in
Logger.warn("Request failed: \(error.shortDescription)")
throw error
}
}
// MARK: Parse API Responses
private static func parseGiphyImages(responseJson: Any?) -> [GiphyImageInfo]? {
guard let responseJson = responseJson else {
Logger.error("Missing response.")
return nil
}
guard let responseDict = responseJson as? [String: Any] else {
Logger.error("Invalid response.")
return nil
}
guard let imageDicts = responseDict["data"] as? [[String: Any]] else {
Logger.error("Invalid response data.")
return nil
}
return imageDicts.compactMap { imageDict in
GiphyImageInfo(parsing: imageDict)
}
}
}