Files
element-x-ios/ElementX/Sources/Services/HealthChat/ExtendedProfileService.swift
T
joel.poyet e5bfc3a26d Add HealthChat API and extended profile services (#9)
Expose OpenID tokens and homeserver credentials from the client proxy, and
add fork-only services for the HealthChat member directory backend
(api.healthchat.ch) plus a service that reads MSC4133 extended profile
fields directly from the homeserver. Groundwork for the members tab and
the profile screens.

Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS
2026-10-19 09:17:29 +02:00

56 lines
2.2 KiB
Swift

//
// Copyright 2026 Element Creations Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import Foundation
/// Reads profiles straight from the homeserver's profile endpoint, which — unlike the
/// Rust SDK's `getProfile` — includes the extended profile fields (MSC4133).
final class ExtendedProfileService: ExtendedProfileServiceProtocol {
private let clientProxy: ClientProxyProtocol
private let urlSession: URLSession
init(clientProxy: ClientProxyProtocol, urlSession: URLSession = .shared) {
self.clientProxy = clientProxy
self.urlSession = urlSession
}
func profile(for userID: String) async -> Result<ExtendedProfile, ExtendedProfileServiceError> {
guard case let .success(credentials) = clientProxy.homeserverCredentials() else {
return .failure(.missingCredentials)
}
let url = credentials.homeserverURL.appending(path: "_matrix/client/v3/profile/\(userID)")
var request = URLRequest(url: url)
request.setValue("Bearer \(credentials.accessToken)", forHTTPHeaderField: "Authorization")
let data: Data
do {
let (responseData, response) = try await urlSession.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
return .failure(.networkFailure)
}
guard httpResponse.statusCode == 200 else {
MXLog.error("Failed fetching the extended profile for \(userID) with status: \(httpResponse.statusCode)")
return .failure(.httpStatus(httpResponse.statusCode))
}
data = responseData
} catch {
MXLog.error("Failed fetching the extended profile for \(userID) with error: \(error)")
return .failure(.networkFailure)
}
do {
return try .success(JSONDecoder().decode(ExtendedProfile.self, from: data))
} catch {
MXLog.error("Failed decoding the extended profile for \(userID) with error: \(error)")
return .failure(.decodingFailure)
}
}
}