99 lines
3.6 KiB
Swift
99 lines
3.6 KiB
Swift
import Foundation
|
|
|
|
class ABSService: ObservableObject {
|
|
static let shared = ABSService()
|
|
|
|
func fetchLibraries(serverURL: String, token: String) async throws -> [Library] {
|
|
let url = URL(string: "\(serverURL)/api/libraries")!
|
|
var request = URLRequest(url: url)
|
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
|
|
|
let (data, _) = try await URLSession.shared.data(for: request)
|
|
let response = try JSONDecoder().decode(LibrariesResponse.self, from: data)
|
|
return response.libraries
|
|
}
|
|
|
|
func fetchBooks(serverURL: String, token: String, libraryId: String) async throws -> [AudiobookItem] {
|
|
let url = URL(string: "\(serverURL)/api/libraries/\(libraryId)/items?limit=100")!
|
|
var request = URLRequest(url: url)
|
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
|
|
|
let (data, _) = try await URLSession.shared.data(for: request)
|
|
let response = try JSONDecoder().decode(LibraryItemsResponse.self, from: data)
|
|
return response.results.compactMap { item in
|
|
AudiobookItem(
|
|
id: item.id,
|
|
title: item.media.metadata.title ?? "Unbekannt",
|
|
author: item.media.metadata.authorName ?? "Unbekannt",
|
|
coverURL: item.media.coverPath != nil ? "\(serverURL)/api/items/\(item.id)/cover" : nil,
|
|
duration: item.media.duration ?? 0,
|
|
mediaFiles: item.media.audioFiles?.map {
|
|
AudiobookItem.MediaFile(ino: $0.ino, name: $0.metadata.filename, path: $0.metadata.path)
|
|
} ?? []
|
|
)
|
|
}
|
|
}
|
|
|
|
func fetchProgress(serverURL: String, token: String, itemId: String) async throws -> LibraryProgress? {
|
|
let url = URL(string: "\(serverURL)/api/me/progress/\(itemId)")!
|
|
var request = URLRequest(url: url)
|
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
|
|
|
let (data, response) = try await URLSession.shared.data(for: request)
|
|
guard (response as? HTTPURLResponse)?.statusCode == 200 else { return nil }
|
|
return try? JSONDecoder().decode(LibraryProgress.self, from: data)
|
|
}
|
|
|
|
func updateProgress(serverURL: String, token: String, itemId: String, currentTime: Double, duration: Double) async {
|
|
guard let url = URL(string: "\(serverURL)/api/me/progress/\(itemId)") else { return }
|
|
var request = URLRequest(url: url)
|
|
request.httpMethod = "PATCH"
|
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
|
|
|
let body: [String: Any] = [
|
|
"currentTime": currentTime,
|
|
"duration": duration,
|
|
"isFinished": currentTime >= duration - 5
|
|
]
|
|
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
|
|
try? await URLSession.shared.data(for: request)
|
|
}
|
|
}
|
|
|
|
// MARK: - API Response Models
|
|
struct LibrariesResponse: Codable {
|
|
let libraries: [Library]
|
|
}
|
|
|
|
struct LibraryItemsResponse: Codable {
|
|
let results: [RawLibraryItem]
|
|
}
|
|
|
|
struct RawLibraryItem: Codable {
|
|
let id: String
|
|
let media: RawMedia
|
|
}
|
|
|
|
struct RawMedia: Codable {
|
|
let metadata: RawMetadata
|
|
let coverPath: String?
|
|
let duration: Double?
|
|
let audioFiles: [RawAudioFile]?
|
|
}
|
|
|
|
struct RawMetadata: Codable {
|
|
let title: String?
|
|
let authorName: String?
|
|
}
|
|
|
|
struct RawAudioFile: Codable {
|
|
let ino: String
|
|
let metadata: RawFileMetadata
|
|
}
|
|
|
|
struct RawFileMetadata: Codable {
|
|
let filename: String
|
|
let path: String
|
|
}
|