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
}
}
|