mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-05-21 14:26:35 +01:00
113 lines
3.0 KiB
Swift
113 lines
3.0 KiB
Swift
import ExpoModulesCore
|
|
import Foundation
|
|
import Security
|
|
#if canImport(TVServices)
|
|
import TVServices
|
|
#endif
|
|
|
|
public class TopShelfCacheModule: Module {
|
|
private let appGroupInfoPlistKey = "StreamyfinAppGroupIdentifier"
|
|
private let keychainAccessGroupInfoPlistKey = "StreamyfinKeychainAccessGroupIdentifier"
|
|
private let cacheKey = "TopShelfCache"
|
|
private let apiKeyService = "StreamyfinTopShelf"
|
|
private let apiKeyAccount = "JellyfinApiKey"
|
|
private var appGroupIdentifier: String? {
|
|
if let appGroupIdentifier = Bundle.main.object(
|
|
forInfoDictionaryKey: appGroupInfoPlistKey
|
|
) as? String {
|
|
return appGroupIdentifier
|
|
}
|
|
|
|
guard let bundleIdentifier = Bundle.main.bundleIdentifier else {
|
|
return nil
|
|
}
|
|
|
|
return "group.\(bundleIdentifier)"
|
|
}
|
|
private var keychainAccessGroupIdentifier: String? {
|
|
Bundle.main.object(forInfoDictionaryKey: keychainAccessGroupInfoPlistKey) as? String
|
|
}
|
|
|
|
public func definition() -> ModuleDefinition {
|
|
Name("TopShelfCache")
|
|
|
|
Function("writeCache") { (json: String, apiKey: String?) -> Bool in
|
|
guard
|
|
let appGroupIdentifier = appGroupIdentifier,
|
|
let defaults = UserDefaults(suiteName: appGroupIdentifier)
|
|
else {
|
|
return false
|
|
}
|
|
|
|
defaults.set(json, forKey: cacheKey)
|
|
defaults.set(Date().timeIntervalSince1970, forKey: "\(cacheKey)UpdatedAt")
|
|
defaults.synchronize()
|
|
let didSaveAPIKey = saveAPIKey(apiKey)
|
|
|
|
#if canImport(TVServices)
|
|
TVTopShelfContentProvider.topShelfContentDidChange()
|
|
#endif
|
|
|
|
return didSaveAPIKey
|
|
}
|
|
|
|
Function("clearCache") { () -> Bool in
|
|
guard
|
|
let appGroupIdentifier = appGroupIdentifier,
|
|
let defaults = UserDefaults(suiteName: appGroupIdentifier)
|
|
else {
|
|
return false
|
|
}
|
|
|
|
defaults.removeObject(forKey: cacheKey)
|
|
defaults.removeObject(forKey: "\(cacheKey)UpdatedAt")
|
|
defaults.synchronize()
|
|
let didDeleteAPIKey = deleteAPIKey()
|
|
|
|
#if canImport(TVServices)
|
|
TVTopShelfContentProvider.topShelfContentDidChange()
|
|
#endif
|
|
|
|
return didDeleteAPIKey
|
|
}
|
|
}
|
|
|
|
private func baseAPIKeyQuery() -> [String: Any] {
|
|
var query: [String: Any] = [
|
|
kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrService as String: apiKeyService,
|
|
kSecAttrAccount as String: apiKeyAccount
|
|
]
|
|
|
|
if let keychainAccessGroupIdentifier {
|
|
query[kSecAttrAccessGroup as String] = keychainAccessGroupIdentifier
|
|
}
|
|
|
|
return query
|
|
}
|
|
|
|
private func saveAPIKey(_ apiKey: String?) -> Bool {
|
|
guard deleteAPIKey() else {
|
|
return false
|
|
}
|
|
|
|
guard
|
|
let apiKey,
|
|
!apiKey.isEmpty,
|
|
let data = apiKey.data(using: .utf8)
|
|
else {
|
|
return true
|
|
}
|
|
|
|
var query = baseAPIKeyQuery()
|
|
query[kSecValueData as String] = data
|
|
let status = SecItemAdd(query as CFDictionary, nil)
|
|
return status == errSecSuccess
|
|
}
|
|
|
|
private func deleteAPIKey() -> Bool {
|
|
let status = SecItemDelete(baseAPIKeyQuery() as CFDictionary)
|
|
return status == errSecSuccess || status == errSecItemNotFound
|
|
}
|
|
}
|