Floatplane channel plugin for Jellyfin 10.10.x: browse, HLS proxy, cookie session, CI release
Some checks failed
release / build-release (push) Has been cancelled
Some checks failed
release / build-release (push) Has been cancelled
- IChannel: creators -> sub-channels -> video posts (public listing API, search mapped) - IRequiresMediaInfoCallback -> signed proxy URLs; stream controller rewrites HLS so the AES-128 key is fetched server-side with the session cookie, segments stay on the CDN - delivery/info cached per token lifetime and throttled (~2/min) - config page: paste sails.sid + validate, extra creators, quality, search test - scripts/package.sh -> plugin folder + zip + md5 + manifest.json; Gitea release workflow - research docs, HAR analysis (HAR itself gitignored), install-pi5.sh Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
61
doc/research/reference-sources/wf_Authentication.swift
Normal file
61
doc/research/reference-sources/wf_Authentication.swift
Normal file
@@ -0,0 +1,61 @@
|
||||
import Foundation
|
||||
import FloatplaneAPIClient
|
||||
import Vapor
|
||||
|
||||
extension FloatplaneAPIClientAPI {
|
||||
|
||||
private static var FloatplaneURL = URL(string: "https://www.floatplane.com")!
|
||||
private static var SailsSidCookieName = "sails.sid"
|
||||
|
||||
public static var rawCookieValue: String = ""
|
||||
|
||||
static func loadAuthenticationCookiesFromStorage() {
|
||||
let storedCookies = HTTPCookieStorage.shared.cookies(for: FloatplaneURL)
|
||||
if let sailsSidCookie = storedCookies?.first(where: { $0.name == SailsSidCookieName }) {
|
||||
FloatplaneAPIClientAPI.customHeaders.cookie = [
|
||||
SailsSidCookieName: Vapor.HTTPCookies.Value(string: sailsSidCookie.value),
|
||||
]
|
||||
rawCookieValue = sailsSidCookie.value
|
||||
|
||||
// Cookies were previously stored for `www.floatplane.com` instead of `.floatplane.com`.
|
||||
// On app startup/loading auth cookies, detect if this cookie is old and re-save it
|
||||
// with the proper domain
|
||||
if sailsSidCookie.domain == "www.floatplane.com" {
|
||||
HTTPCookieStorage.shared.deleteCookie(sailsSidCookie)
|
||||
let newSailsSidCookie = HTTPCookie(properties: [
|
||||
.domain: ".floatplane.com",
|
||||
.path: "/",
|
||||
.name: SailsSidCookieName,
|
||||
.value: sailsSidCookie.value,
|
||||
.secure: "Secure",
|
||||
.expires: sailsSidCookie.expiresDate as Any,
|
||||
])!
|
||||
HTTPCookieStorage.shared.setCookies([newSailsSidCookie], for: FloatplaneURL, mainDocumentURL: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func storeAuthentifcationCookies(from clientResponse: ClientResponse) {
|
||||
if let sailsSidCookie = clientResponse.headers.setCookie?[SailsSidCookieName] {
|
||||
FloatplaneAPIClientAPI.customHeaders.cookie = [SailsSidCookieName: sailsSidCookie]
|
||||
let httpCookie = HTTPCookie(properties: [
|
||||
.domain: ".floatplane.com",
|
||||
.path: "/",
|
||||
.name: SailsSidCookieName,
|
||||
.value: sailsSidCookie.string,
|
||||
.secure: "Secure",
|
||||
.expires: NSDate(timeIntervalSince1970: sailsSidCookie.expires!.timeIntervalSince1970),
|
||||
])
|
||||
HTTPCookieStorage.shared.setCookies([httpCookie!], for: FloatplaneURL, mainDocumentURL: nil)
|
||||
rawCookieValue = sailsSidCookie.string
|
||||
}
|
||||
}
|
||||
|
||||
static func removeAuthenticationCookies() {
|
||||
let storedCookies = HTTPCookieStorage.shared.cookies(for: FloatplaneURL)
|
||||
if let sailsSidCookie = storedCookies?.first(where: { $0.name == SailsSidCookieName }) {
|
||||
HTTPCookieStorage.shared.deleteCookie(sailsSidCookie)
|
||||
}
|
||||
FloatplaneAPIClientAPI.customHeaders.cookie = [:]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user