summaryrefslogtreecommitdiff
path: root/Jel/Controllers/JellyfinClientController.swift
blob: e55afa39dd7a7a35c7c5d2aeef0cb9ccdf4f19d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//
//  JellyfinClientController.swift
//  Jel
//
//  Created by zerocool on 12/12/23.
//

import Foundation
import Get
import JellyfinKit
import Pulse

struct AuthHeaders: Codable {
  var Client: String
  var Device: String
  var DeviceId: String
  var Version: String
  var Token: String
}

enum JellyfinClientError: Error {
  case badResponseCode
}

extension AuthHeaders {
  func format() -> String {
    return "MediaBrowser Client=\(self.Client), Device=\(self.Device), DeviceId=\(self.DeviceId), Version=\(self.Version), Token=\(self.Token)"
  }
}

class JellyfinClientController: ObservableObject {
  private var api: APIClient
  
  private var authHeaders: AuthHeaders
  private var authState: AuthStateController
  
  init(authHeaders: AuthHeaders, serverUrl: URL? = nil, authState: AuthStateController = AuthStateController.shared) {
    self.authHeaders = authHeaders
    self.authState = authState
    
    self.api = APIClient(baseURL: serverUrl)
    self.setUrl(url: serverUrl)
    
    self.setToken(token: self.authState.authToken ?? "")
  }
  
  func setToken(token: String) {
    self.authHeaders.Token = token
    self.setUrl(url: self.authState.serverUrl)
  }
  
  func setUrl(url: URL?) {
    if url == nil {
      return
    }
    
    self.api = APIClient(baseURL: url, {
      $0.sessionConfiguration.httpAdditionalHeaders = ["Authorization": self.authHeaders.format()]
      
      let decoder = JSONDecoder()
      decoder.dateDecodingStrategy = .iso8601withFractionalSeconds
      $0.decoder = decoder
      
      $0.sessionDelegate = Pulse.URLSessionProxyDelegate()
    })
  }
  
  func getUrl() -> URL? {
    return self.api.configuration.baseURL
  }
  
  @discardableResult func send<T>(
    _ request: Request<T>,
    delegate: URLSessionDataDelegate? = nil,
    configure: ((inout URLRequest) throws -> Void)? = nil
  ) async throws -> Response<T> where T : Decodable {
    return try await self.api.send(request, delegate: delegate, configure: configure)
  }
  
  @discardableResult func send(
    _ request: Request<Void>,
    delegate: URLSessionDataDelegate? = nil,
    configure: ((inout URLRequest) throws -> Void)? = nil
  ) async throws -> Response<Void> {
    return try await self.api.send(request, delegate: delegate, configure: configure)
  }
  
}

extension JellyfinClientController {
  func getPublicServerInfo() async -> PublicSystemInfo? {
    let request = Paths.getPublicSystemInfo
    do {
      let res = try await api.send(request)
      if res.statusCode != 200 {
        throw JellyfinClientError.badResponseCode
      }
      
      return res.value
    } catch {
      return nil
    }
  }
  
  func signIn(username: String, pw: String) async throws {
    let request = Paths.authenticateUserByName(AuthenticateUserByName(pw: pw, username: username))
    let res = try await self.api.send(request)
    DispatchQueue.main.async {
      self.authState.loggedIn = true
      self.authState.authToken = res.value.accessToken
      self.authState.userId = res.value.user?.id
      self.authState.save()
      
      self.setToken(token: self.authState.authToken ?? "")
    }
  }
  
  func search(parameters: Paths.GetParameters) async -> SearchHintResult? {
    let request = Paths.get(parameters: parameters)
    do {
      let res = try await self.api.send(request)
      return res.value
    } catch {
    }
    
    return nil
  }
}