Add JellyfinClient actor with curated API surface
This commit is contained in:
parent
8f7d5870bd
commit
87e2e7431f
3 changed files with 621 additions and 2 deletions
617
Sources/LuminateCore/JellyfinClient.swift
Normal file
617
Sources/LuminateCore/JellyfinClient.swift
Normal file
|
|
@ -0,0 +1,617 @@
|
|||
import Foundation
|
||||
import OpenAPIRuntime
|
||||
import OpenAPIURLSession
|
||||
import HTTPTypes
|
||||
|
||||
struct AuthMiddleware: ClientMiddleware {
|
||||
let token: String
|
||||
|
||||
func intercept(
|
||||
_ request: HTTPRequest,
|
||||
body: OpenAPIRuntime.HTTPBody?,
|
||||
baseURL: URL,
|
||||
operationID: String,
|
||||
next: (HTTPRequest, OpenAPIRuntime.HTTPBody?, URL) async throws -> (HTTPResponse, OpenAPIRuntime.HTTPBody?)
|
||||
) async throws -> (HTTPResponse, OpenAPIRuntime.HTTPBody?) {
|
||||
var request = request
|
||||
request.headerFields[.authorization] = "MediaBrowser Token=\"\(token)\""
|
||||
return try await next(request, body, baseURL)
|
||||
}
|
||||
}
|
||||
|
||||
public enum JellyfinError: Error {
|
||||
case httpError(Int)
|
||||
case notAuthenticated
|
||||
case invalidResponse
|
||||
case decodingError(String)
|
||||
}
|
||||
|
||||
public actor JellyfinClient {
|
||||
public let serverURL: URL
|
||||
private var token: String?
|
||||
private var client: Client
|
||||
|
||||
public init(serverURL: URL) {
|
||||
self.serverURL = serverURL
|
||||
self.token = nil
|
||||
self.client = Client(
|
||||
serverURL: serverURL,
|
||||
transport: URLSessionTransport()
|
||||
)
|
||||
}
|
||||
|
||||
private func makeClient(token: String) -> Client {
|
||||
Client(
|
||||
serverURL: serverURL,
|
||||
transport: URLSessionTransport(),
|
||||
middlewares: [AuthMiddleware(token: token)]
|
||||
)
|
||||
}
|
||||
|
||||
public func authenticate(username: String, password: String) async throws -> Components.Schemas.AuthenticationResult {
|
||||
let response = try await client.AuthenticateUserByName(Operations.AuthenticateUserByName.Input(
|
||||
body: .json(.init(value1: .init(Username: username, Pw: password)))
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
guard let accessToken = result.AccessToken else { throw JellyfinError.invalidResponse }
|
||||
token = accessToken
|
||||
client = makeClient(token: accessToken)
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
guard let accessToken = result.AccessToken else { throw JellyfinError.invalidResponse }
|
||||
token = accessToken
|
||||
client = makeClient(token: accessToken)
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
guard let accessToken = result.AccessToken else { throw JellyfinError.invalidResponse }
|
||||
token = accessToken
|
||||
client = makeClient(token: accessToken)
|
||||
return result
|
||||
}
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getItems(
|
||||
userId: String,
|
||||
parentId: String? = nil,
|
||||
includeItemTypes: [Components.Schemas.BaseItemKind]? = nil,
|
||||
fields: [Components.Schemas.ItemFields]? = nil,
|
||||
filters: [Components.Schemas.ItemFilter]? = nil,
|
||||
sortBy: [Components.Schemas.ItemSortBy]? = nil,
|
||||
sortOrder: [Components.Schemas.SortOrder]? = nil,
|
||||
searchTerm: String? = nil,
|
||||
startIndex: Int32? = nil,
|
||||
limit: Int32? = nil,
|
||||
recursive: Bool? = nil,
|
||||
isFavorite: Bool? = nil
|
||||
) async throws -> Components.Schemas.BaseItemDtoQueryResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetItems.Input.Query(userId: userId)
|
||||
query.parentId = parentId
|
||||
query.includeItemTypes = includeItemTypes
|
||||
query.fields = fields
|
||||
query.filters = filters
|
||||
query.sortBy = sortBy
|
||||
query.sortOrder = sortOrder
|
||||
query.searchTerm = searchTerm
|
||||
query.startIndex = startIndex
|
||||
query.limit = limit
|
||||
query.recursive = recursive
|
||||
query.isFavorite = isFavorite
|
||||
let response = try await client.GetItems(Operations.GetItems.Input(query: query))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getItem(itemId: String, userId: String? = nil) async throws -> Components.Schemas.BaseItemDto {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.GetItem(Operations.GetItem.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getUserViews(userId: String) async throws -> Components.Schemas.BaseItemDtoQueryResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.GetUserViews(Operations.GetUserViews.Input(
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getNextUp(
|
||||
userId: String,
|
||||
startIndex: Int32? = nil,
|
||||
limit: Int32? = nil,
|
||||
fields: [Components.Schemas.ItemFields]? = nil,
|
||||
seriesId: String? = nil,
|
||||
parentId: String? = nil,
|
||||
enableResumable: Bool? = nil,
|
||||
enableRewatching: Bool? = nil
|
||||
) async throws -> Components.Schemas.BaseItemDtoQueryResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetNextUp.Input.Query(userId: userId)
|
||||
query.startIndex = startIndex
|
||||
query.limit = limit
|
||||
query.fields = fields
|
||||
query.seriesId = seriesId
|
||||
query.parentId = parentId
|
||||
query.enableResumable = enableResumable
|
||||
query.enableRewatching = enableRewatching
|
||||
let response = try await client.GetNextUp(Operations.GetNextUp.Input(query: query))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getSeasons(
|
||||
seriesId: String,
|
||||
userId: String,
|
||||
fields: [Components.Schemas.ItemFields]? = nil,
|
||||
isSpecialSeason: Bool? = nil,
|
||||
enableImages: Bool? = nil,
|
||||
imageTypeLimit: Int32? = nil,
|
||||
enableImageTypes: [Components.Schemas.ImageType]? = nil,
|
||||
enableUserData: Bool? = nil
|
||||
) async throws -> Components.Schemas.BaseItemDtoQueryResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetSeasons.Input.Query(userId: userId)
|
||||
query.fields = fields
|
||||
query.isSpecialSeason = isSpecialSeason
|
||||
query.enableImages = enableImages
|
||||
query.imageTypeLimit = imageTypeLimit
|
||||
query.enableImageTypes = enableImageTypes
|
||||
query.enableUserData = enableUserData
|
||||
let response = try await client.GetSeasons(Operations.GetSeasons.Input(
|
||||
path: .init(seriesId: seriesId),
|
||||
query: query
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .notFound:
|
||||
throw JellyfinError.httpError(404)
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getEpisodes(
|
||||
seriesId: String,
|
||||
userId: String,
|
||||
seasonId: String? = nil,
|
||||
season: Int32? = nil,
|
||||
fields: [Components.Schemas.ItemFields]? = nil,
|
||||
startIndex: Int32? = nil,
|
||||
limit: Int32? = nil,
|
||||
enableImages: Bool? = nil,
|
||||
imageTypeLimit: Int32? = nil,
|
||||
enableImageTypes: [Components.Schemas.ImageType]? = nil,
|
||||
enableUserData: Bool? = nil
|
||||
) async throws -> Components.Schemas.BaseItemDtoQueryResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetEpisodes.Input.Query(userId: userId)
|
||||
query.seasonId = seasonId
|
||||
query.season = season
|
||||
query.fields = fields
|
||||
query.startIndex = startIndex
|
||||
query.limit = limit
|
||||
query.enableImages = enableImages
|
||||
query.imageTypeLimit = imageTypeLimit
|
||||
query.enableImageTypes = enableImageTypes
|
||||
query.enableUserData = enableUserData
|
||||
let response = try await client.GetEpisodes(Operations.GetEpisodes.Input(
|
||||
path: .init(seriesId: seriesId),
|
||||
query: query
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .notFound:
|
||||
throw JellyfinError.httpError(404)
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getSearchHints(
|
||||
searchTerm: String,
|
||||
userId: String? = nil,
|
||||
startIndex: Int32? = nil,
|
||||
limit: Int32? = nil,
|
||||
includeItemTypes: [Components.Schemas.BaseItemKind]? = nil,
|
||||
parentId: String? = nil
|
||||
) async throws -> Components.Schemas.SearchHintResult {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetSearchHints.Input.Query(searchTerm: searchTerm)
|
||||
query.userId = userId
|
||||
query.startIndex = startIndex
|
||||
query.limit = limit
|
||||
query.includeItemTypes = includeItemTypes
|
||||
query.parentId = parentId
|
||||
let response = try await client.GetSearchHints(Operations.GetSearchHints.Input(query: query))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func markPlayedItem(itemId: String, userId: String, datePlayed: Date? = nil) async throws -> Components.Schemas.UserItemDataDto {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.MarkPlayedItem(Operations.MarkPlayedItem.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId, datePlayed: datePlayed)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .notFound:
|
||||
throw JellyfinError.httpError(404)
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func markUnplayedItem(itemId: String, userId: String) async throws -> Components.Schemas.UserItemDataDto {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.MarkUnplayedItem(Operations.MarkUnplayedItem.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .notFound:
|
||||
throw JellyfinError.httpError(404)
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func markFavoriteItem(itemId: String, userId: String) async throws -> Components.Schemas.UserItemDataDto {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.MarkFavoriteItem(Operations.MarkFavoriteItem.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func unmarkFavoriteItem(itemId: String, userId: String) async throws -> Components.Schemas.UserItemDataDto {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.UnmarkFavoriteItem(Operations.UnmarkFavoriteItem.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getPlaybackInfo(itemId: String, userId: String) async throws -> Components.Schemas.PlaybackInfoResponse {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.GetPlaybackInfo(Operations.GetPlaybackInfo.Input(
|
||||
path: .init(itemId: itemId),
|
||||
query: .init(userId: userId)
|
||||
))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .notFound:
|
||||
throw JellyfinError.httpError(404)
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func reportPlaybackStart(info: Components.Schemas.PlaybackStartInfo) async throws {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.ReportPlaybackStart(Operations.ReportPlaybackStart.Input(
|
||||
body: .json(.init(value1: info))
|
||||
))
|
||||
switch response {
|
||||
case .noContent:
|
||||
return
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func reportPlaybackProgress(info: Components.Schemas.PlaybackProgressInfo) async throws {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.ReportPlaybackProgress(Operations.ReportPlaybackProgress.Input(
|
||||
body: .json(.init(value1: info))
|
||||
))
|
||||
switch response {
|
||||
case .noContent:
|
||||
return
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func reportPlaybackStopped(info: Components.Schemas.PlaybackStopInfo) async throws {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
let response = try await client.ReportPlaybackStopped(Operations.ReportPlaybackStopped.Input(
|
||||
body: .json(.init(value1: info))
|
||||
))
|
||||
switch response {
|
||||
case .noContent:
|
||||
return
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func getLatestMedia(
|
||||
userId: String,
|
||||
parentId: String? = nil,
|
||||
fields: [Components.Schemas.ItemFields]? = nil,
|
||||
includeItemTypes: [Components.Schemas.BaseItemKind]? = nil,
|
||||
limit: Int32? = nil,
|
||||
enableImages: Bool? = nil,
|
||||
imageTypeLimit: Int32? = nil,
|
||||
enableImageTypes: [Components.Schemas.ImageType]? = nil,
|
||||
enableUserData: Bool? = nil,
|
||||
groupItems: Bool? = nil
|
||||
) async throws -> [Components.Schemas.BaseItemDto] {
|
||||
guard token != nil else { throw JellyfinError.notAuthenticated }
|
||||
var query = Operations.GetLatestMedia.Input.Query(userId: userId)
|
||||
query.parentId = parentId
|
||||
query.fields = fields
|
||||
query.includeItemTypes = includeItemTypes
|
||||
query.limit = limit
|
||||
query.enableImages = enableImages
|
||||
query.imageTypeLimit = imageTypeLimit
|
||||
query.enableImageTypes = enableImageTypes
|
||||
query.enableUserData = enableUserData
|
||||
query.groupItems = groupItems
|
||||
let response = try await client.GetLatestMedia(Operations.GetLatestMedia.Input(query: query))
|
||||
switch response {
|
||||
case .ok(let ok):
|
||||
switch ok.body {
|
||||
case .json(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_camelcase_quot_(let result):
|
||||
return result
|
||||
case .application_json_profile__quot_pascalcase_quot_(let result):
|
||||
return result
|
||||
}
|
||||
case .unauthorized:
|
||||
throw JellyfinError.httpError(401)
|
||||
case .forbidden:
|
||||
throw JellyfinError.httpError(403)
|
||||
case .serviceUnavailable:
|
||||
throw JellyfinError.httpError(503)
|
||||
case .undocumented(let code, _):
|
||||
throw JellyfinError.httpError(code)
|
||||
}
|
||||
}
|
||||
|
||||
public func imageURL(itemId: String, imageType: Components.Schemas.ImageType, tag: String? = nil, maxWidth: Int32? = nil, quality: Int32? = 90) -> URL? {
|
||||
guard var components = URLComponents(url: serverURL, resolvingAgainstBaseURL: false) else { return nil }
|
||||
components.path = "/Items/\(itemId)/Images/\(imageType)"
|
||||
var queryItems: [URLQueryItem] = []
|
||||
if let tag { queryItems.append(.init(name: "tag", value: tag)) }
|
||||
if let maxWidth { queryItems.append(.init(name: "maxWidth", value: "\(maxWidth)")) }
|
||||
if let quality { queryItems.append(.init(name: "quality", value: "\(quality)")) }
|
||||
components.queryItems = queryItems.isEmpty ? nil : queryItems
|
||||
return components.url
|
||||
}
|
||||
|
||||
public func userImageURL(userId: String, tag: String? = nil) -> URL? {
|
||||
guard var components = URLComponents(url: serverURL, resolvingAgainstBaseURL: false) else { return nil }
|
||||
components.path = "/Users/\(userId)/Images/Primary"
|
||||
if let tag { components.queryItems = [.init(name: "tag", value: tag)] }
|
||||
return components.url
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import OpenAPIURLSession
|
||||
@_exported import OpenAPIRuntime
|
||||
@_exported import OpenAPIURLSession
|
||||
|
||||
public struct LuminateCore {
|
||||
public enum LuminateCore {
|
||||
public static let version = "0.1.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
generate:
|
||||
- types
|
||||
- client
|
||||
accessModifier: public
|
||||
|
|
|
|||
Loading…
Reference in a new issue