Нет описания

GoogleMeetClient.swift 1.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import Foundation
  2. enum GoogleMeetClientError: Error {
  3. case invalidResponse
  4. case httpStatus(Int)
  5. }
  6. /// Thin Meet REST API wrapper.
  7. /// Note: Meet REST API is best used for conferences/participants/artifacts, while scheduling comes from Calendar.
  8. final class GoogleMeetClient {
  9. private let session: URLSession
  10. init(session: URLSession = .shared) {
  11. self.session = session
  12. }
  13. /// Lists conference records for a given meeting space resource name.
  14. /// This is intentionally minimal scaffolding for phase 2 enrichment.
  15. func listConferenceRecords(accessToken: String, spaceResourceName: String, pageSize: Int = 10) async throws -> [ConferenceRecord] {
  16. var components = URLComponents(string: "https://meet.googleapis.com/v2/\(spaceResourceName)/conferenceRecords")!
  17. components.queryItems = [
  18. URLQueryItem(name: "pageSize", value: String(pageSize))
  19. ]
  20. var request = URLRequest(url: components.url!)
  21. request.httpMethod = "GET"
  22. request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
  23. let (data, response) = try await session.data(for: request)
  24. guard let http = response as? HTTPURLResponse else { throw GoogleMeetClientError.invalidResponse }
  25. guard (200..<300).contains(http.statusCode) else { throw GoogleMeetClientError.httpStatus(http.statusCode) }
  26. let decoded = try JSONDecoder().decode(ListConferenceRecordsResponse.self, from: data)
  27. return decoded.conferenceRecords ?? []
  28. }
  29. }
  30. // MARK: - Minimal models (v2)
  31. struct ConferenceRecord: Decodable, Equatable {
  32. let name: String?
  33. let startTime: Date?
  34. let endTime: Date?
  35. }
  36. private struct ListConferenceRecordsResponse: Decodable {
  37. let conferenceRecords: [ConferenceRecord]?
  38. let nextPageToken: String?
  39. }