mirror of
https://github.com/whoeevee/EeveeSpotifyReborn.git
synced 2026-01-09 00:23:20 +01:00
premium plan info and improvements
This commit is contained in:
@@ -6,11 +6,17 @@ class SPTDataLoaderServiceHook: ClassHook<NSObject>, SpotifySessionDelegate {
|
|||||||
|
|
||||||
// orion:new
|
// orion:new
|
||||||
func shouldModify(_ url: URL) -> Bool {
|
func shouldModify(_ url: URL) -> Bool {
|
||||||
let isModifyingCustomizeResponse = PremiumPatchingGroup.isActive
|
let shouldPatchPremium = PremiumPatchingGroup.isActive
|
||||||
let isModifyingLyrics = LyricsGroup.isActive
|
let shouldReplaceLyrics = LyricsGroup.isActive
|
||||||
|
|
||||||
return (url.isLyrics && isModifyingLyrics)
|
return (shouldReplaceLyrics && url.isLyrics)
|
||||||
|| (url.isCustomize && isModifyingCustomizeResponse)
|
|| (shouldPatchPremium && (url.isCustomize || url.isPremiumPlanRow || url.isPlanOverview))
|
||||||
|
}
|
||||||
|
|
||||||
|
// orion:new
|
||||||
|
func respondWithCustomData(_ data: Data, task: URLSessionDataTask, session: URLSession) {
|
||||||
|
orig.URLSession(session, dataTask: task, didReceiveData: data)
|
||||||
|
orig.URLSession(session, task: task, didCompleteWithError: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func URLSession(
|
func URLSession(
|
||||||
@@ -18,58 +24,65 @@ class SPTDataLoaderServiceHook: ClassHook<NSObject>, SpotifySessionDelegate {
|
|||||||
task: URLSessionDataTask,
|
task: URLSessionDataTask,
|
||||||
didCompleteWithError error: Error?
|
didCompleteWithError error: Error?
|
||||||
) {
|
) {
|
||||||
guard
|
guard let url = task.currentRequest?.url else {
|
||||||
let request = task.currentRequest,
|
|
||||||
let url = request.url
|
|
||||||
else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if error == nil,
|
guard error == nil, shouldModify(url) else {
|
||||||
shouldModify(url),
|
orig.URLSession(session, task: task, didCompleteWithError: error)
|
||||||
let buffer = URLSessionHelper.shared.obtainData(for: url)
|
return
|
||||||
{
|
}
|
||||||
if url.isLyrics {
|
|
||||||
do {
|
do {
|
||||||
orig.URLSession(
|
if let buffer = URLSessionHelper.shared.obtainData(for: url) {
|
||||||
session,
|
if url.isLyrics {
|
||||||
dataTask: task,
|
respondWithCustomData(
|
||||||
didReceiveData: try getLyricsDataForCurrentTrack(
|
try getLyricsDataForCurrentTrack(
|
||||||
originalLyrics: try? Lyrics(serializedBytes: buffer)
|
originalLyrics: try? Lyrics(serializedBytes: buffer)
|
||||||
)
|
),
|
||||||
|
task: task,
|
||||||
|
session: session
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.isPremiumPlanRow {
|
||||||
|
respondWithCustomData(
|
||||||
|
try getPremiumPlanRowData(
|
||||||
|
originalPremiumPlanRow: try PremiumPlanRow(serializedBytes: buffer)
|
||||||
|
),
|
||||||
|
task: task,
|
||||||
|
session: session
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var customizeMessage = try CustomizeMessage(serializedBytes: buffer)
|
||||||
|
modifyRemoteConfiguration(&customizeMessage.response)
|
||||||
|
|
||||||
|
respondWithCustomData(try customizeMessage.serializedData(), task: task, session: session)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.isPlanOverview {
|
||||||
|
do {
|
||||||
|
orig.URLSession(session, dataTask: task, didReceiveData: try getPlanOverviewData())
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: nil)
|
orig.URLSession(session, task: task, didCompleteWithError: nil)
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: error)
|
orig.URLSession(session, task: task, didCompleteWithError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
var customizeMessage = try CustomizeMessage(serializedBytes: buffer)
|
|
||||||
modifyRemoteConfiguration(&customizeMessage.response)
|
|
||||||
|
|
||||||
orig.URLSession(
|
|
||||||
session,
|
|
||||||
dataTask: task,
|
|
||||||
didReceiveData: try customizeMessage.serializedBytes()
|
|
||||||
)
|
|
||||||
|
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: nil)
|
|
||||||
|
|
||||||
NSLog("[EeveeSpotify] Modified customize data")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
catch {
|
}
|
||||||
NSLog("[EeveeSpotify] Unable to modify customize data: \(error)")
|
catch {
|
||||||
}
|
orig.URLSession(session, task: task, didCompleteWithError: error)
|
||||||
}
|
}
|
||||||
|
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: error)
|
orig.URLSession(session, task: task, didCompleteWithError: error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func URLSession(
|
func URLSession(
|
||||||
@@ -79,47 +92,23 @@ class SPTDataLoaderServiceHook: ClassHook<NSObject>, SpotifySessionDelegate {
|
|||||||
completionHandler handler: @escaping (URLSession.ResponseDisposition) -> Void
|
completionHandler handler: @escaping (URLSession.ResponseDisposition) -> Void
|
||||||
) {
|
) {
|
||||||
guard
|
guard
|
||||||
let request = task.currentRequest,
|
let url = task.currentRequest?.url,
|
||||||
let url = request.url
|
url.isLyrics,
|
||||||
|
response.statusCode != 200
|
||||||
else {
|
else {
|
||||||
|
orig.URLSession(session, dataTask: task, didReceiveResponse: response, completionHandler: handler)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if shouldModify(url), url.isLyrics, response.statusCode != 200 {
|
do {
|
||||||
let okResponse = HTTPURLResponse(
|
let data = try getLyricsDataForCurrentTrack()
|
||||||
url: url,
|
let okResponse = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "2.0", headerFields: [:])!
|
||||||
statusCode: 200,
|
|
||||||
httpVersion: "2.0",
|
|
||||||
headerFields: [:]
|
|
||||||
)!
|
|
||||||
|
|
||||||
do {
|
orig.URLSession(session, dataTask: task, didReceiveResponse: okResponse, completionHandler: handler)
|
||||||
let lyricsData = try getLyricsDataForCurrentTrack()
|
respondWithCustomData(data, task: task, session: session)
|
||||||
|
} catch {
|
||||||
orig.URLSession(
|
orig.URLSession(session, task: task, didCompleteWithError: error)
|
||||||
session,
|
|
||||||
dataTask: task,
|
|
||||||
didReceiveResponse: okResponse,
|
|
||||||
completionHandler: handler
|
|
||||||
)
|
|
||||||
|
|
||||||
orig.URLSession(session, dataTask: task, didReceiveData: lyricsData)
|
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: nil)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
orig.URLSession(session, task: task, didCompleteWithError: error)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
orig.URLSession(
|
|
||||||
session,
|
|
||||||
dataTask: task,
|
|
||||||
didReceiveResponse: response,
|
|
||||||
completionHandler: handler
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func URLSession(
|
func URLSession(
|
||||||
@@ -127,10 +116,7 @@ class SPTDataLoaderServiceHook: ClassHook<NSObject>, SpotifySessionDelegate {
|
|||||||
dataTask task: URLSessionDataTask,
|
dataTask task: URLSessionDataTask,
|
||||||
didReceiveData data: Data
|
didReceiveData data: Data
|
||||||
) {
|
) {
|
||||||
guard
|
guard let url = task.currentRequest?.url else {
|
||||||
let request = task.currentRequest,
|
|
||||||
let url = request.url
|
|
||||||
else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ import UIKit
|
|||||||
|
|
||||||
class SPTPlayerTrackHook: ClassHook<NSObject> {
|
class SPTPlayerTrackHook: ClassHook<NSObject> {
|
||||||
typealias Group = LyricsGroup
|
typealias Group = LyricsGroup
|
||||||
static let targetName = "SPTPlayerTrack"
|
static let targetName = EeveeSpotify.hookTarget == .latest
|
||||||
|
? "SPTPlayerTrackImplementation"
|
||||||
|
: "SPTPlayerTrack"
|
||||||
|
|
||||||
func metadata() -> [String: String] {
|
func metadata() -> [String: String] {
|
||||||
var meta = orig.metadata()
|
var meta = orig.metadata()
|
||||||
@@ -31,7 +33,7 @@ class NowPlayingScrollViewControllerHook: ClassHook<NSObject> {
|
|||||||
withDifferentProviders: Bool,
|
withDifferentProviders: Bool,
|
||||||
scrollEnabledValueChanged: Bool
|
scrollEnabledValueChanged: Bool
|
||||||
) -> NowPlayingScrollViewController {
|
) -> NowPlayingScrollViewController {
|
||||||
var controller = orig.nowPlayingScrollViewModelWithDidLoadComponentsFor(
|
let controller = orig.nowPlayingScrollViewModelWithDidLoadComponentsFor(
|
||||||
track,
|
track,
|
||||||
withDifferentProviders: withDifferentProviders,
|
withDifferentProviders: withDifferentProviders,
|
||||||
scrollEnabledValueChanged: scrollEnabledValueChanged
|
scrollEnabledValueChanged: scrollEnabledValueChanged
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ func getLyricsDataForCurrentTrack(originalLyrics: Lyrics? = nil) throws -> Data
|
|||||||
color = Color(hex: extractedColor)
|
color = Color(hex: extractedColor)
|
||||||
.normalized(lyricsColorsSettings.normalizationFactor)
|
.normalized(lyricsColorsSettings.normalizationFactor)
|
||||||
}
|
}
|
||||||
else if let uiColor = nowPlayingScrollViewController?.backgroundViewController.color() {
|
else if let uiColor = nowPlayingScrollViewController?.backgroundViewModel.color() {
|
||||||
color = Color(uiColor)
|
color = Color(uiColor)
|
||||||
.normalized(lyricsColorsSettings.normalizationFactor)
|
.normalized(lyricsColorsSettings.normalizationFactor)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -41,9 +41,15 @@ extension NowPlayingScrollViewController {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
var backgroundViewController: SPTNowPlayingBackgroundViewController {
|
private var backgroundViewController: NSObject {
|
||||||
get {
|
get {
|
||||||
Ivars<SPTNowPlayingBackgroundViewController>(self).backgroundViewController
|
Ivars<NSObject>(self).backgroundViewController
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var backgroundViewModel: SPTNowPlayingBackgroundViewModel {
|
||||||
|
get {
|
||||||
|
Ivars<SPTNowPlayingBackgroundViewModel>(self.backgroundViewController).viewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import UIKit
|
|
||||||
|
|
||||||
@objc protocol SPTNowPlayingBackgroundViewController {
|
|
||||||
func color() -> UIColor
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import UIKit
|
||||||
|
|
||||||
|
@objc protocol SPTNowPlayingBackgroundViewModel {
|
||||||
|
func color() -> UIColor
|
||||||
|
}
|
||||||
@@ -9,79 +9,103 @@ func modifyRemoteConfiguration(_ configuration: inout UcsResponse) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func modifyAttributes(_ attributes: inout [String: AccountAttribute]) {
|
func modifyAttributes(_ attributes: inout [String: AccountAttribute]) {
|
||||||
attributes["type"] = AccountAttribute.with {
|
let oneYearFromNow = Calendar.current.date(byAdding: .year, value: 1, to: Date())!
|
||||||
$0.stringValue = "premium"
|
|
||||||
}
|
|
||||||
attributes["player-license"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "premium"
|
|
||||||
}
|
|
||||||
attributes["financial-product"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "pr:premium,tc:0"
|
|
||||||
}
|
|
||||||
attributes["name"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "Spotify Premium"
|
|
||||||
}
|
|
||||||
attributes["payments-initial-campaign"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "default"
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
let formatter = ISO8601DateFormatter()
|
||||||
|
formatter.timeZone = TimeZone(abbreviation: "UTC")
|
||||||
attributes["unrestricted"] = AccountAttribute.with {
|
|
||||||
$0.boolValue = true
|
|
||||||
}
|
|
||||||
attributes["catalogue"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "premium"
|
|
||||||
}
|
|
||||||
attributes["streaming-rules"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = ""
|
|
||||||
}
|
|
||||||
attributes["pause-after"] = AccountAttribute.with {
|
|
||||||
$0.longValue = 0
|
|
||||||
}
|
|
||||||
attributes["on-demand"] = AccountAttribute.with {
|
|
||||||
$0.boolValue = true
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
attributes["ads"] = AccountAttribute.with {
|
attributes["ads"] = AccountAttribute.with {
|
||||||
$0.boolValue = false
|
$0.boolValue = false
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes.removeValue(forKey: "ad-use-adlogic")
|
attributes["audio-quality"] = AccountAttribute.with {
|
||||||
attributes.removeValue(forKey: "ad-catalogues")
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
attributes["shuffle-eligible"] = AccountAttribute.with {
|
|
||||||
$0.boolValue = true
|
|
||||||
}
|
|
||||||
attributes["high-bitrate"] = AccountAttribute.with {
|
|
||||||
$0.boolValue = true
|
|
||||||
}
|
|
||||||
attributes["offline"] = AccountAttribute.with {
|
|
||||||
$0.boolValue = true // allow downloading
|
|
||||||
}
|
|
||||||
attributes["nft-disabled"] = AccountAttribute.with {
|
|
||||||
$0.stringValue = "1"
|
$0.stringValue = "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes["can_use_superbird"] = AccountAttribute.with {
|
attributes["can_use_superbird"] = AccountAttribute.with {
|
||||||
$0.boolValue = true
|
$0.boolValue = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attributes["catalogue"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "premium"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["financial-product"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "pr:premium,tc:0"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["high-bitrate"] = AccountAttribute.with {
|
||||||
|
$0.boolValue = true
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["is-eligible-premium-unboxing"] = AccountAttribute.with {
|
||||||
|
$0.boolValue = true
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["name"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "Spotify Premium"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["nft-disabled"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["offline"] = AccountAttribute.with {
|
||||||
|
$0.boolValue = true // allow downloading
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["on-demand"] = AccountAttribute.with {
|
||||||
|
$0.boolValue = true
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["payments-initial-campaign"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["player-license"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "premium"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["player-license-v2"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "premium"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["product-expiry"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = formatter.string(from: oneYearFromNow)
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["public-toplist"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["shuffle-eligible"] = AccountAttribute.with {
|
||||||
|
$0.boolValue = true
|
||||||
|
}
|
||||||
|
|
||||||
attributes["social-session"] = AccountAttribute.with {
|
attributes["social-session"] = AccountAttribute.with {
|
||||||
$0.boolValue = true
|
$0.boolValue = true
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes["social-session-free-tier"] = AccountAttribute.with {
|
attributes["social-session-free-tier"] = AccountAttribute.with {
|
||||||
$0.boolValue = false
|
$0.boolValue = false
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
attributes["streaming-rules"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = ""
|
||||||
attributes["com.spotify.madprops.delivered.by.ucs"] = AccountAttribute.with {
|
}
|
||||||
$0.boolValue = true
|
|
||||||
}
|
attributes["subscription-enddate"] = AccountAttribute.with {
|
||||||
attributes["com.spotify.madprops.use.ucs.product.state"] = AccountAttribute.with {
|
$0.stringValue = formatter.string(from: oneYearFromNow)
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["type"] = AccountAttribute.with {
|
||||||
|
$0.stringValue = "premium"
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes["unrestricted"] = AccountAttribute.with {
|
||||||
$0.boolValue = true
|
$0.boolValue = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attributes.removeValue(forKey: "payment-state")
|
||||||
|
attributes.removeValue(forKey: "last-premium-activation-date")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
func getPremiumPlanRowData(originalPremiumPlanRow: PremiumPlanRow) throws -> Data {
|
||||||
|
var premiumPlanRow = originalPremiumPlanRow
|
||||||
|
|
||||||
|
premiumPlanRow.planName = "EeveeSpotify"
|
||||||
|
premiumPlanRow.planIdentifier = "Eevee"
|
||||||
|
premiumPlanRow.colorCode = "#FFD2D7"
|
||||||
|
|
||||||
|
return try premiumPlanRow.serializedData()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPlanOverviewData() throws -> Data {
|
||||||
|
let plan = SpotifyPlan.with {
|
||||||
|
$0.notice = SpotifyPlan.Notice.with {
|
||||||
|
$0.message = "payment_notice".localized
|
||||||
|
$0.status = 2 // 0 - trial, 1 - prepaid, 2 - subsription
|
||||||
|
}
|
||||||
|
$0.subscription = SpotifyPlan.SubscriptionInfo.with {
|
||||||
|
$0.planVariant = 2
|
||||||
|
$0.planName = "EeveeSpotify"
|
||||||
|
$0.planCategory = "Eevee"
|
||||||
|
$0.colorCode = "#FFD2D7"
|
||||||
|
$0.features = [
|
||||||
|
SpotifyPlan.Feature.with {
|
||||||
|
$0.color = "#1ED760"
|
||||||
|
$0.description_p = "ad_free_music_listening".localized
|
||||||
|
$0.icon = SpotifyPlan.IconType.check
|
||||||
|
},
|
||||||
|
SpotifyPlan.Feature.with {
|
||||||
|
$0.color = "#1ED760"
|
||||||
|
$0.description_p = "play_songs_in_any_order".localized
|
||||||
|
$0.icon = SpotifyPlan.IconType.check
|
||||||
|
},
|
||||||
|
SpotifyPlan.Feature.with {
|
||||||
|
$0.color = "#1ED760"
|
||||||
|
$0.description_p = "organize_listening_queue".localized
|
||||||
|
$0.icon = SpotifyPlan.IconType.check
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try plan.serializedData()
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension BootstrapMessage {
|
extension BootstrapMessage {
|
||||||
|
|
||||||
var ucsResponse: UcsResponse {
|
var ucsResponse: UcsResponse {
|
||||||
get {
|
get {
|
||||||
self.wrapper.oneMoreWrapper.message.response
|
self.wrapper.oneMoreWrapper.message.response
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
extension UcsResponse {
|
extension UcsResponse {
|
||||||
|
|
||||||
var assignedValues: [AssignedValue] {
|
var assignedValues: [AssignedValue] {
|
||||||
get {
|
get {
|
||||||
self.resolve.configuration.assignedValues
|
self.resolve.configuration.assignedValues
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
// DO NOT EDIT.
|
||||||
|
// swift-format-ignore-file
|
||||||
|
// swiftlint:disable all
|
||||||
|
//
|
||||||
|
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||||
|
// Source: pam.proto
|
||||||
|
//
|
||||||
|
// For information on using the generated types, please see the documentation:
|
||||||
|
// https://github.com/apple/swift-protobuf/
|
||||||
|
|
||||||
|
import SwiftProtobuf
|
||||||
|
|
||||||
|
// If the compiler emits an error on this type, it is because this file
|
||||||
|
// was generated by a version of the `protoc` Swift plug-in that is
|
||||||
|
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||||
|
// Please ensure that you are building against the same version of the API
|
||||||
|
// that was used to generate this file.
|
||||||
|
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||||
|
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||||
|
typealias Version = _2
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Message emitted by pam-view-service
|
||||||
|
/// GET https://spclient.wg.spotify.com/pam-view-service/v1/GetPremiumPlanRow
|
||||||
|
struct PremiumPlanRow: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var planName: String = String()
|
||||||
|
var colorCode: String = String()
|
||||||
|
var planTypeID: Int32 = 0
|
||||||
|
var billingLabel: String = String()
|
||||||
|
var actionText: String = String()
|
||||||
|
var flag: Int32 = 0
|
||||||
|
var availabilityMessage: String = String()
|
||||||
|
var durationText: String = String()
|
||||||
|
var planCategory: Int32 = 0
|
||||||
|
var planIdentifier: String = String()
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||||
|
|
||||||
|
extension PremiumPlanRow: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = "PremiumPlanRow"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
3: .standard(proto: "plan_name"),
|
||||||
|
4: .standard(proto: "color_code"),
|
||||||
|
6: .standard(proto: "plan_type_id"),
|
||||||
|
8: .standard(proto: "billing_label"),
|
||||||
|
9: .standard(proto: "action_text"),
|
||||||
|
10: .same(proto: "flag"),
|
||||||
|
12: .standard(proto: "availability_message"),
|
||||||
|
14: .standard(proto: "duration_text"),
|
||||||
|
16: .standard(proto: "plan_category"),
|
||||||
|
18: .standard(proto: "plan_identifier"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 3: try { try decoder.decodeSingularStringField(value: &self.planName) }()
|
||||||
|
case 4: try { try decoder.decodeSingularStringField(value: &self.colorCode) }()
|
||||||
|
case 6: try { try decoder.decodeSingularInt32Field(value: &self.planTypeID) }()
|
||||||
|
case 8: try { try decoder.decodeSingularStringField(value: &self.billingLabel) }()
|
||||||
|
case 9: try { try decoder.decodeSingularStringField(value: &self.actionText) }()
|
||||||
|
case 10: try { try decoder.decodeSingularInt32Field(value: &self.flag) }()
|
||||||
|
case 12: try { try decoder.decodeSingularStringField(value: &self.availabilityMessage) }()
|
||||||
|
case 14: try { try decoder.decodeSingularStringField(value: &self.durationText) }()
|
||||||
|
case 16: try { try decoder.decodeSingularInt32Field(value: &self.planCategory) }()
|
||||||
|
case 18: try { try decoder.decodeSingularStringField(value: &self.planIdentifier) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
if !self.planName.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.planName, fieldNumber: 3)
|
||||||
|
}
|
||||||
|
if !self.colorCode.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.colorCode, fieldNumber: 4)
|
||||||
|
}
|
||||||
|
if self.planTypeID != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.planTypeID, fieldNumber: 6)
|
||||||
|
}
|
||||||
|
if !self.billingLabel.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.billingLabel, fieldNumber: 8)
|
||||||
|
}
|
||||||
|
if !self.actionText.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.actionText, fieldNumber: 9)
|
||||||
|
}
|
||||||
|
if self.flag != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.flag, fieldNumber: 10)
|
||||||
|
}
|
||||||
|
if !self.availabilityMessage.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.availabilityMessage, fieldNumber: 12)
|
||||||
|
}
|
||||||
|
if !self.durationText.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.durationText, fieldNumber: 14)
|
||||||
|
}
|
||||||
|
if self.planCategory != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.planCategory, fieldNumber: 16)
|
||||||
|
}
|
||||||
|
if !self.planIdentifier.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.planIdentifier, fieldNumber: 18)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: PremiumPlanRow, rhs: PremiumPlanRow) -> Bool {
|
||||||
|
if lhs.planName != rhs.planName {return false}
|
||||||
|
if lhs.colorCode != rhs.colorCode {return false}
|
||||||
|
if lhs.planTypeID != rhs.planTypeID {return false}
|
||||||
|
if lhs.billingLabel != rhs.billingLabel {return false}
|
||||||
|
if lhs.actionText != rhs.actionText {return false}
|
||||||
|
if lhs.flag != rhs.flag {return false}
|
||||||
|
if lhs.availabilityMessage != rhs.availabilityMessage {return false}
|
||||||
|
if lhs.durationText != rhs.durationText {return false}
|
||||||
|
if lhs.planCategory != rhs.planCategory {return false}
|
||||||
|
if lhs.planIdentifier != rhs.planIdentifier {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,567 @@
|
|||||||
|
// DO NOT EDIT.
|
||||||
|
// swift-format-ignore-file
|
||||||
|
// swiftlint:disable all
|
||||||
|
//
|
||||||
|
// Generated by the Swift generator plugin for the protocol buffer compiler.
|
||||||
|
// Source: SpotifyPlan.proto
|
||||||
|
//
|
||||||
|
// For information on using the generated types, please see the documentation:
|
||||||
|
// https://github.com/apple/swift-protobuf/
|
||||||
|
|
||||||
|
import SwiftProtobuf
|
||||||
|
|
||||||
|
// If the compiler emits an error on this type, it is because this file
|
||||||
|
// was generated by a version of the `protoc` Swift plug-in that is
|
||||||
|
// incompatible with the version of SwiftProtobuf to which you are linking.
|
||||||
|
// Please ensure that you are building against the same version of the API
|
||||||
|
// that was used to generate this file.
|
||||||
|
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
|
||||||
|
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
|
||||||
|
typealias Version = _2
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpotifyPlan: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var subscription: SpotifyPlan.SubscriptionInfo {
|
||||||
|
get {return _subscription ?? SpotifyPlan.SubscriptionInfo()}
|
||||||
|
set {_subscription = newValue}
|
||||||
|
}
|
||||||
|
/// Returns true if `subscription` has been explicitly set.
|
||||||
|
var hasSubscription: Bool {return self._subscription != nil}
|
||||||
|
/// Clears the value of `subscription`. Subsequent reads from it will return its default value.
|
||||||
|
mutating func clearSubscription() {self._subscription = nil}
|
||||||
|
|
||||||
|
var notice: SpotifyPlan.Notice {
|
||||||
|
get {return _notice ?? SpotifyPlan.Notice()}
|
||||||
|
set {_notice = newValue}
|
||||||
|
}
|
||||||
|
/// Returns true if `notice` has been explicitly set.
|
||||||
|
var hasNotice: Bool {return self._notice != nil}
|
||||||
|
/// Clears the value of `notice`. Subsequent reads from it will return its default value.
|
||||||
|
mutating func clearNotice() {self._notice = nil}
|
||||||
|
|
||||||
|
var actions: [SpotifyPlan.Action] = []
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
enum IconType: SwiftProtobuf.Enum, Swift.CaseIterable {
|
||||||
|
typealias RawValue = Int
|
||||||
|
case unspecifiedIcon // = 0
|
||||||
|
case check // = 1
|
||||||
|
case chevron // = 2
|
||||||
|
case ads // = 3
|
||||||
|
case offline // = 4
|
||||||
|
case arrow // = 5
|
||||||
|
case UNRECOGNIZED(Int)
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self = .unspecifiedIcon
|
||||||
|
}
|
||||||
|
|
||||||
|
init?(rawValue: Int) {
|
||||||
|
switch rawValue {
|
||||||
|
case 0: self = .unspecifiedIcon
|
||||||
|
case 1: self = .check
|
||||||
|
case 2: self = .chevron
|
||||||
|
case 3: self = .ads
|
||||||
|
case 4: self = .offline
|
||||||
|
case 5: self = .arrow
|
||||||
|
default: self = .UNRECOGNIZED(rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawValue: Int {
|
||||||
|
switch self {
|
||||||
|
case .unspecifiedIcon: return 0
|
||||||
|
case .check: return 1
|
||||||
|
case .chevron: return 2
|
||||||
|
case .ads: return 3
|
||||||
|
case .offline: return 4
|
||||||
|
case .arrow: return 5
|
||||||
|
case .UNRECOGNIZED(let i): return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The compiler won't synthesize support with the UNRECOGNIZED case.
|
||||||
|
static let allCases: [SpotifyPlan.IconType] = [
|
||||||
|
.unspecifiedIcon,
|
||||||
|
.check,
|
||||||
|
.chevron,
|
||||||
|
.ads,
|
||||||
|
.offline,
|
||||||
|
.arrow,
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SubscriptionInfo: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var planType: Int32 = 0
|
||||||
|
|
||||||
|
var planVariant: Int32 = 0
|
||||||
|
|
||||||
|
var planName: String = String()
|
||||||
|
|
||||||
|
var planCategory: String = String()
|
||||||
|
|
||||||
|
var colorCode: String = String()
|
||||||
|
|
||||||
|
var backgroundImageURL: String = String()
|
||||||
|
|
||||||
|
var features: [SpotifyPlan.Feature] = []
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Feature: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var icon: SpotifyPlan.IconType = .unspecifiedIcon
|
||||||
|
|
||||||
|
var description_p: String = String()
|
||||||
|
|
||||||
|
var color: String = String()
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Notice: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var message: String = String()
|
||||||
|
|
||||||
|
var timestamp: Int64 = 0
|
||||||
|
|
||||||
|
var status: Int32 = 0
|
||||||
|
|
||||||
|
var settings: SpotifyPlan.Settings {
|
||||||
|
get {return _settings ?? SpotifyPlan.Settings()}
|
||||||
|
set {_settings = newValue}
|
||||||
|
}
|
||||||
|
/// Returns true if `settings` has been explicitly set.
|
||||||
|
var hasSettings: Bool {return self._settings != nil}
|
||||||
|
/// Clears the value of `settings`. Subsequent reads from it will return its default value.
|
||||||
|
mutating func clearSettings() {self._settings = nil}
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
fileprivate var _settings: SpotifyPlan.Settings? = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Settings: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var autoRenew: Int32 = 0
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Action: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var actionID: Int32 = 0
|
||||||
|
|
||||||
|
var details: SpotifyPlan.ActionDetails {
|
||||||
|
get {return _details ?? SpotifyPlan.ActionDetails()}
|
||||||
|
set {_details = newValue}
|
||||||
|
}
|
||||||
|
/// Returns true if `details` has been explicitly set.
|
||||||
|
var hasDetails: Bool {return self._details != nil}
|
||||||
|
/// Clears the value of `details`. Subsequent reads from it will return its default value.
|
||||||
|
mutating func clearDetails() {self._details = nil}
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
fileprivate var _details: SpotifyPlan.ActionDetails? = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ActionDetails: Sendable {
|
||||||
|
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||||
|
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||||
|
// methods supported on all messages.
|
||||||
|
|
||||||
|
var title: String = String()
|
||||||
|
|
||||||
|
var subtitle: String = String()
|
||||||
|
|
||||||
|
var url: String = String()
|
||||||
|
|
||||||
|
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
fileprivate var _subscription: SpotifyPlan.SubscriptionInfo? = nil
|
||||||
|
fileprivate var _notice: SpotifyPlan.Notice? = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Code below here is support for the SwiftProtobuf runtime.
|
||||||
|
|
||||||
|
extension SpotifyPlan: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = "SpotifyPlan"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .same(proto: "subscription"),
|
||||||
|
2: .same(proto: "notice"),
|
||||||
|
3: .same(proto: "actions"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularMessageField(value: &self._subscription) }()
|
||||||
|
case 2: try { try decoder.decodeSingularMessageField(value: &self._notice) }()
|
||||||
|
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.actions) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every if/case branch local when no optimizations
|
||||||
|
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||||
|
// https://github.com/apple/swift-protobuf/issues/1182
|
||||||
|
try { if let v = self._subscription {
|
||||||
|
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||||
|
} }()
|
||||||
|
try { if let v = self._notice {
|
||||||
|
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||||
|
} }()
|
||||||
|
if !self.actions.isEmpty {
|
||||||
|
try visitor.visitRepeatedMessageField(value: self.actions, fieldNumber: 3)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan, rhs: SpotifyPlan) -> Bool {
|
||||||
|
if lhs._subscription != rhs._subscription {return false}
|
||||||
|
if lhs._notice != rhs._notice {return false}
|
||||||
|
if lhs.actions != rhs.actions {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.IconType: SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
0: .same(proto: "UNSPECIFIED_ICON"),
|
||||||
|
1: .same(proto: "CHECK"),
|
||||||
|
2: .same(proto: "CHEVRON"),
|
||||||
|
3: .same(proto: "ADS"),
|
||||||
|
4: .same(proto: "OFFLINE"),
|
||||||
|
5: .same(proto: "ARROW"),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.SubscriptionInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".SubscriptionInfo"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .standard(proto: "plan_type"),
|
||||||
|
2: .standard(proto: "plan_variant"),
|
||||||
|
3: .standard(proto: "plan_name"),
|
||||||
|
4: .standard(proto: "plan_category"),
|
||||||
|
5: .standard(proto: "color_code"),
|
||||||
|
19: .standard(proto: "background_image_url"),
|
||||||
|
20: .same(proto: "features"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularInt32Field(value: &self.planType) }()
|
||||||
|
case 2: try { try decoder.decodeSingularInt32Field(value: &self.planVariant) }()
|
||||||
|
case 3: try { try decoder.decodeSingularStringField(value: &self.planName) }()
|
||||||
|
case 4: try { try decoder.decodeSingularStringField(value: &self.planCategory) }()
|
||||||
|
case 5: try { try decoder.decodeSingularStringField(value: &self.colorCode) }()
|
||||||
|
case 19: try { try decoder.decodeSingularStringField(value: &self.backgroundImageURL) }()
|
||||||
|
case 20: try { try decoder.decodeRepeatedMessageField(value: &self.features) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
if self.planType != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.planType, fieldNumber: 1)
|
||||||
|
}
|
||||||
|
if self.planVariant != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.planVariant, fieldNumber: 2)
|
||||||
|
}
|
||||||
|
if !self.planName.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.planName, fieldNumber: 3)
|
||||||
|
}
|
||||||
|
if !self.planCategory.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.planCategory, fieldNumber: 4)
|
||||||
|
}
|
||||||
|
if !self.colorCode.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.colorCode, fieldNumber: 5)
|
||||||
|
}
|
||||||
|
if !self.backgroundImageURL.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.backgroundImageURL, fieldNumber: 19)
|
||||||
|
}
|
||||||
|
if !self.features.isEmpty {
|
||||||
|
try visitor.visitRepeatedMessageField(value: self.features, fieldNumber: 20)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.SubscriptionInfo, rhs: SpotifyPlan.SubscriptionInfo) -> Bool {
|
||||||
|
if lhs.planType != rhs.planType {return false}
|
||||||
|
if lhs.planVariant != rhs.planVariant {return false}
|
||||||
|
if lhs.planName != rhs.planName {return false}
|
||||||
|
if lhs.planCategory != rhs.planCategory {return false}
|
||||||
|
if lhs.colorCode != rhs.colorCode {return false}
|
||||||
|
if lhs.backgroundImageURL != rhs.backgroundImageURL {return false}
|
||||||
|
if lhs.features != rhs.features {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.Feature: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".Feature"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .same(proto: "icon"),
|
||||||
|
2: .same(proto: "description"),
|
||||||
|
4: .same(proto: "color"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularEnumField(value: &self.icon) }()
|
||||||
|
case 2: try { try decoder.decodeSingularStringField(value: &self.description_p) }()
|
||||||
|
case 4: try { try decoder.decodeSingularStringField(value: &self.color) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
if self.icon != .unspecifiedIcon {
|
||||||
|
try visitor.visitSingularEnumField(value: self.icon, fieldNumber: 1)
|
||||||
|
}
|
||||||
|
if !self.description_p.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.description_p, fieldNumber: 2)
|
||||||
|
}
|
||||||
|
if !self.color.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.color, fieldNumber: 4)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.Feature, rhs: SpotifyPlan.Feature) -> Bool {
|
||||||
|
if lhs.icon != rhs.icon {return false}
|
||||||
|
if lhs.description_p != rhs.description_p {return false}
|
||||||
|
if lhs.color != rhs.color {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.Notice: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".Notice"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .same(proto: "message"),
|
||||||
|
4: .same(proto: "timestamp"),
|
||||||
|
7: .same(proto: "status"),
|
||||||
|
8: .same(proto: "settings"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularStringField(value: &self.message) }()
|
||||||
|
case 4: try { try decoder.decodeSingularInt64Field(value: &self.timestamp) }()
|
||||||
|
case 7: try { try decoder.decodeSingularInt32Field(value: &self.status) }()
|
||||||
|
case 8: try { try decoder.decodeSingularMessageField(value: &self._settings) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every if/case branch local when no optimizations
|
||||||
|
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||||
|
// https://github.com/apple/swift-protobuf/issues/1182
|
||||||
|
if !self.message.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.message, fieldNumber: 1)
|
||||||
|
}
|
||||||
|
if self.timestamp != 0 {
|
||||||
|
try visitor.visitSingularInt64Field(value: self.timestamp, fieldNumber: 4)
|
||||||
|
}
|
||||||
|
if self.status != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.status, fieldNumber: 7)
|
||||||
|
}
|
||||||
|
try { if let v = self._settings {
|
||||||
|
try visitor.visitSingularMessageField(value: v, fieldNumber: 8)
|
||||||
|
} }()
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.Notice, rhs: SpotifyPlan.Notice) -> Bool {
|
||||||
|
if lhs.message != rhs.message {return false}
|
||||||
|
if lhs.timestamp != rhs.timestamp {return false}
|
||||||
|
if lhs.status != rhs.status {return false}
|
||||||
|
if lhs._settings != rhs._settings {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.Settings: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".Settings"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
2: .standard(proto: "auto_renew"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 2: try { try decoder.decodeSingularInt32Field(value: &self.autoRenew) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
if self.autoRenew != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.autoRenew, fieldNumber: 2)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.Settings, rhs: SpotifyPlan.Settings) -> Bool {
|
||||||
|
if lhs.autoRenew != rhs.autoRenew {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.Action: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".Action"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .standard(proto: "action_id"),
|
||||||
|
2: .same(proto: "details"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularInt32Field(value: &self.actionID) }()
|
||||||
|
case 2: try { try decoder.decodeSingularMessageField(value: &self._details) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every if/case branch local when no optimizations
|
||||||
|
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||||
|
// https://github.com/apple/swift-protobuf/issues/1182
|
||||||
|
if self.actionID != 0 {
|
||||||
|
try visitor.visitSingularInt32Field(value: self.actionID, fieldNumber: 1)
|
||||||
|
}
|
||||||
|
try { if let v = self._details {
|
||||||
|
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||||
|
} }()
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.Action, rhs: SpotifyPlan.Action) -> Bool {
|
||||||
|
if lhs.actionID != rhs.actionID {return false}
|
||||||
|
if lhs._details != rhs._details {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SpotifyPlan.ActionDetails: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||||
|
static let protoMessageName: String = SpotifyPlan.protoMessageName + ".ActionDetails"
|
||||||
|
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||||
|
1: .same(proto: "title"),
|
||||||
|
2: .same(proto: "subtitle"),
|
||||||
|
3: .same(proto: "url"),
|
||||||
|
]
|
||||||
|
|
||||||
|
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||||
|
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||||
|
// The use of inline closures is to circumvent an issue where the compiler
|
||||||
|
// allocates stack space for every case branch when no optimizations are
|
||||||
|
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||||
|
switch fieldNumber {
|
||||||
|
case 1: try { try decoder.decodeSingularStringField(value: &self.title) }()
|
||||||
|
case 2: try { try decoder.decodeSingularStringField(value: &self.subtitle) }()
|
||||||
|
case 3: try { try decoder.decodeSingularStringField(value: &self.url) }()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||||
|
if !self.title.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.title, fieldNumber: 1)
|
||||||
|
}
|
||||||
|
if !self.subtitle.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.subtitle, fieldNumber: 2)
|
||||||
|
}
|
||||||
|
if !self.url.isEmpty {
|
||||||
|
try visitor.visitSingularStringField(value: self.url, fieldNumber: 3)
|
||||||
|
}
|
||||||
|
try unknownFields.traverse(visitor: &visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SpotifyPlan.ActionDetails, rhs: SpotifyPlan.ActionDetails) -> Bool {
|
||||||
|
if lhs.title != rhs.title {return false}
|
||||||
|
if lhs.subtitle != rhs.subtitle {return false}
|
||||||
|
if lhs.url != rhs.url {return false}
|
||||||
|
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,14 @@ extension URL {
|
|||||||
var isLyrics: Bool {
|
var isLyrics: Bool {
|
||||||
self.path.contains("color-lyrics/v2")
|
self.path.contains("color-lyrics/v2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPlanOverview: Bool {
|
||||||
|
self.path.contains("GetPlanOverview")
|
||||||
|
}
|
||||||
|
|
||||||
|
var isPremiumPlanRow: Bool {
|
||||||
|
self.path.contains("v1/GetPremiumPlanRow")
|
||||||
|
}
|
||||||
|
|
||||||
var isOpenSpotifySafariExtension: Bool {
|
var isOpenSpotifySafariExtension: Bool {
|
||||||
self.host == "eevee"
|
self.host == "eevee"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ func exitApplication() {
|
|||||||
struct PremiumPatchingGroup: HookGroup { }
|
struct PremiumPatchingGroup: HookGroup { }
|
||||||
|
|
||||||
struct EeveeSpotify: Tweak {
|
struct EeveeSpotify: Tweak {
|
||||||
static let version = "6.0.2"
|
static let version = "6.1"
|
||||||
|
|
||||||
static var hookTarget: VersionHookTarget {
|
static var hookTarget: VersionHookTarget {
|
||||||
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
|
let version = Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Package: com.eevee.spotify
|
Package: com.eevee.spotify
|
||||||
Name: EeveeSpotify
|
Name: EeveeSpotify
|
||||||
Version: 6.0.2
|
Version: 6.1
|
||||||
Architecture: iphoneos-arm
|
Architecture: iphoneos-arm
|
||||||
Description: A tweak to get Spotify Premium for free, just like Spotilife
|
Description: A tweak to get Spotify Premium for free, just like Spotilife
|
||||||
Maintainer: Eevee
|
Maintainer: Eevee
|
||||||
|
|||||||
@@ -131,3 +131,11 @@ request_anonymous_token = "Request Anonymous Token";
|
|||||||
request_anonymous_token_description = "Tap “Request Anonymous Token” to request a token from Musixmatch without authorization.";
|
request_anonymous_token_description = "Tap “Request Anonymous Token” to request a token from Musixmatch without authorization.";
|
||||||
|
|
||||||
lrclib_api = "Server Address";
|
lrclib_api = "Server Address";
|
||||||
|
|
||||||
|
// Snapshot of your benefits, should match official spotify loc
|
||||||
|
|
||||||
|
ad_free_music_listening = "Ad-free music listening";
|
||||||
|
play_songs_in_any_order = "Play songs in any order";
|
||||||
|
organize_listening_queue = "Organize listening queue";
|
||||||
|
|
||||||
|
payment_notice = "EeveeSpotify applies patches to unlock certain Premium features. It's free.";
|
||||||
|
|||||||
Binary file not shown.
@@ -129,3 +129,11 @@ request_anonymous_token = "Запросить анонимный токен";
|
|||||||
request_anonymous_token_description = "Нажмите Запросить анонимный токен, чтобы запросить токен у Musixmatch без авторизации.";
|
request_anonymous_token_description = "Нажмите Запросить анонимный токен, чтобы запросить токен у Musixmatch без авторизации.";
|
||||||
|
|
||||||
lrclib_api = "Адрес сервера";
|
lrclib_api = "Адрес сервера";
|
||||||
|
|
||||||
|
// Snapshot of your benefits, should match official spotify loc
|
||||||
|
|
||||||
|
ad_free_music_listening = "Музыка без рекламы";
|
||||||
|
play_songs_in_any_order = "Треки в любом порядке";
|
||||||
|
organize_listening_queue = "Добавление треков в очередь";
|
||||||
|
|
||||||
|
payment_notice = "EeveeSpotify применяет патчи, которые активируют некоторые возможности Premium. Это бесплатно.";
|
||||||
|
|||||||
Reference in New Issue
Block a user