This commit is contained in:
eevee
2025-11-13 17:04:23 +03:00
parent 6b89139078
commit ea9bf6610c
13 changed files with 100 additions and 22 deletions
@@ -20,7 +20,7 @@ class SPTPlayerTrackHook: ClassHook<NSObject> {
guard shouldOverrideLocalTrackURI,
let absoluteString = uri?.absoluteString,
absoluteString.hasPrefix("spotify:local:") else {
absoluteString.isLocalTrackIdentifier else {
return uri
}
@@ -128,7 +128,9 @@ func getLyricsDataForCurrentTrack(_ originalPath: String, originalLyrics: Lyrics
throw LyricsError.noCurrentTrack
}
if !originalPath.contains(track.trackIdentifier) {
let trackIdentifier = track.trackIdentifier
if !trackIdentifier.isEmpty && !originalPath.contains(trackIdentifier) {
throw LyricsError.trackMismatch
}
@@ -0,0 +1,5 @@
extension String {
var isLocalTrackIdentifier: Bool {
self.hasPrefix("spotify:local:")
}
}
@@ -8,6 +8,26 @@ var scrollDataSource: NowPlayingScrollDataSourceImplementation?
var nowPlayingScrollViewController: NowPlayingScrollViewController?
var npvScrollViewController: NPVScrollViewController?
class LegacyNowPlayingPlatformSwiftServiceImplementationHook: ClassHook<NSObject> {
typealias Group = IOS14PremiumPatchingGroup
static let targetName = "NowPlaying_PlatformImpl.NowPlayingPlatformSwiftServiceImplementation"
func provideStatefulPlayer() -> StatefulPlayerImplementation {
statefulPlayer = orig.provideStatefulPlayer()
return statefulPlayer!
}
}
class NowPlayingPlatformSwiftServiceImplementationHook: ClassHook<NSObject> {
typealias Group = NonIOS14PremiumPatchingGroup
static let targetName = "NowPlaying_PlatformImpl.NowPlayingPlatformSwiftServiceImplementation"
func provideStatefulPlayerWithFeatureIdentifier(_ identifier: NSString) -> StatefulPlayerImplementation {
statefulPlayer = orig.provideStatefulPlayerWithFeatureIdentifier(identifier)
return statefulPlayer!
}
}
class NowPlayingScrollPrivateServiceImplementationHook: ClassHook<NSObject> {
typealias Group = BaseLyricsGroup
static let targetName = "NowPlaying_ScrollImpl.NowPlayingScrollPrivateServiceImplementation"
@@ -22,7 +42,6 @@ class NowPlayingScrollPrivateServiceImplementationHook: ClassHook<NSObject> {
)
}
else {
statefulPlayer = Ivars<StatefulPlayerImplementation>(dependencies).statefulPlayer
scrollDataSource = Ivars<NowPlayingScrollDataSourceImplementation>(target)
.$__lazy_storage_$_scrollDataSource
npvScrollViewController = Dynamic.convert(
@@ -2,30 +2,65 @@ import Foundation
import UIKit
func modifyRemoteConfiguration(_ configuration: inout UcsResponse) {
modifyAttributes(&configuration.attributes.accountAttributes)
if UserDefaults.overwriteConfiguration {
configuration.resolve.configuration = try! BundleHelper.shared.resolveConfiguration()
}
modifyAttributes(&configuration.attributes.accountAttributes)
modifyAssignedValues(&configuration.assignedValues)
else {
modifyAssignedValues(&configuration.assignedValues)
}
}
private let propertyToRemoveNames = [
"enable_common_capping",
"enable_pns_common_capping",
"enable_pick_and_shuffle_common_capping",
"enable_pick_and_shuffle_dynamic_cap",
"pick_and_shuffle_timecap", // capping
"should_nova_scroll_use_scrollsita" // 😡😡😡
// spotify, stop changing the scroll logic
private let propertyReplacements = [
// capping
EeveePropertyReplacement(name: "enable_common_capping", modification: .remove),
EeveePropertyReplacement(name: "enable_pns_common_capping", modification: .remove),
EeveePropertyReplacement(name: "enable_pick_and_shuffle_common_capping", modification: .remove),
EeveePropertyReplacement(name: "enable_pick_and_shuffle_dynamic_cap", modification: .remove),
EeveePropertyReplacement(name: "pick_and_shuffle_timecap", modification: .remove),
EeveePropertyReplacement(scope: "ios-feature-queue", modification: .remove),
// also capping idk
EeveePropertyReplacement(name: "enable_free_on_demand_experiment", modification: .remove),
EeveePropertyReplacement(name: "enable_free_on_demand_context_menu_experiment", modification: .remove),
EeveePropertyReplacement(name: "enable_mft_plus_queue", modification: .remove),
EeveePropertyReplacement(name: "enable_mft_plus_extended_queue", modification: .remove),
EeveePropertyReplacement(name: "enable_playback_timeout_service", modification: .setBool(false)),
EeveePropertyReplacement(name: "enable_playback_timeout_error_ui", modification: .setBool(false)),
EeveePropertyReplacement(name: "playback_timeout_action", modification: .setEnum("Nothing")),
EeveePropertyReplacement(name: "is_remove_from_queue_enabled_for_mft_plus", modification: .remove),
EeveePropertyReplacement(name: "is_reordering_for_mft_plus_allowed", modification: .remove),
// 😡😡😡 spotify, stop changing the scroll logic
EeveePropertyReplacement(name: "should_nova_scroll_use_scrollsita", modification: .remove)
]
func modifyAssignedValues(_ values: inout [AssignedValue]) {
values.removeAll(where: { propertyToRemoveNames.contains($0.propertyID.name) })
values.removeAll(where: { $0.propertyID.scope == "ios-feature-queue" })
private func modifyAssignedValues(_ values: inout [AssignedValue]) {
for replacement in propertyReplacements {
let matchingIndices = values.indices.filter({ index in
let value = values[index]
let nameMatches = replacement.name.map { value.propertyID.name == $0 } ?? true
let scopeMatches = replacement.scope.map { value.propertyID.scope == $0 } ?? true
return nameMatches && scopeMatches
})
for index in matchingIndices.sorted(by: >) {
switch replacement.modification {
case .remove:
values.remove(at: index)
case .setBool(let newValue):
values[index].boolValue = BoolValue.with { $0.value = newValue }
case .setEnum(let newValue):
values[index].enumValue = EnumValue.with { $0.value = newValue }
}
}
}
}
func modifyAttributes(_ attributes: inout [String: AccountAttribute]) {
private func modifyAttributes(_ attributes: inout [String: AccountAttribute]) {
let oneYearFromNow = Calendar.current.date(byAdding: .year, value: 1, to: Date())!
let formatter = ISO8601DateFormatter()
@@ -1,6 +1,6 @@
import Foundation
enum PatchType: Int {
enum EeveePatchType: Int {
case notSet
case disabled
case requests
@@ -0,0 +1,17 @@
enum EeveePropertyModification {
case remove
case setBool(Bool)
case setEnum(String)
}
struct EeveePropertyReplacement {
let scope: String?
let name: String?
let modification: EeveePropertyModification
init(name: String? = nil, scope: String? = nil, modification: EeveePropertyModification) {
self.name = name
self.scope = scope
self.modification = modification
}
}
@@ -1,7 +1,7 @@
import Orion
class SPTFreeTierArtistHubRemoteURLResolverHook: ClassHook<NSObject> {
typealias Group = BasePremiumPatchingGroup
typealias Group = IOS14And15PremiumPatchingGroup
static let targetName = "SPTFreeTierArtistHubRemoteURLResolver"
func initWithViewURI(
@@ -29,10 +29,10 @@ extension UserDefaults {
}
}
static var patchType: PatchType {
static var patchType: EeveePatchType {
get {
if let rawValue = container.object(forKey: patchTypeKey) as? Int {
return PatchType(rawValue: rawValue) ?? .requests
return EeveePatchType(rawValue: rawValue) ?? .requests
}
return .notSet