// // FervorClient.swift // Fervor // // Created by Shadowfacts on 11/25/21. // import Foundation public class FervorClient { let instanceURL: URL let session: URLSession public var accessToken: String? private let decoder = JSONDecoder() public init(instanceURL: URL, accessToken: String?, session: URLSession = .shared) { self.instanceURL = instanceURL self.accessToken = accessToken self.session = session } private func buildURL(path: String) -> URL { var components = URLComponents(url: instanceURL, resolvingAgainstBaseURL: false)! components.path = path return components.url! } private func performRequest(_ request: URLRequest) async throws -> T { var request = request if let accessToken = accessToken { request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") } let (data, _) = try await session.data(for: request, delegate: nil) let decoded = try decoder.decode(T.self, from: data) return decoded } public func register(clientName: String, website: URL? = nil, redirectURI: URL) async throws -> ClientRegistration { var request = URLRequest(url: buildURL(path: "/api/v1/register")) request.httpMethod = "POST" request.setURLEncodedBody(params: [ "client_name": clientName, "website": website?.absoluteString, "redirect_uri": redirectURI.absoluteString, ]) return try await performRequest(request) } public func token(authCode: String, redirectURI: URL, clientID: String, clientSecret: String) async throws -> Token { var request = URLRequest(url: buildURL(path: "/oauth/token")) request.httpMethod = "POST" request.setURLEncodedBody(params: [ "grant_type": "authorization_code", "authorization_code": authCode, "redirect_uri": redirectURI.absoluteString, "client_id": clientID, "client_secret": clientSecret, ]) return try await performRequest(request) } public struct Auth { public let accessToken: String public let refreshToken: String? } public enum Error: Swift.Error { case urlSession(Swift.Error) case decode(Swift.Error) } }