summaryrefslogtreecommitdiff
path: root/Jel/Controllers/JellyfinClientController.swift
blob: 6fdd1f18bdf6ee53e569bbfde688b10dffe88f74 (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
130
//
//  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.username = username
      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
  }
}