75 lines
2.6 KiB
Swift
75 lines
2.6 KiB
Swift
// The Swift Programming Language
|
|
// https://docs.swift.org/swift-book
|
|
|
|
import Foundation
|
|
import ArgumentParser
|
|
import JellyfinAPI
|
|
import CryptoKit
|
|
import Logging
|
|
|
|
let SeanutVersion = "0.0.1"
|
|
|
|
@main
|
|
struct Seanut: AsyncParsableCommand {
|
|
static var configuration = CommandConfiguration(
|
|
abstract: "A utility to download media from jellyfin servers",
|
|
subcommands: [SearchCommand.self, DownloadCommand.self, LoginCommand.self],
|
|
defaultSubcommand: SearchCommand.self
|
|
)
|
|
|
|
static var Logger: Logger? = nil
|
|
|
|
struct CommonArguments: ParsableArguments {
|
|
@Option(name: .shortAndLong, help: "jellyfin server domain name")
|
|
var domain: String
|
|
|
|
@Flag(name: .long, help: "prints extra information to the console")
|
|
var verbose = false
|
|
}
|
|
|
|
static func maybeSetLogger(_ opts: CommonArguments) {
|
|
Seanut.Logger = opts.verbose ? Logging.Logger(label: "garden.focks.SeanutSwift.logger") : nil
|
|
}
|
|
|
|
static func generateJellyfinConfiguration(url: URL) -> JellyfinClient.Configuration {
|
|
let hostname = Host.current().localizedName ?? "Seanut-Device"
|
|
let digest = SHA256.hash(data: hostname.data(using: .utf8)!)
|
|
|
|
return JellyfinClient.Configuration(
|
|
url: url,
|
|
client: "SeanutSwift",
|
|
deviceName: hostname,
|
|
deviceID: digest.compactMap({ String(format: "%02x", $0) }).joined(),
|
|
version: SeanutVersion
|
|
)
|
|
}
|
|
|
|
static func getAccessToken(client: JellyfinClient, username: String, password: String?) async {
|
|
let pass: String? = password ?? {
|
|
print("password>", terminator: " ")
|
|
return readLine(strippingNewline: true)
|
|
}()
|
|
let domain = client.configuration.url.host!
|
|
|
|
do {
|
|
let auth = try await client.signIn(username: username,
|
|
password: pass ?? "")
|
|
let fileName = FileManager.default
|
|
.homeDirectoryForCurrentUser
|
|
.appendingPathComponent(".seanut/\(domain)")
|
|
|
|
try auth.accessToken!.write(to: fileName, atomically: false, encoding: .utf8)
|
|
print("Access token retrieved ☑️")
|
|
} catch {
|
|
print("Failed to login with provided credentials. please try again later.")
|
|
exit(withError: error)
|
|
}
|
|
}
|
|
|
|
static func retrieveAccessToken(for domain: URL) -> String? {
|
|
let tokenPath = FileManager.default
|
|
.homeDirectoryForCurrentUser
|
|
.appendingPathComponent(".seanut/\(domain.host!)")
|
|
return try? String(contentsOf: tokenPath)
|
|
}
|
|
}
|