From 682b60f0b1907d728c3975a015a6b165b2785ced Mon Sep 17 00:00:00 2001 From: Avi Wadhwa Date: Thu, 11 Apr 2024 13:55:58 -0700 Subject: [PATCH] =?UTF-8?q?Fake=20the=20UserAgent:=20Spotify=20has=20start?= =?UTF-8?q?ed=20blocking=20lyric=20requests=20from=20my=20app=20?= =?UTF-8?q?=F0=9F=A4=A3=20+=20reset=20PersistentID=20and=20SpotifyID=20var?= =?UTF-8?q?s=20on=20song=20end=20(we=20only=20ever=20reach=20this=20on=20A?= =?UTF-8?q?pple=20Music)=20(necessary=20for=20songs=20on=20repeat=20in=20a?= =?UTF-8?q?pple=20music,=20my=20fake=20lyric=20at=20the=20end=20is=20not?= =?UTF-8?q?=20long=20enough=20for=20apple=20music=20songs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SongObject+CoreDataClass.swift | 3 +++ SpotifyLyricsInMenubar/viewModel.swift | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/SongObject+CoreDataClass.swift b/SongObject+CoreDataClass.swift index 14907c8..d175a33 100644 --- a/SongObject+CoreDataClass.swift +++ b/SongObject+CoreDataClass.swift @@ -26,6 +26,9 @@ public class SongObject: NSManagedObject, Decodable { self.downloadDate = Date.now let container = try decoder.container(keyedBy: CodingKeys.self) if let syncType = try? container.decode(String.self, forKey: .syncType), syncType == "LINE_SYNCED", var lyrics = try? container.decode([LyricLine].self, forKey: .lines) { + // Dummy lyric at the end to keep the timer going past the last lyric, necessary for someone playing a single song on repeat + // Spotify doesn't give playback notifications when it's the same song on repeat + // Apple Music does, but unfortunately has every song slightly longer than it's spotify counterpart so this doesn't help us if !lyrics.isEmpty { lyrics.append(LyricLine(startTime: duration-1400, words: "Now Playing: \(title)")) } diff --git a/SpotifyLyricsInMenubar/viewModel.swift b/SpotifyLyricsInMenubar/viewModel.swift index 2baaf29..b8f77ba 100644 --- a/SpotifyLyricsInMenubar/viewModel.swift +++ b/SpotifyLyricsInMenubar/viewModel.swift @@ -52,6 +52,11 @@ import MediaPlayer @AppStorage("spDcCookie") var cookie = "" let decoder = JSONDecoder() + // Fake Spotify User Agent + // Spotify's started blocking my app's useragent. A win honestly 🤣 + let fakeSpotifyUserAgentconfig = URLSessionConfiguration.default + let fakeSpotifyUserAgentSession: URLSession + init() { // Load framework let bundle = CFBundleCreate(kCFAllocatorDefault, NSURL(fileURLWithPath: "/System/Library/PrivateFrameworks/MediaRemote.framework")) @@ -62,6 +67,10 @@ import MediaPlayer updaterController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil) coreDataContainer = NSPersistentContainer(name: "Lyrics") + + fakeSpotifyUserAgentconfig.httpAdditionalHeaders = ["User-Agent": "Spotify/121000760 Win32/0 (PC laptop)"] + fakeSpotifyUserAgentSession = URLSession(configuration: fakeSpotifyUserAgentconfig) + coreDataContainer.loadPersistentStores { description, error in if let error = error { fatalError("Error: \(error.localizedDescription)") @@ -91,6 +100,8 @@ import MediaPlayer // spotifyScript?.nextTrack?() // we've reached the end of the song, we're past the last lyric // so we set the timer till the duration of the song, in case the user skips ahead or forward + currentlyPlayingAppleMusicPersistentID = nil + currentlyPlaying = nil return nil } else if currentTime > currentlyPlayingLyrics[currentlyPlayingLyricsIndex].startTimeMS, currentTime < currentlyPlayingLyrics[newIndex].startTimeMS { @@ -225,8 +236,11 @@ import MediaPlayer request.addValue("WebPlayer", forHTTPHeaderField: "app-platform") print("the access token is \(accessToken.accessToken)") request.addValue("Bearer \(accessToken.accessToken)", forHTTPHeaderField: "authorization") - let urlResponseAndData = try await URLSession.shared.data(for: request) + + let urlResponseAndData = try await fakeSpotifyUserAgentSession.data(for: request) + print(urlResponseAndData) if urlResponseAndData.0.isEmpty { + print("F") return [] } print(String(decoding: urlResponseAndData.0, as: UTF8.self))