mirror of
https://github.com/whoeevee/EeveeSpotifyReborn.git
synced 2026-01-09 00:23:20 +01:00
Musixmatch Invalid Token Alert, better token input, Overwrite Configuration Option
This commit is contained in:
@@ -47,23 +47,36 @@ func getCurrentTrackLyricsData(originalLyrics: Lyrics? = nil) throws -> Data {
|
||||
)
|
||||
}
|
||||
|
||||
catch {
|
||||
|
||||
if source != .genius && UserDefaults.geniusFallback {
|
||||
catch let error as LyricsError {
|
||||
|
||||
switch error {
|
||||
|
||||
NSLog("[EeveeSpotify] Unable to load lyrics from \(source): \(error), trying Genius as fallback")
|
||||
source = .genius
|
||||
|
||||
plainLyrics = try LyricsRepository.getLyrics(
|
||||
title: track.trackTitle(),
|
||||
artist: track.artistTitle(),
|
||||
spotifyTrackId: track.URI().spt_trackIdentifier(),
|
||||
source: source
|
||||
case .InvalidMusixmatchToken:
|
||||
|
||||
PopUpHelper.showPopUp(
|
||||
delayed: false,
|
||||
message: "The tweak is unable to load lyrics from Musixmatch due to Unauthorized error. Please check or update your Musixmatch token.",
|
||||
buttonText: "OK"
|
||||
)
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
else {
|
||||
|
||||
if source == .genius || !UserDefaults.geniusFallback {
|
||||
throw error
|
||||
}
|
||||
|
||||
NSLog("[EeveeSpotify] Unable to load lyrics from \(source): \(error), trying Genius as fallback")
|
||||
source = .genius
|
||||
|
||||
plainLyrics = try LyricsRepository.getLyrics(
|
||||
title: track.trackTitle(),
|
||||
artist: track.artistTitle(),
|
||||
spotifyTrackId: track.URI().spt_trackIdentifier(),
|
||||
source: source
|
||||
)
|
||||
}
|
||||
|
||||
let lyrics = try Lyrics.with {
|
||||
|
||||
@@ -65,6 +65,11 @@ struct MusixmatchLyricsDataSource {
|
||||
else {
|
||||
throw LyricsError.DecodingError
|
||||
}
|
||||
|
||||
if let header = message["header"] as? [String: Any],
|
||||
header["status_code"] as? Int == 401 {
|
||||
throw LyricsError.InvalidMusixmatchToken
|
||||
}
|
||||
|
||||
if let trackSubtitlesGet = macroCalls["track.subtitles.get"] as? [String: Any],
|
||||
let subtitlesMessage = trackSubtitlesGet["message"] as? [String: Any],
|
||||
|
||||
@@ -2,6 +2,7 @@ import Foundation
|
||||
|
||||
enum LyricsError: Swift.Error {
|
||||
case NoCurrentTrack
|
||||
case InvalidMusixmatchToken
|
||||
case DecodingError
|
||||
case NoSuchSong
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,4 +44,19 @@ extension String {
|
||||
withTemplate: ""
|
||||
)
|
||||
}
|
||||
|
||||
var hexadecimal: Data? {
|
||||
var data = Data(capacity: count / 2)
|
||||
|
||||
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
|
||||
regex.enumerateMatches(in: self, range: NSRange(startIndex..., in: self)) { match, _, _ in
|
||||
let byteString = (self as NSString).substring(with: match!.range)
|
||||
let num = UInt8(byteString, radix: 16)!
|
||||
data.append(num)
|
||||
}
|
||||
|
||||
guard data.count > 0 else { return nil }
|
||||
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ extension UserDefaults {
|
||||
private static let geniusFallbackKey = "geniusFallback"
|
||||
private static let darkPopUpsKey = "darkPopUps"
|
||||
private static let patchTypeKey = "patchType"
|
||||
private static let overwriteConfigurationKey = "overwriteConfiguration"
|
||||
|
||||
static var lyricsSource: LyricsSource {
|
||||
get {
|
||||
@@ -62,4 +63,13 @@ extension UserDefaults {
|
||||
defaults.set(patchType.rawValue, forKey: patchTypeKey)
|
||||
}
|
||||
}
|
||||
|
||||
static var overwriteConfiguration: Bool {
|
||||
get {
|
||||
defaults.bool(forKey: overwriteConfigurationKey)
|
||||
}
|
||||
set (overwriteConfiguration) {
|
||||
defaults.set(overwriteConfiguration, forKey: overwriteConfigurationKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
func modifyRemoteConfiguration(_ configuration: inout UcsResponse) {
|
||||
|
||||
if UserDefaults.overwriteConfiguration {
|
||||
configuration.resolve.configuration = try! BundleHelper.shared.resolveConfiguration()
|
||||
}
|
||||
|
||||
modifyAttributes(&configuration.attributes.accountAttributes)
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,19 @@ class SPTCoreURLSessionDataDelegateHook: ClassHook<NSObject> {
|
||||
|
||||
var bootstrapMessage = try BootstrapMessage(serializedData: buffer)
|
||||
|
||||
if UserDefaults.patchType == .notSet {
|
||||
|
||||
if bootstrapMessage.attributes["type"]?.stringValue == "premium" {
|
||||
UserDefaults.patchType = .disabled
|
||||
showHavePremiumPopUp()
|
||||
}
|
||||
else {
|
||||
UserDefaults.patchType = .requests
|
||||
}
|
||||
|
||||
NSLog("[EeveeSpotify] Fetched bootstrap, \(UserDefaults.patchType) was set")
|
||||
}
|
||||
|
||||
if UserDefaults.patchType == .requests {
|
||||
|
||||
modifyRemoteConfiguration(&bootstrapMessage.ucsResponse)
|
||||
@@ -75,21 +88,6 @@ class SPTCoreURLSessionDataDelegateHook: ClassHook<NSObject> {
|
||||
NSLog("[EeveeSpotify] Modified bootstrap data")
|
||||
}
|
||||
else {
|
||||
|
||||
if UserDefaults.patchType == .notSet {
|
||||
|
||||
if bootstrapMessage.attributes["type"]?.stringValue == "premium" {
|
||||
UserDefaults.patchType = .disabled
|
||||
showHavePremiumPopUp()
|
||||
}
|
||||
else {
|
||||
UserDefaults.patchType = .offlineBnk
|
||||
showOfflineBnkMethodSetPopUp()
|
||||
}
|
||||
|
||||
NSLog("[EeveeSpotify] Fetched bootstrap, \(UserDefaults.patchType) was set")
|
||||
}
|
||||
|
||||
orig.URLSession(session, dataTask: task, didReceiveData: buffer)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,4 +26,15 @@ class BundleHelper {
|
||||
)!
|
||||
)
|
||||
}
|
||||
|
||||
func resolveConfiguration() throws -> ResolveConfiguration {
|
||||
return try ResolveConfiguration(
|
||||
serializedData: try Data(
|
||||
contentsOf: self.bundle.url(
|
||||
forResource: "resolveconfiguration",
|
||||
withExtension: "bnk"
|
||||
)!
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -2,7 +2,7 @@ import SwiftUI
|
||||
|
||||
extension EeveeSettingsView {
|
||||
|
||||
@ViewBuilder func PremiumSection() -> some View {
|
||||
@ViewBuilder func PremiumSections() -> some View {
|
||||
|
||||
Section(footer: patchType == .disabled ? nil : Text("""
|
||||
You can select the Premium patching method you prefer. App restart is required after changing.
|
||||
@@ -17,7 +17,7 @@ If you have an active Premium subscription, you can turn on Do Not Patch Premium
|
||||
"Do Not Patch Premium",
|
||||
isOn: Binding<Bool>(
|
||||
get: { patchType == .disabled },
|
||||
set: { patchType = $0 ? .disabled : .offlineBnk }
|
||||
set: { patchType = $0 ? .disabled : .requests }
|
||||
)
|
||||
)
|
||||
|
||||
@@ -31,5 +31,16 @@ If you have an active Premium subscription, you can turn on Do Not Patch Premium
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if patchType == .requests {
|
||||
Section(
|
||||
footer: Text("Replace remote configuration with the dumped Premium one. It might fix some issues, such as appearing ads, but it's not guaranteed.")
|
||||
) {
|
||||
Toggle(
|
||||
"Overwrite Configuration",
|
||||
isOn: $overwriteConfiguration
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,20 @@ struct EeveeSettingsView: View {
|
||||
@State var musixmatchToken = UserDefaults.musixmatchToken
|
||||
@State var patchType = UserDefaults.patchType
|
||||
@State var lyricsSource = UserDefaults.lyricsSource
|
||||
@State var overwriteConfiguration = UserDefaults.overwriteConfiguration
|
||||
|
||||
private func getMusixmatchToken(_ input: String) -> String? {
|
||||
|
||||
if let match = input.firstMatch("\\[UserToken\\]: ([a-f0-9]+)"),
|
||||
let tokenRange = Range(match.range(at: 1), in: input) {
|
||||
return String(input[tokenRange])
|
||||
}
|
||||
else if input ~= "^[a-f0-9]+$" {
|
||||
return input
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
private func showMusixmatchTokenAlert(_ oldSource: LyricsSource) {
|
||||
|
||||
@@ -25,16 +39,8 @@ struct EeveeSettingsView: View {
|
||||
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default) { _ in
|
||||
let text = alert.textFields!.first!.text!
|
||||
let token: String
|
||||
|
||||
if let match = text.firstMatch("\\[UserToken\\]: ([a-f0-9]+)"),
|
||||
let tokenRange = Range(match.range(at: 1), in: text) {
|
||||
token = String(text[tokenRange])
|
||||
}
|
||||
else if text ~= "^[a-f0-9]+$" {
|
||||
token = text
|
||||
}
|
||||
else {
|
||||
|
||||
guard let token = getMusixmatchToken(text) else {
|
||||
lyricsSource = oldSource
|
||||
return
|
||||
}
|
||||
@@ -50,7 +56,7 @@ struct EeveeSettingsView: View {
|
||||
|
||||
List {
|
||||
|
||||
PremiumSection()
|
||||
PremiumSections()
|
||||
|
||||
LyricsSections()
|
||||
|
||||
@@ -73,14 +79,26 @@ struct EeveeSettingsView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.padding(.bottom, 45)
|
||||
|
||||
.listStyle(GroupedListStyle())
|
||||
|
||||
.padding(.bottom, 60)
|
||||
.ignoresSafeArea(.keyboard)
|
||||
|
||||
.animation(.default, value: lyricsSource)
|
||||
.animation(.default, value: patchType)
|
||||
|
||||
.onChange(of: musixmatchToken) { token in
|
||||
UserDefaults.musixmatchToken = token
|
||||
.onChange(of: musixmatchToken) { input in
|
||||
|
||||
if input.isEmpty { return }
|
||||
|
||||
if let token = getMusixmatchToken(input) {
|
||||
UserDefaults.musixmatchToken = token
|
||||
self.musixmatchToken = token
|
||||
}
|
||||
else {
|
||||
self.musixmatchToken = ""
|
||||
}
|
||||
}
|
||||
|
||||
.onChange(of: lyricsSource) { [lyricsSource] newSource in
|
||||
@@ -104,8 +122,18 @@ struct EeveeSettingsView: View {
|
||||
NSLog("Unable to reset offline.bnk: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
.listStyle(GroupedListStyle())
|
||||
|
||||
.onChange(of: overwriteConfiguration) { overwriteConfiguration in
|
||||
|
||||
UserDefaults.overwriteConfiguration = overwriteConfiguration
|
||||
|
||||
do {
|
||||
try OfflineHelper.resetOfflineBnk()
|
||||
}
|
||||
catch {
|
||||
NSLog("Unable to reset offline.bnk: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
.onAppear {
|
||||
UIView.appearance(
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ If the tweak is unable to find a song or process the lyrics, you'll see a "Could
|
||||
|
||||
Text("Musixmatch User Token")
|
||||
|
||||
TextField("Enter User Token", text: $musixmatchToken)
|
||||
TextField("Enter User Token or Paste Debug Info", text: $musixmatchToken)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user