From d82d94b76cb6472621f797f481c67c98fcebcd70 Mon Sep 17 00:00:00 2001 From: Benedikt Date: Thu, 19 Dec 2024 22:31:28 +0100 Subject: [PATCH 1/3] discovery: don't panic on libmdns errors (#1427) On panic, the discovery task crashes, but the main program is not notified of this. Returning an error will result in the Discovery stream yielding None, serving as notification to the application (which might shutdown with error, for example, if no other means of authentication is available). --- CHANGELOG.md | 3 ++- discovery/src/lib.rs | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72710acc0..a9821e2c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 on Android platform. - [core] Fix "Invalid Credentials" when using a Keymaster access token and client ID on Android platform. -= [connect] Fix "play" command not handled if missing "offset" property +- [connect] Fix "play" command not handled if missing "offset" property +- [discovery] Fix libmdns zerconf setup errors not propagating to the main task. ### Removed diff --git a/discovery/src/lib.rs b/discovery/src/lib.rs index d829e0f57..c6d88a2e7 100644 --- a/discovery/src/lib.rs +++ b/discovery/src/lib.rs @@ -396,7 +396,7 @@ fn launch_libmdns( let task_handle = tokio::task::spawn_blocking(move || { let inner = move || -> Result<(), DiscoveryError> { - let svc = if !zeroconf_ip.is_empty() { + let responder = if !zeroconf_ip.is_empty() { libmdns::Responder::spawn_with_ip_list( &tokio::runtime::Handle::current(), zeroconf_ip, @@ -404,9 +404,9 @@ fn launch_libmdns( } else { libmdns::Responder::spawn(&tokio::runtime::Handle::current()) } - .map_err(|e| DiscoveryError::DnsSdError(Box::new(e))) - .unwrap() - .register( + .map_err(|e| DiscoveryError::DnsSdError(Box::new(e)))?; + + let svc = responder.register( DNS_SD_SERVICE_NAME.to_owned(), name.into_owned(), port, From 0ad1f7249b8a1e9a71da4a3b527f793cb938bd62 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Mon, 23 Dec 2024 10:28:06 +0100 Subject: [PATCH 2/3] Update MSRV to 1.81 (#1428) * bump MSRV to 1.81 * Update zbus to v5 * Update jack to 0.13 --- .devcontainer/Dockerfile | 2 +- .devcontainer/Dockerfile.alpine | 2 +- .github/workflows/test.yml | 6 +- CHANGELOG.md | 1 + Cargo.lock | 201 +++++------------------- Cargo.toml | 4 +- contrib/Dockerfile | 2 +- discovery/Cargo.toml | 2 +- discovery/src/avahi.rs | 8 +- playback/Cargo.toml | 2 +- playback/src/audio_backend/jackaudio.rs | 4 +- 11 files changed, 54 insertions(+), 180 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ce845a52b..233ac8383 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 ARG debian_version=slim-bookworm -ARG rust_version=1.75.0 +ARG rust_version=1.81.0 FROM rust:${rust_version}-${debian_version} ARG DEBIAN_FRONTEND=noninteractive diff --git a/.devcontainer/Dockerfile.alpine b/.devcontainer/Dockerfile.alpine index fd3b75c3e..1a9089555 100644 --- a/.devcontainer/Dockerfile.alpine +++ b/.devcontainer/Dockerfile.alpine @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 ARG alpine_version=alpine3.19 -ARG rust_version=1.75.0 +ARG rust_version=1.81.0 FROM rust:${rust_version}-${alpine_version} ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL="sparse" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 41928ed5d..ff877e125 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -109,7 +109,7 @@ jobs: matrix: os: [ubuntu-latest] toolchain: - - "1.75" # MSRV (Minimum supported rust version) + - "1.81" # MSRV (Minimum supported rust version) - stable experimental: [false] # Ignore failures in beta @@ -164,7 +164,7 @@ jobs: matrix: os: [windows-latest] toolchain: - - "1.75" # MSRV (Minimum supported rust version) + - "1.81" # MSRV (Minimum supported rust version) - stable steps: - name: Checkout code @@ -215,7 +215,7 @@ jobs: - aarch64-unknown-linux-gnu - riscv64gc-unknown-linux-gnu toolchain: - - "1.75" # MSRV (Minimum supported rust version) + - "1.81" # MSRV (Minimum supported rust version) - stable steps: - name: Checkout code diff --git a/CHANGELOG.md b/CHANGELOG.md index a9821e2c8..8e27f8634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- [core] MSRV is now 1.81 (breaking) - [connect] Replaced `ConnectConfig` with `ConnectStateConfig` (breaking) - [connect] Replaced `playing_track_index` field of `SpircLoadCommand` with `playing_track` (breaking) - [connect] Replaced Mercury usage in `Spirc` with Dealer diff --git a/Cargo.lock b/Cargo.lock index b3b25e5f3..2d253687e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,67 +147,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-io" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "tracing", -] - [[package]] name = "async-recursion" version = "1.1.1" @@ -219,30 +158,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "async-signal" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.83" @@ -400,19 +315,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -607,7 +509,7 @@ dependencies = [ "core-foundation-sys", "coreaudio-rs", "dasp_sample", - "jack", + "jack 0.11.4", "jni", "js-sys", "libc", @@ -982,19 +884,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" -[[package]] -name = "futures-lite" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - [[package]] name = "futures-macro" version = "0.3.31" @@ -1375,12 +1264,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - [[package]] name = "hex" version = "0.4.3" @@ -1747,6 +1630,19 @@ dependencies = [ "log", ] +[[package]] +name = "jack" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a4ae24f4ee29676aef8330fed1104e72f314cab16643dbeb61bfd99b4a8273" +dependencies = [ + "bitflags 2.6.0", + "jack-sys", + "lazy_static", + "libc", + "log", +] + [[package]] name = "jack-sys" version = "0.5.1" @@ -2100,7 +1996,7 @@ dependencies = [ "gstreamer", "gstreamer-app", "gstreamer-audio", - "jack", + "jack 0.13.0", "libpulse-binding", "libpulse-simple-binding", "librespot-audio", @@ -2202,7 +2098,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", "wasi", "windows-sys 0.52.0", @@ -2605,17 +2501,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkcs1" version = "0.7.5" @@ -2643,21 +2528,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" -[[package]] -name = "polling" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "portable-atomic" version = "1.9.0" @@ -4540,31 +4410,28 @@ dependencies = [ [[package]] name = "zbus" -version = "4.4.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +checksum = "fb67eadba43784b6fb14857eba0d8fc518686d3ee537066eb6086dc318e2c8a1" dependencies = [ "async-broadcast", - "async-process", "async-recursion", "async-trait", "enumflags2", "event-listener", "futures-core", - "futures-sink", "futures-util", "hex", "nix", "ordered-stream", - "rand", "serde", "serde_repr", - "sha1", "static_assertions", "tokio", "tracing", "uds_windows", - "windows-sys 0.52.0", + "windows-sys 0.59.0", + "winnow", "xdg-home", "zbus_macros", "zbus_names", @@ -4573,25 +4440,28 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.4.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +checksum = "2c9d49ebc960ceb660f2abe40a5904da975de6986f2af0d7884b39eec6528c57" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.90", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" dependencies = [ "serde", "static_assertions", + "winnow", "zvariant", ] @@ -4644,22 +4514,24 @@ checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zvariant" -version = "4.2.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", + "winnow", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.2.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -4670,11 +4542,14 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "2.1.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" dependencies = [ "proc-macro2", "quote", + "serde", + "static_assertions", "syn 2.0.90", + "winnow", ] diff --git a/Cargo.toml b/Cargo.toml index 1e63fb3c8..ae89da48d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "librespot" version = "0.6.0-dev" -rust-version = "1.75" +rust-version = "1.81" authors = ["Librespot Org"] license = "MIT" description = "An open source client library for Spotify, with support for Spotify Connect" @@ -103,4 +103,4 @@ assets = [ ] [workspace.package] -rust-version = "1.75" +rust-version = "1.81" diff --git a/contrib/Dockerfile b/contrib/Dockerfile index a36fef88c..a450d6ca0 100644 --- a/contrib/Dockerfile +++ b/contrib/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get install -y curl git build-essential crossbuild-essential-arm64 cross RUN apt-get install -y libasound2-dev libasound2-dev:arm64 libasound2-dev:armel libasound2-dev:armhf RUN apt-get install -y libpulse0 libpulse0:arm64 libpulse0:armel libpulse0:armhf -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.75 -y +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.81 -y ENV PATH="/root/.cargo/bin/:${PATH}" RUN rustup target add aarch64-unknown-linux-gnu RUN rustup target add arm-unknown-linux-gnueabi diff --git a/discovery/Cargo.toml b/discovery/Cargo.toml index 39c35a09d..8eac51a5f 100644 --- a/discovery/Cargo.toml +++ b/discovery/Cargo.toml @@ -30,7 +30,7 @@ serde_json = "1.0" sha1 = "0.10" thiserror = "2.0" tokio = { version = "1", features = ["parking_lot", "sync", "rt"] } -zbus = { version = "4", default-features = false, features = ["tokio"], optional = true } # zbus > 4 requires a MSRV of 1.80 +zbus = { version = "5", default-features = false, features = ["tokio"], optional = true } [dependencies.librespot-core] path = "../core" diff --git a/discovery/src/avahi.rs b/discovery/src/avahi.rs index 7c098168e..de720d652 100644 --- a/discovery/src/avahi.rs +++ b/discovery/src/avahi.rs @@ -19,7 +19,7 @@ mod server { default_path = "/", gen_blocking = false )] - trait Server { + pub trait Server { /// EntryGroupNew method #[zbus(object = "super::entry_group::EntryGroup")] fn entry_group_new(&self); @@ -53,9 +53,7 @@ mod entry_group { } impl zvariant::Type for EntryGroupState { - fn signature() -> zvariant::Signature<'static> { - zvariant::Signature::try_from("i").unwrap() - } + const SIGNATURE: &'static zvariant::Signature = &zvariant::Signature::I32; } #[zbus::proxy( @@ -63,7 +61,7 @@ mod entry_group { default_service = "org.freedesktop.Avahi", gen_blocking = false )] - trait EntryGroup { + pub trait EntryGroup { /// AddAddress method fn add_address( &self, diff --git a/playback/Cargo.toml b/playback/Cargo.toml index 433829be8..e24f9868d 100644 --- a/playback/Cargo.toml +++ b/playback/Cargo.toml @@ -34,7 +34,7 @@ alsa = { version = "0.9.0", optional = true } portaudio-rs = { version = "0.3", optional = true } libpulse-binding = { version = "2", optional = true, default-features = false } libpulse-simple-binding = { version = "2", optional = true, default-features = false } -jack = { version = "0.11", optional = true } # jack >0.11 requires a MSRV of 1.80 +jack = { version = "0.13", optional = true } sdl2 = { version = "0.37", optional = true } gstreamer = { version = "0.23.1", optional = true } gstreamer-app = { version = "0.23.0", optional = true } diff --git a/playback/src/audio_backend/jackaudio.rs b/playback/src/audio_backend/jackaudio.rs index 5c7a28fbc..9d40ee82c 100644 --- a/playback/src/audio_backend/jackaudio.rs +++ b/playback/src/audio_backend/jackaudio.rs @@ -47,8 +47,8 @@ impl Open for JackSink { let client_name = client_name.unwrap_or_else(|| "librespot".to_string()); let (client, _status) = Client::new(&client_name[..], ClientOptions::NO_START_SERVER).unwrap(); - let ch_r = client.register_port("out_0", AudioOut).unwrap(); - let ch_l = client.register_port("out_1", AudioOut).unwrap(); + let ch_r = client.register_port("out_0", AudioOut::default()).unwrap(); + let ch_l = client.register_port("out_1", AudioOut::default()).unwrap(); // buffer for samples from librespot (~10ms) let (tx, rx) = sync_channel::(NUM_CHANNELS as usize * 1024 * AudioFormat::F32.size()); let jack_data = JackData { From 2a574267ae4c04360242f1516f4caec98025b635 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Tue, 24 Dec 2024 09:39:49 +0100 Subject: [PATCH 3/3] Update protobuf files (#1424) * update protobuf definitions * add additionally required proto files * update version.rs * adjust code to protobuf changes * fix formatting * apply suggestions, improve errors --- CHANGELOG.md | 4 + connect/src/model.rs | 10 +- connect/src/spirc.rs | 79 ++++--- connect/src/state.rs | 44 ++-- connect/src/state/context.rs | 93 ++++---- connect/src/state/metadata.rs | 2 +- connect/src/state/options.rs | 2 +- connect/src/state/transfer.rs | 55 +++-- core/src/dealer/protocol/request.rs | 11 +- core/src/spclient.rs | 11 +- core/src/version.rs | 15 +- metadata/src/album.rs | 2 - metadata/src/artist.rs | 2 - playback/src/player.rs | 37 ++- protocol/build.rs | 16 ++ protocol/proto/apiv1.proto | 65 ++++- protocol/proto/audio_files_extension.proto | 8 +- protocol/proto/audio_format.proto | 35 +++ .../proto/autodownload_backend_service.proto | 2 +- protocol/proto/automix_mode.proto | 6 +- protocol/proto/autoplay_context_request.proto | 3 +- protocol/proto/autoplay_node.proto | 3 +- protocol/proto/canvaz.proto | 23 +- protocol/proto/client-tts.proto | 5 +- protocol/proto/client_config.proto | 2 +- protocol/proto/client_update.proto | 2 +- .../collection/album_collection_state.proto | 2 +- .../collection/artist_collection_state.proto | 3 +- .../collection/episode_collection_state.proto | 2 +- .../collection/show_collection_state.proto | 2 +- .../collection/track_collection_state.proto | 2 +- protocol/proto/collection2v2.proto | 10 +- .../collection_add_remove_items_request.proto | 9 +- protocol/proto/collection_ban_request.proto | 5 +- .../proto/collection_decoration_policy.proto | 25 +- .../proto/collection_get_bans_request.proto | 18 +- protocol/proto/collection_index.proto | 46 +++- protocol/proto/collection_item.proto | 34 ++- .../proto/collection_platform_items.proto | 19 ++ .../proto/collection_platform_requests.proto | 23 +- .../proto/collection_platform_responses.proto | 38 ++- protocol/proto/connect.proto | 99 +++----- protocol/proto/contains_request.proto | 2 +- protocol/proto/context.proto | 2 +- .../proto/context_application_desktop.proto | 3 +- protocol/proto/context_client_id.proto | 2 +- protocol/proto/context_device_desktop.proto | 2 +- protocol/proto/context_index.proto | 2 +- protocol/proto/context_installation_id.proto | 2 +- protocol/proto/context_monotonic_clock.proto | 2 +- protocol/proto/context_node.proto | 4 +- protocol/proto/context_page.proto | 2 +- protocol/proto/context_player_options.proto | 7 +- protocol/proto/context_processor.proto | 2 +- protocol/proto/context_sdk.proto | 2 +- protocol/proto/context_time.proto | 2 +- protocol/proto/context_track.proto | 2 +- protocol/proto/context_view.proto | 5 +- protocol/proto/context_view_cyclic_list.proto | 2 +- protocol/proto/context_view_entry.proto | 6 +- protocol/proto/context_view_entry_key.proto | 2 +- protocol/proto/cosmos_changes_request.proto | 3 +- protocol/proto/cosmos_decorate_request.proto | 2 +- .../proto/cosmos_get_album_list_request.proto | 3 +- .../cosmos_get_episode_list_request.proto | 2 +- .../proto/cosmos_get_tags_info_request.proto | 5 +- ...smos_get_track_list_metadata_request.proto | 2 +- .../proto/cosmos_get_track_list_request.proto | 5 +- ...cosmos_get_unplayed_episodes_request.proto | 2 +- protocol/proto/cuepoints.proto | 2 +- protocol/proto/decorate_request.proto | 37 ++- protocol/proto/devices.proto | 2 +- .../proto/display_segments_extension.proto | 29 +-- protocol/proto/entity_extension_data.proto | 3 +- protocol/proto/es_add_to_queue_request.proto | 2 +- protocol/proto/es_command_options.proto | 2 +- protocol/proto/es_context.proto | 4 +- protocol/proto/es_context_page.proto | 4 +- protocol/proto/es_context_player_error.proto | 12 +- .../proto/es_context_player_options.proto | 6 +- protocol/proto/es_context_player_state.proto | 21 +- protocol/proto/es_context_track.proto | 2 +- protocol/proto/es_delete_session.proto | 3 +- protocol/proto/es_get_error_request.proto | 3 +- protocol/proto/es_get_play_history.proto | 3 +- protocol/proto/es_get_position_state.proto | 7 +- protocol/proto/es_get_queue_request.proto | 3 +- protocol/proto/es_get_state_request.proto | 2 +- protocol/proto/es_optional.proto | 2 +- protocol/proto/es_pause.proto | 4 +- protocol/proto/es_pauseresume_origin.proto | 11 + protocol/proto/es_play.proto | 2 +- protocol/proto/es_play_origin.proto | 3 +- protocol/proto/es_prefs.proto | 4 +- protocol/proto/es_prepare_play.proto | 2 +- protocol/proto/es_prepare_play_options.proto | 8 +- protocol/proto/es_provided_track.proto | 2 +- protocol/proto/es_queue.proto | 2 +- protocol/proto/es_remote_config.proto | 22 +- protocol/proto/es_request_info.proto | 4 +- protocol/proto/es_response_with_reasons.proto | 6 +- protocol/proto/es_restrictions.proto | 14 +- protocol/proto/es_resume.proto | 10 +- protocol/proto/es_seek_to.proto | 13 +- protocol/proto/es_session_response.proto | 2 +- protocol/proto/es_set_options.proto | 4 +- protocol/proto/es_set_queue_request.proto | 2 +- protocol/proto/es_set_repeating_context.proto | 2 +- protocol/proto/es_set_repeating_track.proto | 2 +- protocol/proto/es_set_shuffling_context.proto | 2 +- protocol/proto/es_skip_next.proto | 2 +- protocol/proto/es_skip_prev.proto | 2 +- protocol/proto/es_skip_to_track.proto | 2 +- protocol/proto/es_stop.proto | 8 +- protocol/proto/es_storage.proto | 16 +- protocol/proto/es_update.proto | 2 +- protocol/proto/esperanto_options.proto | 6 + protocol/proto/event_entity.proto | 2 +- protocol/proto/explicit_content_pubsub.proto | 7 +- protocol/proto/extended_metadata.proto | 3 +- protocol/proto/extension_kind.proto | 158 ++++++++++++- protocol/proto/extracted_colors.proto | 2 +- protocol/proto/follow_request.proto | 7 +- protocol/proto/followed_users_request.proto | 2 +- protocol/proto/frecency.proto | 2 +- protocol/proto/frecency_storage.proto | 2 +- protocol/proto/gabito.proto | 11 +- protocol/proto/global_node.proto | 5 +- protocol/proto/google/protobuf/any.proto | 2 +- .../proto/google/protobuf/descriptor.proto | 222 ++++++++++++++---- protocol/proto/google/protobuf/duration.proto | 2 +- protocol/proto/google/protobuf/empty.proto | 4 +- .../proto/google/protobuf/field_mask.proto | 2 +- .../google/protobuf/source_context.proto | 2 +- .../proto/google/protobuf/timestamp.proto | 2 +- protocol/proto/google/protobuf/type.proto | 13 +- protocol/proto/google/protobuf/wrappers.proto | 2 +- protocol/proto/identity.proto | 18 +- protocol/proto/installation_data.proto | 6 +- protocol/proto/instrumentation_params.proto | 2 +- protocol/proto/lens-model.proto | 19 ++ protocol/proto/lfs_secret_provider.proto | 2 +- .../proto/liked_songs_tags_sync_state.proto | 2 +- .../proto/listen_later_cosmos_response.proto | 7 +- protocol/proto/local_bans_storage.proto | 6 +- protocol/proto/local_sync_state.proto | 2 +- protocol/proto/logging_params.proto | 4 +- protocol/proto/mdata.proto | 19 +- protocol/proto/mdata_cosmos.proto | 3 +- protocol/proto/mdata_storage.proto | 3 +- protocol/proto/media.proto | 19 ++ protocol/proto/media_manifest.proto | 31 +-- protocol/proto/media_type.proto | 5 +- protocol/proto/members_request.proto | 2 +- protocol/proto/members_response.proto | 2 +- protocol/proto/metadata.proto | 80 ++++--- protocol/proto/metadata/album_metadata.proto | 2 +- protocol/proto/metadata/artist_metadata.proto | 2 +- .../proto/metadata/episode_metadata.proto | 20 +- protocol/proto/metadata/extension.proto | 2 +- protocol/proto/metadata/image_group.proto | 2 +- protocol/proto/metadata/show_metadata.proto | 3 +- protocol/proto/metadata/track_metadata.proto | 7 +- protocol/proto/metadata_cosmos.proto | 2 +- protocol/proto/metadata_esperanto.proto | 2 +- protocol/proto/modification_request.proto | 39 ++- protocol/proto/net-fortune.proto | 4 +- protocol/proto/offline.proto | 13 +- .../proto/offline_playlists_containing.proto | 2 +- protocol/proto/on_demand_in_free_reason.proto | 3 +- .../proto/on_demand_set_cosmos_request.proto | 2 +- .../proto/on_demand_set_cosmos_response.proto | 2 +- protocol/proto/on_demand_set_response.proto | 2 +- protocol/proto/pause_resume_origin.proto | 12 + protocol/proto/pending_event_entity.proto | 2 +- protocol/proto/pin_request.proto | 27 ++- protocol/proto/play_history.proto | 20 ++ protocol/proto/play_origin.proto | 3 +- protocol/proto/play_queue_node.proto | 3 +- protocol/proto/play_reason.proto | 4 +- protocol/proto/playback.proto | 4 +- protocol/proto/playback_esperanto.proto | 46 +++- protocol/proto/playback_stack.proto | 13 + protocol/proto/playback_stack_v2.proto | 14 ++ protocol/proto/playback_state.proto | 14 ++ protocol/proto/played_state.proto | 2 +- .../played_state/episode_played_state.proto | 2 +- .../playability_restriction.proto | 3 +- .../played_state/show_played_state.proto | 17 +- .../played_state/track_played_state.proto | 2 +- protocol/proto/player.proto | 111 +++------ protocol/proto/player_license.proto | 2 +- protocol/proto/playlist4_external.proto | 93 +++++++- .../proto/playlist_contains_request.proto | 2 +- protocol/proto/playlist_folder_state.proto | 2 +- protocol/proto/playlist_get_request.proto | 26 +- protocol/proto/playlist_members_request.proto | 2 +- .../proto/playlist_modification_request.proto | 2 +- protocol/proto/playlist_offline_request.proto | 2 +- protocol/proto/playlist_permission.proto | 81 ++++++- protocol/proto/playlist_play_request.proto | 2 +- .../proto/playlist_playback_request.proto | 2 +- protocol/proto/playlist_playlist_state.proto | 4 +- protocol/proto/playlist_query.proto | 32 ++- protocol/proto/playlist_request.proto | 62 ++++- ...playlist_set_base_permission_request.proto | 2 +- ...aylist_set_member_permission_request.proto | 2 +- .../playlist_set_permission_request.proto | 2 +- protocol/proto/playlist_track_state.proto | 2 +- protocol/proto/playlist_user_state.proto | 2 +- protocol/proto/plugin.proto | 64 ++--- protocol/proto/podcast_ad_segments.proto | 3 +- protocol/proto/podcast_cta_cards.proto | 4 +- protocol/proto/podcast_poll.proto | 2 +- protocol/proto/podcast_qna.proto | 2 +- protocol/proto/podcast_subscription.proto | 4 +- protocol/proto/podcastextensions.proto | 5 +- .../policy/album_decoration_policy.proto | 2 +- .../policy/artist_decoration_policy.proto | 3 +- .../policy/episode_decoration_policy.proto | 15 +- .../policy/folder_decoration_policy.proto | 2 +- .../playlist_album_decoration_policy.proto | 2 +- .../policy/playlist_decoration_policy.proto | 9 +- .../playlist_episode_decoration_policy.proto | 4 +- .../playlist_request_decoration_policy.proto | 36 ++- .../playlist_track_decoration_policy.proto | 4 +- .../rootlist_folder_decoration_policy.proto | 2 +- .../rootlist_playlist_decoration_policy.proto | 2 +- .../rootlist_request_decoration_policy.proto | 2 +- .../proto/policy/show_decoration_policy.proto | 20 +- .../supported_link_types_in_playlists.proto | 17 ++ .../policy/track_decoration_policy.proto | 7 +- .../proto/policy/user_decoration_policy.proto | 2 +- protocol/proto/popcount2_external.proto | 19 +- protocol/proto/prepare_play_options.proto | 10 +- protocol/proto/profile_cosmos.proto | 2 +- protocol/proto/profile_service.proto | 4 +- protocol/proto/property_definition.proto | 41 ++-- protocol/proto/protobuf_delta.proto | 4 +- protocol/proto/queue.proto | 2 +- protocol/proto/rate_limited_events.proto | 2 +- protocol/proto/rcs.proto | 70 +++--- protocol/proto/recently_played.proto | 4 +- protocol/proto/recently_played_backend.proto | 2 +- protocol/proto/record_id.proto | 2 +- protocol/proto/remote.proto | 2 +- protocol/proto/request_failure.proto | 2 +- protocol/proto/resolve.proto | 70 +++--- protocol/proto/resource_type.proto | 2 +- protocol/proto/response_status.proto | 2 +- protocol/proto/restrictions.proto | 17 +- protocol/proto/rootlist_request.proto | 2 +- protocol/proto/seek_to_position.proto | 2 +- protocol/proto/sequence_number_entity.proto | 2 +- protocol/proto/session.proto | 5 +- .../proto/set_member_permission_request.proto | 2 +- protocol/proto/show_access.proto | 79 ++++++- protocol/proto/show_episode_state.proto | 2 +- protocol/proto/show_offline_state.proto | 9 + protocol/proto/show_request.proto | 64 +++-- protocol/proto/show_show_state.proto | 5 +- protocol/proto/signal-model.proto | 16 ++ protocol/proto/skip_to_track.proto | 2 +- protocol/proto/social_connect_v2.proto | 10 +- protocol/proto/social_service.proto | 10 +- .../proto/socialgraph_response_status.proto | 2 +- protocol/proto/socialgraphv2.proto | 2 +- .../audiobookcashier/v1/audiobook_price.proto | 18 ++ .../ads_rules_inject_tracks.proto | 2 +- .../proto/state_restore/automix_rules.proto | 9 + .../state_restore/automix_talk_rules.proto | 11 + .../behavior_metadata_rules.proto | 2 +- .../state_restore/circuit_breaker_rules.proto | 2 +- .../proto/state_restore/context_loader.proto | 10 + .../context_player_restorable.proto | 23 ++ .../state_restore/context_player_rules.proto | 68 +++++- .../state_restore/context_player_state.proto | 59 +++++ .../explicit_content_rules.proto | 2 +- .../state_restore/kitteh_box_rules.proto | 30 +++ .../state_restore/mft_context_history.proto | 3 +- .../mft_context_switch_rules.proto | 2 + .../mft_fallback_page_history.proto | 2 +- .../proto/state_restore/mft_rules_core.proto | 2 +- .../mft_rules_inject_filler_tracks.proto | 2 +- protocol/proto/state_restore/mft_state.proto | 10 +- .../mod_interruption_state.proto | 2 +- .../mod_rules_interruptions.proto | 13 +- .../state_restore/music_injection_rules.proto | 2 +- .../proto/state_restore/playback_state.proto | 15 ++ .../proto/state_restore/player_model.proto | 38 +++ .../proto/state_restore/player_session.proto | 39 +++ .../state_restore/player_session_fake.proto | 13 + .../state_restore/player_session_queue.proto | 25 +- .../proto/state_restore/provided_track.proto | 2 +- .../proto/state_restore/random_source.proto | 2 +- .../remove_banned_tracks_rules.proto | 2 +- .../state_restore/resume_points_rules.proto | 2 +- .../state_restore/track_error_rules.proto | 2 +- protocol/proto/status.proto | 2 +- protocol/proto/status_code.proto | 9 +- protocol/proto/status_response.proto | 3 +- protocol/proto/storage-resolve.proto | 4 +- protocol/proto/storylines.proto | 2 +- protocol/proto/stream_end_request.proto | 5 +- protocol/proto/stream_handle.proto | 5 +- protocol/proto/stream_progress_request.proto | 13 +- protocol/proto/stream_seek_request.proto | 6 +- protocol/proto/stream_start_request.proto | 43 +++- protocol/proto/stream_start_response.proto | 2 +- protocol/proto/streaming_rule.proto | 3 +- protocol/proto/suppressions.proto | 2 +- protocol/proto/sync/album_sync_state.proto | 2 +- protocol/proto/sync/artist_sync_state.proto | 2 +- protocol/proto/sync/episode_sync_state.proto | 2 +- protocol/proto/sync/track_sync_state.proto | 2 +- protocol/proto/sync_request.proto | 2 +- protocol/proto/track_instance.proto | 5 +- protocol/proto/track_instantiator.proto | 2 +- protocol/proto/transfer_state.proto | 4 +- protocol/proto/tts-resolve.proto | 57 ++++- protocol/proto/ucs.proto | 15 +- .../proto/unfinished_episodes_request.proto | 4 +- protocol/proto/useraccount.proto | 2 +- protocol/proto/your_library_config.proto | 57 +++++ .../proto/your_library_contains_request.proto | 7 +- .../your_library_contains_response.proto | 5 +- .../proto/your_library_decorate_request.proto | 7 +- .../your_library_decorate_response.proto | 5 +- .../proto/your_library_decorated_entity.proto | 108 +++++++-- protocol/proto/your_library_entity.proto | 27 +-- protocol/proto/your_library_index.proto | 77 +++++- protocol/proto/your_library_request.proto | 45 +++- protocol/proto/your_library_response.proto | 31 ++- protocol/src/conversion.rs | 173 ++++++++++++++ protocol/src/lib.rs | 2 + 335 files changed, 3321 insertions(+), 1194 deletions(-) create mode 100644 protocol/proto/audio_format.proto create mode 100644 protocol/proto/collection_platform_items.proto create mode 100644 protocol/proto/es_pauseresume_origin.proto create mode 100644 protocol/proto/esperanto_options.proto create mode 100644 protocol/proto/lens-model.proto create mode 100644 protocol/proto/media.proto create mode 100644 protocol/proto/pause_resume_origin.proto create mode 100644 protocol/proto/play_history.proto create mode 100644 protocol/proto/playback_stack.proto create mode 100644 protocol/proto/playback_stack_v2.proto create mode 100644 protocol/proto/playback_state.proto create mode 100644 protocol/proto/policy/supported_link_types_in_playlists.proto create mode 100644 protocol/proto/show_offline_state.proto create mode 100644 protocol/proto/signal-model.proto create mode 100755 protocol/proto/spotify/audiobookcashier/v1/audiobook_price.proto create mode 100644 protocol/proto/state_restore/automix_rules.proto create mode 100644 protocol/proto/state_restore/automix_talk_rules.proto create mode 100644 protocol/proto/state_restore/context_loader.proto create mode 100644 protocol/proto/state_restore/context_player_restorable.proto create mode 100644 protocol/proto/state_restore/context_player_state.proto create mode 100644 protocol/proto/state_restore/kitteh_box_rules.proto create mode 100644 protocol/proto/state_restore/playback_state.proto create mode 100644 protocol/proto/state_restore/player_model.proto create mode 100644 protocol/proto/state_restore/player_session.proto create mode 100644 protocol/proto/state_restore/player_session_fake.proto create mode 100644 protocol/proto/your_library_config.proto create mode 100644 protocol/src/conversion.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e27f8634..146b6fe16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed +- [core] Removed `get_canvases` from SpClient (breaking) +- [metadata] Removed `genres` from Album (breaking) +- [metadata] Removed `genre` from Artists (breaking) + ## [0.6.0] - 2024-10-30 This version takes another step into the direction of the HTTP API, fixes a diff --git a/connect/src/model.rs b/connect/src/model.rs index f9165eaee..a080f9686 100644 --- a/connect/src/model.rs +++ b/connect/src/model.rs @@ -1,6 +1,6 @@ use crate::state::ConnectState; use librespot_core::dealer::protocol::SkipTo; -use librespot_protocol::player::Context; +use librespot_protocol::context::Context; use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; @@ -77,7 +77,7 @@ impl ResolveContext { let fallback_uri = fallback.into(); Self { context: Context { - uri: uri.into(), + uri: Some(uri.into()), ..Default::default() }, fallback: (!fallback_uri.is_empty()).then_some(fallback_uri), @@ -114,7 +114,7 @@ impl ResolveContext { Self { context: Context { - uri, + uri: Some(uri), ..Default::default() }, fallback: None, @@ -134,7 +134,7 @@ impl ResolveContext { /// the actual context uri pub fn context_uri(&self) -> &str { - &self.context.uri + self.context.uri.as_deref().unwrap_or_default() } pub fn autoplay(&self) -> bool { @@ -150,7 +150,7 @@ impl Display for ResolveContext { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!( f, - "resolve_uri: <{:?}>, context_uri: <{}>, autoplay: <{}>, update: <{}>", + "resolve_uri: <{:?}>, context_uri: <{:?}>, autoplay: <{}>, update: <{}>", self.resolve_uri(), self.context.uri, self.autoplay, diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index 32124570a..e82865233 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -17,10 +17,11 @@ use crate::{ protocol::{ autoplay_context_request::AutoplayContextRequest, connect::{Cluster, ClusterUpdate, LogoutCommand, SetVolumeCommand}, + context::Context, explicit_content_pubsub::UserAttributesUpdate, - player::{Context, TransferState}, playlist4_external::PlaylistModificationInfo, - social_connect_v2::{session::_host_active_device_id, SessionUpdate}, + social_connect_v2::SessionUpdate, + transfer_state::TransferState, user_attributes::UserAttributesMutation, }, }; @@ -49,6 +50,8 @@ use tokio::{sync::mpsc, time::sleep}; pub enum SpircError { #[error("response payload empty")] NoData, + #[error("{0} had no uri")] + NoUri(&'static str), #[error("message pushed for another URI")] InvalidUri(String), #[error("tried resolving not allowed context: {0:?}")] @@ -63,7 +66,7 @@ impl From for Error { fn from(err: SpircError) -> Self { use SpircError::*; match err { - NoData | NotAllowedContext(_) => Error::unavailable(err), + NoData | NoUri(_) | NotAllowedContext(_) => Error::unavailable(err), InvalidUri(_) | FailedDealerSetup => Error::aborted(err), UnknownEndpoint(_) => Error::unimplemented(err), } @@ -522,14 +525,14 @@ impl SpircTask { let mut ctx = self.session.spclient().get_context(resolve_uri).await?; if update { - ctx.uri = context_uri.to_string(); - ctx.url = format!("context://{context_uri}"); + ctx.uri = Some(context_uri.to_string()); + ctx.url = Some(format!("context://{context_uri}")); self.connect_state .update_context(ctx, UpdateContext::Default)? } else if matches!(ctx.pages.first(), Some(p) if !p.tracks.is_empty()) { debug!( - "update context from single page, context {} had {} pages", + "update context from single page, context {:?} had {} pages", ctx.uri, ctx.pages.len() ); @@ -883,7 +886,7 @@ impl SpircTask { let attributes: UserAttributes = update .pairs .iter() - .map(|pair| (pair.key().to_owned(), pair.value().to_owned())) + .map(|(key, value)| (key.to_owned(), value.to_owned())) .collect(); self.session.set_user_attributes(attributes) } @@ -998,9 +1001,10 @@ impl SpircTask { Unknown(unknown) => Err(SpircError::UnknownEndpoint(unknown))?, // implicit update of the connect_state UpdateContext(update_context) => { - if &update_context.context.uri != self.connect_state.context_uri() { + if matches!(update_context.context.uri, Some(ref uri) if uri != self.connect_state.context_uri()) + { debug!( - "ignoring context update for <{}>, because it isn't the current context <{}>", + "ignoring context update for <{:?}>, because it isn't the current context <{}>", update_context.context.uri, self.connect_state.context_uri() ) } else { @@ -1020,24 +1024,30 @@ impl SpircTask { .options .player_options_override .as_ref() - .map(|o| o.shuffling_context) + .map(|o| o.shuffling_context.unwrap_or_default()) .unwrap_or_else(|| self.connect_state.shuffling_context()); let repeat = play .options .player_options_override .as_ref() - .map(|o| o.repeating_context) + .map(|o| o.repeating_context.unwrap_or_default()) .unwrap_or_else(|| self.connect_state.repeat_context()); let repeat_track = play .options .player_options_override .as_ref() - .map(|o| o.repeating_track) + .map(|o| o.repeating_track.unwrap_or_default()) .unwrap_or_else(|| self.connect_state.repeat_track()); + let context_uri = play + .context + .uri + .clone() + .ok_or(SpircError::NoUri("context"))?; + self.handle_load( SpircLoadCommand { - context_uri: play.context.uri.clone(), + context_uri, start_playing: true, seek_to: play.options.seek_to.unwrap_or_default(), playing_track: play.options.skip_to.unwrap_or_default().into(), @@ -1088,12 +1098,13 @@ impl SpircTask { } fn handle_transfer(&mut self, mut transfer: TransferState) -> Result<(), Error> { - self.connect_state - .reset_context(ResetContext::WhenDifferent( - &transfer.current_session.context.uri, - )); + let mut ctx_uri = match transfer.current_session.context.uri { + None => Err(SpircError::NoUri("transfer context"))?, + Some(ref uri) => uri.clone(), + }; - let mut ctx_uri = transfer.current_session.context.uri.clone(); + self.connect_state + .reset_context(ResetContext::WhenDifferent(&ctx_uri)); match self.connect_state.current_track_from_transfer(&transfer) { Err(why) => warn!("didn't find initial track: {why}"), @@ -1118,17 +1129,18 @@ impl SpircTask { state.set_active(true); state.handle_initial_transfer(&mut transfer); - // update position if the track continued playing - let position = if transfer.playback.is_paused { - transfer.playback.position_as_of_timestamp.into() - } else if transfer.playback.position_as_of_timestamp > 0 { - let time_since_position_update = timestamp - transfer.playback.timestamp; - i64::from(transfer.playback.position_as_of_timestamp) + time_since_position_update - } else { - 0 + let transfer_timestamp = transfer.playback.timestamp.unwrap_or_default(); + let position = match transfer.playback.position_as_of_timestamp { + Some(position) if transfer.playback.is_paused.unwrap_or_default() => position.into(), + // update position if the track continued playing + Some(position) if position > 0 => { + let time_since_position_update = timestamp - transfer_timestamp; + i64::from(position) + time_since_position_update + } + _ => 0, }; - let is_playing = !transfer.playback.is_paused; + let is_playing = matches!(transfer.playback.is_paused, Some(is_playing) if is_playing); if self.connect_state.current_track(|t| t.is_autoplay()) || autoplay { debug!("currently in autoplay context, async resolving autoplay for {ctx_uri}"); @@ -1514,7 +1526,9 @@ impl SpircTask { &mut self, playlist_modification_info: PlaylistModificationInfo, ) -> Result<(), Error> { - let uri = playlist_modification_info.uri.ok_or(SpircError::NoData)?; + let uri = playlist_modification_info + .uri + .ok_or(SpircError::NoUri("playlist modification"))?; let uri = String::from_utf8(uri)?; if self.connect_state.context_uri() != &uri { @@ -1540,14 +1554,7 @@ impl SpircTask { Some(session) => session, }; - let active_device = session._host_active_device_id.take().map(|id| match id { - _host_active_device_id::HostActiveDeviceId(id) => id, - other => { - warn!("unexpected active device id {other:?}"); - String::new() - } - }); - + let active_device = session.host_active_device_id.take(); if matches!(active_device, Some(ref device) if device == self.session.device_id()) { info!( "session update: <{:?}> for self, current session_id {}, new session_id {}", diff --git a/connect/src/state.rs b/connect/src/state.rs index 28e57dadd..eff83bacc 100644 --- a/connect/src/state.rs +++ b/connect/src/state.rs @@ -8,21 +8,25 @@ mod tracks; mod transfer; use crate::model::SpircPlayStatus; -use crate::state::{ - context::{ContextType, ResetContext, StateContext}, - provider::{IsProvider, Provider}, -}; -use librespot_core::{ - config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult, version, - Error, Session, -}; -use librespot_protocol::connect::{ - Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest, -}; -use librespot_protocol::player::{ - ContextIndex, ContextPage, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack, - Suppressions, +use crate::{ + core::{ + config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult, + version, Error, Session, + }, + protocol::{ + connect::{Capabilities, Device, DeviceInfo, MemberType, PutStateReason, PutStateRequest}, + context_page::ContextPage, + player::{ + ContextIndex, ContextPlayerOptions, PlayOrigin, PlayerState, ProvidedTrack, + Suppressions, + }, + }, + state::{ + context::{ContextType, ResetContext, StateContext}, + provider::{IsProvider, Provider}, + }, }; + use log::LevelFilter; use protobuf::{EnumOrUnknown, MessageField}; use std::{ @@ -40,20 +44,21 @@ const SPOTIFY_MAX_NEXT_TRACKS_SIZE: usize = 80; pub enum StateError { #[error("the current track couldn't be resolved from the transfer state")] CouldNotResolveTrackFromTransfer, - #[error("message field {0} was not available")] - MessageFieldNone(String), #[error("context is not available. type: {0:?}")] NoContext(ContextType), #[error("could not find track {0:?} in context of {1}")] CanNotFindTrackInContext(Option, usize), #[error("currently {action} is not allowed because {reason}")] - CurrentlyDisallowed { action: String, reason: String }, + CurrentlyDisallowed { + action: &'static str, + reason: String, + }, #[error("the provided context has no tracks")] ContextHasNoTracks, #[error("playback of local files is not supported")] UnsupportedLocalPlayBack, - #[error("track uri <{0}> contains invalid characters")] - InvalidTrackUri(String), + #[error("track uri <{0:?}> contains invalid characters")] + InvalidTrackUri(Option), } impl From for Error { @@ -61,7 +66,6 @@ impl From for Error { use StateError::*; match err { CouldNotResolveTrackFromTransfer - | MessageFieldNone(_) | NoContext(_) | CanNotFindTrackInContext(_, _) | ContextHasNoTracks diff --git a/connect/src/state/context.rs b/connect/src/state/context.rs index 3e9d720e6..11827cc53 100644 --- a/connect/src/state/context.rs +++ b/connect/src/state/context.rs @@ -1,7 +1,13 @@ -use crate::state::{metadata::Metadata, provider::Provider, ConnectState, StateError}; -use librespot_core::{Error, SpotifyId}; -use librespot_protocol::player::{ - Context, ContextIndex, ContextPage, ContextTrack, ProvidedTrack, Restrictions, +use crate::{ + core::{Error, SpotifyId}, + protocol::{ + context::Context, + context_page::ContextPage, + context_track::ContextTrack, + player::{ContextIndex, ProvidedTrack}, + restrictions::Restrictions, + }, + state::{metadata::Metadata, provider::Provider, ConnectState, StateError}, }; use protobuf::MessageField; use std::collections::HashMap; @@ -104,14 +110,16 @@ impl ConnectState { } pub fn get_context_uri_from_context(context: &Context) -> Option<&String> { - if !context.uri.starts_with(SEARCH_IDENTIFIER) { - return Some(&context.uri); + let context_uri = context.uri.as_ref()?; + + if !context_uri.starts_with(SEARCH_IDENTIFIER) { + return Some(context_uri); } context .pages .first() - .and_then(|p| p.tracks.first().map(|t| &t.uri)) + .and_then(|p| p.tracks.first().and_then(|t| t.uri.as_ref())) } pub fn set_active_context(&mut self, new_context: ContextType) { @@ -134,7 +142,7 @@ impl ConnectState { player.restrictions.clear(); if let Some(restrictions) = restrictions.take() { - player.restrictions = MessageField::some(restrictions); + player.restrictions = MessageField::some(restrictions.into()); } for (key, value) in metadata { @@ -146,7 +154,7 @@ impl ConnectState { if context.pages.iter().all(|p| p.tracks.is_empty()) { error!("context didn't have any tracks: {context:#?}"); return Err(StateError::ContextHasNoTracks.into()); - } else if context.uri.starts_with(LOCAL_FILES_IDENTIFIER) { + } else if matches!(context.uri, Some(ref uri) if uri.starts_with(LOCAL_FILES_IDENTIFIER)) { return Err(StateError::UnsupportedLocalPlayBack.into()); } @@ -174,7 +182,7 @@ impl ConnectState { }; debug!( - "updated context {ty:?} from <{}> ({} tracks) to <{}> ({} tracks)", + "updated context {ty:?} from <{:?}> ({} tracks) to <{:?}> ({} tracks)", self.context_uri(), prev_context .map(|c| c.tracks.len().to_string()) @@ -188,14 +196,14 @@ impl ConnectState { let mut new_context = self.state_context_from_page( page, context.restrictions.take(), - Some(&context.uri), + context.uri.as_deref(), None, ); // when we update the same context, we should try to preserve the previous position // otherwise we might load the entire context twice if !self.context_uri().contains(SEARCH_IDENTIFIER) - && self.context_uri() == &context.uri + && matches!(context.uri, Some(ref uri) if uri == self.context_uri()) { match Self::find_index_in_context(Some(&new_context), |t| { self.current_track(|t| &t.uri) == &t.uri @@ -217,18 +225,18 @@ impl ConnectState { self.context = Some(new_context); - if !context.url.contains(SEARCH_IDENTIFIER) { - self.player_mut().context_url = context.url; + if !matches!(context.url, Some(ref url) if url.contains(SEARCH_IDENTIFIER)) { + self.player_mut().context_url = context.url.take().unwrap_or_default(); } else { self.player_mut().context_url.clear() } - self.player_mut().context_uri = context.uri; + self.player_mut().context_uri = context.uri.take().unwrap_or_default(); } UpdateContext::Autoplay => { self.autoplay_context = Some(self.state_context_from_page( page, context.restrictions.take(), - Some(&context.uri), + context.uri.as_deref(), Some(Provider::Autoplay), )) } @@ -271,7 +279,7 @@ impl ConnectState { pub fn merge_context(&mut self, context: Option) -> Option<()> { let mut context = context?; - if self.context_uri() != &context.uri { + if matches!(context.uri, Some(ref uri) if uri != self.context_uri()) { return None; } @@ -279,12 +287,13 @@ impl ConnectState { let new_page = context.pages.pop()?; for new_track in new_page.tracks { - if new_track.uri.is_empty() { + if new_track.uri.is_none() || matches!(new_track.uri, Some(ref uri) if uri.is_empty()) { continue; } + let new_track_uri = new_track.uri.unwrap_or_default(); if let Ok(position) = - Self::find_index_in_context(Some(current_context), |t| t.uri == new_track.uri) + Self::find_index_in_context(Some(current_context), |t| t.uri == new_track_uri) { let context_track = current_context.tracks.get_mut(position)?; @@ -294,8 +303,10 @@ impl ConnectState { } // the uid provided from another context might be actual uid of an item - if !new_track.uid.is_empty() { - context_track.uid = new_track.uid; + if new_track.uid.is_some() + || matches!(new_track.uid, Some(ref uid) if uid.is_empty()) + { + context_track.uid = new_track.uid.unwrap_or_default(); } } } @@ -325,19 +336,19 @@ impl ConnectState { context_uri: Option<&str>, provider: Option, ) -> Result { - let id = if !ctx_track.uri.is_empty() { - if ctx_track.uri.contains(['?', '%']) { - Err(StateError::InvalidTrackUri(ctx_track.uri.clone()))? + let id = match (ctx_track.uri.as_ref(), ctx_track.gid.as_ref()) { + (None, None) => Err(StateError::InvalidTrackUri(None))?, + (Some(uri), _) if uri.contains(['?', '%']) => { + Err(StateError::InvalidTrackUri(Some(uri.clone())))? } - - SpotifyId::from_uri(&ctx_track.uri)? - } else if !ctx_track.gid.is_empty() { - SpotifyId::from_raw(&ctx_track.gid)? - } else { - Err(StateError::InvalidTrackUri(String::new()))? + (Some(uri), _) if !uri.is_empty() => SpotifyId::from_uri(uri)?, + (None, Some(gid)) if !gid.is_empty() => SpotifyId::from_raw(gid)?, + _ => Err(StateError::InvalidTrackUri(None))?, }; - let provider = if self.unavailable_uri.contains(&ctx_track.uri) { + let uri = id.to_uri()?.replace("unknown", "track"); + + let provider = if self.unavailable_uri.contains(&uri) { Provider::Unavailable } else { provider.unwrap_or(Provider::Context) @@ -346,11 +357,10 @@ impl ConnectState { // assumption: the uid is used as unique-id of any item // - queue resorting is done by each client and orients itself by the given uid // - if no uid is present, resorting doesn't work or behaves not as intended - let uid = if ctx_track.uid.is_empty() { - // so setting providing a unique id should allow to resort the queue - Uuid::new_v4().as_simple().to_string() - } else { - ctx_track.uid.to_string() + let uid = match ctx_track.uid.as_ref() { + Some(uid) if !uid.is_empty() => uid.to_string(), + // so providing a unique id should allow to resort the queue + _ => Uuid::new_v4().as_simple().to_string(), }; let mut metadata = HashMap::new(); @@ -359,7 +369,7 @@ impl ConnectState { } let mut track = ProvidedTrack { - uri: id.to_uri()?.replace("unknown", "track"), + uri, uid, metadata, provider: provider.to_string(), @@ -399,12 +409,13 @@ impl ConnectState { }; if next.tracks.is_empty() { - if next.page_url.is_empty() { - Err(StateError::NoContext(ContextType::Default))? - } + let next_page_url = match next.page_url { + Some(page_url) if !page_url.is_empty() => page_url, + _ => Err(StateError::NoContext(ContextType::Default))?, + }; self.update_current_index(|i| i.page += 1); - return Ok(LoadNext::PageUrl(next.page_url)); + return Ok(LoadNext::PageUrl(next_page_url)); } self.fill_context_from_page(next)?; diff --git a/connect/src/state/metadata.rs b/connect/src/state/metadata.rs index d3788b22b..b1effb688 100644 --- a/connect/src/state/metadata.rs +++ b/connect/src/state/metadata.rs @@ -1,4 +1,4 @@ -use librespot_protocol::player::{ContextTrack, ProvidedTrack}; +use librespot_protocol::{context_track::ContextTrack, player::ProvidedTrack}; use std::collections::HashMap; const CONTEXT_URI: &str = "context_uri"; diff --git a/connect/src/state/options.rs b/connect/src/state/options.rs index b6bc331c9..b9c2c5766 100644 --- a/connect/src/state/options.rs +++ b/connect/src/state/options.rs @@ -41,7 +41,7 @@ impl ConnectState { .first() { Err(StateError::CurrentlyDisallowed { - action: "shuffle".to_string(), + action: "shuffle", reason: reason.clone(), })? } diff --git a/connect/src/state/transfer.rs b/connect/src/state/transfer.rs index c310e0b9c..53d420a12 100644 --- a/connect/src/state/transfer.rs +++ b/connect/src/state/transfer.rs @@ -1,9 +1,13 @@ -use crate::state::context::ContextType; -use crate::state::metadata::Metadata; -use crate::state::provider::{IsProvider, Provider}; -use crate::state::{ConnectState, StateError}; -use librespot_core::Error; -use librespot_protocol::player::{ProvidedTrack, TransferState}; +use crate::{ + core::Error, + protocol::{player::ProvidedTrack, transfer_state::TransferState}, + state::{ + context::ContextType, + metadata::Metadata, + provider::{IsProvider, Provider}, + {ConnectState, StateError}, + }, +}; use protobuf::MessageField; impl ConnectState { @@ -11,7 +15,7 @@ impl ConnectState { &self, transfer: &TransferState, ) -> Result { - let track = if transfer.queue.is_playing_queue { + let track = if transfer.queue.is_playing_queue.unwrap_or_default() { transfer.queue.tracks.first() } else { transfer.playback.current_track.as_ref() @@ -20,8 +24,11 @@ impl ConnectState { self.context_to_provided_track( track, - Some(&transfer.current_session.context.uri), - transfer.queue.is_playing_queue.then_some(Provider::Queue), + transfer.current_session.context.uri.as_deref(), + transfer + .queue + .is_playing_queue + .and_then(|b| b.then_some(Provider::Queue)), ) } @@ -33,23 +40,22 @@ impl ConnectState { player.is_buffering = false; if let Some(options) = transfer.options.take() { - player.options = MessageField::some(options); + player.options = MessageField::some(options.into()); } - player.is_paused = transfer.playback.is_paused; - player.is_playing = !transfer.playback.is_paused; + player.is_paused = transfer.playback.is_paused.unwrap_or_default(); + player.is_playing = !player.is_paused; - if transfer.playback.playback_speed != 0. { - player.playback_speed = transfer.playback.playback_speed - } else { - player.playback_speed = 1.; + match transfer.playback.playback_speed { + Some(speed) if speed != 0. => player.playback_speed = speed, + _ => player.playback_speed = 1., } if let Some(session) = transfer.current_session.as_mut() { - player.play_origin = session.play_origin.take().into(); - player.suppressions = session.suppressions.take().into(); + player.play_origin = session.play_origin.take().map(Into::into).into(); + player.suppressions = session.suppressions.take().map(Into::into).into(); if let Some(mut ctx) = session.context.take() { - player.restrictions = ctx.restrictions.take().into(); + player.restrictions = ctx.restrictions.take().map(Into::into).into(); for (key, value) in ctx.metadata { player.context_metadata.insert(key, value); } @@ -87,11 +93,10 @@ impl ConnectState { let ctx = self.get_context(&self.active_context).ok(); - let current_index = if track.is_queue() { - Self::find_index_in_context(ctx, |c| c.uid == transfer.current_session.current_uid) - .map(|i| if i > 0 { i - 1 } else { i }) - } else { - Self::find_index_in_context(ctx, |c| c.uri == track.uri || c.uid == track.uid) + let current_index = match transfer.current_session.current_uid.as_ref() { + Some(uid) if track.is_queue() => Self::find_index_in_context(ctx, |c| &c.uid == uid) + .map(|i| if i > 0 { i - 1 } else { i }), + _ => Self::find_index_in_context(ctx, |c| c.uri == track.uri || c.uid == track.uid), }; debug!( @@ -116,7 +121,7 @@ impl ConnectState { ); for (i, track) in transfer.queue.tracks.iter().enumerate() { - if transfer.queue.is_playing_queue && i == 0 { + if transfer.queue.is_playing_queue.unwrap_or_default() && i == 0 { // if we are currently playing from the queue, // don't add the first queued item, because we are currently playing that item continue; diff --git a/core/src/dealer/protocol/request.rs b/core/src/dealer/protocol/request.rs index 67992437d..86c44cf16 100644 --- a/core/src/dealer/protocol/request.rs +++ b/core/src/dealer/protocol/request.rs @@ -1,6 +1,11 @@ -use crate::deserialize_with::*; -use librespot_protocol::player::{ - Context, ContextPlayerOptionOverrides, PlayOrigin, ProvidedTrack, TransferState, +use crate::{ + deserialize_with::*, + protocol::{ + context::Context, + context_player_options::ContextPlayerOptionOverrides, + player::{PlayOrigin, ProvidedTrack}, + transfer_state::TransferState, + }, }; use serde::Deserialize; use serde_json::Value; diff --git a/core/src/spclient.rs b/core/src/spclient.rs index c818570ac..42213a574 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -10,12 +10,13 @@ use crate::{ config::SessionConfig, error::ErrorKind, protocol::{ - canvaz::EntityCanvazRequest, + autoplay_context_request::AutoplayContextRequest, clienttoken_http::{ ChallengeAnswer, ChallengeType, ClientTokenRequest, ClientTokenRequestType, ClientTokenResponse, ClientTokenResponseType, }, connect::PutStateRequest, + context::Context, extended_metadata::BatchedEntityRequest, }, token::Token, @@ -32,7 +33,6 @@ use hyper::{ HeaderMap, Method, Request, }; use hyper_util::client::legacy::ResponseFuture; -use librespot_protocol::{autoplay_context_request::AutoplayContextRequest, player::Context}; use protobuf::{Enum, Message, MessageFull}; use rand::RngCore; use sysinfo::System; @@ -716,13 +716,6 @@ impl SpClient { // TODO: Seen-in-the-wild but unimplemented endpoints // - /presence-view/v1/buddylist - // TODO: Find endpoint for newer canvas.proto and upgrade to that. - pub async fn get_canvases(&self, request: EntityCanvazRequest) -> SpClientResult { - let endpoint = "/canvaz-cache/v0/canvases"; - self.request_with_protobuf(&Method::POST, endpoint, None, &request) - .await - } - pub async fn get_extended_metadata(&self, request: BatchedEntityRequest) -> SpClientResult { let endpoint = "/extended-metadata/v0/extended-metadata"; self.request_with_protobuf(&Method::POST, endpoint, None, &request) diff --git a/core/src/version.rs b/core/src/version.rs index 4fce65ad1..0e48a47ad 100644 --- a/core/src/version.rs +++ b/core/src/version.rs @@ -17,19 +17,26 @@ pub const SEMVER: &str = env!("CARGO_PKG_VERSION"); pub const BUILD_ID: &str = env!("LIBRESPOT_BUILD_ID"); /// The protocol version of the Spotify desktop client. -pub const SPOTIFY_VERSION: u64 = 117300517; +pub const SPOTIFY_VERSION: u64 = 124200290; /// The semantic version of the Spotify desktop client. -pub const SPOTIFY_SEMANTIC_VERSION: &str = "1.2.31.1205.g4d59ad7c"; +pub const SPOTIFY_SEMANTIC_VERSION: &str = "1.2.52.442"; + +/// `property_set_id` related to desktop version 1.2.52.442 +pub const SPOTIFY_PROPERTY_SET_ID: &str = "b4c7e4b5835079ed94391b2e65fca0fdba65eb50"; /// The protocol version of the Spotify mobile app. -pub const SPOTIFY_MOBILE_VERSION: &str = "8.6.84"; +pub const SPOTIFY_MOBILE_VERSION: &str = "8.9.82.620"; + +/// `property_set_id` related to mobile version 8.9.82.620 +pub const SPOTIFY_MOBILE_PROPERTY_SET_ID: &str = + "5ec87c2cc32e7c509703582cfaaa3c7ad253129d5701127c1f5eab5c9531736c"; /// The general spirc version pub const SPOTIFY_SPIRC_VERSION: &str = "3.2.6"; /// The user agent to fall back to, if one could not be determined dynamically. -pub const FALLBACK_USER_AGENT: &str = "Spotify/117300517 Linux/0 (librespot)"; +pub const FALLBACK_USER_AGENT: &str = "Spotify/124200290 Linux/0 (librespot)"; pub fn spotify_version() -> String { match crate::config::OS { diff --git a/metadata/src/album.rs b/metadata/src/album.rs index ede9cc5b4..6663b9c34 100644 --- a/metadata/src/album.rs +++ b/metadata/src/album.rs @@ -32,7 +32,6 @@ pub struct Album { pub label: String, pub date: Date, pub popularity: i32, - pub genres: Vec, pub covers: Images, pub external_ids: ExternalIds, pub discs: Discs, @@ -95,7 +94,6 @@ impl TryFrom<&::Message> for Album { label: album.label().to_owned(), date: album.date.get_or_default().try_into()?, popularity: album.popularity(), - genres: album.genre.to_vec(), covers: album.cover_group.get_or_default().into(), external_ids: album.external_id.as_slice().into(), discs: album.disc.as_slice().try_into()?, diff --git a/metadata/src/artist.rs b/metadata/src/artist.rs index 927846a39..6a3a63fcb 100644 --- a/metadata/src/artist.rs +++ b/metadata/src/artist.rs @@ -37,7 +37,6 @@ pub struct Artist { pub singles: AlbumGroups, pub compilations: AlbumGroups, pub appears_on_albums: AlbumGroups, - pub genre: Vec, pub external_ids: ExternalIds, pub portraits: Images, pub biographies: Biographies, @@ -193,7 +192,6 @@ impl TryFrom<&::Message> for Artist { singles: artist.single_group.as_slice().try_into()?, compilations: artist.compilation_group.as_slice().try_into()?, appears_on_albums: artist.appears_on_group.as_slice().try_into()?, - genre: artist.genre.to_vec(), external_ids: artist.external_id.as_slice().into(), portraits: artist.portrait.as_slice().into(), biographies: artist.biography.as_slice().into(), diff --git a/playback/src/player.rs b/playback/src/player.rs index 6a4170f00..e9663a706 100644 --- a/playback/src/player.rs +++ b/playback/src/player.rs @@ -907,27 +907,24 @@ impl PlayerTrackLoader { fn stream_data_rate(&self, format: AudioFileFormat) -> Option { let kbps = match format { - AudioFileFormat::OGG_VORBIS_96 => 12, - AudioFileFormat::OGG_VORBIS_160 => 20, - AudioFileFormat::OGG_VORBIS_320 => 40, - AudioFileFormat::MP3_256 => 32, - AudioFileFormat::MP3_320 => 40, - AudioFileFormat::MP3_160 => 20, - AudioFileFormat::MP3_96 => 12, - AudioFileFormat::MP3_160_ENC => 20, - AudioFileFormat::AAC_24 => 3, - AudioFileFormat::AAC_48 => 6, - AudioFileFormat::AAC_160 => 20, - AudioFileFormat::AAC_320 => 40, - AudioFileFormat::MP4_128 => 16, - AudioFileFormat::OTHER5 => 40, - AudioFileFormat::FLAC_FLAC => 112, // assume 900 kbit/s on average - AudioFileFormat::UNKNOWN_FORMAT => { - error!("Unknown stream data rate"); - return None; - } + AudioFileFormat::OGG_VORBIS_96 => 12., + AudioFileFormat::OGG_VORBIS_160 => 20., + AudioFileFormat::OGG_VORBIS_320 => 40., + AudioFileFormat::MP3_256 => 32., + AudioFileFormat::MP3_320 => 40., + AudioFileFormat::MP3_160 => 20., + AudioFileFormat::MP3_96 => 12., + AudioFileFormat::MP3_160_ENC => 20., + AudioFileFormat::AAC_24 => 3., + AudioFileFormat::AAC_48 => 6., + AudioFileFormat::FLAC_FLAC => 112., // assume 900 kbit/s on average + AudioFileFormat::XHE_AAC_12 => 1.5, + AudioFileFormat::XHE_AAC_16 => 2., + AudioFileFormat::XHE_AAC_24 => 3., + AudioFileFormat::FLAC_FLAC_24BIT => 3., }; - Some(kbps * 1024) + let data_rate: f32 = kbps * 1024.; + Some(data_rate.ceil() as usize) } async fn load_track( diff --git a/protocol/build.rs b/protocol/build.rs index 43971bc84..a20ea22d2 100644 --- a/protocol/build.rs +++ b/protocol/build.rs @@ -17,6 +17,7 @@ fn compile() { let files = &[ proto_dir.join("connect.proto"), + proto_dir.join("media.proto"), proto_dir.join("connectivity.proto"), proto_dir.join("devices.proto"), proto_dir.join("entity_extension_data.proto"), @@ -27,6 +28,8 @@ fn compile() { proto_dir.join("playlist_annotate3.proto"), proto_dir.join("playlist_permission.proto"), proto_dir.join("playlist4_external.proto"), + proto_dir.join("lens-model.proto"), + proto_dir.join("signal-model.proto"), proto_dir.join("spotify/clienttoken/v0/clienttoken_http.proto"), proto_dir.join("spotify/login5/v3/challenges/code.proto"), proto_dir.join("spotify/login5/v3/challenges/hashcash.proto"), @@ -39,6 +42,19 @@ fn compile() { proto_dir.join("user_attributes.proto"), proto_dir.join("autoplay_context_request.proto"), proto_dir.join("social_connect_v2.proto"), + proto_dir.join("transfer_state.proto"), + proto_dir.join("context_player_options.proto"), + proto_dir.join("playback.proto"), + proto_dir.join("play_history.proto"), + proto_dir.join("session.proto"), + proto_dir.join("queue.proto"), + proto_dir.join("context_track.proto"), + proto_dir.join("context.proto"), + proto_dir.join("restrictions.proto"), + proto_dir.join("context_page.proto"), + proto_dir.join("play_origin.proto"), + proto_dir.join("suppressions.proto"), + proto_dir.join("instrumentation_params.proto"), // TODO: remove these legacy protobufs when we are on the new API completely proto_dir.join("authentication.proto"), proto_dir.join("canvaz.proto"), diff --git a/protocol/proto/apiv1.proto b/protocol/proto/apiv1.proto index 2d8b9c285..e8a10b4e0 100644 --- a/protocol/proto/apiv1.proto +++ b/protocol/proto/apiv1.proto @@ -1,4 +1,4 @@ -// No longer present in Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -19,7 +19,7 @@ message ListDevicesResponse { message PutDeviceRequest { string user_id = 1; - + Body body = 2; message Body { Device device = 1; @@ -39,8 +39,27 @@ message RemoveDeviceRequest { bool is_force_remove = 2; } +message OfflineEnableDeviceRequest { + message Body { + bool auto_opc = 1; + } + + DeviceKey key = 1; + Body body = 2; + string name = 9; + int32 platform = 7; + string client_id = 8; +} + message OfflineEnableDeviceResponse { + enum StatusCode { + UNKNOWN = 0; + OK = 1; + DEVICE_LIMIT_REACHED = 2; + } + Restrictions restrictions = 1; + StatusCode status_code = 2; } message ListResourcesResponse { @@ -50,7 +69,7 @@ message ListResourcesResponse { message WriteResourcesRequest { DeviceKey key = 1; - + Body body = 2; message Body { repeated ResourceOperation operations = 1; @@ -66,7 +85,7 @@ message ResourcesUpdate { message DeltaResourcesRequest { DeviceKey key = 1; - + Body body = 2; message Body { google.protobuf.Timestamp last_known_server_time = 1; @@ -90,7 +109,7 @@ message GetResourceResponse { message WriteResourcesDetailsRequest { DeviceKey key = 1; - + Body body = 2; message Body { repeated Resource resources = 1; @@ -106,3 +125,39 @@ message GetResourceForDevicesResponse { repeated Device devices = 1; repeated ResourceForDevice resources = 2; } + +message ListDevicesWithResourceRequest { + message Body { + string uri = 1; + } + + string user_id = 1; + string username = 2; + Body body = 3; +} + +message ListDevicesWithResourceResponse { + message DeviceWithResource { + Device device = 1; + bool is_supported = 2; + optional Resource resource = 3; + } + + repeated DeviceWithResource deviceWithResource = 1; + FetchStrategy fetch_strategy = 2; +} + +message FetchStrategy { + oneof fetch_strategy { + PollStrategy poll_strategy = 1; + SubStrategy sub_strategy = 2; + } +} + +message PollStrategy { + int32 interval_ms = 1; +} + +message SubStrategy { +} + diff --git a/protocol/proto/audio_files_extension.proto b/protocol/proto/audio_files_extension.proto index 32efd9958..7c0a8b620 100644 --- a/protocol/proto/audio_files_extension.proto +++ b/protocol/proto/audio_files_extension.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -15,13 +15,15 @@ message NormalizationParams { } message ExtendedAudioFile { + reserved 2; + reserved 3; metadata.AudioFile file = 1; - NormalizationParams file_normalization_params = 2; - NormalizationParams album_normalization_params = 3; + int32 average_bitrate = 4; } message AudioFilesExtensionResponse { repeated ExtendedAudioFile files = 1; NormalizationParams default_file_normalization_params = 2; NormalizationParams default_album_normalization_params = 3; + bytes audio_id = 4; } diff --git a/protocol/proto/audio_format.proto b/protocol/proto/audio_format.proto new file mode 100644 index 000000000..1985c37b4 --- /dev/null +++ b/protocol/proto/audio_format.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; + +package spotify.stream_reporting_esperanto.proto; + +option java_package = "com.spotify.stream_reporting_esperanto.proto"; +option objc_class_prefix = "ESP"; + +enum AudioFormat { + FORMAT_UNKNOWN = 0; + FORMAT_OGG_VORBIS_96 = 1; + FORMAT_OGG_VORBIS_160 = 2; + FORMAT_OGG_VORBIS_320 = 3; + FORMAT_MP3_256 = 4; + FORMAT_MP3_320 = 5; + FORMAT_MP3_160 = 6; + FORMAT_MP3_96 = 7; + FORMAT_MP3_160_ENCRYPTED = 8; + FORMAT_AAC_24 = 9; + FORMAT_AAC_48 = 10; + FORMAT_MP4_128 = 11; + FORMAT_MP4_128_DUAL = 12; + FORMAT_MP4_128_CBCS = 13; + FORMAT_MP4_256 = 14; + FORMAT_MP4_256_DUAL = 15; + FORMAT_MP4_256_CBCS = 16; + FORMAT_FLAC_FLAC = 17; + FORMAT_MP4_FLAC = 18; + FORMAT_MP4_Unknown = 19; + FORMAT_MP3_Unknown = 20; + FORMAT_XHE_AAC_12 = 21; + FORMAT_XHE_AAC_16 = 22; + FORMAT_XHE_AAC_24 = 23; + FORMAT_FLAC_FLAC_24 = 24; +} + diff --git a/protocol/proto/autodownload_backend_service.proto b/protocol/proto/autodownload_backend_service.proto index fa088feb6..69ee6dfe9 100644 --- a/protocol/proto/autodownload_backend_service.proto +++ b/protocol/proto/autodownload_backend_service.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/automix_mode.proto b/protocol/proto/automix_mode.proto index d0d7f938a..50f730ca5 100644 --- a/protocol/proto/automix_mode.proto +++ b/protocol/proto/automix_mode.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -32,10 +32,14 @@ enum AutomixStyle { SLEEP = 5; MIXED = 6; CUSTOM = 7; + HEURISTIC = 8; + BACKEND = 9; } enum TransitionType { CUEPOINTS = 0; CROSSFADE = 1; GAPLESS = 2; + HEURISTIC_TRANSITION = 3; + BACKEND_TRANSITION = 4; } diff --git a/protocol/proto/autoplay_context_request.proto b/protocol/proto/autoplay_context_request.proto index 4fa4b0bc0..35b12b07a 100644 --- a/protocol/proto/autoplay_context_request.proto +++ b/protocol/proto/autoplay_context_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -9,4 +9,5 @@ option optimize_for = CODE_SIZE; message AutoplayContextRequest { required string context_uri = 1; repeated string recent_track_uri = 2; + optional bool is_video = 3; } diff --git a/protocol/proto/autoplay_node.proto b/protocol/proto/autoplay_node.proto index 18709f12d..9d8012a6a 100644 --- a/protocol/proto/autoplay_node.proto +++ b/protocol/proto/autoplay_node.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -12,4 +12,5 @@ message AutoplayNode { map filler_node = 1; required bool is_playing_filler = 2; required LoggingParams logging_params = 3; + optional bool called_play_on_filler = 4; } diff --git a/protocol/proto/canvaz.proto b/protocol/proto/canvaz.proto index 2493da958..936a53323 100644 --- a/protocol/proto/canvaz.proto +++ b/protocol/proto/canvaz.proto @@ -1,11 +1,9 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.canvaz.cache; -import "canvaz-meta.proto"; - option java_multiple_files = true; option optimize_for = CODE_SIZE; option java_package = "com.spotify.canvazcache.proto"; @@ -17,12 +15,11 @@ message Artist { } message EntityCanvazResponse { - repeated Canvaz canvases = 1; message Canvaz { string id = 1; string url = 2; string file_id = 3; - spotify.canvaz.Type type = 4; + Type type = 4; string entity_uri = 5; Artist artist = 6; bool explicit = 7; @@ -31,14 +28,14 @@ message EntityCanvazResponse { string canvas_uri = 11; string storylines_id = 12; } - - int64 ttl_in_seconds = 2; + } -message EntityCanvazRequest { - repeated Entity entities = 1; - message Entity { - string entity_uri = 1; - string etag = 2; - } +enum Type { + IMAGE = 0; + VIDEO = 1; + VIDEO_LOOPING = 2; + VIDEO_LOOPING_RANDOM = 3; + GIF = 4; } + diff --git a/protocol/proto/client-tts.proto b/protocol/proto/client-tts.proto index 0968f5158..fe40b025c 100644 --- a/protocol/proto/client-tts.proto +++ b/protocol/proto/client-tts.proto @@ -1,8 +1,8 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; -package spotify.narration_injection.proto; +package spotify.narration.proto; import "tts-resolve.proto"; @@ -18,7 +18,6 @@ message TtsRequest { ResolveRequest.TtsVoice tts_voice = 5; ResolveRequest.TtsProvider tts_provider = 6; int32 sample_rate_hz = 7; - oneof prompt { string text = 1; string ssml = 2; diff --git a/protocol/proto/client_config.proto b/protocol/proto/client_config.proto index b838873e0..177344624 100644 --- a/protocol/proto/client_config.proto +++ b/protocol/proto/client_config.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/client_update.proto b/protocol/proto/client_update.proto index fb93c9bd1..c7aa5ecb2 100644 --- a/protocol/proto/client_update.proto +++ b/protocol/proto/client_update.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/collection/album_collection_state.proto b/protocol/proto/collection/album_collection_state.proto index 1258961d4..c4cfbfed1 100644 --- a/protocol/proto/collection/album_collection_state.proto +++ b/protocol/proto/collection/album_collection_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/collection/artist_collection_state.proto b/protocol/proto/collection/artist_collection_state.proto index 33ade56a2..cdc001a71 100644 --- a/protocol/proto/collection/artist_collection_state.proto +++ b/protocol/proto/collection/artist_collection_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -15,4 +15,5 @@ message ArtistCollectionState { optional uint32 num_albums_in_collection = 4; optional bool is_banned = 5; optional bool can_ban = 6; + optional uint32 num_explicitly_liked_tracks = 7; } diff --git a/protocol/proto/collection/episode_collection_state.proto b/protocol/proto/collection/episode_collection_state.proto index 56fcc5330..c900c17dc 100644 --- a/protocol/proto/collection/episode_collection_state.proto +++ b/protocol/proto/collection/episode_collection_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/collection/show_collection_state.proto b/protocol/proto/collection/show_collection_state.proto index d3904b513..6b9e4101b 100644 --- a/protocol/proto/collection/show_collection_state.proto +++ b/protocol/proto/collection/show_collection_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/collection/track_collection_state.proto b/protocol/proto/collection/track_collection_state.proto index 68e42ed28..6782cb174 100644 --- a/protocol/proto/collection/track_collection_state.proto +++ b/protocol/proto/collection/track_collection_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/collection2v2.proto b/protocol/proto/collection2v2.proto index 19530fe8c..71d4b75c4 100644 --- a/protocol/proto/collection2v2.proto +++ b/protocol/proto/collection2v2.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -18,6 +18,7 @@ message CollectionItem { string uri = 1; int32 added_at = 2; bool is_removed = 3; + optional string context_uri = 4; } message PageResponse { @@ -45,13 +46,6 @@ message WriteRequest { string client_update_id = 4; } -message PubSubUpdate { - string username = 1; - string set = 2; - repeated CollectionItem items = 3; - string client_update_id = 4; -} - message InitializedRequest { string username = 1; string set = 2; diff --git a/protocol/proto/collection_add_remove_items_request.proto b/protocol/proto/collection_add_remove_items_request.proto index 4dac680ee..6be1eb2d2 100644 --- a/protocol/proto/collection_add_remove_items_request.proto +++ b/protocol/proto/collection_add_remove_items_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,12 +6,15 @@ package spotify.collection_cosmos.proto; import "status.proto"; +option java_package = "spotify.collection.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionAddRemoveItemsRequest { - repeated string item = 1; + repeated string uri = 1; } message CollectionAddRemoveItemsResponse { - Status status = 1; + Status status = 1; } diff --git a/protocol/proto/collection_ban_request.proto b/protocol/proto/collection_ban_request.proto index e64220dfc..78cb0c55d 100644 --- a/protocol/proto/collection_ban_request.proto +++ b/protocol/proto/collection_ban_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,6 +6,9 @@ package spotify.collection_cosmos.proto; import "status.proto"; +option java_package = "spotify.collection.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionBanRequest { diff --git a/protocol/proto/collection_decoration_policy.proto b/protocol/proto/collection_decoration_policy.proto index 79b4b8cf5..e673b86f8 100644 --- a/protocol/proto/collection_decoration_policy.proto +++ b/protocol/proto/collection_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,7 +7,12 @@ package spotify.collection_cosmos.proto; import "policy/artist_decoration_policy.proto"; import "policy/album_decoration_policy.proto"; import "policy/track_decoration_policy.proto"; +import "policy/show_decoration_policy.proto"; +import "policy/episode_decoration_policy.proto"; +option java_package = "spotify.collection.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionArtistDecorationPolicy { @@ -35,4 +40,22 @@ message CollectionTrackDecorationPolicy { CollectionAlbumDecorationPolicy album_policy = 5; cosmos_util.proto.ArtistDecorationPolicy artist_policy = 6; bool decorated = 7; + cosmos_util.proto.ArtistCollectionDecorationPolicy artist_collection_policy = 8; } + +message CollectionShowDecorationPolicy { + cosmos_util.proto.ShowDecorationPolicy show_policy = 1; + cosmos_util.proto.ShowPlayedStateDecorationPolicy played_state_policy = 2; + cosmos_util.proto.ShowCollectionDecorationPolicy collection_policy = 3; + bool decorated = 4; +} + +message CollectionEpisodeDecorationPolicy { + cosmos_util.proto.EpisodeDecorationPolicy episode_policy = 1; + cosmos_util.proto.EpisodeCollectionDecorationPolicy collection_policy = 2; + cosmos_util.proto.EpisodeSyncDecorationPolicy sync_policy = 3; + cosmos_util.proto.EpisodePlayedStateDecorationPolicy played_state_policy = 4; + CollectionShowDecorationPolicy show_policy = 5; + bool decorated = 6; +} + diff --git a/protocol/proto/collection_get_bans_request.proto b/protocol/proto/collection_get_bans_request.proto index a67574ae8..bb4c44f2d 100644 --- a/protocol/proto/collection_get_bans_request.proto +++ b/protocol/proto/collection_get_bans_request.proto @@ -1,21 +1,21 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.collection_cosmos.proto; -import "policy/track_decoration_policy.proto"; -import "policy/artist_decoration_policy.proto"; -import "metadata/track_metadata.proto"; -import "metadata/artist_metadata.proto"; +import "collection_decoration_policy.proto"; +import "collection_item.proto"; import "status.proto"; +option java_multiple_files = true; +option java_package = "spotify.collection.esperanto.proto"; option objc_class_prefix = "SPTCollectionCosmos"; option optimize_for = CODE_SIZE; message CollectionGetBansRequest { - cosmos_util.proto.TrackDecorationPolicy track_policy = 1; - cosmos_util.proto.ArtistDecorationPolicy artist_policy = 2; + CollectionTrackDecorationPolicy track_policy = 1; + CollectionArtistDecorationPolicy artist_policy = 2; string sort = 3; bool timestamp = 4; uint32 update_throttling = 5; @@ -23,8 +23,8 @@ message CollectionGetBansRequest { message Item { uint32 add_time = 1; - cosmos_util.proto.TrackMetadata track_metadata = 2; - cosmos_util.proto.ArtistMetadata artist_metadata = 3; + CollectionTrack track_metadata = 2; + CollectionArtist artist_metadata = 3; } message CollectionGetBansResponse { diff --git a/protocol/proto/collection_index.proto b/protocol/proto/collection_index.proto index ee6b3efc8..359e8eb3d 100644 --- a/protocol/proto/collection_index.proto +++ b/protocol/proto/collection_index.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,6 +11,10 @@ message IndexRepairerState { int64 last_full_check_finished_at = 2; } +message AddTime { + int64 timestamp = 1; +} + message CollectionTrackEntry { string uri = 1; string track_name = 2; @@ -23,16 +27,52 @@ message CollectionTrackEntry { int64 add_time = 9; } -message CollectionAlbumLikeEntry { +message CollectionAlbumEntry { string uri = 1; string album_name = 2; - string creator_uri = 4; + string artist_uri = 4; + string artist_name = 5; + int64 add_time = 6; + int64 last_played = 8; + int64 release_date = 9; +} + +message CollectionShowEntry { + string uri = 1; + string show_name = 2; string creator_name = 5; int64 add_time = 6; + int64 publish_date = 7; + int64 last_played = 8; +} + +message CollectionBookEntry { + string uri = 1; + string book_name = 2; + string author_name = 5; + int64 add_time = 6; + int64 last_played = 8; } message CollectionArtistEntry { string uri = 1; string artist_name = 2; int64 add_time = 4; + int64 last_played = 8; +} + +message CollectionAuthorEntry { + string uri = 1; + string author_name = 2; + int64 add_time = 4; } + +message CollectionEpisodeEntry { + string uri = 1; + string episode_name = 2; + string show_uri = 3; + string show_name = 4; + int64 add_time = 5; + int64 publish_time = 6; +} + diff --git a/protocol/proto/collection_item.proto b/protocol/proto/collection_item.proto index 4a98e9d03..514de22f7 100644 --- a/protocol/proto/collection_item.proto +++ b/protocol/proto/collection_item.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,14 +7,24 @@ package spotify.collection_cosmos.proto; import "metadata/album_metadata.proto"; import "metadata/artist_metadata.proto"; import "metadata/track_metadata.proto"; +import "metadata/show_metadata.proto"; +import "metadata/episode_metadata.proto"; import "collection/artist_collection_state.proto"; import "collection/album_collection_state.proto"; import "collection/track_collection_state.proto"; +import "collection/show_collection_state.proto"; +import "collection/episode_collection_state.proto"; import "sync/artist_sync_state.proto"; import "sync/album_sync_state.proto"; import "sync/track_sync_state.proto"; +import "sync/episode_sync_state.proto"; import "played_state/track_played_state.proto"; +import "played_state/show_played_state.proto"; +import "played_state/episode_played_state.proto"; +option java_package = "spotify.collection.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionTrack { @@ -27,6 +37,8 @@ message CollectionTrack { bool decorated = 7; CollectionAlbum album = 8; string cover = 9; + string link = 10; + repeated cosmos_util.proto.ArtistCollectionState artist_collection_state = 11; } message CollectionAlbum { @@ -37,6 +49,7 @@ message CollectionAlbum { bool decorated = 5; string album_type = 6; repeated CollectionTrack track = 7; + string link = 11; } message CollectionArtist { @@ -45,4 +58,23 @@ message CollectionArtist { cosmos_util.proto.ArtistSyncState artist_sync_state = 3; bool decorated = 4; repeated CollectionAlbum album = 5; + string link = 6; } + +message CollectionShow { + cosmos_util.proto.ShowMetadata show_metadata = 1; + cosmos_util.proto.ShowCollectionState show_collection_state = 2; + cosmos_util.proto.ShowPlayState show_play_state = 3; + uint32 add_time = 4; + string link = 5; +} + +message CollectionEpisode { + cosmos_util.proto.EpisodeMetadata episode_metadata = 1; + cosmos_util.proto.EpisodeCollectionState episode_collection_state = 2; + cosmos_util.proto.EpisodeSyncState episode_offline_state = 3; + cosmos_util.proto.EpisodePlayState episode_play_state = 4; + CollectionShow show = 5; + string link = 6; +} + diff --git a/protocol/proto/collection_platform_items.proto b/protocol/proto/collection_platform_items.proto new file mode 100644 index 000000000..fde06a053 --- /dev/null +++ b/protocol/proto/collection_platform_items.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package spotify.collection_platform.proto; + +option java_package = "com.spotify.collection_platform.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; + +message CollectionPlatformItem { + string uri = 1; + int64 add_time = 2; +} + +message CollectionPlatformContextItem { + string uri = 1; + int64 add_time = 2; + string context_uri = 3; +} + diff --git a/protocol/proto/collection_platform_requests.proto b/protocol/proto/collection_platform_requests.proto index a855c2173..01bbd24df 100644 --- a/protocol/proto/collection_platform_requests.proto +++ b/protocol/proto/collection_platform_requests.proto @@ -1,9 +1,14 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.collection_platform.proto; +import "collection_platform_items.proto"; + +option java_package = "com.spotify.collection_platform.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionPlatformItemsRequest { @@ -11,11 +16,21 @@ message CollectionPlatformItemsRequest { repeated string items = 2; } +message CollectionPlatformContextItemsRequest { + CollectionSet set = 1; + repeated CollectionPlatformContextItem items = 2; +} + enum CollectionSet { UNKNOWN = 0; - SHOW = 1; - BAN = 2; - LISTENLATER = 3; IGNOREINRECS = 4; ENHANCED = 5; + BANNED_ARTISTS = 8; + CONCERTS = 10; + TAGS = 11; + PRERELEASE = 12; + MARKED_AS_FINISHED = 13; + NOT_INTERESTED = 14; + LOCAL_BANS = 15; } + diff --git a/protocol/proto/collection_platform_responses.proto b/protocol/proto/collection_platform_responses.proto index 6b7716d85..98e2a0917 100644 --- a/protocol/proto/collection_platform_responses.proto +++ b/protocol/proto/collection_platform_responses.proto @@ -1,20 +1,20 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.collection_platform.proto; +import "collection_platform_items.proto"; + +option java_package = "com.spotify.collection_platform.esperanto.proto"; +option java_multiple_files = true; +option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; message CollectionPlatformSimpleResponse { string error_msg = 1; } -message CollectionPlatformItem { - string uri = 1; - int64 add_time = 2; -} - message CollectionPlatformItemsResponse { repeated CollectionPlatformItem items = 1; } @@ -22,3 +22,29 @@ message CollectionPlatformItemsResponse { message CollectionPlatformContainsResponse { repeated bool found = 1; } + +message Status { + int32 code = 1; + string reason = 2; +} + +message CollectionPlatformEsperantoContainsResponse { + Status status = 1; + CollectionPlatformContainsResponse contains = 2; +} + +message CollectionPlatformEsperantoItemsResponse { + Status status = 1; + repeated CollectionPlatformItem items = 2; +} + +message CollectionPlatformContextItemsResponse { + Status status = 1; + repeated CollectionPlatformContextItem items = 2; +} + +message CollectionPlatformContainsContextItemsResponse { + Status status = 1; + repeated bool found = 2; +} + diff --git a/protocol/proto/connect.proto b/protocol/proto/connect.proto index d6485252c..9e10c796b 100644 --- a/protocol/proto/connect.proto +++ b/protocol/proto/connect.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,9 +6,10 @@ package spotify.connectstate; import "player.proto"; import "devices.proto"; +import "media.proto"; -option optimize_for = CODE_SIZE; option java_package = "com.spotify.connectstate.model"; +option optimize_for = CODE_SIZE; message ClusterUpdate { Cluster cluster = 1; @@ -17,10 +18,6 @@ message ClusterUpdate { repeated string devices_that_changed = 4; } -message PostCommandResponse { - string ack_id = 1; -} - message Device { DeviceInfo device_info = 1; PlayerState player_state = 2; @@ -29,15 +26,18 @@ message Device { } message Cluster { + reserved 7; + int64 changed_timestamp_ms = 1; string active_device_id = 2; PlayerState player_state = 3; map device = 4; bytes transfer_data = 5; uint64 transfer_data_timestamp = 6; - int64 not_playing_since_timestamp = 7; bool need_full_player_state = 8; int64 server_timestamp_ms = 9; + optional bool needs_state_updates = 10; + optional uint64 started_playing_at_timestamp = 11; } message PutStateRequest { @@ -59,18 +59,15 @@ message PrivateDeviceInfo { string platform = 1; } -message SubscribeRequest { - string callback_url = 1; -} - message DeviceInfo { + reserved 5; + bool can_play = 1; uint32 volume = 2; string name = 3; Capabilities capabilities = 4; - repeated DeviceMetadata metadata = 5; string device_software_version = 6; - spotify.connectstate.devices.DeviceType device_type = 7; + devices.DeviceType device_type = 7; string spirc_version = 9; string device_id = 10; bool is_private_session = 11; @@ -82,7 +79,7 @@ message DeviceInfo { string product_id = 17; string deduplication_id = 18; uint32 selected_alias_id = 19; - map device_aliases = 20; + map device_aliases = 20; bool is_offline = 21; string public_ip = 22; string license = 23; @@ -90,29 +87,20 @@ message DeviceInfo { bool is_dynamic_device = 26; repeated string disallow_playback_reasons = 27; repeated string disallow_transfer_reasons = 28; - - oneof _audio_output_device_info { - AudioOutputDeviceInfo audio_output_device_info = 24; - } + optional AudioOutputDeviceInfo audio_output_device_info = 24; } message AudioOutputDeviceInfo { - oneof _audio_output_device_type { - AudioOutputDeviceType audio_output_device_type = 1; - } - - oneof _device_name { - string device_name = 2; - } -} - -message DeviceMetadata { - option deprecated = true; - string type = 1; - string metadata = 2; + optional AudioOutputDeviceType audio_output_device_type = 1; + optional string device_name = 2; } message Capabilities { + reserved "supported_contexts"; + reserved "supports_lossless_audio"; + reserved 1; + reserved 4; + reserved 24; bool can_be_player = 2; bool restrict_to_local = 3; bool gaia_eq_connect_id = 5; @@ -137,8 +125,9 @@ message Capabilities { bool supports_set_options_command = 25; CapabilitySupportDetails supports_hifi = 26; string connect_capabilities = 27; - - //reserved 1, 4, 24, "supported_contexts", "supports_lossless_audio"; + bool supports_rooms = 28; + bool supports_dj = 29; + common.media.AudioQuality supported_audio_quality = 30; } message CapabilitySupportDetails { @@ -152,6 +141,11 @@ message ConnectCommandOptions { uint32 target_alias_id = 3; } +message ConnectLoggingParams { + repeated string interaction_ids = 1; + repeated string page_instance_ids = 2; +} + message LogoutCommand { ConnectCommandOptions command_options = 1; } @@ -159,6 +153,8 @@ message LogoutCommand { message SetVolumeCommand { int32 volume = 1; ConnectCommandOptions command_options = 2; + ConnectLoggingParams logging_params = 3; + string connection_type = 4; } message RenameCommand { @@ -166,35 +162,18 @@ message RenameCommand { ConnectCommandOptions command_options = 2; } -message ConnectPlayerCommand { - string player_command_json = 1; - ConnectCommandOptions command_options = 2; -} - message SetBackendMetadataCommand { map metadata = 1; } -message CommandAndSourceDevice { - string command = 1; - DeviceInfo source_device_info = 2; -} - -message ActiveDeviceUpdate { - string device_id = 1; -} - -message StartedPlayingEvent { - bytes user_info_header = 1; - string device_id = 2; -} - enum AudioOutputDeviceType { UNKNOWN_AUDIO_OUTPUT_DEVICE_TYPE = 0; BUILT_IN_SPEAKER = 1; LINE_OUT = 2; BLUETOOTH = 3; AIRPLAY = 4; + AUTOMOTIVE = 5; + CAR_PROJECTED = 6; } enum PutStateReason { @@ -207,6 +186,11 @@ enum PutStateReason { PICKER_OPENED = 6; BECAME_INACTIVE = 7; ALIAS_CHANGED = 8; + NEW_CONNECTION = 9; + PULL_PLAYBACK = 10; + AUDIO_DRIVER_INFO_CHANGED = 11; + PUT_STATE_RATE_LIMITED = 12; + BACKEND_METADATA_APPLIED = 13; } enum MemberType { @@ -225,15 +209,6 @@ enum ClusterUpdateReason { NEW_DEVICE_APPEARED = 3; DEVICE_VOLUME_CHANGED = 4; DEVICE_ALIAS_CHANGED = 5; + DEVICE_NEW_CONNECTION = 6; } -enum SendCommandResult { - UNKNOWN_SEND_COMMAND_RESULT = 0; - SUCCESS = 1; - DEVICE_NOT_FOUND = 2; - CONTEXT_PLAYER_ERROR = 3; - DEVICE_DISAPPEARED = 4; - UPSTREAM_ERROR = 5; - DEVICE_DOES_NOT_SUPPORT_COMMAND = 6; - RATE_LIMITED = 7; -} diff --git a/protocol/proto/contains_request.proto b/protocol/proto/contains_request.proto index cf59c5f5a..52cc73827 100644 --- a/protocol/proto/contains_request.proto +++ b/protocol/proto/contains_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context.proto b/protocol/proto/context.proto index eb0224156..bc1d4722c 100644 --- a/protocol/proto/context.proto +++ b/protocol/proto/context.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_application_desktop.proto b/protocol/proto/context_application_desktop.proto index 04f443b26..a754673c1 100644 --- a/protocol/proto/context_application_desktop.proto +++ b/protocol/proto/context_application_desktop.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,4 +9,5 @@ option optimize_for = CODE_SIZE; message ApplicationDesktop { string version_string = 1; int64 version_code = 2; + bytes session_id = 3; } diff --git a/protocol/proto/context_client_id.proto b/protocol/proto/context_client_id.proto index bab3b6b8d..7e1165322 100644 --- a/protocol/proto/context_client_id.proto +++ b/protocol/proto/context_client_id.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_device_desktop.proto b/protocol/proto/context_device_desktop.proto index a6b38372d..8ff3b874a 100644 --- a/protocol/proto/context_device_desktop.proto +++ b/protocol/proto/context_device_desktop.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_index.proto b/protocol/proto/context_index.proto index c7049eacc..40edd57d9 100644 --- a/protocol/proto/context_index.proto +++ b/protocol/proto/context_index.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_installation_id.proto b/protocol/proto/context_installation_id.proto index 08fe25805..b690db118 100644 --- a/protocol/proto/context_installation_id.proto +++ b/protocol/proto/context_installation_id.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_monotonic_clock.proto b/protocol/proto/context_monotonic_clock.proto index 3ec525ff6..c2e807af2 100644 --- a/protocol/proto/context_monotonic_clock.proto +++ b/protocol/proto/context_monotonic_clock.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_node.proto b/protocol/proto/context_node.proto index 82dd9d62b..398db4279 100644 --- a/protocol/proto/context_node.proto +++ b/protocol/proto/context_node.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -9,6 +9,7 @@ import "play_origin.proto"; import "prepare_play_options.proto"; import "track_instance.proto"; import "track_instantiator.proto"; +import "context_track.proto"; option optimize_for = CODE_SIZE; @@ -21,4 +22,5 @@ message ContextNode { optional string session_id = 7; optional sint32 iteration = 8; optional bool pending_pause = 9; + optional ContextTrack injected_connect_transfer_track = 10; } diff --git a/protocol/proto/context_page.proto b/protocol/proto/context_page.proto index b6e8ecdca..c3c7f9a46 100644 --- a/protocol/proto/context_page.proto +++ b/protocol/proto/context_page.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_player_options.proto b/protocol/proto/context_player_options.proto index 57e069b5f..1dca43600 100644 --- a/protocol/proto/context_player_options.proto +++ b/protocol/proto/context_player_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -10,10 +10,15 @@ message ContextPlayerOptions { optional bool shuffling_context = 1; optional bool repeating_context = 2; optional bool repeating_track = 3; + optional float playback_speed = 4; + map modes = 5; } message ContextPlayerOptionOverrides { optional bool shuffling_context = 1; optional bool repeating_context = 2; optional bool repeating_track = 3; + optional float playback_speed = 4; + map modes = 5; } + diff --git a/protocol/proto/context_processor.proto b/protocol/proto/context_processor.proto index 2d931b0bd..fbfa1c30e 100644 --- a/protocol/proto/context_processor.proto +++ b/protocol/proto/context_processor.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_sdk.proto b/protocol/proto/context_sdk.proto index 419f7aa56..fa3b0f71a 100644 --- a/protocol/proto/context_sdk.proto +++ b/protocol/proto/context_sdk.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_time.proto b/protocol/proto/context_time.proto index 93749b417..009cad103 100644 --- a/protocol/proto/context_time.proto +++ b/protocol/proto/context_time.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/context_track.proto b/protocol/proto/context_track.proto index e9d06f219..12fe06f54 100644 --- a/protocol/proto/context_track.proto +++ b/protocol/proto/context_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_view.proto b/protocol/proto/context_view.proto index 0b78991a5..63efd0043 100644 --- a/protocol/proto/context_view.proto +++ b/protocol/proto/context_view.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -13,6 +13,5 @@ message ContextView { map patch_map = 1; optional uint32 iteration_size = 2; optional cyclic_list.proto.CyclicEntryKeyList cyclic_list = 3; - - reserved 4; } + diff --git a/protocol/proto/context_view_cyclic_list.proto b/protocol/proto/context_view_cyclic_list.proto index 76cde3ed1..56ace3e21 100644 --- a/protocol/proto/context_view_cyclic_list.proto +++ b/protocol/proto/context_view_cyclic_list.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/context_view_entry.proto b/protocol/proto/context_view_entry.proto index 8451f4818..23c9ce2e1 100644 --- a/protocol/proto/context_view_entry.proto +++ b/protocol/proto/context_view_entry.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -10,14 +10,14 @@ import "context_track.proto"; option optimize_for = CODE_SIZE; message Entry { - optional Type type = 1; enum Type { TRACK = 0; DELIMITER = 1; PAGE_PLACEHOLDER = 2; CONTEXT_PLACEHOLDER = 3; } - + + optional Type type = 1; optional player.proto.ContextTrack track = 2; optional player.proto.ContextIndex index = 3; optional int32 page_index = 4; diff --git a/protocol/proto/context_view_entry_key.proto b/protocol/proto/context_view_entry_key.proto index 6c8a019ff..7cb7a1e6f 100644 --- a/protocol/proto/context_view_entry_key.proto +++ b/protocol/proto/context_view_entry_key.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/cosmos_changes_request.proto b/protocol/proto/cosmos_changes_request.proto index 2e4b70407..81c818944 100644 --- a/protocol/proto/cosmos_changes_request.proto +++ b/protocol/proto/cosmos_changes_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -8,5 +8,4 @@ option objc_class_prefix = "SPTCollectionCosmosChanges"; option optimize_for = CODE_SIZE; message Response { - } diff --git a/protocol/proto/cosmos_decorate_request.proto b/protocol/proto/cosmos_decorate_request.proto index 9e5860218..c20c561a5 100644 --- a/protocol/proto/cosmos_decorate_request.proto +++ b/protocol/proto/cosmos_decorate_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/cosmos_get_album_list_request.proto b/protocol/proto/cosmos_get_album_list_request.proto index 448dcd46e..83f2ad92e 100644 --- a/protocol/proto/cosmos_get_album_list_request.proto +++ b/protocol/proto/cosmos_get_album_list_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -34,5 +34,4 @@ message Response { optional bool loading_contents = 4; optional string offline = 5; optional uint32 sync_progress = 6; - repeated GroupHeader group_index = 7; } diff --git a/protocol/proto/cosmos_get_episode_list_request.proto b/protocol/proto/cosmos_get_episode_list_request.proto index 437a621fd..72bd7c424 100644 --- a/protocol/proto/cosmos_get_episode_list_request.proto +++ b/protocol/proto/cosmos_get_episode_list_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/cosmos_get_tags_info_request.proto b/protocol/proto/cosmos_get_tags_info_request.proto index 5480c7bcc..d1a349560 100644 --- a/protocol/proto/cosmos_get_tags_info_request.proto +++ b/protocol/proto/cosmos_get_tags_info_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,6 +7,9 @@ package spotify.collection_cosmos.tags_info_request.proto; option objc_class_prefix = "SPTCollectionCosmosTagsInfo"; option optimize_for = CODE_SIZE; +message Request { +} + message Response { bool is_synced = 1; } diff --git a/protocol/proto/cosmos_get_track_list_metadata_request.proto b/protocol/proto/cosmos_get_track_list_metadata_request.proto index a4586249a..2399656ca 100644 --- a/protocol/proto/cosmos_get_track_list_metadata_request.proto +++ b/protocol/proto/cosmos_get_track_list_metadata_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/cosmos_get_track_list_request.proto b/protocol/proto/cosmos_get_track_list_request.proto index 95c834108..21eea1b11 100644 --- a/protocol/proto/cosmos_get_track_list_request.proto +++ b/protocol/proto/cosmos_get_track_list_request.proto @@ -1,9 +1,10 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.collection_cosmos.track_list_request.proto; +import "collection/artist_collection_state.proto"; import "collection/track_collection_state.proto"; import "played_state/track_played_state.proto"; import "sync/track_sync_state.proto"; @@ -21,6 +22,7 @@ message Item { optional cosmos_util.proto.TrackPlayState track_play_state = 6; optional cosmos_util.proto.TrackCollectionState track_collection_state = 7; optional string group_label = 8; + repeated cosmos_util.proto.ArtistCollectionState artist_collection_state = 9; } message GroupHeader { @@ -36,5 +38,4 @@ message Response { optional bool loading_contents = 4; optional string offline = 5; optional uint32 sync_progress = 6; - repeated GroupHeader group_index = 7; } diff --git a/protocol/proto/cosmos_get_unplayed_episodes_request.proto b/protocol/proto/cosmos_get_unplayed_episodes_request.proto index 09339c78d..691761b3c 100644 --- a/protocol/proto/cosmos_get_unplayed_episodes_request.proto +++ b/protocol/proto/cosmos_get_unplayed_episodes_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/cuepoints.proto b/protocol/proto/cuepoints.proto index 16bfd6a97..77a01a670 100644 --- a/protocol/proto/cuepoints.proto +++ b/protocol/proto/cuepoints.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/decorate_request.proto b/protocol/proto/decorate_request.proto index ff1fa0edf..4d56f65be 100644 --- a/protocol/proto/decorate_request.proto +++ b/protocol/proto/decorate_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -7,45 +7,38 @@ package spotify.show_cosmos.decorate_request.proto; import "metadata/episode_metadata.proto"; import "metadata/show_metadata.proto"; import "played_state/episode_played_state.proto"; -import "show_access.proto"; +import "played_state/show_played_state.proto"; import "show_episode_state.proto"; import "show_show_state.proto"; -import "podcast_segments.proto"; -import "podcast_virality.proto"; -import "podcastextensions.proto"; -import "podcast_poll.proto"; -import "podcast_qna.proto"; -import "podcast_ratings.proto"; -import "transcripts.proto"; -import "clips_cover.proto"; +import "show_offline_state.proto"; option objc_class_prefix = "SPTShowCosmosDecorate"; option optimize_for = CODE_SIZE; message Show { + reserved 5; + reserved 6; optional cosmos_util.proto.ShowMetadata show_metadata = 1; optional show_cosmos.proto.ShowCollectionState show_collection_state = 2; - optional show_cosmos.proto.ShowPlayState show_play_state = 3; + optional cosmos_util.proto.ShowPlayState show_play_state = 3; optional string link = 4; - optional podcast_paywalls.ShowAccess access_info = 5; - optional ratings.PodcastRating podcast_rating = 6; + optional show_cosmos.proto.ShowOfflineState show_offline_state = 7; } message Episode { + reserved 6; + reserved 7; + reserved 8; + reserved 9; + reserved 10; + reserved 11; + reserved 12; + reserved 13; optional cosmos_util.proto.EpisodeMetadata episode_metadata = 1; optional show_cosmos.proto.EpisodeCollectionState episode_collection_state = 2; optional show_cosmos.proto.EpisodeOfflineState episode_offline_state = 3; optional cosmos_util.proto.EpisodePlayState episode_play_state = 4; optional string link = 5; - optional podcast_segments.PodcastSegments segments = 6; - optional podcast.extensions.PodcastHtmlDescription html_description = 7; - optional corex.transcripts.metadata.EpisodeTranscript transcripts = 9; - optional podcastvirality.v1.PodcastVirality virality = 10; - optional polls.PodcastPoll podcast_poll = 11; - optional qanda.PodcastQna podcast_qna = 12; - optional clips.ClipsCover clips = 13; - - reserved 8; } message Response { diff --git a/protocol/proto/devices.proto b/protocol/proto/devices.proto index ebfadc1bc..00deaa4d2 100644 --- a/protocol/proto/devices.proto +++ b/protocol/proto/devices.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/display_segments_extension.proto b/protocol/proto/display_segments_extension.proto index 047144461..55914bd7e 100644 --- a/protocol/proto/display_segments_extension.proto +++ b/protocol/proto/display_segments_extension.proto @@ -1,9 +1,10 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.displaysegments.v1; +option objc_class_prefix = "ESP"; option java_multiple_files = true; option optimize_for = CODE_SIZE; option java_outer_classname = "DisplaySegmentsExtensionProto"; @@ -13,9 +14,9 @@ message DisplaySegmentsExtension { string episode_uri = 1; repeated DisplaySegment segments = 2; int32 duration_ms = 3; - oneof decoration { MusicAndTalkDecoration music_and_talk_decoration = 4; + PodcastChaptersDecoration podcast_chapters_decoration = 5; } } @@ -25,28 +26,20 @@ message DisplaySegment { int32 duration_ms = 3; int32 seek_start_ms = 4; int32 seek_stop_ms = 5; - - oneof _title { - string title = 6; - } - - oneof _subtitle { - string subtitle = 7; - } - - oneof _image_url { - string image_url = 8; - } - - oneof _is_preview { - bool is_preview = 9; - } + optional string title = 6; + optional string subtitle = 7; + optional string image_url = 8; + optional bool is_preview = 9; } message MusicAndTalkDecoration { bool can_upsell = 1; } +message PodcastChaptersDecoration { + repeated string tags = 1; +} + enum SegmentType { SEGMENT_TYPE_UNSPECIFIED = 0; SEGMENT_TYPE_TALK = 1; diff --git a/protocol/proto/entity_extension_data.proto b/protocol/proto/entity_extension_data.proto index e26d735e4..589ee687e 100644 --- a/protocol/proto/entity_extension_data.proto +++ b/protocol/proto/entity_extension_data.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -30,7 +30,6 @@ message PlainListAssoc { } message AssocHeader { - } message Assoc { diff --git a/protocol/proto/es_add_to_queue_request.proto b/protocol/proto/es_add_to_queue_request.proto index 349977310..dd0e009b9 100644 --- a/protocol/proto/es_add_to_queue_request.proto +++ b/protocol/proto/es_add_to_queue_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_command_options.proto b/protocol/proto/es_command_options.proto index 0a37e8017..8f6c5bc14 100644 --- a/protocol/proto/es_command_options.proto +++ b/protocol/proto/es_command_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_context.proto b/protocol/proto/es_context.proto index 05962fa78..19e1f8857 100644 --- a/protocol/proto/es_context.proto +++ b/protocol/proto/es_context.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -16,6 +16,6 @@ message Context { map metadata = 2; string uri = 3; string url = 4; - bool is_loaded = 5; + bool is_loading = 5; Restrictions restrictions = 6; } diff --git a/protocol/proto/es_context_page.proto b/protocol/proto/es_context_page.proto index f4cc69302..28776cfd2 100644 --- a/protocol/proto/es_context_page.proto +++ b/protocol/proto/es_context_page.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -15,5 +15,5 @@ message ContextPage { map metadata = 2; string page_url = 3; string next_page_url = 4; - bool is_loaded = 5; + bool is_loading = 5; } diff --git a/protocol/proto/es_context_player_error.proto b/protocol/proto/es_context_player_error.proto index f332fe8a2..bd6ded162 100644 --- a/protocol/proto/es_context_player_error.proto +++ b/protocol/proto/es_context_player_error.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,7 +9,6 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message ContextPlayerError { - ErrorCode code = 1; enum ErrorCode { SUCCESS = 0; PLAYBACK_STUCK = 1; @@ -48,8 +47,15 @@ message ContextPlayerError { TIMEOUT = 34; PLAYBACK_REPORTING_ERROR = 35; UNKNOWN = 36; + ADD_TO_QUEUE_RESTRICTED = 37; + PICK_AND_SHUFFLE_CAPPED = 38; + PICK_AND_SHUFFLE_CONNECT_RESTRICTED = 39; + CONTEXT_LOADING_FAILED = 40; + AUDIOBOOK_NOT_PLAYABLE = 41; + SIGNAL_NOT_AVAILABLE = 42; } - + + ErrorCode code = 1; string message = 2; map data = 3; } diff --git a/protocol/proto/es_context_player_options.proto b/protocol/proto/es_context_player_options.proto index 372b53c08..337f85969 100644 --- a/protocol/proto/es_context_player_options.proto +++ b/protocol/proto/es_context_player_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -14,10 +14,14 @@ message ContextPlayerOptions { bool shuffling_context = 1; bool repeating_context = 2; bool repeating_track = 3; + map modes = 5; + optional float playback_speed = 4; } message ContextPlayerOptionOverrides { OptionalBoolean shuffling_context = 1; OptionalBoolean repeating_context = 2; OptionalBoolean repeating_track = 3; + map modes = 5; + optional float playback_speed = 4; } diff --git a/protocol/proto/es_context_player_state.proto b/protocol/proto/es_context_player_state.proto index f16265726..c0023411b 100644 --- a/protocol/proto/es_context_player_state.proto +++ b/protocol/proto/es_context_player_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -21,7 +21,6 @@ message ContextIndex { } message PlaybackQuality { - BitrateLevel bitrate_level = 1; enum BitrateLevel { UNKNOWN = 0; LOW = 1; @@ -29,9 +28,9 @@ message PlaybackQuality { HIGH = 3; VERY_HIGH = 4; HIFI = 5; + HIFI24 = 6; } - - BitrateStrategy strategy = 2; + enum BitrateStrategy { UNKNOWN_STRATEGY = 0; BEST_MATCHING = 1; @@ -40,16 +39,18 @@ message PlaybackQuality { CACHED_FILE = 4; LOCAL_FILE = 5; } - - BitrateLevel target_bitrate_level = 3; - bool target_bitrate_available = 4; - - HiFiStatus hifi_status = 5; + enum HiFiStatus { NONE = 0; OFF = 1; ON = 2; } + + BitrateLevel bitrate_level = 1; + BitrateStrategy strategy = 2; + BitrateLevel target_bitrate_level = 3; + bool target_bitrate_available = 4; + HiFiStatus hifi_status = 5; } message ContextPlayerState { @@ -79,4 +80,6 @@ message ContextPlayerState { string session_id = 24; uint64 queue_revision = 25; PreparePlayOptions.AudioStream audio_stream = 26; + repeated string signals = 27; + string session_command_id = 28; } diff --git a/protocol/proto/es_context_track.proto b/protocol/proto/es_context_track.proto index cdcbd7c26..c80e29ac4 100644 --- a/protocol/proto/es_context_track.proto +++ b/protocol/proto/es_context_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_delete_session.proto b/protocol/proto/es_delete_session.proto index e45893c4c..140f62a4f 100644 --- a/protocol/proto/es_delete_session.proto +++ b/protocol/proto/es_delete_session.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,5 +13,4 @@ message DeleteSessionRequest { } message DeleteSessionResponse { - } diff --git a/protocol/proto/es_get_error_request.proto b/protocol/proto/es_get_error_request.proto index 3119beaad..f62feff81 100644 --- a/protocol/proto/es_get_error_request.proto +++ b/protocol/proto/es_get_error_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,5 +9,4 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message GetErrorRequest { - } diff --git a/protocol/proto/es_get_play_history.proto b/protocol/proto/es_get_play_history.proto index 08bb053cc..e887b3c48 100644 --- a/protocol/proto/es_get_play_history.proto +++ b/protocol/proto/es_get_play_history.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,7 +11,6 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message GetPlayHistoryRequest { - } message GetPlayHistoryResponse { diff --git a/protocol/proto/es_get_position_state.proto b/protocol/proto/es_get_position_state.proto index 6147f0c58..4018d996a 100644 --- a/protocol/proto/es_get_position_state.proto +++ b/protocol/proto/es_get_position_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,16 +9,15 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message GetPositionStateRequest { - } message GetPositionStateResponse { - Error error = 1; enum Error { OK = 0; NOT_FOUND = 1; } - + + Error error = 1; uint64 timestamp = 2; uint64 position = 3; double playback_speed = 4; diff --git a/protocol/proto/es_get_queue_request.proto b/protocol/proto/es_get_queue_request.proto index 68b6830a7..65a2a24a2 100644 --- a/protocol/proto/es_get_queue_request.proto +++ b/protocol/proto/es_get_queue_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,5 +9,4 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message GetQueueRequest { - } diff --git a/protocol/proto/es_get_state_request.proto b/protocol/proto/es_get_state_request.proto index d8cd5335a..b4d29dce5 100644 --- a/protocol/proto/es_get_state_request.proto +++ b/protocol/proto/es_get_state_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_optional.proto b/protocol/proto/es_optional.proto index 2ca0b01f3..2f75c54c6 100644 --- a/protocol/proto/es_optional.proto +++ b/protocol/proto/es_optional.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_pause.proto b/protocol/proto/es_pause.proto index 56378fb5f..7e8c4955c 100644 --- a/protocol/proto/es_pause.proto +++ b/protocol/proto/es_pause.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,6 +6,7 @@ package spotify.player.esperanto.proto; import "es_command_options.proto"; import "es_logging_params.proto"; +import "es_pauseresume_origin.proto"; option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; @@ -14,4 +15,5 @@ option java_package = "com.spotify.player.esperanto.proto"; message PauseRequest { CommandOptions options = 1; LoggingParams logging_params = 2; + PauseResumeOrigin pause_origin = 3; } diff --git a/protocol/proto/es_pauseresume_origin.proto b/protocol/proto/es_pauseresume_origin.proto new file mode 100644 index 000000000..20446a200 --- /dev/null +++ b/protocol/proto/es_pauseresume_origin.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package spotify.player.esperanto.proto; + +option java_package = "com.spotify.player.esperanto.proto"; +option objc_class_prefix = "ESP"; + +message PauseResumeOrigin { + string feature_identifier = 1; +} + diff --git a/protocol/proto/es_play.proto b/protocol/proto/es_play.proto index 34dca48a5..ed7196caf 100644 --- a/protocol/proto/es_play.proto +++ b/protocol/proto/es_play.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_play_origin.proto b/protocol/proto/es_play_origin.proto index 62cff8b79..c9d8004ae 100644 --- a/protocol/proto/es_play_origin.proto +++ b/protocol/proto/es_play_origin.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -16,4 +16,5 @@ message PlayOrigin { string referrer_identifier = 5; string device_identifier = 6; repeated string feature_classes = 7; + string restriction_identifier = 8; } diff --git a/protocol/proto/es_prefs.proto b/protocol/proto/es_prefs.proto index f81916ca1..220d89428 100644 --- a/protocol/proto/es_prefs.proto +++ b/protocol/proto/es_prefs.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -25,11 +25,9 @@ message SubParams { } message GetAllParams { - } message SubAllParams { - } message Value { diff --git a/protocol/proto/es_prepare_play.proto b/protocol/proto/es_prepare_play.proto index 6662eb654..bee7d5107 100644 --- a/protocol/proto/es_prepare_play.proto +++ b/protocol/proto/es_prepare_play.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_prepare_play_options.proto b/protocol/proto/es_prepare_play_options.proto index b4a4449cb..de1798140 100644 --- a/protocol/proto/es_prepare_play_options.proto +++ b/protocol/proto/es_prepare_play_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -21,19 +21,19 @@ message PreparePlayOptions { bool system_initiated = 6; ContextPlayerOptionOverrides player_options_override = 7; repeated string suppressions = 8; - + PrefetchLevel prefetch_level = 9; enum PrefetchLevel { NONE = 0; MEDIA = 1; } - + AudioStream audio_stream = 10; enum AudioStream { DEFAULT = 0; ALARM = 1; } - + string session_id = 11; string license = 12; map configuration_override = 13; diff --git a/protocol/proto/es_provided_track.proto b/protocol/proto/es_provided_track.proto index 6dcffc0d9..76e86c4c7 100644 --- a/protocol/proto/es_provided_track.proto +++ b/protocol/proto/es_provided_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_queue.proto b/protocol/proto/es_queue.proto index 625b184df..2f7a7b67d 100644 --- a/protocol/proto/es_queue.proto +++ b/protocol/proto/es_queue.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_remote_config.proto b/protocol/proto/es_remote_config.proto index fca7f0f9e..adf31a39b 100644 --- a/protocol/proto/es_remote_config.proto +++ b/protocol/proto/es_remote_config.proto @@ -1,21 +1,33 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.remote_config.esperanto.proto; +import "esperanto_options.proto"; + option objc_class_prefix = "ESP"; option java_package = "com.spotify.remoteconfig.esperanto.proto"; service RemoteConfig { - rpc lookupBool(LookupRequest) returns (BoolResponse); + rpc lookupBool(LookupRequest) returns (.spotify.remote_config.esperanto.proto.BoolResponse) {} + rpc lookupInt(LookupRequest) returns (.spotify.remote_config.esperanto.proto.IntResponse) {} + rpc lookupEnum(LookupRequest) returns (.spotify.remote_config.esperanto.proto.EnumResponse) {} } message LookupRequest { - string component_id = 1; - string key = 2; + string scope = 1; + string name = 2; } message BoolResponse { - bool value = 1; + optional bool value = 1; +} + +message IntResponse { + optional int32 value = 1; +} + +message EnumResponse { + optional string value = 1; } diff --git a/protocol/proto/es_request_info.proto b/protocol/proto/es_request_info.proto index 95b5cb817..91a659c90 100644 --- a/protocol/proto/es_request_info.proto +++ b/protocol/proto/es_request_info.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -24,4 +24,6 @@ message RequestInfo { int64 event_first_byte_received = 11; int64 event_last_byte_received = 12; int64 event_ended = 13; + string protocol = 14; + int64 event_redirects_done = 15; } diff --git a/protocol/proto/es_response_with_reasons.proto b/protocol/proto/es_response_with_reasons.proto index 6570a177b..d12fcd251 100644 --- a/protocol/proto/es_response_with_reasons.proto +++ b/protocol/proto/es_response_with_reasons.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,13 +9,13 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message ResponseWithReasons { - Error error = 1; enum Error { OK = 0; FORBIDDEN = 1; NOT_FOUND = 2; CONFLICT = 3; } - + + Error error = 1; string reasons = 2; } diff --git a/protocol/proto/es_restrictions.proto b/protocol/proto/es_restrictions.proto index 3a5c3a0aa..225cc9c22 100644 --- a/protocol/proto/es_restrictions.proto +++ b/protocol/proto/es_restrictions.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,6 +8,14 @@ option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; +message ModeRestrictions { + map values = 1; +} + +message RestrictionReasons { + repeated string reasons = 1; +} + message Restrictions { repeated string disallow_pausing_reasons = 1; repeated string disallow_resuming_reasons = 2; @@ -30,4 +38,8 @@ message Restrictions { repeated string disallow_removing_from_next_tracks_reasons = 19; repeated string disallow_removing_from_context_tracks_reasons = 20; repeated string disallow_updating_context_reasons = 21; + repeated string disallow_add_to_queue_reasons = 22; + repeated string disallow_setting_playback_speed_reasons = 23; + map disallow_setting_modes = 25; + map disallow_signals = 26; } diff --git a/protocol/proto/es_resume.proto b/protocol/proto/es_resume.proto index 1af5980f4..257a5b9f2 100644 --- a/protocol/proto/es_resume.proto +++ b/protocol/proto/es_resume.proto @@ -1,17 +1,19 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.player.esperanto.proto; -import "es_command_options.proto"; -import "es_logging_params.proto"; - option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; +import "es_command_options.proto"; +import "es_logging_params.proto"; +import "es_pauseresume_origin.proto"; + message ResumeRequest { CommandOptions options = 1; LoggingParams logging_params = 2; + PauseResumeOrigin resume_origin = 3; } diff --git a/protocol/proto/es_seek_to.proto b/protocol/proto/es_seek_to.proto index 59073cf9d..a185a7d9e 100644 --- a/protocol/proto/es_seek_to.proto +++ b/protocol/proto/es_seek_to.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -12,14 +12,15 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.player.esperanto.proto"; message SeekToRequest { - CommandOptions options = 1; - LoggingParams logging_params = 2; - int64 position = 3; - - Relative relative = 4; enum Relative { BEGINNING = 0; END = 1; CURRENT = 2; } + + CommandOptions options = 1; + LoggingParams logging_params = 2; + int64 position = 3; + Relative relative = 4; } + diff --git a/protocol/proto/es_session_response.proto b/protocol/proto/es_session_response.proto index 692ae30fc..26f599b4f 100644 --- a/protocol/proto/es_session_response.proto +++ b/protocol/proto/es_session_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_set_options.proto b/protocol/proto/es_set_options.proto index 33faf5f8c..f4c2f4380 100644 --- a/protocol/proto/es_set_options.proto +++ b/protocol/proto/es_set_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -18,4 +18,6 @@ message SetOptionsRequest { OptionalBoolean shuffling_context = 3; CommandOptions options = 4; LoggingParams logging_params = 5; + map modes = 7; + optional float playback_speed = 6; } diff --git a/protocol/proto/es_set_queue_request.proto b/protocol/proto/es_set_queue_request.proto index 83715232a..7cc6dd17b 100644 --- a/protocol/proto/es_set_queue_request.proto +++ b/protocol/proto/es_set_queue_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_set_repeating_context.proto b/protocol/proto/es_set_repeating_context.proto index 25667c816..2f2d65710 100644 --- a/protocol/proto/es_set_repeating_context.proto +++ b/protocol/proto/es_set_repeating_context.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_set_repeating_track.proto b/protocol/proto/es_set_repeating_track.proto index 01ae3b56b..dd0588be7 100644 --- a/protocol/proto/es_set_repeating_track.proto +++ b/protocol/proto/es_set_repeating_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_set_shuffling_context.proto b/protocol/proto/es_set_shuffling_context.proto index 6eb779e62..9a1a470cf 100644 --- a/protocol/proto/es_set_shuffling_context.proto +++ b/protocol/proto/es_set_shuffling_context.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_skip_next.proto b/protocol/proto/es_skip_next.proto index d6b0dc834..2761b0b9e 100644 --- a/protocol/proto/es_skip_next.proto +++ b/protocol/proto/es_skip_next.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_skip_prev.proto b/protocol/proto/es_skip_prev.proto index 2a6b9a71a..da354be2f 100644 --- a/protocol/proto/es_skip_prev.proto +++ b/protocol/proto/es_skip_prev.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_skip_to_track.proto b/protocol/proto/es_skip_to_track.proto index ecf0d03f5..ba5888116 100644 --- a/protocol/proto/es_skip_to_track.proto +++ b/protocol/proto/es_skip_to_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/es_stop.proto b/protocol/proto/es_stop.proto index 068490e08..cb3760fcf 100644 --- a/protocol/proto/es_stop.proto +++ b/protocol/proto/es_stop.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,13 +13,13 @@ option java_package = "com.spotify.player.esperanto.proto"; message StopRequest { CommandOptions options = 1; - - Reason reason = 2; + + StopRequest.Reason reason = 2; enum Reason { INTERACTIVE = 0; REMOTE_TRANSFER = 1; SHUTDOWN = 2; } - + LoggingParams logging_params = 3; } diff --git a/protocol/proto/es_storage.proto b/protocol/proto/es_storage.proto index c20b3be71..c7d35f71f 100644 --- a/protocol/proto/es_storage.proto +++ b/protocol/proto/es_storage.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,8 +6,8 @@ package spotify.storage.esperanto.proto; import "google/protobuf/empty.proto"; -option objc_class_prefix = "ESP"; option java_package = "com.spotify.storage.esperanto.proto"; +option objc_class_prefix = "ESP"; service Storage { rpc GetCacheSizeLimit(GetCacheSizeLimitParams) returns (CacheSizeLimit); @@ -23,7 +23,6 @@ message CacheSizeLimit { } message GetCacheSizeLimitParams { - } message SetCacheSizeLimitParams { @@ -31,11 +30,9 @@ message SetCacheSizeLimitParams { } message DeleteExpiredItemsParams { - } message DeleteUnlockedItemsParams { - } message RealmStats { @@ -58,18 +55,17 @@ message Stats { } message GetStatsParams { - } message FileRanges { - bool byte_size_known = 1; - uint64 byte_size = 2; - - repeated Range ranges = 3; message Range { uint64 from_byte = 1; uint64 to_byte = 2; } + + bool byte_size_known = 1; + uint64 byte_size = 2; + repeated Range ranges = 3; } message GetFileRangesParams { diff --git a/protocol/proto/es_update.proto b/protocol/proto/es_update.proto index 90734b5d9..498a0d266 100644 --- a/protocol/proto/es_update.proto +++ b/protocol/proto/es_update.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/esperanto_options.proto b/protocol/proto/esperanto_options.proto new file mode 100644 index 000000000..5c914f068 --- /dev/null +++ b/protocol/proto/esperanto_options.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +package spotify.esperanto; + +import "google/protobuf/descriptor.proto"; + diff --git a/protocol/proto/event_entity.proto b/protocol/proto/event_entity.proto index 06239d598..b926ba6b5 100644 --- a/protocol/proto/event_entity.proto +++ b/protocol/proto/event_entity.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/explicit_content_pubsub.proto b/protocol/proto/explicit_content_pubsub.proto index 1bb45f91f..146794883 100644 --- a/protocol/proto/explicit_content_pubsub.proto +++ b/protocol/proto/explicit_content_pubsub.proto @@ -6,11 +6,6 @@ package spotify.explicit_content.proto; option optimize_for = CODE_SIZE; -message KeyValuePair { - required string key = 1; - required string value = 2; -} - message UserAttributesUpdate { - repeated KeyValuePair pairs = 1; + map pairs = 1; } diff --git a/protocol/proto/extended_metadata.proto b/protocol/proto/extended_metadata.proto index 2e38d28db..b48b34eb3 100644 --- a/protocol/proto/extended_metadata.proto +++ b/protocol/proto/extended_metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -47,7 +47,6 @@ message EntityExtensionDataArray { } message BatchedExtensionResponseHeader { - } message BatchedExtensionResponse { diff --git a/protocol/proto/extension_kind.proto b/protocol/proto/extension_kind.proto index 02444deae..6bb8182bb 100644 --- a/protocol/proto/extension_kind.proto +++ b/protocol/proto/extension_kind.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -18,6 +18,7 @@ enum ExtensionKind { PODCAST_SEGMENTS = 4; AUDIO_FILES = 5; TRACK_DESCRIPTOR = 6; + PODCAST_COUNTER = 7; ARTIST_V4 = 8; ALBUM_V4 = 9; TRACK_V4 = 10; @@ -44,11 +45,166 @@ enum ExtensionKind { SHOW_ACCESS = 31; PODCAST_QNA = 32; CLIPS = 33; + SHOW_V5 = 34; + EPISODE_V5 = 35; PODCAST_CTA_CARDS = 36; PODCAST_RATING = 37; DISPLAY_SEGMENTS = 38; GREENROOM = 39; USER_CREATED = 40; + SHOW_DESCRIPTION = 41; + SHOW_HTML_DESCRIPTION = 42; + SHOW_PLAYABILITY = 43; + EPISODE_DESCRIPTION = 44; + EPISODE_HTML_DESCRIPTION = 45; + EPISODE_PLAYABILITY = 46; + SHOW_EPISODES_ASSOC = 47; CLIENT_CONFIG = 48; + PLAYLISTABILITY = 49; + AUDIOBOOK_V5 = 50; + CHAPTER_V5 = 51; AUDIOBOOK_SPECIFICS = 52; + EPISODE_RANKING = 53; + HTML_DESCRIPTION = 54; + CREATOR_CHANNEL = 55; + AUDIOBOOK_PROVIDERS = 56; + PLAY_TRAIT = 57; + CONTENT_WARNING = 58; + IMAGE_CUE = 59; + STREAM_COUNT = 60; + AUDIO_ATTRIBUTES = 61; + NAVIGABLE_TRAIT = 62; + NEXT_BEST_EPISODE = 63; + AUDIOBOOK_PRICE = 64; + EXPRESSIVE_PLAYLISTS = 65; + DYNAMIC_SHOW_EPISODE = 66; + LIVE = 67; + SKIP_PLAYED = 68; + AD_BREAK_FREE_PODCASTS = 69; + ASSOCIATIONS = 70; + PLAYLIST_EVALUATION = 71; + CACHE_INVALIDATIONS = 72; + LIVESTREAM_ENTITY = 73; + SINGLE_TAP_REACTIONS = 74; + USER_COMMENTS = 75; + CLIENT_RESTRICTIONS = 76; + PODCAST_GUEST = 77; + PLAYABILITY = 78; + COVER_IMAGE = 79; + SHARE_TRAIT = 80; + INSTANCE_SHARING = 81; + ARTIST_TOUR = 82; + AUDIOBOOK_GENRE = 83; + CONCEPT = 84; + ORIGINAL_VIDEO = 85; + SMART_SHUFFLE = 86; + LIVE_EVENTS = 87; + AUDIOBOOK_RELATIONS = 88; + HOME_POC_BASECARD = 89; + AUDIOBOOK_SUPPLEMENTS = 90; + PAID_PODCAST_BANNER = 91; + FEWER_ADS = 92; + WATCH_FEED_SHOW_EXPLORER = 93; + TRACK_EXTRA_DESCRIPTORS = 94; + TRACK_EXTRA_AUDIO_ATTRIBUTES = 95; + TRACK_EXTENDED_CREDITS = 96; + SIMPLE_TRAIT = 97; + AUDIO_ASSOCIATIONS = 98; + VIDEO_ASSOCIATIONS = 99; + PLAYLIST_TUNER = 100; + ARTIST_VIDEOS_ENTRYPOINT = 101; + ALBUM_PRERELEASE = 102; + CONTENT_ALTERNATIVES = 103; + SNAPSHOT_SHARING = 105; + DISPLAY_SEGMENTS_COUNT = 106; + PODCAST_FEATURED_EPISODE = 107; + PODCAST_SPONSORED_CONTENT = 108; + PODCAST_EPISODE_TOPICS_LLM = 109; + PODCAST_EPISODE_TOPICS_KG = 110; + EPISODE_RANKING_POPULARITY = 111; + MERCH = 112; + COMPANION_CONTENT = 113; + WATCH_FEED_ENTITY_EXPLORER = 114; + ANCHOR_CARD_TRAIT = 115; + AUDIO_PREVIEW_PLAYBACK_TRAIT = 116; + VIDEO_PREVIEW_STILL_TRAIT = 117; + PREVIEW_CARD_TRAIT = 118; + SHORTCUTS_CARD_TRAIT = 119; + VIDEO_PREVIEW_PLAYBACK_TRAIT = 120; + COURSE_SPECIFICS = 121; + CONCERT = 122; + CONCERT_LOCATION = 123; + CONCERT_MARKETING = 124; + CONCERT_PERFORMERS = 125; + TRACK_PAIR_TRANSITION = 126; + CONTENT_TYPE_TRAIT = 127; + NAME_TRAIT = 128; + ARTWORK_TRAIT = 129; + RELEASE_DATE_TRAIT = 130; + CREDITS_TRAIT = 131; + RELEASE_URI_TRAIT = 132; + ENTITY_CAPPING = 133; + LESSON_SPECIFICS = 134; + CONCERT_OFFERS = 135; + TRANSITION_MAPS = 136; + ARTIST_HAS_CONCERTS = 137; + PRERELEASE = 138; + PLAYLIST_ATTRIBUTES_V2 = 139; + LIST_ATTRIBUTES_V2 = 140; + LIST_METADATA = 141; + LIST_TUNER_AUDIO_ANALYSIS = 142; + LIST_TUNER_CUEPOINTS = 143; + CONTENT_RATING_TRAIT = 144; + COPYRIGHT_TRAIT = 145; + SUPPORTED_BADGES = 146; + BADGES = 147; + PREVIEW_TRAIT = 148; + ROOTLISTABILITY_TRAIT = 149; + LOCAL_CONCERTS = 150; + RECOMMENDED_PLAYLISTS = 151; + POPULAR_RELEASES = 152; + RELATED_RELEASES = 153; + SHARE_RESTRICTIONS = 154; + CONCERT_OFFER = 155; + CONCERT_OFFER_PROVIDER = 156; + ENTITY_BOOKMARKS = 157; + PRIVACY_TRAIT = 158; + DUPLICATE_ITEMS_TRAIT = 159; + REORDERING_TRAIT = 160; + PODCAST_RESUMPTION_SEGMENTS = 161; + ARTIST_EXPRESSION_VIDEO = 162; + PRERELEASE_VIDEO = 163; + GATED_ENTITY_RELATIONS = 164; + RELATED_CREATORS_SECTION = 165; + CREATORS_APPEARS_ON_SECTION = 166; + PROMO_V1_TRAIT = 167; + SPEECHLESS_SHARE_CARD = 168; + TOP_PLAYABLES_SECTION = 169; + AUTO_LENS = 170; + PROMO_V3_TRAIT = 171; + TRACK_CONTENT_FILTER = 172; + HIGHLIGHTABILITY = 173; + LINK_CARD_WITH_IMAGE_TRAIT = 174; + TRACK_CLOUD_SECTION = 175; + EPISODE_TOPICS = 176; + VIDEO_THUMBNAIL = 177; + IDENTITY_TRAIT = 178; + VISUAL_IDENTITY_TRAIT = 179; + CONTENT_TYPE_V2_TRAIT = 180; + PREVIEW_PLAYBACK_TRAIT = 181; + CONSUMPTION_EXPERIENCE_TRAIT = 182; + PUBLISHING_METADATA_TRAIT = 183; + DETAILED_EVALUATION_TRAIT = 184; + ON_PLATFORM_REPUTATION_TRAIT = 185; + CREDITS_V2_TRAIT = 186; + HIGHLIGHT_PLAYABILITY_TRAIT = 187; + SHOW_EPISODE_LIST = 188; + AVAILABLE_RELEASES = 189; + PLAYLIST_DESCRIPTORS = 190; + LINK_CARD_WITH_ANIMATIONS_TRAIT = 191; + RECAP = 192; + AUDIOBOOK_COMPANION_CONTENT = 193; + THREE_OH_THREE_PLAY_TRAIT = 194; + ARTIST_WRAPPED_2024_VIDEO = 195; } + diff --git a/protocol/proto/extracted_colors.proto b/protocol/proto/extracted_colors.proto index 999a27ea4..cf8b8ca56 100644 --- a/protocol/proto/extracted_colors.proto +++ b/protocol/proto/extracted_colors.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/follow_request.proto b/protocol/proto/follow_request.proto index 5a0268950..913573eee 100644 --- a/protocol/proto/follow_request.proto +++ b/protocol/proto/follow_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -16,6 +16,11 @@ message FollowRequest { bool follow = 2; } +message FollowRequestV4 { + string username = 1; + bool follow = 2; +} + message FollowResponse { ResponseStatus status = 1; } diff --git a/protocol/proto/followed_users_request.proto b/protocol/proto/followed_users_request.proto index afb71f437..a0d2dfc00 100644 --- a/protocol/proto/followed_users_request.proto +++ b/protocol/proto/followed_users_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/frecency.proto b/protocol/proto/frecency.proto index 89c6c7f6e..3f875aa15 100644 --- a/protocol/proto/frecency.proto +++ b/protocol/proto/frecency.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/frecency_storage.proto b/protocol/proto/frecency_storage.proto index 9e32269fa..f1b504876 100644 --- a/protocol/proto/frecency_storage.proto +++ b/protocol/proto/frecency_storage.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/gabito.proto b/protocol/proto/gabito.proto index b47f4fdd5..3256727eb 100644 --- a/protocol/proto/gabito.proto +++ b/protocol/proto/gabito.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,16 +8,16 @@ option optimize_for = CODE_SIZE; message EventEnvelope { string event_name = 2; - + repeated EventFragment event_fragment = 3; message EventFragment { string name = 1; bytes data = 2; } - + bytes sequence_id = 4; int64 sequence_number = 5; - + reserved 1; } @@ -27,10 +27,11 @@ message PublishEventsRequest { } message PublishEventsResponse { - repeated EventError error = 1; message EventError { int32 index = 1; bool transient = 2; int32 reason = 3; } + + repeated EventError error = 1; } diff --git a/protocol/proto/global_node.proto b/protocol/proto/global_node.proto index cd6f1b6c8..f54604a5d 100644 --- a/protocol/proto/global_node.proto +++ b/protocol/proto/global_node.proto @@ -1,10 +1,11 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.player.proto; import "context_player_options.proto"; +import "pause_resume_origin.proto"; import "player_license.proto"; option optimize_for = CODE_SIZE; @@ -13,4 +14,6 @@ message GlobalNode { optional ContextPlayerOptions options = 1; optional PlayerLicense license = 2; map configuration = 3; + optional PauseResumeOrigin pause_resume_origin = 4; + optional bool is_paused = 5; } diff --git a/protocol/proto/google/protobuf/any.proto b/protocol/proto/google/protobuf/any.proto index bb7f136cb..7a7e77fb0 100644 --- a/protocol/proto/google/protobuf/any.proto +++ b/protocol/proto/google/protobuf/any.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/google/protobuf/descriptor.proto b/protocol/proto/google/protobuf/descriptor.proto index 884a51517..49ccd18ba 100644 --- a/protocol/proto/google/protobuf/descriptor.proto +++ b/protocol/proto/google/protobuf/descriptor.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -29,6 +29,7 @@ message FileDescriptorProto { optional FileOptions options = 8; optional SourceCodeInfo source_code_info = 9; optional string syntax = 12; + optional Edition edition = 14; } message DescriptorProto { @@ -37,43 +38,58 @@ message DescriptorProto { repeated FieldDescriptorProto extension = 6; repeated DescriptorProto nested_type = 3; repeated EnumDescriptorProto enum_type = 4; - + repeated ExtensionRange extension_range = 5; message ExtensionRange { optional int32 start = 1; optional int32 end = 2; optional ExtensionRangeOptions options = 3; } - + repeated OneofDescriptorProto oneof_decl = 8; optional MessageOptions options = 7; - + repeated ReservedRange reserved_range = 9; message ReservedRange { optional int32 start = 1; optional int32 end = 2; } - + repeated string reserved_name = 10; } message ExtensionRangeOptions { + message Declaration { + reserved 4; + optional int32 number = 1; + optional string full_name = 2; + optional string type = 3; + optional bool reserved = 5; + optional bool repeated = 6; + } + + enum VerificationState { + DECLARATION = 0; + UNVERIFIED = 1; + } + repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; + repeated Declaration declaration = 2; + optional FeatureSet features = 50; + optional VerificationState verification = 3 [default = UNVERIFIED]; } message FieldDescriptorProto { optional string name = 1; optional int32 number = 3; - + optional Label label = 4; enum Label { LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; LABEL_REPEATED = 3; + LABEL_REQUIRED = 2; } - + optional Type type = 5; enum Type { TYPE_DOUBLE = 1; @@ -95,7 +111,7 @@ message FieldDescriptorProto { TYPE_SINT32 = 17; TYPE_SINT64 = 18; } - + optional string type_name = 6; optional string extendee = 2; optional string default_value = 7; @@ -111,16 +127,16 @@ message OneofDescriptorProto { } message EnumDescriptorProto { - optional string name = 1; + optional string name = 1; repeated EnumValueDescriptorProto value = 2; optional EnumOptions options = 3; - + repeated EnumReservedRange reserved_range = 4; message EnumReservedRange { optional int32 start = 1; optional int32 end = 2; } - + repeated string reserved_name = 5; } @@ -149,16 +165,16 @@ message FileOptions { optional string java_package = 1; optional string java_outer_classname = 8; optional bool java_multiple_files = 10 [default = false]; - optional bool java_generate_equals_and_hash = 20 [deprecated = true]; + optional bool java_generate_equals_and_hash = 20; optional bool java_string_check_utf8 = 27 [default = false]; - + optional OptimizeMode optimize_for = 9 [default = SPEED]; enum OptimizeMode { SPEED = 1; CODE_SIZE = 2; LITE_RUNTIME = 3; } - + optional string go_package = 11; optional bool cc_generic_services = 16 [default = false]; optional bool java_generic_services = 17 [default = false]; @@ -173,10 +189,9 @@ message FileOptions { optional string php_namespace = 41; optional string php_metadata_namespace = 44; optional string ruby_package = 45; + optional FeatureSet features = 50; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; - + reserved 38; } @@ -185,10 +200,10 @@ message MessageOptions { optional bool no_standard_descriptor_accessor = 2 [default = false]; optional bool deprecated = 3 [default = false]; optional bool map_entry = 7; + optional bool deprecated_legacy_json_field_conflicts = 11; + optional FeatureSet features = 12; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; - + reserved 4, 5, 6, 8, 9; } @@ -199,78 +214,105 @@ message FieldOptions { CORD = 1; STRING_PIECE = 2; } - + optional bool packed = 2; - + optional JSType jstype = 6 [default = JS_NORMAL]; enum JSType { JS_NORMAL = 0; JS_STRING = 1; JS_NUMBER = 2; } - + optional bool lazy = 5 [default = false]; + optional bool unverified_lazy = 15 [default = false]; optional bool deprecated = 3 [default = false]; optional bool weak = 10 [default = false]; + optional bool debug_redact = 16 [default = false]; + + optional OptionRetention retention = 17; + enum OptionRetention { + RETENTION_UNKNOWN = 0; + RETENTION_RUNTIME = 1; + RETENTION_SOURCE = 2; + } + + repeated OptionTargetType targets = 19; + enum OptionTargetType { + TARGET_TYPE_UNKNOWN = 0; + TARGET_TYPE_FILE = 1; + TARGET_TYPE_EXTENSION_RANGE = 2; + TARGET_TYPE_MESSAGE = 3; + TARGET_TYPE_FIELD = 4; + TARGET_TYPE_ONEOF = 5; + TARGET_TYPE_ENUM = 6; + TARGET_TYPE_ENUM_ENTRY = 7; + TARGET_TYPE_SERVICE = 8; + TARGET_TYPE_METHOD = 9; + } + + + repeated EditionDefault edition_defaults = 20; + message EditionDefault { + optional Edition edition = 3; + optional string value = 2; + } + + optional FeatureSet features = 21; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; - - reserved 4; + + reserved 4, 18; } message OneofOptions { + optional FeatureSet features = 1; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; } message EnumOptions { optional bool allow_alias = 2; optional bool deprecated = 3 [default = false]; + optional bool deprecated_legacy_json_field_conflicts = 6; + optional FeatureSet features = 7; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; - + reserved 5; } message EnumValueOptions { optional bool deprecated = 1 [default = false]; + optional FeatureSet features = 2; + optional bool debug_redact = 3 [default = false]; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; } message ServiceOptions { + optional FeatureSet features = 34; optional bool deprecated = 33 [default = false]; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; } message MethodOptions { optional bool deprecated = 33 [default = false]; - + optional IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN]; enum IdempotencyLevel { IDEMPOTENCY_UNKNOWN = 0; NO_SIDE_EFFECTS = 1; IDEMPOTENT = 2; } - + + optional FeatureSet features = 35; repeated UninterpretedOption uninterpreted_option = 999; - - extensions 1000 to max; } message UninterpretedOption { - repeated NamePart name = 2; message NamePart { required string name_part = 1; required bool is_extension = 2; } - + + repeated UninterpretedOption.NamePart name = 2; optional string identifier_value = 3; optional uint64 positive_int_value = 4; optional int64 negative_int_value = 5; @@ -279,23 +321,103 @@ message UninterpretedOption { optional string aggregate_value = 8; } +message FeatureSet { + reserved 999; + enum FieldPresence { + FIELD_PRESENCE_UNKNOWN = 0; + EXPLICIT = 1; + IMPLICIT = 2; + LEGACY_REQUIRED = 3; + } + + enum EnumType { + ENUM_TYPE_UNKNOWN = 0; + OPEN = 1; + CLOSED = 2; + } + + enum RepeatedFieldEncoding { + REPEATED_FIELD_ENCODING_UNKNOWN = 0; + PACKED = 1; + EXPANDED = 2; + } + + enum Utf8Validation { + UTF8_VALIDATION_UNKNOWN = 0; + NONE = 1; + VERIFY = 2; + } + + enum MessageEncoding { + MESSAGE_ENCODING_UNKNOWN = 0; + LENGTH_PREFIXED = 1; + DELIMITED = 2; + } + + enum JsonFormat { + JSON_FORMAT_UNKNOWN = 0; + ALLOW = 1; + LEGACY_BEST_EFFORT = 2; + } + + optional FieldPresence field_presence = 1; + optional EnumType enum_type = 2; + optional RepeatedFieldEncoding repeated_field_encoding = 3; + optional Utf8Validation utf8_validation = 4; + optional MessageEncoding message_encoding = 5; + optional JsonFormat json_format = 6; +} + +message FeatureSetDefaults { + message FeatureSetEditionDefault { + optional Edition edition = 3; + optional FeatureSet features = 2; + } + + repeated FeatureSetDefaults.FeatureSetEditionDefault defaults = 1; + optional Edition minimum_edition = 4; + optional Edition maximum_edition = 5; +} + message SourceCodeInfo { - repeated Location location = 1; message Location { - repeated int32 path = 1 [packed = true]; - repeated int32 span = 2 [packed = true]; + repeated int32 path = 1; + repeated int32 span = 2; optional string leading_comments = 3; optional string trailing_comments = 4; repeated string leading_detached_comments = 6; } + + repeated Location location = 1; } message GeneratedCodeInfo { - repeated Annotation annotation = 1; message Annotation { - repeated int32 path = 1 [packed = true]; + enum Semantic { + NONE = 0; + SET = 1; + ALIAS = 2; + } + + repeated int32 path = 1; optional string source_file = 2; optional int32 begin = 3; optional int32 end = 4; + optional Annotation.Semantic semantic = 5; } + + repeated Annotation annotation = 1; +} + +enum Edition { + EDITION_UNKNOWN = 0; + EDITION_PROTO2 = 998; + EDITION_PROTO3 = 999; + EDITION_2023 = 1000; + EDITION_1_TEST_ONLY = 1; + EDITION_2_TEST_ONLY = 2; + EDITION_99997_TEST_ONLY = 99997; + EDITION_99998_TEST_ONLY = 99998; + EDITION_99999_TEST_ONLY = 99999; } + diff --git a/protocol/proto/google/protobuf/duration.proto b/protocol/proto/google/protobuf/duration.proto index f7d013016..dc76d4eb0 100644 --- a/protocol/proto/google/protobuf/duration.proto +++ b/protocol/proto/google/protobuf/duration.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/google/protobuf/empty.proto b/protocol/proto/google/protobuf/empty.proto index 28c4d77b2..25f743773 100644 --- a/protocol/proto/google/protobuf/empty.proto +++ b/protocol/proto/google/protobuf/empty.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,5 +13,5 @@ option java_outer_classname = "EmptyProto"; option java_package = "com.google.protobuf"; message Empty { - + } diff --git a/protocol/proto/google/protobuf/field_mask.proto b/protocol/proto/google/protobuf/field_mask.proto index 3ae487122..860a8709d 100644 --- a/protocol/proto/google/protobuf/field_mask.proto +++ b/protocol/proto/google/protobuf/field_mask.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/google/protobuf/source_context.proto b/protocol/proto/google/protobuf/source_context.proto index 8449fd4b5..e19c07cc2 100644 --- a/protocol/proto/google/protobuf/source_context.proto +++ b/protocol/proto/google/protobuf/source_context.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/google/protobuf/timestamp.proto b/protocol/proto/google/protobuf/timestamp.proto index e402c47a8..084f311a0 100644 --- a/protocol/proto/google/protobuf/timestamp.proto +++ b/protocol/proto/google/protobuf/timestamp.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/google/protobuf/type.proto b/protocol/proto/google/protobuf/type.proto index 38d7f2d1b..d7b796519 100644 --- a/protocol/proto/google/protobuf/type.proto +++ b/protocol/proto/google/protobuf/type.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -22,10 +22,10 @@ message Type { repeated Option options = 4; SourceContext source_context = 5; Syntax syntax = 6; + string edition = 7; } message Field { - Kind kind = 1; enum Kind { TYPE_UNKNOWN = 0; TYPE_DOUBLE = 1; @@ -47,15 +47,16 @@ message Field { TYPE_SINT32 = 17; TYPE_SINT64 = 18; } - - Cardinality cardinality = 2; + enum Cardinality { CARDINALITY_UNKNOWN = 0; CARDINALITY_OPTIONAL = 1; CARDINALITY_REQUIRED = 2; CARDINALITY_REPEATED = 3; } - + + Kind kind = 1; + Cardinality cardinality = 2; int32 number = 3; string name = 4; string type_url = 6; @@ -72,6 +73,7 @@ message Enum { repeated Option options = 3; SourceContext source_context = 4; Syntax syntax = 5; + string edition = 6; } message EnumValue { @@ -88,4 +90,5 @@ message Option { enum Syntax { SYNTAX_PROTO2 = 0; SYNTAX_PROTO3 = 1; + SYNTAX_EDITIONS = 2; } diff --git a/protocol/proto/google/protobuf/wrappers.proto b/protocol/proto/google/protobuf/wrappers.proto index 10e94ee01..647641a3e 100644 --- a/protocol/proto/google/protobuf/wrappers.proto +++ b/protocol/proto/google/protobuf/wrappers.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/identity.proto b/protocol/proto/identity.proto index efd8b9e13..c6963862e 100644 --- a/protocol/proto/identity.proto +++ b/protocol/proto/identity.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -29,9 +29,25 @@ message UserProfile { google.protobuf.BoolValue has_spotify_name = 9; google.protobuf.BoolValue has_spotify_image = 10; google.protobuf.Int32Value color = 11; + google.protobuf.BoolValue is_private = 12; + google.protobuf.StringValue pronouns = 13; + google.protobuf.StringValue location = 14; + google.protobuf.StringValue bio = 15; + google.protobuf.BoolValue abuse_reported_bio = 17; + google.protobuf.BoolValue edit_name_disabled = 18; + google.protobuf.BoolValue edit_image_disabled = 19; + google.protobuf.BoolValue edit_bio_disabled = 20; + google.protobuf.BoolValue is_kid = 21; } message UserProfileUpdateRequest { google.protobuf.FieldMask mask = 1; UserProfile user_profile = 2; + bool skip_emit_events = 3; } + +message UserProfileChangedEvent { + string userid = 1; + UserProfile user_profile = 2; +} + diff --git a/protocol/proto/installation_data.proto b/protocol/proto/installation_data.proto index 083fe466d..f0451981e 100644 --- a/protocol/proto/installation_data.proto +++ b/protocol/proto/installation_data.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -12,7 +12,7 @@ message InstallationEntity { } message InstallationData { - string installation_id = 1; - string last_seen_device_id = 2; + bytes installation_id = 1; + bytes last_seen_device_id = 2; int64 monotonic_clock_id = 3; } diff --git a/protocol/proto/instrumentation_params.proto b/protocol/proto/instrumentation_params.proto index b8e44f4a7..c317f16d0 100644 --- a/protocol/proto/instrumentation_params.proto +++ b/protocol/proto/instrumentation_params.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/lens-model.proto b/protocol/proto/lens-model.proto new file mode 100644 index 000000000..aa85defcb --- /dev/null +++ b/protocol/proto/lens-model.proto @@ -0,0 +1,19 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + +syntax = "proto3"; + +package spotify.lens.model.proto; + +option java_package = "com.spotify.lens.model.proto"; +option java_outer_classname = "LensModelProto"; +option optimize_for = CODE_SIZE; + +message Lens { + string identifier = 1; +} + +message LensState { + string identifier = 1; + bytes revision = 2; +} + diff --git a/protocol/proto/lfs_secret_provider.proto b/protocol/proto/lfs_secret_provider.proto index 0862181e9..782d19d06 100644 --- a/protocol/proto/lfs_secret_provider.proto +++ b/protocol/proto/lfs_secret_provider.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/liked_songs_tags_sync_state.proto b/protocol/proto/liked_songs_tags_sync_state.proto index 634f9d037..60bea86ab 100644 --- a/protocol/proto/liked_songs_tags_sync_state.proto +++ b/protocol/proto/liked_songs_tags_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/listen_later_cosmos_response.proto b/protocol/proto/listen_later_cosmos_response.proto index f71c577cc..c35615f34 100644 --- a/protocol/proto/listen_later_cosmos_response.proto +++ b/protocol/proto/listen_later_cosmos_response.proto @@ -1,14 +1,17 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.listen_later_cosmos.proto; + import "collection/episode_collection_state.proto"; import "metadata/episode_metadata.proto"; import "played_state/episode_played_state.proto"; import "sync/episode_sync_state.proto"; +option java_package = "spotify.listen_later_cosmos.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; message Episode { @@ -25,4 +28,6 @@ message EpisodesResponse { repeated Episode episode = 3; optional string offline_availability = 5; optional uint32 offline_progress = 6; + optional uint32 status_code = 98; + optional string error = 99; } diff --git a/protocol/proto/local_bans_storage.proto b/protocol/proto/local_bans_storage.proto index 388f05b59..d40dca714 100644 --- a/protocol/proto/local_bans_storage.proto +++ b/protocol/proto/local_bans_storage.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -12,6 +12,10 @@ message BanItem { required int64 timestamp = 3; } +message LocalBansTimestamp { + required int64 timestamp = 1; +} + message Bans { repeated BanItem items = 1; } diff --git a/protocol/proto/local_sync_state.proto b/protocol/proto/local_sync_state.proto index 630f1843f..6c0969269 100644 --- a/protocol/proto/local_sync_state.proto +++ b/protocol/proto/local_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/logging_params.proto b/protocol/proto/logging_params.proto index 1f11809dd..545d7b641 100644 --- a/protocol/proto/logging_params.proto +++ b/protocol/proto/logging_params.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -11,4 +11,6 @@ message LoggingParams { optional int64 command_received_time = 2; repeated string page_instance_ids = 3; repeated string interaction_ids = 4; + optional string device_identifier = 5; + optional string command_id = 6; } diff --git a/protocol/proto/mdata.proto b/protocol/proto/mdata.proto index 29faad9c2..5045d868a 100644 --- a/protocol/proto/mdata.proto +++ b/protocol/proto/mdata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -20,12 +20,6 @@ message LocalBatchedEntityRequest { } message LocalBatchedExtensionResponse { - repeated Extension extension = 1; - message Extension { - extendedmetadata.ExtensionKind extension_kind = 1; - repeated EntityExtension entity_extension = 2; - } - message ExtensionHeader { bool cache_valid = 1; bool offline_valid = 2; @@ -33,11 +27,20 @@ message LocalBatchedExtensionResponse { bool is_empty = 4; int64 cache_expiry_timestamp = 5; int64 offline_expiry_timestamp = 6; + string etag = 7; } - + message EntityExtension { string entity_uri = 1; ExtensionHeader header = 2; google.protobuf.Any extension_data = 3; } + + message Extension { + extendedmetadata.ExtensionKind extension_kind = 1; + repeated EntityExtension entity_extension = 2; + } + + repeated Extension extension = 1; } + diff --git a/protocol/proto/mdata_cosmos.proto b/protocol/proto/mdata_cosmos.proto index 3c67357c6..2639ae9f9 100644 --- a/protocol/proto/mdata_cosmos.proto +++ b/protocol/proto/mdata_cosmos.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -17,5 +17,4 @@ message InvalidateCacheRequest { } message InvalidateCacheResponse { - } diff --git a/protocol/proto/mdata_storage.proto b/protocol/proto/mdata_storage.proto index 8703fe543..d293ff7b5 100644 --- a/protocol/proto/mdata_storage.proto +++ b/protocol/proto/mdata_storage.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -23,6 +23,7 @@ message CacheInfo { string etag = 5; fixed64 cache_checksum_lo = 6; fixed64 cache_checksum_hi = 7; + uint64 last_modified = 8; } message OfflineLock { diff --git a/protocol/proto/media.proto b/protocol/proto/media.proto new file mode 100644 index 000000000..5be102bfb --- /dev/null +++ b/protocol/proto/media.proto @@ -0,0 +1,19 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + +syntax = "proto3"; + +package spotify.common.media; + +option java_package = "com.spotify.common.proto"; +option optimize_for = CODE_SIZE; + +enum AudioQuality { + DEFAULT = 0; + LOW = 1; + NORMAL = 2; + HIGH = 3; + VERY_HIGH = 4; + HIFI = 5; + HIFI_24 = 6; +} + diff --git a/protocol/proto/media_manifest.proto b/protocol/proto/media_manifest.proto index e9fe45fd4..b6f32e773 100644 --- a/protocol/proto/media_manifest.proto +++ b/protocol/proto/media_manifest.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -18,38 +18,39 @@ message AudioFile { MP3_160_ENC = 7; AAC_24 = 8; AAC_48 = 9; - AAC_160 = 10; - AAC_320 = 11; - MP4_128 = 12; - OTHER5 = 13; FLAC_FLAC = 16; } } message File { - int32 bitrate = 3; - string mime_type = 4; - - oneof file { - ExternalFile external_file = 1; - FileIdFile file_id_file = 2; - } - message ExternalFile { string method = 1; bytes body = 4; - oneof endpoint { string url = 2; string service = 3; } + optional bool disable_range_requests = 5; } - + message FileIdFile { string file_id_hex = 1; AudioFile.Format download_format = 2; EncryptionType encryption = 3; } + + message NormalizationParams { + float loudness_db = 1; + float true_peak_db = 2; + } + + int32 bitrate = 3; + string mime_type = 4; + oneof file { + ExternalFile external_file = 1; + FileIdFile file_id_file = 2; + } + optional NormalizationParams normalization_params = 5; } message Files { diff --git a/protocol/proto/media_type.proto b/protocol/proto/media_type.proto index 2d8def46b..a2f9a41be 100644 --- a/protocol/proto/media_type.proto +++ b/protocol/proto/media_type.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -10,4 +10,7 @@ option java_package = "com.spotify.stream_reporting_esperanto.proto"; enum MediaType { AUDIO = 0; VIDEO = 1; + MEDIA_TYPE_AUDIO = 0; + MEDIA_TYPE_VIDEO = 1; + MEDIA_TYPE_UNKNOWN = 2; } diff --git a/protocol/proto/members_request.proto b/protocol/proto/members_request.proto index 931f91d3c..486eff7cf 100644 --- a/protocol/proto/members_request.proto +++ b/protocol/proto/members_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/members_response.proto b/protocol/proto/members_response.proto index f341a8d2b..386228ab6 100644 --- a/protocol/proto/members_response.proto +++ b/protocol/proto/members_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata.proto b/protocol/proto/metadata.proto index 4c52e0edf..fa7aec95a 100644 --- a/protocol/proto/metadata.proto +++ b/protocol/proto/metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -9,6 +9,7 @@ option java_outer_classname = "Metadata"; option java_package = "com.spotify.metadata.proto"; message Artist { + reserved 9; optional bytes gid = 1; optional string name = 2; optional sint32 popularity = 3; @@ -17,7 +18,6 @@ message Artist { repeated AlbumGroup single_group = 6; repeated AlbumGroup compilation_group = 7; repeated AlbumGroup appears_on_group = 8; - repeated string genre = 9; repeated ExternalId external_id = 10; repeated Image portrait = 11; repeated Biography biography = 12; @@ -31,10 +31,12 @@ message Artist { } message Album { + reserved 8; + optional bytes gid = 1; optional string name = 2; repeated Artist artist = 3; - + optional Type type = 4; enum Type { ALBUM = 1; @@ -44,11 +46,10 @@ message Album { AUDIOBOOK = 5; PODCAST = 6; } - + optional string label = 5; optional Date date = 6; optional sint32 popularity = 7; - repeated string genre = 8; repeated Image cover = 9; repeated ExternalId external_id = 10; repeated Disc disc = 11; @@ -86,17 +87,16 @@ message Track { repeated Availability availability = 19; optional Licensor licensor = 21; repeated string language_of_performance = 22; + optional Audio original_audio = 24; repeated ContentRating content_rating = 25; optional string original_title = 27; optional string version_title = 28; repeated ArtistWithRole artist_with_role = 32; + optional string canonical_uri = 36; + repeated Video original_video = 38; } message ArtistWithRole { - optional bytes artist_gid = 1; - optional string artist_name = 2; - - optional ArtistRole role = 3; enum ArtistRole { ARTIST_ROLE_UNKNOWN = 0; ARTIST_ROLE_MAIN_ARTIST = 1; @@ -107,6 +107,10 @@ message ArtistWithRole { ARTIST_ROLE_CONDUCTOR = 6; ARTIST_ROLE_ORCHESTRA = 7; } + + optional bytes artist_gid = 1; + optional string artist_name = 2; + optional ArtistRole role = 3; } message Show { @@ -122,25 +126,26 @@ message Show { repeated Copyright copyright = 71; repeated Restriction restriction = 72; repeated string keyword = 73; - + optional MediaType media_type = 74; enum MediaType { MIXED = 0; AUDIO = 1; VIDEO = 2; } - + optional ConsumptionOrder consumption_order = 75; enum ConsumptionOrder { SEQUENTIAL = 1; EPISODIC = 2; RECENT = 3; } - + repeated Availability availability = 78; optional string trailer_uri = 83; optional bool music_and_talk = 85; optional bool is_audiobook = 89; + optional bool is_creator_channel = 90; } message Episode { @@ -165,23 +170,29 @@ message Episode { optional bool allow_background_playback = 81; repeated Availability availability = 82; optional string external_url = 83; - - optional EpisodeType type = 87; + optional Audio original_audio = 84; + + optional Episode.EpisodeType type = 87; enum EpisodeType { FULL = 0; TRAILER = 1; BONUS = 2; } - + optional bool music_and_talk = 91; repeated ContentRating content_rating = 95; optional bool is_audiobook_chapter = 96; + optional bool is_podcast_short = 97; } message Licensor { optional bytes uuid = 1; } +message Audio { + optional bytes uuid = 1; +} + message TopTracks { optional string country = 1; repeated Track track = 2; @@ -206,16 +217,15 @@ message Date { } message Image { - optional bytes file_id = 1; - - optional Size size = 2; enum Size { DEFAULT = 0; SMALL = 1; LARGE = 2; XLARGE = 3; } - + + optional bytes file_id = 1; + optional Size size = 2; optional sint32 width = 3; optional sint32 height = 4; } @@ -237,17 +247,16 @@ message Disc { } message Copyright { - optional Type type = 1; enum Type { P = 0; C = 1; } - + + optional Type type = 1; optional string text = 2; } message Restriction { - repeated Catalogue catalogue = 1; enum Catalogue { AD = 0; SUBSCRIPTION = 1; @@ -255,14 +264,14 @@ message Restriction { SHUFFLE = 3; COMMERCIAL = 4; } - - optional Type type = 4; + enum Type { STREAMING = 0; } - + + repeated Catalogue catalogue = 1; + optional Type type = 4; repeated string catalogue_str = 5; - oneof country_restriction { string countries_allowed = 2; string countries_forbidden = 3; @@ -286,9 +295,6 @@ message ExternalId { } message AudioFile { - optional bytes file_id = 1; - - optional Format format = 2 [default = UNKNOWN_FORMAT]; enum Format { OGG_VORBIS_96 = 0; OGG_VORBIS_160 = 1; @@ -300,13 +306,19 @@ message AudioFile { MP3_160_ENC = 7; AAC_24 = 8; AAC_48 = 9; - AAC_160 = 10; - AAC_320 = 11; - MP4_128 = 12; - OTHER5 = 13; FLAC_FLAC = 16; - UNKNOWN_FORMAT = 255; + XHE_AAC_24 = 18; + XHE_AAC_16 = 19; + XHE_AAC_12 = 20; + FLAC_FLAC_24BIT = 22; } + + optional bytes file_id = 1; + optional Format format = 2; +} + +message Video { + optional bytes gid = 1; } message VideoFile { diff --git a/protocol/proto/metadata/album_metadata.proto b/protocol/proto/metadata/album_metadata.proto index 5a7de5f9a..8df63e7da 100644 --- a/protocol/proto/metadata/album_metadata.proto +++ b/protocol/proto/metadata/album_metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata/artist_metadata.proto b/protocol/proto/metadata/artist_metadata.proto index 4e5e9bfe8..8521fdde4 100644 --- a/protocol/proto/metadata/artist_metadata.proto +++ b/protocol/proto/metadata/artist_metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata/episode_metadata.proto b/protocol/proto/metadata/episode_metadata.proto index 5d4a0b25f..fa77b59d5 100644 --- a/protocol/proto/metadata/episode_metadata.proto +++ b/protocol/proto/metadata/episode_metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -6,8 +6,6 @@ package spotify.cosmos_util.proto; import "metadata/extension.proto"; import "metadata/image_group.proto"; -import "podcast_segments.proto"; -import "podcast_subscription.proto"; option java_multiple_files = true; option optimize_for = CODE_SIZE; @@ -21,6 +19,9 @@ message EpisodeShowMetadata { } message EpisodeMetadata { + reserved 20; + reserved 21; + optional EpisodeShowMetadata show = 1; optional string link = 2; optional string name = 3; @@ -32,20 +33,20 @@ message EpisodeMetadata { optional ImageGroup freeze_frames = 9; optional string language = 10; optional bool available = 11; - + optional MediaType media_type_enum = 12; enum MediaType { VODCAST = 0; AUDIO = 1; VIDEO = 2; } - + optional int32 number = 13; optional bool backgroundable = 14; optional string preview_manifest_id = 15; optional bool is_explicit = 16; optional string preview_id = 17; - + optional EpisodeType episode_type = 18; enum EpisodeType { UNKNOWN = 0; @@ -53,11 +54,12 @@ message EpisodeMetadata { TRAILER = 2; BONUS = 3; } - + optional bool is_music_and_talk = 19; - optional podcast_segments.PodcastSegments podcast_segments = 20; - optional podcast_paywalls.PodcastSubscription podcast_subscription = 21; repeated Extension extension = 22; optional bool is_19_plus_only = 23; optional bool is_book_chapter = 24; + optional bool is_podcast_short = 25; + optional bool is_curated = 26; } + diff --git a/protocol/proto/metadata/extension.proto b/protocol/proto/metadata/extension.proto index b10a0f080..7a4b46790 100644 --- a/protocol/proto/metadata/extension.proto +++ b/protocol/proto/metadata/extension.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata/image_group.proto b/protocol/proto/metadata/image_group.proto index 310a408b3..779249042 100644 --- a/protocol/proto/metadata/image_group.proto +++ b/protocol/proto/metadata/image_group.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata/show_metadata.proto b/protocol/proto/metadata/show_metadata.proto index 9b9891d32..76a4bb5f1 100644 --- a/protocol/proto/metadata/show_metadata.proto +++ b/protocol/proto/metadata/show_metadata.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -28,4 +28,5 @@ message ShowMetadata { optional bool is_music_and_talk = 14; repeated Extension extension = 15; optional bool is_book = 16; + optional bool is_creator_channel = 17; } diff --git a/protocol/proto/metadata/track_metadata.proto b/protocol/proto/metadata/track_metadata.proto index 08bff4015..9916b797b 100644 --- a/protocol/proto/metadata/track_metadata.proto +++ b/protocol/proto/metadata/track_metadata.proto @@ -1,9 +1,10 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.cosmos_util.proto; +import "metadata/extension.proto"; import "metadata/image_group.proto"; option java_multiple_files = true; @@ -30,6 +31,7 @@ message TrackArtistMetadata { message TrackDescriptor { optional string name = 1; + optional float weight = 2; } message TrackMetadata { @@ -52,4 +54,7 @@ message TrackMetadata { optional uint32 popularity = 17; optional bool is_19_plus_only = 18; repeated TrackDescriptor track_descriptors = 19; + repeated Extension extension = 20; + optional bool is_curated = 21; + optional bool to_be_obfuscated = 22; } diff --git a/protocol/proto/metadata_cosmos.proto b/protocol/proto/metadata_cosmos.proto index f04e5957a..bc2b2a428 100644 --- a/protocol/proto/metadata_cosmos.proto +++ b/protocol/proto/metadata_cosmos.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/metadata_esperanto.proto b/protocol/proto/metadata_esperanto.proto index 601290a11..26ec73cf7 100644 --- a/protocol/proto/metadata_esperanto.proto +++ b/protocol/proto/metadata_esperanto.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/modification_request.proto b/protocol/proto/modification_request.proto index d35b613c4..f8da2506f 100644 --- a/protocol/proto/modification_request.proto +++ b/protocol/proto/modification_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -14,7 +14,7 @@ message ModificationRequest { optional string after = 3; optional string name = 4; optional bool playlist = 5; - + optional Attributes attributes = 6; message Attributes { optional bool published = 1; @@ -23,15 +23,48 @@ message ModificationRequest { optional string description = 4; optional string imageUri = 5; optional string picture = 6; + optional string ai_curation_reference_id = 7; + optional PublishedState published_state = 8; } - + repeated string uris = 7; repeated string rows = 8; optional bool contents = 9; optional string item_id = 10; + repeated ListAttributeKind attributes_to_clear = 11; + optional CreateItemKind create_item_kind = 12; } message ModificationResponse { optional bool success = 1; optional string uri = 2; } + +enum ListAttributeKind { + LIST_UNKNOWN = 0; + LIST_NAME = 1; + LIST_DESCRIPTION = 2; + LIST_PICTURE = 3; + LIST_COLLABORATIVE = 4; + LIST_PL3_VERSION = 5; + LIST_DELETED_BY_OWNER = 6; + LIST_CLIENT_ID = 10; + LIST_FORMAT = 11; + LIST_FORMAT_ATTRIBUTES = 12; + LIST_PICTURE_SIZE = 13; + LIST_SEQUENCE_CONTEXT_TEMPLATE = 14; + LIST_AI_CURATION_REFERENCE_ID = 15; +} + +enum PublishedState { + PUBLISHED_STATE_UNSPECIFIED = 0; + PUBLISHED_STATE_NOT_PUBLISHED = 1; + PUBLISHED_STATE_PUBLISHED = 2; +} + +enum CreateItemKind { + CREATE_ITEM_KIND_UNSPECIFIED = 0; + CREATE_ITEM_KIND_PLAYLIST = 1; + CREATE_ITEM_KIND_FOLDER = 2; +} + diff --git a/protocol/proto/net-fortune.proto b/protocol/proto/net-fortune.proto index dbf476b20..62ba5e09b 100644 --- a/protocol/proto/net-fortune.proto +++ b/protocol/proto/net-fortune.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,4 +13,6 @@ message NetFortuneResponse { message NetFortuneV2Response { string predict_id = 1; int32 estimated_max_bitrate = 2; + optional int32 advised_prefetch_bitrate_metered = 3; + optional int32 advised_prefetch_bitrate_non_metered = 4; } diff --git a/protocol/proto/offline.proto b/protocol/proto/offline.proto index b3d124919..f84a73c97 100644 --- a/protocol/proto/offline.proto +++ b/protocol/proto/offline.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -17,6 +17,10 @@ message Capacity { uint64 episode_count = 5; } +message Capabilities { + bool remote_downloads_enabled = 1; +} + message Device { string device_id = 1; string cache_id = 2; @@ -25,9 +29,11 @@ message Device { int32 platform = 5; bool offline_enabled = 6; Capacity capacity = 7; + Capabilities capabilities = 8; google.protobuf.Timestamp updated_at = 9; google.protobuf.Timestamp last_seen_at = 10; bool removal_pending = 11; + string client_id = 12; } message Restrictions { @@ -35,6 +41,7 @@ message Restrictions { uint64 max_tracks = 2; google.protobuf.Duration allowed_duration_episodes = 3; uint64 max_episodes = 4; + google.protobuf.Duration allowed_duration_abp_chapters = 5; } message Resource { @@ -58,13 +65,13 @@ message ResourceForDevice { } message ResourceOperation { - Operation operation = 2; enum Operation { INVALID = 0; ADD = 1; REMOVE = 2; } - + + Operation operation = 2; string uri = 3; } diff --git a/protocol/proto/offline_playlists_containing.proto b/protocol/proto/offline_playlists_containing.proto index 3d75865f7..7573f493c 100644 --- a/protocol/proto/offline_playlists_containing.proto +++ b/protocol/proto/offline_playlists_containing.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/on_demand_in_free_reason.proto b/protocol/proto/on_demand_in_free_reason.proto index bf3a820ef..164d22aa2 100644 --- a/protocol/proto/on_demand_in_free_reason.proto +++ b/protocol/proto/on_demand_in_free_reason.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -11,4 +11,5 @@ enum OnDemandInFreeReason { NOT_ON_DEMAND = 1; ON_DEMAND = 2; ON_DEMAND_EPISODES_ONLY = 3; + ON_DEMAND_NON_MUSIC_ONLY = 4; } diff --git a/protocol/proto/on_demand_set_cosmos_request.proto b/protocol/proto/on_demand_set_cosmos_request.proto index 72d4d3d91..ebbd0f537 100644 --- a/protocol/proto/on_demand_set_cosmos_request.proto +++ b/protocol/proto/on_demand_set_cosmos_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/on_demand_set_cosmos_response.proto b/protocol/proto/on_demand_set_cosmos_response.proto index 8ca68cbe2..9a17849b6 100644 --- a/protocol/proto/on_demand_set_cosmos_response.proto +++ b/protocol/proto/on_demand_set_cosmos_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/on_demand_set_response.proto b/protocol/proto/on_demand_set_response.proto index 9d914dd76..9633bb26f 100644 --- a/protocol/proto/on_demand_set_response.proto +++ b/protocol/proto/on_demand_set_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/pause_resume_origin.proto b/protocol/proto/pause_resume_origin.proto new file mode 100644 index 000000000..b65d3db27 --- /dev/null +++ b/protocol/proto/pause_resume_origin.proto @@ -0,0 +1,12 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + +syntax = "proto2"; + +package spotify.player.proto; + +option optimize_for = CODE_SIZE; + +message PauseResumeOrigin { + optional string feature_identifier = 1; +} + diff --git a/protocol/proto/pending_event_entity.proto b/protocol/proto/pending_event_entity.proto index 0dd5c099a..965b8cab5 100644 --- a/protocol/proto/pending_event_entity.proto +++ b/protocol/proto/pending_event_entity.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/pin_request.proto b/protocol/proto/pin_request.proto index a53373206..bbc388d7e 100644 --- a/protocol/proto/pin_request.proto +++ b/protocol/proto/pin_request.proto @@ -1,25 +1,42 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; +option java_package = "spotify.your_library.esperanto.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; message PinRequest { string uri = 1; + oneof position { + string after_uri = 2; + string before_uri = 3; + bool first = 4; + } +} + +message MovePinRequest { + string move_uri = 1; + oneof position { + string after_uri = 2; + string before_uri = 3; + bool first = 4; + } } message PinResponse { - PinStatus status = 1; enum PinStatus { UNKNOWN = 0; PINNED = 1; NOT_PINNED = 2; } - + + PinStatus status = 1; bool has_maximum_pinned_items = 2; int32 maximum_pinned_items = 3; + uint32 status_code = 98; string error = 99; } @@ -28,7 +45,3 @@ message PinItem { bool in_library = 2; } -message PinList { - repeated PinItem item = 1; - string error = 99; -} diff --git a/protocol/proto/play_history.proto b/protocol/proto/play_history.proto new file mode 100644 index 000000000..f2a4a789c --- /dev/null +++ b/protocol/proto/play_history.proto @@ -0,0 +1,20 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + +syntax = "proto2"; + +package spotify.player.proto.transfer; + +option optimize_for = CODE_SIZE; + +message PlayHistory { + message Item { + optional string context_id = 1; + optional string uid = 2; + optional bool disliked = 3; + repeated transfer.PlayHistory.Item children = 4; + } + + repeated transfer.PlayHistory.Item backward_items = 1; + repeated transfer.PlayHistory.Item forward_items = 2; +} + diff --git a/protocol/proto/play_origin.proto b/protocol/proto/play_origin.proto index 53bb07061..02903cec6 100644 --- a/protocol/proto/play_origin.proto +++ b/protocol/proto/play_origin.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -14,4 +14,5 @@ message PlayOrigin { optional string referrer_identifier = 5; optional string device_identifier = 6; repeated string feature_classes = 7; + optional string restriction_identifier = 8; } diff --git a/protocol/proto/play_queue_node.proto b/protocol/proto/play_queue_node.proto index d79a98250..bf763dfd7 100644 --- a/protocol/proto/play_queue_node.proto +++ b/protocol/proto/play_queue_node.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -16,4 +16,5 @@ message PlayQueueNode { optional TrackInstantiator instantiator = 3; optional uint32 next_uid = 4; optional sint32 iteration = 5; + optional bool delay_enqueued_tracks = 6; } diff --git a/protocol/proto/play_reason.proto b/protocol/proto/play_reason.proto index 04bba83f4..c124ebaee 100644 --- a/protocol/proto/play_reason.proto +++ b/protocol/proto/play_reason.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -29,4 +29,6 @@ enum PlayReason { PLAY_REASON_OFFLINE = 18; PLAY_REASON_UNEXPECTED_EXIT = 19; PLAY_REASON_UNEXPECTED_EXIT_WHILE_PAUSED = 20; + PLAY_REASON_SWITCHED_TO_AUDIO = 21; + PLAY_REASON_SWITCHED_TO_VIDEO = 22; } diff --git a/protocol/proto/playback.proto b/protocol/proto/playback.proto index 94d8ae7e1..06dcfcc92 100644 --- a/protocol/proto/playback.proto +++ b/protocol/proto/playback.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -14,4 +14,6 @@ message Playback { optional double playback_speed = 3; optional bool is_paused = 4; optional ContextTrack current_track = 5; + optional ContextTrack associated_current_track = 6; + optional int32 associated_position_as_of_timestamp = 7; } diff --git a/protocol/proto/playback_esperanto.proto b/protocol/proto/playback_esperanto.proto index 3c57325aa..80ae1a7ac 100644 --- a/protocol/proto/playback_esperanto.proto +++ b/protocol/proto/playback_esperanto.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,30 +8,55 @@ option objc_class_prefix = "ESP"; option optimize_for = CODE_SIZE; option java_package = "com.spotify.playback_esperanto.proto"; +message ConnectLoggingParams { + repeated string interaction_ids = 1; + repeated string page_instance_ids = 2; +} + message GetVolumeResponse { Status status = 1; double volume = 2; } +message GetRawVolumeResponse { + Status status = 1; + int32 volume = 2; +} + message SubVolumeResponse { Status status = 1; double volume = 2; VolumeChangeSource source = 3; } +message SubRawVolumeResponse { + Status status = 1; + int32 volume = 2; + VolumeChangeSource source = 3; +} + message SetVolumeRequest { VolumeChangeSource source = 1; double volume = 2; + ConnectLoggingParams connect_logging_params = 3; +} + +message SetRawVolumeRequest { + VolumeChangeSource source = 1; + int32 volume = 2; + ConnectLoggingParams connect_logging_params = 3; } message NudgeVolumeRequest { VolumeChangeSource source = 1; + ConnectLoggingParams connect_logging_params = 2; } message PlaybackInfoResponse { + reserved 3; + reserved 16; Status status = 1; uint64 length_ms = 2; - uint64 position_ms = 3; bool playing = 4; bool buffering = 5; int32 error = 6; @@ -48,12 +73,10 @@ message PlaybackInfoResponse { int32 target_bitrate = 18; int32 advised_bitrate = 19; bool target_file_available = 20; - - reserved 16; + string audio_id = 21; } message GetFormatsResponse { - repeated Format formats = 1; message Format { string enum_key = 1; uint32 enum_value = 2; @@ -61,6 +84,8 @@ message GetFormatsResponse { uint32 bitrate = 4; string mime_type = 5; } + + repeated GetFormatsResponse.Format formats = 1; } message SubPositionRequest { @@ -77,24 +102,24 @@ message GetFilesRequest { } message GetFilesResponse { - GetFilesStatus status = 1; - - repeated File files = 2; message File { string file_id = 1; string format = 2; uint32 bitrate = 3; uint32 format_enum = 4; } + + GetFilesStatus status = 1; + repeated File files = 2; } message DuckRequest { - Action action = 2; enum Action { START = 0; STOP = 1; } - + + Action action = 2; double volume = 3; uint32 fade_duration_ms = 4; } @@ -119,4 +144,5 @@ enum GetFilesStatus { enum VolumeChangeSource { USER = 0; SYSTEM = 1; + CONNECT = 2; } diff --git a/protocol/proto/playback_stack.proto b/protocol/proto/playback_stack.proto new file mode 100644 index 000000000..81ebf7523 --- /dev/null +++ b/protocol/proto/playback_stack.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package spotify.stream_reporting_esperanto.proto; + +option java_package = "com.spotify.stream_reporting_esperanto.proto"; +option objc_class_prefix = "ESP"; + +enum PlaybackStack { + BOOMBOX = 0; + BETAMAX = 1; + UNKNOWN = 2; +} + diff --git a/protocol/proto/playback_stack_v2.proto b/protocol/proto/playback_stack_v2.proto new file mode 100644 index 000000000..302b1bb4e --- /dev/null +++ b/protocol/proto/playback_stack_v2.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package spotify.stream_reporting_esperanto.proto; + +option java_package = "com.spotify.stream_reporting_esperanto.proto"; +option objc_class_prefix = "ESP"; + +enum PlaybackStackV2 { + PLAYBACK_STACK_UNKNOWN = 0; + PLAYBACK_STACK_BOOMBOX = 1; + PLAYBACK_STACK_BETAMAX = 2; + PLAYBACK_STACK_KUBRICK = 3; +} + diff --git a/protocol/proto/playback_state.proto b/protocol/proto/playback_state.proto new file mode 100644 index 000000000..aaf34a777 --- /dev/null +++ b/protocol/proto/playback_state.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package spotify.stream_reporting_esperanto.proto; + +option java_package = "com.spotify.stream_reporting_esperanto.proto"; +option objc_class_prefix = "ESP"; + +enum PlaybackState { + ACTIVE = 0; + PAUSED = 1; + SUSPENDED = 2; + INVALID_PLAYBACK_STATE = 3; +} + diff --git a/protocol/proto/played_state.proto b/protocol/proto/played_state.proto index 58990254e..f13715789 100644 --- a/protocol/proto/played_state.proto +++ b/protocol/proto/played_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/played_state/episode_played_state.proto b/protocol/proto/played_state/episode_played_state.proto index 696b2e7ac..6a90905dc 100644 --- a/protocol/proto/played_state/episode_played_state.proto +++ b/protocol/proto/played_state/episode_played_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/played_state/playability_restriction.proto b/protocol/proto/played_state/playability_restriction.proto index d6de6f4e3..b1471fc05 100644 --- a/protocol/proto/played_state/playability_restriction.proto +++ b/protocol/proto/played_state/playability_restriction.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -15,4 +15,5 @@ enum PlayabilityRestriction { AGE_RESTRICTED = 3; NOT_IN_CATALOGUE = 4; NOT_AVAILABLE_OFFLINE = 5; + PREMIUM_ONLY = 6; } diff --git a/protocol/proto/played_state/show_played_state.proto b/protocol/proto/played_state/show_played_state.proto index 47f13ec7f..912c7dbf1 100644 --- a/protocol/proto/played_state/show_played_state.proto +++ b/protocol/proto/played_state/show_played_state.proto @@ -1,14 +1,29 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.cosmos_util.proto; +import "played_state/playability_restriction.proto"; + option objc_class_prefix = "SPTCosmosUtil"; option java_multiple_files = true; option optimize_for = CODE_SIZE; option java_package = "com.spotify.cosmos.util.proto"; message ShowPlayState { + enum Label { + UNKNOWN_LABEL = 0; + NOT_STARTED = 1; + IN_PROGRESS = 2; + COMPLETED = 3; + } + optional string latest_played_episode_link = 1; + optional uint64 played_time = 2; + optional bool is_playable = 3; + optional PlayabilityRestriction playability_restriction = 4 [default = UNKNOWN]; + optional Label label = 5; + optional uint32 played_percentage = 6; + optional string resume_episode_link = 7; } diff --git a/protocol/proto/played_state/track_played_state.proto b/protocol/proto/played_state/track_played_state.proto index 3a8e4c869..2f26c7741 100644 --- a/protocol/proto/played_state/track_played_state.proto +++ b/protocol/proto/played_state/track_played_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/player.proto b/protocol/proto/player.proto index dfe5e5ab3..3b5716c3f 100644 --- a/protocol/proto/player.proto +++ b/protocol/proto/player.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,6 +8,14 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.connectstate.model"; message PlayerState { + reserved 26; + reserved 27; + reserved 28; + reserved 29; + reserved 30; + reserved 31; + reserved 34; + int64 timestamp = 1; string context_uri = 2; string context_url = 3; @@ -33,16 +41,14 @@ message PlayerState { string session_id = 23; string queue_revision = 24; int64 position = 25; - string entity_uri = 26; - repeated ProvidedTrack reverse = 27; - repeated ProvidedTrack future = 28; - string audio_stream = 29; - bool is_optional = 30 [deprecated = true]; - int64 bitrate = 31 [deprecated = true]; PlaybackQuality playback_quality = 32; + repeated string signals = 33; + string session_command_id = 35; } message ProvidedTrack { + reserved 11; + string uri = 1; string uid = 2; map metadata = 3; @@ -53,7 +59,6 @@ message ProvidedTrack { string album_uri = 8; repeated string disallow_reasons = 9; string artist_uri = 10; - repeated string disallow_undecided = 11; } message ContextIndex { @@ -61,7 +66,18 @@ message ContextIndex { uint32 track = 2; } +message ModeRestrictions { + map values = 1; +} + +message RestrictionReasons { + repeated string reasons = 1; +} + message Restrictions { + reserved 26; + reserved 27; + repeated string disallow_pausing_reasons = 1; repeated string disallow_resuming_reasons = 2; repeated string disallow_seeking_reasons = 3; @@ -85,6 +101,10 @@ message Restrictions { repeated string disallow_updating_context_reasons = 21; repeated string disallow_playing_reasons = 22; repeated string disallow_stopping_reasons = 23; + repeated string disallow_add_to_queue_reasons = 24; + repeated string disallow_setting_playback_speed_reasons = 25; + map disallow_setting_modes = 28; + map disallow_signals = 29; } message PlayOrigin { @@ -95,89 +115,21 @@ message PlayOrigin { string referrer_identifier = 5; string device_identifier = 6; repeated string feature_classes = 7; + string restriction_identifier = 8; } message ContextPlayerOptions { bool shuffling_context = 1; bool repeating_context = 2; bool repeating_track = 3; + map modes = 5; + optional float playback_speed = 4; } message Suppressions { repeated string providers = 1; } -message InstrumentationParams { - repeated string interaction_ids = 6; - repeated string page_instance_ids = 7; -} - -message Playback { - int64 timestamp = 1; - int32 position_as_of_timestamp = 2; - double playback_speed = 3; - bool is_paused = 4; - ContextTrack current_track = 5; -} - -message Queue { - repeated ContextTrack tracks = 1; - bool is_playing_queue = 2; -} - -message Session { - PlayOrigin play_origin = 1; - Context context = 2; - string current_uid = 3; - ContextPlayerOptionOverrides option_overrides = 4; - Suppressions suppressions = 5; - InstrumentationParams instrumentation_params = 6; -} - -message TransferState { - ContextPlayerOptions options = 1; - Playback playback = 2; - Session current_session = 3; - Queue queue = 4; -} - -message ContextTrack { - string uri = 1; - string uid = 2; - bytes gid = 3; - map metadata = 4; -} - -message ContextPlayerOptionOverrides { - bool shuffling_context = 1; - bool repeating_context = 2; - bool repeating_track = 3; -} - -message Context { - string uri = 1; - string url = 2; - map metadata = 3; - Restrictions restrictions = 4; - repeated ContextPage pages = 5; - bool loading = 6; -} - -message ContextPage { - string page_url = 1; - string next_page_url = 2; - map metadata = 3; - repeated ContextTrack tracks = 4; - bool loading = 5; -} - -message PlayerQueue { - string revision = 1; - repeated ProvidedTrack next_tracks = 2; - repeated ProvidedTrack prev_tracks = 3; - ProvidedTrack track = 4; -} - message PlaybackQuality { BitrateLevel bitrate_level = 1; BitrateStrategy strategy = 2; @@ -193,6 +145,7 @@ enum BitrateLevel { high = 3; very_high = 4; hifi = 5; + hifi24 = 6; } enum BitrateStrategy { diff --git a/protocol/proto/player_license.proto b/protocol/proto/player_license.proto index 3d0e905dd..106bb3562 100644 --- a/protocol/proto/player_license.proto +++ b/protocol/proto/player_license.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/playlist4_external.proto b/protocol/proto/playlist4_external.proto index 2a7b44b9b..1e4f4e7c7 100644 --- a/protocol/proto/playlist4_external.proto +++ b/protocol/proto/playlist4_external.proto @@ -1,10 +1,12 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.playlist4.proto; +import "lens-model.proto"; import "playlist_permission.proto"; +import "signal-model.proto"; option optimize_for = CODE_SIZE; option java_outer_classname = "Playlist4ApiProto"; @@ -22,7 +24,9 @@ message MetaItem { optional int64 timestamp = 4; optional string owner_username = 5; optional bool abuse_reporting_enabled = 6; - optional spotify.playlist_permission.proto.Capabilities capabilities = 7; + optional playlist_permission.proto.Capabilities capabilities = 7; + repeated GeoblockBlockingType geoblock = 8; + optional sint32 status_code = 9; } message ListItems { @@ -30,6 +34,25 @@ message ListItems { required bool truncated = 2; repeated Item items = 3; repeated MetaItem meta_items = 4; + repeated playlist.signal.proto.Signal available_signals = 5; + optional string continuation_token = 6; +} + +message PaginatedUnfollowedListItems { + optional int32 limit = 1; + optional int32 offset = 2; + optional int32 nextPageIndex = 3; + optional int32 previousPageIndex = 4; + optional int32 totalPages = 5; + repeated UnfollowedListItem items = 6; +} + +message UnfollowedListItem { + optional string uri = 1; + optional bool recoverable = 2; + optional string name = 3; + optional int64 deleted_at = 4; + optional int32 length = 5; } message FormatListAttribute { @@ -42,6 +65,10 @@ message PictureSize { optional string url = 2; } +message RecommendationInfo { + optional bool is_recommendation = 1; +} + message ListAttributes { optional string name = 1; optional string description = 2; @@ -53,6 +80,8 @@ message ListAttributes { optional string format = 11; repeated FormatListAttribute format_attributes = 12; repeated PictureSize picture_size = 13; + optional bytes sequence_context_template = 14; + optional bytes ai_curation_reference_id = 15; } message ItemAttributes { @@ -62,6 +91,10 @@ message ItemAttributes { optional bool public = 10; repeated FormatListAttribute format_attributes = 11; optional bytes item_id = 12; + optional lens.model.proto.Lens source_lens = 13; + repeated playlist.signal.proto.Signal available_signals = 14; + optional RecommendationInfo recommendation_info = 15; + optional bytes sequence_child_template = 16; } message Add { @@ -69,6 +102,8 @@ message Add { repeated Item items = 2; optional bool add_last = 4; optional bool add_first = 5; + optional Item add_before_item = 6; + optional Item add_after_item = 7; } message Rem { @@ -79,9 +114,14 @@ message Rem { } message Mov { - required int32 from_index = 1; - required int32 length = 2; - required int32 to_index = 3; + optional int32 from_index = 1; + optional int32 length = 2; + optional int32 to_index = 3; + repeated Item items = 4; + optional Item add_before_item = 5; + optional Item add_after_item = 6; + optional bool add_first = 7; + optional bool add_last = 8; } message ItemAttributesPartialState { @@ -95,9 +135,10 @@ message ListAttributesPartialState { } message UpdateItemAttributes { - required int32 index = 1; + optional int32 index = 1; required ItemAttributesPartialState new_attributes = 2; optional ItemAttributesPartialState old_attributes = 3; + optional Item item = 4; } message UpdateListAttributes { @@ -105,8 +146,17 @@ message UpdateListAttributes { optional ListAttributesPartialState old_attributes = 2; } +message UpdateItemUris { + repeated UriReplacement uri_replacements = 1; +} + +message UriReplacement { + optional int32 index = 1; + optional Item item = 2; + optional string new_uri = 3; +} + message Op { - required Kind kind = 1; enum Kind { KIND_UNKNOWN = 0; ADD = 2; @@ -114,13 +164,16 @@ message Op { MOV = 4; UPDATE_ITEM_ATTRIBUTES = 5; UPDATE_LIST_ATTRIBUTES = 6; + UPDATE_ITEM_URIS = 7; } - + + required Kind kind = 1; optional Add add = 2; optional Rem rem = 3; optional Mov mov = 4; optional UpdateItemAttributes update_item_attributes = 5; optional UpdateListAttributes update_list_attributes = 6; + optional UpdateItemUris update_item_uris = 7; } message OpList { @@ -141,7 +194,6 @@ message ChangeInfo { } message SourceInfo { - optional Client client = 1; enum Client { CLIENT_UNKNOWN = 0; NATIVE_HERMES = 1; @@ -151,10 +203,12 @@ message SourceInfo { WEBPLAYER = 5; LIBSPOTIFY = 6; } - + + optional Client client = 1; optional string app = 3; optional string source = 4; optional string version = 5; + optional string server_domain = 6; } message Delta { @@ -177,6 +231,11 @@ message ListChanges { repeated int64 nonces = 6; } +message ListSignals { + optional bytes base_revision = 1; + repeated playlist.signal.proto.Signal emitted_signals = 2; +} + message SelectedListContent { optional bytes revision = 1; optional int32 length = 2; @@ -193,6 +252,13 @@ message SelectedListContent { optional bool abuse_reporting_enabled = 17; optional spotify.playlist_permission.proto.Capabilities capabilities = 18; repeated GeoblockBlockingType geoblock = 19; + optional bool changes_require_resync = 20; + optional int64 created_at = 21; + optional AppliedLenses applied_lenses = 22; +} + +message AppliedLenses { + repeated lens.model.proto.LensState states = 1; } message CreateListReply { @@ -272,6 +338,8 @@ enum ListAttributeKind { LIST_FORMAT = 11; LIST_FORMAT_ATTRIBUTES = 12; LIST_PICTURE_SIZE = 13; + LIST_SEQUENCE_CONTEXT_TEMPLATE = 14; + LIST_AI_CURATION_REFERENCE_ID = 15; } enum ItemAttributeKind { @@ -282,6 +350,10 @@ enum ItemAttributeKind { ITEM_PUBLIC = 10; ITEM_FORMAT_ATTRIBUTES = 11; ITEM_ID = 12; + ITEM_SOURCE_LENS = 13; + ITEM_AVAILABLE_SIGNALS = 14; + ITEM_RECOMMENDATION_INFO = 15; + ITEM_SEQUENCE_CHILD_TEMPLATE = 16; } enum GeoblockBlockingType { @@ -290,3 +362,4 @@ enum GeoblockBlockingType { GEOBLOCK_BLOCKING_TYPE_DESCRIPTION = 2; GEOBLOCK_BLOCKING_TYPE_IMAGE = 3; } + diff --git a/protocol/proto/playlist_contains_request.proto b/protocol/proto/playlist_contains_request.proto index 072d53796..c18e48497 100644 --- a/protocol/proto/playlist_contains_request.proto +++ b/protocol/proto/playlist_contains_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_folder_state.proto b/protocol/proto/playlist_folder_state.proto index a2d32d715..c78e3e781 100644 --- a/protocol/proto/playlist_folder_state.proto +++ b/protocol/proto/playlist_folder_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/playlist_get_request.proto b/protocol/proto/playlist_get_request.proto index 7e6dd3f0d..5ed15ee30 100644 --- a/protocol/proto/playlist_get_request.proto +++ b/protocol/proto/playlist_get_request.proto @@ -1,9 +1,10 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.playlist_esperanto.proto; +import "google/protobuf/duration.proto"; import "policy/playlist_request_decoration_policy.proto"; import "playlist_query.proto"; import "playlist_request.proto"; @@ -20,7 +21,30 @@ message PlaylistGetRequest { playlist.cosmos.proto.PlaylistRequestDecorationPolicy policy = 3; } +message PlaylistMultiGetSingleRequest { + string id = 1; + PlaylistGetRequest request = 2; +} + +message PlaylistMultiGetRequest { + repeated PlaylistMultiGetSingleRequest requests = 1; + google.protobuf.Duration timeout = 2; +} + message PlaylistGetResponse { ResponseStatus status = 1; playlist.cosmos.playlist_request.proto.Response data = 2; + PlaylistQuery query = 3; +} + +message PlaylistMultiGetSingleResponse { + string id = 1; + string uri = 2; + PlaylistGetResponse response = 3; } + +message PlaylistMultiGetResponse { + ResponseStatus status = 1; + repeated PlaylistMultiGetSingleResponse responses = 2; +} + diff --git a/protocol/proto/playlist_members_request.proto b/protocol/proto/playlist_members_request.proto index d5bd9b98c..d7304257a 100644 --- a/protocol/proto/playlist_members_request.proto +++ b/protocol/proto/playlist_members_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_modification_request.proto b/protocol/proto/playlist_modification_request.proto index 2bdb01464..c5fea0b47 100644 --- a/protocol/proto/playlist_modification_request.proto +++ b/protocol/proto/playlist_modification_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_offline_request.proto b/protocol/proto/playlist_offline_request.proto index e0ab6312c..30c7ebbbe 100644 --- a/protocol/proto/playlist_offline_request.proto +++ b/protocol/proto/playlist_offline_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_permission.proto b/protocol/proto/playlist_permission.proto index 96e9c06d7..f155f6e0e 100644 --- a/protocol/proto/playlist_permission.proto +++ b/protocol/proto/playlist_permission.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -13,6 +13,24 @@ message Permission { optional PermissionLevel permission_level = 2; } +message GrantableLevels { + repeated PermissionLevel base = 1; + repeated PermissionLevel member = 2; +} + +message AttributeCapabilities { + optional bool can_edit = 1; +} + +message ListAttributeCapabilities { + optional AttributeCapabilities name = 1; + optional AttributeCapabilities description = 2; + optional AttributeCapabilities picture = 3; + optional AttributeCapabilities collaborative = 4; + optional AttributeCapabilities deleted_by_owner = 6; + optional AttributeCapabilities ai_curation_reference_id = 15; +} + message Capabilities { optional bool can_view = 1; optional bool can_administrate_permissions = 2; @@ -20,6 +38,8 @@ message Capabilities { optional bool can_edit_metadata = 4; optional bool can_edit_items = 5; optional bool can_cancel_membership = 6; + optional GrantableLevels grantable_levels = 7; + optional ListAttributeCapabilities list_attribute_capabilities = 8; } message CapabilitiesMultiRequest { @@ -29,11 +49,17 @@ message CapabilitiesMultiRequest { optional string fallback_uri = 4; } +message CapabilitiesRequestOptions { + optional bool can_view_only = 1; +} + message CapabilitiesRequest { optional string username = 1; optional string user_id = 2; optional string uri = 3; optional bool user_is_owner = 4; + optional string permission_grant_token = 5; + optional CapabilitiesRequestOptions request_options = 6; } message CapabilitiesMultiResponse { @@ -82,9 +108,29 @@ message PermissionGrant { optional PermissionGrantOptions permission_grant_options = 2; } +message PermissionGrantDetails { + optional bool permission_level_downgraded = 1; +} + +message PermissionGrantDescription { + enum ClaimFailReason { + CLAIM_FAIL_REASON_UNSPECIFIED = 0; + CLAIM_FAIL_REASON_ANONYMOUS = 1; + CLAIM_FAIL_REASON_NO_GRANT_FOUND = 2; + CLAIM_FAIL_REASON_GRANT_EXPIRED = 3; + } + + optional PermissionGrantOptions permission_grant_options = 1; + optional ClaimFailReason claim_fail_reason = 2; + optional bool is_effective = 3; + optional Capabilities capabilities = 4; + repeated PermissionGrantDetails details = 5; +} + message ClaimPermissionGrantResponse { optional Permission user_permission = 1; optional Capabilities capabilities = 2; + repeated PermissionGrantDetails details = 3; } message ResponseStatus { @@ -92,9 +138,42 @@ message ResponseStatus { optional string status_message = 2; } +message PermissionIdentifier { + required PermissionIdentifierKind kind = 1; + optional string user_id = 2; +} + +message PermissionEntry { + optional PermissionIdentifier identifier = 1; + optional Permission permission = 2; +} + +message CreateInitialPermissions { + repeated PermissionEntry permission_entry = 1; +} + +message CreateInitialPermissionsResponse { + repeated PermissionEntry permission_entry = 1; +} + +message DefaultOwnerCapabilitiesResponse { + optional Capabilities capabilities = 1; +} + enum PermissionLevel { UNKNOWN = 0; BLOCKED = 1; VIEWER = 2; CONTRIBUTOR = 3; + MADE_FOR = 4; } + +enum PermissionIdentifierKind { + PERMISSION_IDENTIFIER_KIND_UNSPECIFIED = 0; + PERMISSION_IDENTIFIER_KIND_BASE = 1; + PERMISSION_IDENTIFIER_KIND_MEMBER = 2; + PERMISSION_IDENTIFIER_KIND_ABUSE = 3; + PERMISSION_IDENTIFIER_KIND_PROFILE = 4; + PERMISSION_IDENTIFIER_KIND_AUTHORIZED = 5; +} + diff --git a/protocol/proto/playlist_play_request.proto b/protocol/proto/playlist_play_request.proto index 032b2b2a5..eb1667567 100644 --- a/protocol/proto/playlist_play_request.proto +++ b/protocol/proto/playlist_play_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_playback_request.proto b/protocol/proto/playlist_playback_request.proto index 8cd202575..83435a31e 100644 --- a/protocol/proto/playlist_playback_request.proto +++ b/protocol/proto/playlist_playback_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_playlist_state.proto b/protocol/proto/playlist_playlist_state.proto index 5663252ce..28e783777 100644 --- a/protocol/proto/playlist_playlist_state.proto +++ b/protocol/proto/playlist_playlist_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -44,6 +44,8 @@ message PlaylistMetadata { optional string load_state = 19; optional User made_for = 20; repeated cosmos_util.proto.Extension extension = 21; + optional uint32 length_ignoring_text_filter = 22; + optional string ai_curation_reference_id = 23; } message PlaylistOfflineState { diff --git a/protocol/proto/playlist_query.proto b/protocol/proto/playlist_query.proto index afd97614b..1aedb0cfe 100644 --- a/protocol/proto/playlist_query.proto +++ b/protocol/proto/playlist_query.proto @@ -1,9 +1,11 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.playlist_esperanto.proto; +import "policy/supported_link_types_in_playlists.proto"; + option objc_class_prefix = "ESP"; option java_multiple_files = true; option optimize_for = CODE_SIZE; @@ -24,10 +26,14 @@ message PlaylistQuery { NOT_BANNED = 4; NOT_EXPLICIT = 5; NOT_EPISODE = 6; + NOT_RECOMMENDATION = 7; + UNPLAYED = 8; + IN_PROGRESS = 9; + NOT_FULLY_PLAYED = 10; } - + string text_filter = 2; - + SortBy sort_by = 3; enum SortBy { NO_SORT = 0; @@ -45,8 +51,16 @@ message PlaylistQuery { NAME_DESC = 12; ADD_TIME_ASC = 13; ADD_TIME_DESC = 14; + ADDED_BY_ASC = 15; + ADDED_BY_DESC = 16; + DURATION_ASC = 17; + DURATION_DESC = 18; + SHOW_NAME_ASC = 19; + SHOW_NAME_DESC = 20; + PUBLISH_DATE_ASC = 21; + PUBLISH_DATE_DESC = 22; } - + PlaylistRange range = 4; int32 update_throttling_ms = 5; bool group = 6; @@ -54,6 +68,16 @@ message PlaylistQuery { bool show_unavailable = 8; bool always_show_windowed = 9; bool load_recommendations = 10; + repeated playlist.cosmos.proto.LinkType supported_placeholder_types = 11; + repeated string descriptor_filter = 12; + string item_id_filter = 13; + + repeated AttributeFilter attribute_filter = 14; + message AttributeFilter { + repeated string contains_one_of = 1; + } + + bool include_all_placeholders = 15; } enum PlaylistSourceRestriction { diff --git a/protocol/proto/playlist_request.proto b/protocol/proto/playlist_request.proto index 52befb1fd..5ad7803d4 100644 --- a/protocol/proto/playlist_request.proto +++ b/protocol/proto/playlist_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -15,12 +15,40 @@ import "playlist_permission.proto"; import "playlist_playlist_state.proto"; import "playlist_track_state.proto"; import "playlist_user_state.proto"; +import "policy/supported_link_types_in_playlists.proto"; import "metadata/track_metadata.proto"; +import "metadata/extension.proto"; option objc_class_prefix = "SPTPlaylistCosmosPlaylist"; option optimize_for = CODE_SIZE; option java_package = "com.spotify.playlist.proto"; +message AvailableSignal { + optional string name = 1; + optional .spotify.playlist.cosmos.playlist_request.proto.SignalState state = 2; +} + +message ItemOfflineState { + optional string offline = 1; + optional uint32 sync_progress = 2; + optional bool locally_playable = 3; +} + +message ItemCollectionState { + optional bool is_in_collection = 1; + optional bool is_banned = 2; +} + +message ItemMetadata { + optional string name = 1; + optional string image = 2; + optional bool is_explicit = 3; +} + +message ItemCurationState { + optional bool is_curated = 1; +} + message Item { optional string header_field = 1; optional uint32 add_time = 2; @@ -36,11 +64,30 @@ message Item { optional cosmos_util.proto.EpisodeCollectionState episode_collection_state = 12; optional cosmos_util.proto.EpisodePlayState episode_play_state = 13; optional cosmos_util.proto.ImageGroup display_covers = 14; + repeated AvailableSignal available_signals = 15; + optional bool is_recommendation = 16; + repeated cosmos_util.proto.Extension extension = 17; + optional string uri = 18; + optional ItemOfflineState offline_state = 19; + optional ItemCollectionState collection_state = 20; + optional ItemMetadata metadata = 21; + optional ItemCurationState curation_state = 22; + optional bool should_be_obfuscated = 23; +} + +message Lens { + optional string name = 1; +} + +message LensState { + repeated Lens requested_lenses = 1; + repeated Lens applied_lenses = 2; } message Playlist { optional cosmos.proto.PlaylistMetadata playlist_metadata = 1; optional cosmos.proto.PlaylistOfflineState playlist_offline_state = 2; + optional LensState lenses = 3; } message RecommendationItem { @@ -63,6 +110,11 @@ message Collaborators { repeated Collaborator collaborator = 2; } +message NumberOfItemsForLinkType { + optional cosmos.proto.LinkType link_type = 1; + optional int32 num_items = 2; +} + message Response { repeated Item item = 1; optional Playlist playlist = 2; @@ -88,4 +140,12 @@ message Response { optional Collaborators collaborators = 22; optional playlist_permission.proto.Permission base_permission = 23; optional playlist_permission.proto.Capabilities user_capabilities = 24; + repeated NumberOfItemsForLinkType number_of_items_per_link_type = 25; + repeated AvailableSignal available_signals = 26; +} + +enum SignalState { + READY = 0; + PENDING = 1; } + diff --git a/protocol/proto/playlist_set_base_permission_request.proto b/protocol/proto/playlist_set_base_permission_request.proto index 3e8e1838f..45d7bb5a7 100644 --- a/protocol/proto/playlist_set_base_permission_request.proto +++ b/protocol/proto/playlist_set_base_permission_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_set_member_permission_request.proto b/protocol/proto/playlist_set_member_permission_request.proto index d3d687a42..1fe6ba697 100644 --- a/protocol/proto/playlist_set_member_permission_request.proto +++ b/protocol/proto/playlist_set_member_permission_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/playlist_set_permission_request.proto b/protocol/proto/playlist_set_permission_request.proto index a410cc233..60e95c764 100644 --- a/protocol/proto/playlist_set_permission_request.proto +++ b/protocol/proto/playlist_set_permission_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/playlist_track_state.proto b/protocol/proto/playlist_track_state.proto index cd55947f0..b6fa87ef1 100644 --- a/protocol/proto/playlist_track_state.proto +++ b/protocol/proto/playlist_track_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/playlist_user_state.proto b/protocol/proto/playlist_user_state.proto index 86c07dee8..4f8565afd 100644 --- a/protocol/proto/playlist_user_state.proto +++ b/protocol/proto/playlist_user_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/plugin.proto b/protocol/proto/plugin.proto index c0e912ce3..a1f61fffa 100644 --- a/protocol/proto/plugin.proto +++ b/protocol/proto/plugin.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,19 +11,20 @@ import "resource_type.proto"; option optimize_for = CODE_SIZE; message PluginRegistry { - repeated Entry plugins = 1; message Entry { string id = 1; repeated LinkType supported_link_types = 2; ResourceType resource_type = 3; repeated extendedmetadata.ExtensionKind extension_kinds = 4; } - + enum LinkType { EMPTY = 0; TRACK = 1; EPISODE = 2; } + + repeated Entry plugins = 1; } message PluginInit { @@ -35,63 +36,74 @@ message TargetFormat { } message Metadata { - Header header = 1; message Header { int32 status_code = 1; bool is_empty = 2; } - + + Header header = 1; google.protobuf.Any extension_data = 2; } message IdentifyCommand { - Header header = 3; message Header { TargetFormat target_format = 1; } - - repeated Query query = 4; + message Query { + message MetadataEntry { + int32 key = 1; + Metadata value = 2; + } + string link = 1; - map metadata = 2; + repeated MetadataEntry metadata = 2; } + + Header header = 3; + repeated Query query = 4; } message IdentifyResponse { - map results = 1; - message Result { - Status status = 1; enum Status { UNKNOWN = 0; MISSING = 1; COMPLETE = 2; NOT_APPLICABLE = 3; } - + + Status status = 1; int64 estimated_file_size = 2; } + + map results = 1; } message DownloadCommand { + message MetadataEntry { + int32 key = 1; + Metadata value = 2; + } + string link = 1; TargetFormat target_format = 2; - map metadata = 3; + repeated MetadataEntry metadata = 3; } message DownloadResponse { - string link = 1; - bool complete = 2; - int64 file_size = 3; - int64 bytes_downloaded = 4; - - Error error = 5; enum Error { OK = 0; TEMPORARY_ERROR = 1; PERMANENT_ERROR = 2; DISK_FULL = 3; } + + string link = 1; + bool complete = 2; + int64 file_size = 3; + int64 bytes_downloaded = 4; + Error error = 5; } message StopDownloadCommand { @@ -99,28 +111,25 @@ message StopDownloadCommand { } message StopDownloadResponse { - } message RemoveCommand { - Header header = 2; message Header { - } - - repeated Query query = 3; + message Query { string link = 1; } + + Header header = 2; + repeated Query query = 3; } message RemoveResponse { - } message PluginCommand { string id = 1; - oneof command { IdentifyCommand identify = 2; DownloadCommand download = 3; @@ -131,7 +140,6 @@ message PluginCommand { message PluginResponse { string id = 1; - oneof response { IdentifyResponse identify = 2; DownloadResponse download = 3; diff --git a/protocol/proto/podcast_ad_segments.proto b/protocol/proto/podcast_ad_segments.proto index ebff73854..d24b697b1 100644 --- a/protocol/proto/podcast_ad_segments.proto +++ b/protocol/proto/podcast_ad_segments.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -14,6 +14,7 @@ message PodcastAds { repeated string file_ids = 1; repeated string manifest_ids = 2; repeated Segment segments = 3; + string request_id = 4; } message Segment { diff --git a/protocol/proto/podcast_cta_cards.proto b/protocol/proto/podcast_cta_cards.proto index 9cd4dfc61..a516fb407 100644 --- a/protocol/proto/podcast_cta_cards.proto +++ b/protocol/proto/podcast_cta_cards.proto @@ -1,8 +1,8 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; -package spotify.context_track_exts.podcastctacards; +package spotify.context_mdata.podcastctacards; message Card { bool has_cards = 1; diff --git a/protocol/proto/podcast_poll.proto b/protocol/proto/podcast_poll.proto index 60dc04c65..7374c175c 100644 --- a/protocol/proto/podcast_poll.proto +++ b/protocol/proto/podcast_poll.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/podcast_qna.proto b/protocol/proto/podcast_qna.proto index fca3ba55c..340d21f00 100644 --- a/protocol/proto/podcast_qna.proto +++ b/protocol/proto/podcast_qna.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/podcast_subscription.proto b/protocol/proto/podcast_subscription.proto index 52b7f8f34..36107386f 100644 --- a/protocol/proto/podcast_subscription.proto +++ b/protocol/proto/podcast_subscription.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,7 +13,7 @@ option java_package = "com.spotify.podcastsubscription.proto"; message PodcastSubscription { bool is_paywalled = 1; bool is_user_subscribed = 2; - + UserExplanation user_explanation = 3; enum UserExplanation { SUBSCRIPTION_DIALOG = 0; diff --git a/protocol/proto/podcastextensions.proto b/protocol/proto/podcastextensions.proto index 4c85e3969..7a5c93631 100644 --- a/protocol/proto/podcastextensions.proto +++ b/protocol/proto/podcastextensions.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -22,8 +22,7 @@ message PodcastTopic { message PodcastHtmlDescription { Header header = 1; message Header { - } - + string html_description = 2; } diff --git a/protocol/proto/policy/album_decoration_policy.proto b/protocol/proto/policy/album_decoration_policy.proto index 359347d41..11a38c63a 100644 --- a/protocol/proto/policy/album_decoration_policy.proto +++ b/protocol/proto/policy/album_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/policy/artist_decoration_policy.proto b/protocol/proto/policy/artist_decoration_policy.proto index 0419dc31c..1e60743b2 100644 --- a/protocol/proto/policy/artist_decoration_policy.proto +++ b/protocol/proto/policy/artist_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -22,6 +22,7 @@ message ArtistCollectionDecorationPolicy { bool num_albums_in_collection = 4; bool is_banned = 5; bool can_ban = 6; + bool num_explicitly_liked_tracks = 8; } message ArtistSyncDecorationPolicy { diff --git a/protocol/proto/policy/episode_decoration_policy.proto b/protocol/proto/policy/episode_decoration_policy.proto index 467426bdd..a194ddaf8 100644 --- a/protocol/proto/policy/episode_decoration_policy.proto +++ b/protocol/proto/policy/episode_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,6 +11,8 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.cosmos.util.policy.proto"; message EpisodeDecorationPolicy { + reserved 19; + reserved 20; bool link = 1; bool length = 2; bool name = 3; @@ -29,11 +31,11 @@ message EpisodeDecorationPolicy { bool is_explicit = 16; bool type = 17; bool is_music_and_talk = 18; - PodcastSegmentsPolicy podcast_segments = 19; - bool podcast_subscription = 20; repeated extendedmetadata.ExtensionKind extension = 21; bool is_19_plus_only = 22; bool is_book_chapter = 23; + bool is_podcast_short = 24; + bool is_curated = 25; } message EpisodeCollectionDecorationPolicy { @@ -55,10 +57,3 @@ message EpisodePlayedStateDecorationPolicy { bool last_played_at = 5; } -message PodcastSegmentsPolicy { - bool playback_segments = 1; - bool embedded_segments = 2; - bool can_upsell = 3; - bool album_mosaic_uri = 4; - bool artists = 5; -} diff --git a/protocol/proto/policy/folder_decoration_policy.proto b/protocol/proto/policy/folder_decoration_policy.proto index 0d47e4d61..16e3eb110 100644 --- a/protocol/proto/policy/folder_decoration_policy.proto +++ b/protocol/proto/policy/folder_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/policy/playlist_album_decoration_policy.proto b/protocol/proto/policy/playlist_album_decoration_policy.proto index 01537c784..97bbf72b2 100644 --- a/protocol/proto/policy/playlist_album_decoration_policy.proto +++ b/protocol/proto/policy/playlist_album_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/policy/playlist_decoration_policy.proto b/protocol/proto/policy/playlist_decoration_policy.proto index a6aef1b7e..e2376c224 100644 --- a/protocol/proto/policy/playlist_decoration_policy.proto +++ b/protocol/proto/policy/playlist_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -60,4 +60,11 @@ message PlaylistDecorationPolicy { bool base_permission = 41; bool user_capabilities = 42; repeated extendedmetadata.ExtensionKind extension = 43; + bool lenses = 44; + bool length_ignoring_text_filter = 45; + bool number_of_items_per_link_type = 46; + bool available_signals = 47; + bool ai_curation_reference_id = 48; + bool unranged_length = 49; + bool unfiltered_length = 50; } diff --git a/protocol/proto/policy/playlist_episode_decoration_policy.proto b/protocol/proto/policy/playlist_episode_decoration_policy.proto index 4e038944c..04a63b0b2 100644 --- a/protocol/proto/policy/playlist_episode_decoration_policy.proto +++ b/protocol/proto/policy/playlist_episode_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -22,4 +22,6 @@ message PlaylistEpisodeDecorationPolicy { cosmos_util.proto.EpisodePlayedStateDecorationPolicy played_state = 7; UserDecorationPolicy added_by = 8; cosmos_util.proto.ShowDecorationPolicy show = 9; + bool signals = 10; + bool is_recommendation = 11; } diff --git a/protocol/proto/policy/playlist_request_decoration_policy.proto b/protocol/proto/policy/playlist_request_decoration_policy.proto index a1663d282..66fdea323 100644 --- a/protocol/proto/policy/playlist_request_decoration_policy.proto +++ b/protocol/proto/policy/playlist_request_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,13 +7,47 @@ package spotify.playlist.cosmos.proto; import "policy/playlist_decoration_policy.proto"; import "policy/playlist_episode_decoration_policy.proto"; import "policy/playlist_track_decoration_policy.proto"; +import "policy/supported_link_types_in_playlists.proto"; +import "extension_kind.proto"; option java_multiple_files = true; option optimize_for = CODE_SIZE; option java_package = "com.spotify.playlist.policy.proto"; +message ItemExtensionPolicy { + LinkType link_type = 1; + extendedmetadata.ExtensionKind extension = 2; +} + +message ItemOfflineStateDecorationPolicy { + bool offline_state = 1; + bool sync_progress = 2; + bool locally_playable = 3; +} + +message ItemMetadataPolicy { + bool name = 1; + bool image = 2; + bool is_explicit = 3; +} + +message ItemCurationStatePolicy { + bool is_curated = 1; +} + +message PlaylistItemDecorationPolicy { + bool uri = 1; + repeated ItemExtensionPolicy extension_policy = 2; + ItemOfflineStateDecorationPolicy offline_state = 3; + bool collection_state = 4; + ItemMetadataPolicy metadata = 5; + ItemCurationStatePolicy curation_state = 6; + bool obfuscation_state = 7; +} + message PlaylistRequestDecorationPolicy { PlaylistDecorationPolicy playlist = 1; PlaylistTrackDecorationPolicy track = 2; PlaylistEpisodeDecorationPolicy episode = 3; + PlaylistItemDecorationPolicy item = 4; } diff --git a/protocol/proto/policy/playlist_track_decoration_policy.proto b/protocol/proto/policy/playlist_track_decoration_policy.proto index 97eb0187b..cad855ab3 100644 --- a/protocol/proto/policy/playlist_track_decoration_policy.proto +++ b/protocol/proto/policy/playlist_track_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -28,4 +28,6 @@ message PlaylistTrackDecorationPolicy { UserDecorationPolicy added_by = 12; PlaylistAlbumDecorationPolicy album = 13; cosmos_util.proto.ArtistDecorationPolicy artist = 14; + bool signals = 15; + bool is_recommendation = 16; } diff --git a/protocol/proto/policy/rootlist_folder_decoration_policy.proto b/protocol/proto/policy/rootlist_folder_decoration_policy.proto index f93888b49..5c58a3f13 100644 --- a/protocol/proto/policy/rootlist_folder_decoration_policy.proto +++ b/protocol/proto/policy/rootlist_folder_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/policy/rootlist_playlist_decoration_policy.proto b/protocol/proto/policy/rootlist_playlist_decoration_policy.proto index 9e8446ab8..2c052c376 100644 --- a/protocol/proto/policy/rootlist_playlist_decoration_policy.proto +++ b/protocol/proto/policy/rootlist_playlist_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/policy/rootlist_request_decoration_policy.proto b/protocol/proto/policy/rootlist_request_decoration_policy.proto index ebad00ca3..cf7b5ab90 100644 --- a/protocol/proto/policy/rootlist_request_decoration_policy.proto +++ b/protocol/proto/policy/rootlist_request_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/policy/show_decoration_policy.proto b/protocol/proto/policy/show_decoration_policy.proto index 2e5e2020f..fbb1617af 100644 --- a/protocol/proto/policy/show_decoration_policy.proto +++ b/protocol/proto/policy/show_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,6 +11,7 @@ option optimize_for = CODE_SIZE; option java_package = "com.spotify.cosmos.util.policy.proto"; message ShowDecorationPolicy { + reserved 15; bool link = 1; bool name = 2; bool description = 3; @@ -25,11 +26,26 @@ message ShowDecorationPolicy { bool copyrights = 12; bool trailer_uri = 13; bool is_music_and_talk = 14; - bool access_info = 15; repeated extendedmetadata.ExtensionKind extension = 16; bool is_book = 17; + bool is_creator_channel = 18; } message ShowPlayedStateDecorationPolicy { bool latest_played_episode_link = 1; + bool played_time = 2; + bool is_playable = 3; + bool playability_restriction = 4; + bool label = 5; + bool resume_episode_link = 7; } + +message ShowCollectionDecorationPolicy { + bool is_in_collection = 1; +} + +message ShowOfflineStateDecorationPolicy { + bool offline = 1; + bool sync_progress = 2; +} + diff --git a/protocol/proto/policy/supported_link_types_in_playlists.proto b/protocol/proto/policy/supported_link_types_in_playlists.proto new file mode 100644 index 000000000..4c1897a52 --- /dev/null +++ b/protocol/proto/policy/supported_link_types_in_playlists.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package spotify.playlist.cosmos.proto; + +option java_package = "com.spotify.playlist.policy.proto"; +option java_multiple_files = true; + +enum LinkType { + EMPTY = 0; + ARTIST = 1; + ALBUM = 2; + TRACK = 4; + LOCAL_TRACK = 9; + SHOW = 62; + EPISODE = 63; +} + diff --git a/protocol/proto/policy/track_decoration_policy.proto b/protocol/proto/policy/track_decoration_policy.proto index aa71f4970..e68922c92 100644 --- a/protocol/proto/policy/track_decoration_policy.proto +++ b/protocol/proto/policy/track_decoration_policy.proto @@ -1,9 +1,11 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.cosmos_util.proto; +import "extension_kind.proto"; + option java_multiple_files = true; option optimize_for = CODE_SIZE; option java_package = "com.spotify.cosmos.util.policy.proto"; @@ -27,6 +29,9 @@ message TrackDecorationPolicy { bool popularity = 16; bool is_19_plus_only = 17; bool track_descriptors = 18; + repeated extendedmetadata.ExtensionKind extension = 19; + bool is_curated = 20; + bool to_be_obfuscated = 22; } message TrackPlayedStateDecorationPolicy { diff --git a/protocol/proto/policy/user_decoration_policy.proto b/protocol/proto/policy/user_decoration_policy.proto index f2c342eb2..c284df3e5 100644 --- a/protocol/proto/policy/user_decoration_policy.proto +++ b/protocol/proto/policy/user_decoration_policy.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/popcount2_external.proto b/protocol/proto/popcount2_external.proto index 069cdcfd2..8c69a4b4e 100644 --- a/protocol/proto/popcount2_external.proto +++ b/protocol/proto/popcount2_external.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -7,24 +7,29 @@ package spotify.popcount2.proto; option optimize_for = CODE_SIZE; message PopcountRequest { - } message PopcountResult { optional sint64 count = 1; optional bool truncated = 2; repeated string user = 3; + repeated string userid = 6; + optional int64 raw_count = 7; + optional bool count_hidden_from_users = 8; } message PopcountUserUpdate { optional string user = 1; optional sint64 timestamp = 2; optional bool added = 3; + optional string userid = 4; } -message PopcountUpdate { - repeated PopcountUserUpdate updates = 1; - optional sint64 common_timestamp = 2; - optional sint64 remove_older_than_timestamp = 3; - optional bool verify_counter = 4; +message PopcountFollowerResult { + optional bool is_truncated = 1; + repeated bytes user_id = 2; +} + +message PopcountSetFollowerCounterValueRequest { + optional int64 count = 1; } diff --git a/protocol/proto/prepare_play_options.proto b/protocol/proto/prepare_play_options.proto index cb27650d9..9c545824a 100644 --- a/protocol/proto/prepare_play_options.proto +++ b/protocol/proto/prepare_play_options.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -27,11 +27,11 @@ message PreparePlayOptions { } enum PrefetchLevel { - kNone = 0; - kMedia = 1; + NONE = 0; + MEDIA = 1; } enum AudioStream { - kDefault = 0; - kAlarm = 1; + DEFAULT = 0; + ALARM = 1; } diff --git a/protocol/proto/profile_cosmos.proto b/protocol/proto/profile_cosmos.proto index c6c945db4..a643e6f39 100644 --- a/protocol/proto/profile_cosmos.proto +++ b/protocol/proto/profile_cosmos.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/profile_service.proto b/protocol/proto/profile_service.proto index 194e5fea6..84425e49f 100644 --- a/protocol/proto/profile_service.proto +++ b/protocol/proto/profile_service.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,6 +6,8 @@ package spotify.profile_esperanto.proto.v1; import "identity.proto"; +option java_package = "spotify.profile_esperanto.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; service ProfileService { diff --git a/protocol/proto/property_definition.proto b/protocol/proto/property_definition.proto index 9df7caa7f..277f73f42 100644 --- a/protocol/proto/property_definition.proto +++ b/protocol/proto/property_definition.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,38 +7,39 @@ package spotify.remote_config.ucs.proto; option optimize_for = CODE_SIZE; message PropertyDefinition { + reserved "hash"; + reserved 2; + + message BoolSpec { + bool default = 1; + } + + message IntSpec { + int32 default = 1; + int32 lower = 2; + int32 upper = 3; + } + + message EnumSpec { + string default = 1; + repeated string values = 2; + } + Identifier id = 1; message Identifier { string scope = 1; string name = 2; } - + Metadata metadata = 4; message Metadata { string component_id = 1; string description = 2; } - + oneof specification { BoolSpec bool_spec = 5; IntSpec int_spec = 6; EnumSpec enum_spec = 7; } - - //reserved 2, "hash"; - - message BoolSpec { - bool default = 1; - } - - message IntSpec { - int32 default = 1; - int32 lower = 2; - int32 upper = 3; - } - - message EnumSpec { - string default = 1; - repeated string values = 2; - } } diff --git a/protocol/proto/protobuf_delta.proto b/protocol/proto/protobuf_delta.proto index c0a89fecb..95ac7e144 100644 --- a/protocol/proto/protobuf_delta.proto +++ b/protocol/proto/protobuf_delta.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -14,7 +14,7 @@ message Delta { DELETE = 0; INSERT = 1; } - + required uint32 index = 2; required uint32 length = 3; } diff --git a/protocol/proto/queue.proto b/protocol/proto/queue.proto index 24b45b7c9..64d104144 100644 --- a/protocol/proto/queue.proto +++ b/protocol/proto/queue.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/rate_limited_events.proto b/protocol/proto/rate_limited_events.proto index c9116b6d8..6d0807056 100644 --- a/protocol/proto/rate_limited_events.proto +++ b/protocol/proto/rate_limited_events.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/rcs.proto b/protocol/proto/rcs.proto index 00e861033..8225eb27f 100644 --- a/protocol/proto/rcs.proto +++ b/protocol/proto/rcs.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,35 +7,35 @@ package spotify.remote_config.proto; option optimize_for = CODE_SIZE; message GranularConfiguration { - repeated AssignedPropertyValue properties = 1; message AssignedPropertyValue { Platform platform = 7; string client_id = 4; string component_id = 5; int64 groupId = 8; string name = 6; - oneof structured_value { BoolValue bool_value = 1; IntValue int_value = 2; EnumValue enum_value = 3; } - + message BoolValue { bool value = 1; } - + message IntValue { int32 value = 1; } - + message EnumValue { string value = 1; } } - + + repeated AssignedPropertyValue properties = 1; int64 rcs_fetch_time = 2; string configuration_assignment_id = 3; + string etag = 10; } message PolicyGroupId { @@ -44,58 +44,56 @@ message PolicyGroupId { } message ClientPropertySet { - string client_id = 1; - string version = 2; - repeated PropertyDefinition properties = 5; - - repeated ComponentInfo component_infos = 6; message ComponentInfo { + reserved "owner"; + reserved "tags"; + reserved 1; + reserved 2; string name = 3; - - //reserved 1, 2, "owner", "tags"; } - - string property_set_key = 7; - - PublisherInfo publisherInfo = 8; + message PublisherInfo { string published_for_client_version = 1; int64 published_at = 2; } + + string client_id = 1; + string version = 2; + repeated PropertyDefinition properties = 5; + repeated ComponentInfo component_infos = 6; + string property_set_key = 7; + PublisherInfo publisherInfo = 8; } message PropertyDefinition { - string description = 2; - string component_id = 3; - Platform platform = 8; - - oneof identifier { - string id = 9; - string name = 7; - } - - oneof spec { - BoolSpec bool_spec = 4; - IntSpec int_spec = 5; - EnumSpec enum_spec = 6; - } - reserved 1; - message BoolSpec { bool default = 1; } - + message IntSpec { int32 default = 1; int32 lower = 2; int32 upper = 3; } - + message EnumSpec { string default = 1; repeated string values = 2; } + + string description = 2; + string component_id = 3; + Platform platform = 8; + oneof identifier { + string id = 9; + string name = 7; + } + oneof spec { + BoolSpec bool_spec = 4; + IntSpec int_spec = 5; + EnumSpec enum_spec = 6; + } } enum Platform { diff --git a/protocol/proto/recently_played.proto b/protocol/proto/recently_played.proto index fd22fdd9c..95b8f2cd5 100644 --- a/protocol/proto/recently_played.proto +++ b/protocol/proto/recently_played.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,7 +7,7 @@ package spotify.recently_played.proto; option optimize_for = CODE_SIZE; message Item { - string link = 1; + string uri = 1; int64 timestamp = 2; bool hidden = 3; } diff --git a/protocol/proto/recently_played_backend.proto b/protocol/proto/recently_played_backend.proto index fa137288c..5533f3d34 100644 --- a/protocol/proto/recently_played_backend.proto +++ b/protocol/proto/recently_played_backend.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/record_id.proto b/protocol/proto/record_id.proto index 167c0ecd3..5839058a7 100644 --- a/protocol/proto/record_id.proto +++ b/protocol/proto/record_id.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/remote.proto b/protocol/proto/remote.proto index a81c1c0f8..06a1d3223 100644 --- a/protocol/proto/remote.proto +++ b/protocol/proto/remote.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/request_failure.proto b/protocol/proto/request_failure.proto index 10deb1be4..504455422 100644 --- a/protocol/proto/request_failure.proto +++ b/protocol/proto/request_failure.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/resolve.proto b/protocol/proto/resolve.proto index 793b8c5a6..e0af636eb 100644 --- a/protocol/proto/resolve.proto +++ b/protocol/proto/resolve.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,15 +9,16 @@ import "property_definition.proto"; option optimize_for = CODE_SIZE; message ResolveRequest { + reserved "custom_context"; + reserved "projection"; + reserved 4; + reserved 5; string property_set_id = 1; Fetch fetch_type = 2; Context context = 11; - oneof resolution_context { - BackendContext backend_context = 12 [deprecated = true]; + BackendContext backend_context = 12; } - - //reserved 4, 5, "custom_context", "projection"; } message ResolveResponse { @@ -25,42 +26,40 @@ message ResolveResponse { } message Configuration { - string configuration_assignment_id = 1; - int64 fetch_time_millis = 2; - - repeated AssignedValue assigned_values = 3; message AssignedValue { - PropertyDefinition.Identifier property_id = 1; - - Metadata metadata = 2; message Metadata { int64 policy_id = 1; string external_realm = 2; int64 external_realm_id = 3; } - - oneof structured_value { - BoolValue bool_value = 3; - IntValue int_value = 4; - EnumValue enum_value = 5; - } - + message BoolValue { bool value = 1; } - + message IntValue { int32 value = 1; } - + message EnumValue { string value = 1; } + + PropertyDefinition.Identifier property_id = 1; + Metadata metadata = 2; + oneof structured_value { + BoolValue bool_value = 3; + IntValue int_value = 4; + EnumValue enum_value = 5; + } } + + string configuration_assignment_id = 1; + int64 fetch_time_millis = 2; + repeated AssignedValue assigned_values = 3; } message Fetch { - Type type = 1; enum Type { BLOCKING = 0; BACKGROUND_SYNC = 1; @@ -68,49 +67,52 @@ message Fetch { PUSH_INITIATED = 3; RECONNECT = 4; } + + Type type = 1; } message Context { - repeated ContextEntry context = 1; message ContextEntry { string value = 10; - oneof context { DynamicContext.KnownContext known_context = 1; + string policy_input_name = 2; } } + + repeated ContextEntry context = 1; } message BackendContext { - string system = 1 [deprecated = true]; - string service_name = 2 [deprecated = true]; - - StaticContext static_context = 3; message StaticContext { string system = 1; string service_name = 2; } - - DynamicContext dynamic_context = 4; - - SurfaceMetadata surface_metadata = 10; + message SurfaceMetadata { string backend_sdk_version = 1; } + + string system = 1; + string service_name = 2; + StaticContext static_context = 3; + DynamicContext dynamic_context = 4; + SurfaceMetadata surface_metadata = 10; } message DynamicContext { - repeated ContextDefinition context_definition = 1; message ContextDefinition { oneof context { KnownContext known_context = 1; } } - + enum KnownContext { KNOWN_CONTEXT_INVALID = 0; KNOWN_CONTEXT_USER_ID = 1; KNOWN_CONTEXT_INSTALLATION_ID = 2; KNOWN_CONTEXT_VERSION = 3; } + + repeated ContextDefinition context_definition = 1; } diff --git a/protocol/proto/resource_type.proto b/protocol/proto/resource_type.proto index ccea69205..0803390c6 100644 --- a/protocol/proto/resource_type.proto +++ b/protocol/proto/resource_type.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/response_status.proto b/protocol/proto/response_status.proto index 5709571f9..af2717d9a 100644 --- a/protocol/proto/response_status.proto +++ b/protocol/proto/response_status.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/restrictions.proto b/protocol/proto/restrictions.proto index 0661858c7..7cf3521db 100644 --- a/protocol/proto/restrictions.proto +++ b/protocol/proto/restrictions.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -6,7 +6,17 @@ package spotify.player.proto; option optimize_for = CODE_SIZE; +message ModeRestrictions { + map values = 1; +} + +message RestrictionReasons { + repeated string reasons = 1; +} + message Restrictions { + reserved 24; + repeated string disallow_pausing_reasons = 1; repeated string disallow_resuming_reasons = 2; repeated string disallow_seeking_reasons = 3; @@ -28,4 +38,9 @@ message Restrictions { repeated string disallow_removing_from_next_tracks_reasons = 19; repeated string disallow_removing_from_context_tracks_reasons = 20; repeated string disallow_updating_context_reasons = 21; + repeated string disallow_add_to_queue_reasons = 22; + repeated string disallow_setting_playback_speed = 23; + map disallow_setting_modes = 25; + map disallow_signals = 26; } + diff --git a/protocol/proto/rootlist_request.proto b/protocol/proto/rootlist_request.proto index ae055475b..b21e41e02 100644 --- a/protocol/proto/rootlist_request.proto +++ b/protocol/proto/rootlist_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/seek_to_position.proto b/protocol/proto/seek_to_position.proto index 6f426842d..ec5cc67c8 100644 --- a/protocol/proto/seek_to_position.proto +++ b/protocol/proto/seek_to_position.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sequence_number_entity.proto b/protocol/proto/sequence_number_entity.proto index a3b88c814..7f78d6993 100644 --- a/protocol/proto/sequence_number_entity.proto +++ b/protocol/proto/sequence_number_entity.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/session.proto b/protocol/proto/session.proto index 7c4589f31..6038cdf61 100644 --- a/protocol/proto/session.proto +++ b/protocol/proto/session.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -19,4 +19,7 @@ message Session { optional ContextPlayerOptionOverrides option_overrides = 4; optional Suppressions suppressions = 5; optional InstrumentationParams instrumentation_params = 6; + optional string shuffle_seed = 7; + optional Context main_context = 8; + optional string original_session_id = 9; } diff --git a/protocol/proto/set_member_permission_request.proto b/protocol/proto/set_member_permission_request.proto index 160eaf92c..f35be29ee 100644 --- a/protocol/proto/set_member_permission_request.proto +++ b/protocol/proto/set_member_permission_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/show_access.proto b/protocol/proto/show_access.proto index eddc03429..54a9cee60 100644 --- a/protocol/proto/show_access.proto +++ b/protocol/proto/show_access.proto @@ -1,9 +1,11 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.podcast_paywalls; +import "spotify/audiobookcashier/v1/audiobook_price.proto"; + option objc_class_prefix = "SPT"; option java_multiple_files = true; option optimize_for = CODE_SIZE; @@ -11,16 +13,30 @@ option java_outer_classname = "ShowAccessProto"; option java_package = "com.spotify.podcast.access.proto"; message ShowAccess { + reserved 7; AccountLinkPrompt prompt = 5; - + bool is_user_member_of_at_least_one_group = 8; + repeated UnlockingMethod unlocked_by = 10; + repeated UnlockingMethod unlocking_methods = 14; + Signifier signifier = 15; + Disclaimer disclaimer = 16; oneof explanation { NoExplanation none = 1; LegacyExplanation legacy = 2; BasicExplanation basic = 3; UpsellLinkExplanation upsellLink = 4; + EngagementExplanation engagement = 6; + MultiPassExplanation multiPass = 9; + CheckoutOnWebOverlayExplanation checkoutOnWebOverlay = 11; + FreeCheckoutExplanation freeCheckout = 12; + ConsumptionCappedExplanation consumptionCapped = 13; } } +message Signifier { + string text = 1; +} + message BasicExplanation { string title = 1; string body = 2; @@ -28,11 +44,9 @@ message BasicExplanation { } message LegacyExplanation { - } message NoExplanation { - } message UpsellLinkExplanation { @@ -42,9 +56,66 @@ message UpsellLinkExplanation { string url = 4; } +message EngagementExplanation { + string header = 1; + string title = 2; + string body = 3; + string cta = 4; + string dismiss = 5; + string action_type = 6; + string body_secondary = 7; +} + +message CheckoutOnWebOverlayExplanation { + string cta = 1; + string snackbar_success = 2; + string snackbar_error = 3; + string snackbar_fulfilment_complete = 4; + audiobookcashier.v1.AudiobookPrice price = 5; + bool is_price_displayed = 6; +} + +message FreeCheckoutExplanation { + string snackbar_awaiting_fulfilment = 1; +} + +message ConsumptionCappedExplanation { + string title = 1; + string body = 2; + string cta = 3; +} + +message MultiPassExplanation { + string title = 1; + string soa_description = 2; + repeated .spotify.podcast_paywalls.SOAPartner soa_partner = 3; +} + +message SOAPartner { + string display_name = 1; + string link_url = 2; + string logo_url = 3; +} + message AccountLinkPrompt { string title = 1; string body = 2; string cta = 3; string url = 4; } + +message Disclaimer { + string title = 1; + string body = 2; +} + +enum UnlockingMethod { + UNKNOWN = 0; + ANCHOR_PAYWALL = 1; + OAP_OTP = 2; + OAP_LINKING = 3; + AUDIOBOOK_DIRECT_SALES = 4; + ABP = 5; + AUDIOBOOK_PROMOTION = 6; +} + diff --git a/protocol/proto/show_episode_state.proto b/protocol/proto/show_episode_state.proto index b780dbb64..d9c52879b 100644 --- a/protocol/proto/show_episode_state.proto +++ b/protocol/proto/show_episode_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/show_offline_state.proto b/protocol/proto/show_offline_state.proto new file mode 100644 index 000000000..a3cd8ae93 --- /dev/null +++ b/protocol/proto/show_offline_state.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package spotify.show_cosmos.proto; + +message ShowOfflineState { + optional string offline_state = 1; + optional uint32 sync_progress = 2; +} + diff --git a/protocol/proto/show_request.proto b/protocol/proto/show_request.proto index 3624fa04f..75c3a69ec 100644 --- a/protocol/proto/show_request.proto +++ b/protocol/proto/show_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -7,39 +7,37 @@ package spotify.show_cosmos.proto; import "metadata/episode_metadata.proto"; import "metadata/show_metadata.proto"; import "played_state/episode_played_state.proto"; +import "played_state/show_played_state.proto"; import "show_episode_state.proto"; import "show_show_state.proto"; -import "podcast_virality.proto"; -import "transcripts.proto"; -import "podcastextensions.proto"; -import "clips_cover.proto"; -import "show_access.proto"; -import "podcast_ratings.proto"; -import "greenroom_extension.proto"; +import "show_offline_state.proto"; option objc_class_prefix = "SPTShowCosmos"; option optimize_for = CODE_SIZE; message Item { + reserved 6; + reserved 7; + reserved 8; + reserved 9; optional string header_field = 1; optional cosmos_util.proto.EpisodeMetadata episode_metadata = 2; optional EpisodeCollectionState episode_collection_state = 3; optional EpisodeOfflineState episode_offline_state = 4; optional cosmos_util.proto.EpisodePlayState episode_play_state = 5; - optional corex.transcripts.metadata.EpisodeTranscript episode_transcripts = 7; - optional podcastvirality.v1.PodcastVirality episode_virality = 8; - optional clips.ClipsCover episode_clips = 9; - - reserved 6; } message Header { optional cosmos_util.proto.ShowMetadata show_metadata = 1; optional ShowCollectionState show_collection_state = 2; - optional ShowPlayState show_play_state = 3; + optional cosmos_util.proto.ShowPlayState show_play_state = 3; + optional ShowOfflineState show_offline_state = 4; } message Response { + reserved "online_data"; + reserved 3; + reserved 9; repeated Item item = 1; optional Header header = 2; optional uint32 unfiltered_length = 4; @@ -47,23 +45,21 @@ message Response { optional bool loading_contents = 6; optional uint32 unranged_length = 7; optional AuxiliarySections auxiliary_sections = 8; - optional podcast_paywalls.ShowAccess access_info = 9; optional uint32 range_offset = 10; - - reserved 3, "online_data"; } message AuxiliarySections { + reserved 2; + reserved 4; + reserved 5; + reserved 6; + reserved 7; + reserved 8; optional ContinueListeningSection continue_listening = 1; - optional podcast.extensions.PodcastTopics topics_section = 2; optional TrailerSection trailer_section = 3; - optional podcast.extensions.PodcastHtmlDescription html_description_section = 5; - optional clips.ClipsCover clips_section = 6; - optional ratings.PodcastRating rating_section = 7; - optional greenroom.api.extendedmetadata.v1.GreenroomSection greenroom_section = 8; optional LatestUnplayedEpisodeSection latest_unplayed_episode_section = 9; - - reserved 4; + optional NextBestEpisodeSection next_best_episode_section = 10; + optional SavedEpisodesSection saved_episodes_section = 11; } message ContinueListeningSection { @@ -77,3 +73,23 @@ message TrailerSection { message LatestUnplayedEpisodeSection { optional Item item = 1; } + +message NextBestEpisodeSection { + enum Label { + UNKNOWN = 0; + TRAILER = 1; + CONTINUE_LISTENING = 2; + LATEST_PUBLISHED = 3; + UP_NEXT = 4; + FIRST_PUBLISHED = 5; + } + + optional Label label = 1; + optional Item item = 2; +} + +message SavedEpisodesSection { + optional uint32 saved_episodes_count = 1; + optional uint32 downloaded_episodes_count = 2; +} + diff --git a/protocol/proto/show_show_state.proto b/protocol/proto/show_show_state.proto index c9c3548ae..126b19e32 100644 --- a/protocol/proto/show_show_state.proto +++ b/protocol/proto/show_show_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -11,6 +11,3 @@ message ShowCollectionState { optional bool is_in_collection = 1; } -message ShowPlayState { - optional string latest_played_episode_link = 1; -} diff --git a/protocol/proto/signal-model.proto b/protocol/proto/signal-model.proto new file mode 100644 index 000000000..d3824455f --- /dev/null +++ b/protocol/proto/signal-model.proto @@ -0,0 +1,16 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + +syntax = "proto3"; + +package spotify.playlist.signal.proto; + +option java_package = "com.spotify.playlist_signal.model.proto"; +option java_outer_classname = "SignalModelProto"; +option optimize_for = CODE_SIZE; + +message Signal { + string identifier = 1; + bytes data = 2; + bytes client_payload = 3; +} + diff --git a/protocol/proto/skip_to_track.proto b/protocol/proto/skip_to_track.proto index 67b5f7177..2d7830ef5 100644 --- a/protocol/proto/skip_to_track.proto +++ b/protocol/proto/skip_to_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/social_connect_v2.proto b/protocol/proto/social_connect_v2.proto index f4d084c86..86b3a38e8 100644 --- a/protocol/proto/social_connect_v2.proto +++ b/protocol/proto/social_connect_v2.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,6 +7,7 @@ package socialconnect; option optimize_for = CODE_SIZE; message Session { + reserved 8; int64 timestamp = 1; string session_id = 2; string join_session_token = 3; @@ -19,12 +20,7 @@ message Session { bool is_controlling = 11; bool is_discoverable = 12; SessionType initial_session_type = 13; - - oneof _host_active_device_id { - string host_active_device_id = 14; - } - - reserved 8; + optional string host_active_device_id = 14; } message SessionMember { diff --git a/protocol/proto/social_service.proto b/protocol/proto/social_service.proto index d5c108a82..05875dc72 100644 --- a/protocol/proto/social_service.proto +++ b/protocol/proto/social_service.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -19,15 +19,12 @@ message SetAccessTokenRequest { } message SetAccessTokenResponse { - } message SubscribeToEventsRequest { - } message SubscribeToEventsResponse { - Error status = 1; enum Error { NONE = 0; FAILED_TO_CONNECT = 1; @@ -36,12 +33,12 @@ message SubscribeToEventsResponse { SERVICE_CONNECT_NOT_PERMITTED = 4; USER_UNAUTHORIZED = 5; } - + + Error status = 1; string description = 2; } message SubscribeToStateRequest { - } message SubscribeToStateResponse { @@ -50,3 +47,4 @@ message SubscribeToStateResponse { repeated string missingPermissions = 3; string accessToken = 4; } + diff --git a/protocol/proto/socialgraph_response_status.proto b/protocol/proto/socialgraph_response_status.proto index 1518daf13..91acaddfd 100644 --- a/protocol/proto/socialgraph_response_status.proto +++ b/protocol/proto/socialgraph_response_status.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/socialgraphv2.proto b/protocol/proto/socialgraphv2.proto index ace70589a..f365f2f9e 100644 --- a/protocol/proto/socialgraphv2.proto +++ b/protocol/proto/socialgraphv2.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/spotify/audiobookcashier/v1/audiobook_price.proto b/protocol/proto/spotify/audiobookcashier/v1/audiobook_price.proto new file mode 100755 index 000000000..403527425 --- /dev/null +++ b/protocol/proto/spotify/audiobookcashier/v1/audiobook_price.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package spotify.audiobookcashier.v1; + +option java_package = "com.spotify.audiobookcashier.v1"; +option java_multiple_files = true; + +message Price { + double amount = 1; + string currency = 2; + string formatted_price = 3; +} + +message AudiobookPrice { + .spotify.audiobookcashier.v1.Price final_price = 1; + .spotify.audiobookcashier.v1.Price final_list_price = 2; +} + diff --git a/protocol/proto/state_restore/ads_rules_inject_tracks.proto b/protocol/proto/state_restore/ads_rules_inject_tracks.proto index 569c8cdf8..8dfaa6f35 100644 --- a/protocol/proto/state_restore/ads_rules_inject_tracks.proto +++ b/protocol/proto/state_restore/ads_rules_inject_tracks.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/automix_rules.proto b/protocol/proto/state_restore/automix_rules.proto new file mode 100644 index 000000000..8421c7c89 --- /dev/null +++ b/protocol/proto/state_restore/automix_rules.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +message AutomixRules { + required bool automix = 1; + required string current_track_uri = 2; +} + diff --git a/protocol/proto/state_restore/automix_talk_rules.proto b/protocol/proto/state_restore/automix_talk_rules.proto new file mode 100644 index 000000000..8fb157138 --- /dev/null +++ b/protocol/proto/state_restore/automix_talk_rules.proto @@ -0,0 +1,11 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "state_restore/provided_track.proto"; + +message AutomixTalkRules { + optional ProvidedTrack current_track = 1; + optional int64 narration_duration = 2; +} + diff --git a/protocol/proto/state_restore/behavior_metadata_rules.proto b/protocol/proto/state_restore/behavior_metadata_rules.proto index 4bb65cd42..94ced855b 100644 --- a/protocol/proto/state_restore/behavior_metadata_rules.proto +++ b/protocol/proto/state_restore/behavior_metadata_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/circuit_breaker_rules.proto b/protocol/proto/state_restore/circuit_breaker_rules.proto index e81eaf579..c628122f9 100644 --- a/protocol/proto/state_restore/circuit_breaker_rules.proto +++ b/protocol/proto/state_restore/circuit_breaker_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/context_loader.proto b/protocol/proto/state_restore/context_loader.proto new file mode 100644 index 000000000..ba016bb3c --- /dev/null +++ b/protocol/proto/state_restore/context_loader.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "context.proto"; + +message ContextLoader { + required Context context = 1; +} + diff --git a/protocol/proto/state_restore/context_player_restorable.proto b/protocol/proto/state_restore/context_player_restorable.proto new file mode 100644 index 000000000..2f278da87 --- /dev/null +++ b/protocol/proto/state_restore/context_player_restorable.proto @@ -0,0 +1,23 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "state_restore/play_history.proto"; +import "state_restore/player_model.proto"; +import "state_restore/mft_state.proto"; +import "state_restore/mft_context_history.proto"; +import "state_restore/mft_fallback_page_history.proto"; +import "state_restore/pns_capper.proto"; + +message ContextPlayerRestorable { + reserved 8; + required int32 version = 1; + optional string version_suffix = 2; + required PlayerModel player_model = 3; + required PlayHistory play_history = 4; + required MftState mft_can_play_checker = 5; + required MftContextHistory mft_context_history = 6; + required MftFallbackPageHistory mft_fallback_page_history = 7; + optional PnsCapper pns_capper = 9; +} + diff --git a/protocol/proto/state_restore/context_player_rules.proto b/protocol/proto/state_restore/context_player_rules.proto index b06bf8e85..e4a406b05 100644 --- a/protocol/proto/state_restore/context_player_rules.proto +++ b/protocol/proto/state_restore/context_player_rules.proto @@ -1,16 +1,72 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; package spotify.player.proto.state_restore; -import "state_restore/context_player_rules_base.proto"; -import "state_restore/mft_rules.proto"; +import "state_restore/ads_rules_inject_tracks.proto"; +import "state_restore/automix_rules.proto"; +import "state_restore/automix_talk_rules.proto"; +import "state_restore/behavior_metadata_rules.proto"; +import "state_restore/circuit_breaker_rules.proto"; +import "state_restore/explicit_content_rules.proto"; +import "state_restore/kitteh_box_rules.proto"; +import "state_restore/mft_rules_core.proto"; +import "state_restore/mod_rules_interruptions.proto"; +import "state_restore/music_injection_rules.proto"; +import "state_restore/remove_banned_tracks_rules.proto"; +import "state_restore/resume_points_rules.proto"; +import "state_restore/track_error_rules.proto"; option optimize_for = CODE_SIZE; +message PlayEvents { + required uint64 max_consecutive = 1; + required uint64 max_occurrences_in_period = 2; + required int64 period = 3; +} + +message SkipEvents { + required uint64 max_occurrences_in_period = 1; + required int64 period = 2; +} + +message Context { + required uint64 min_tracks = 1; +} + +message MftConfiguration { + optional PlayEvents track = 1; + optional PlayEvents album = 2; + optional PlayEvents artist = 3; + optional SkipEvents skip = 4; + optional Context context = 5; + optional PlayEvents social_track = 6; +} + +message MftRules { + required bool locked = 1; + optional MftConfiguration config = 2; + map old_forward_rules = 3; + optional ContextPlayerRules forward_rules = 4; +} + message ContextPlayerRules { - optional ContextPlayerRulesBase base = 1; - optional MftRules mft_rules = 2; - map sub_rules = 3; + optional BehaviorMetadataRules behavior_metadata_rules = 1; + optional CircuitBreakerRules circuit_breaker_rules = 2; + optional ExplicitContentRules explicit_content_rules = 3; + optional MusicInjectionRules music_injection_rules = 5; + optional RemoveBannedTracksRules remove_banned_tracks_rules = 6; + optional ResumePointsRules resume_points_rules = 7; + optional TrackErrorRules track_error_rules = 8; + optional AdsRulesInjectTracks ads_rules_inject_tracks = 9; + optional MftRulesCore mft_rules_core = 10; + optional ModRulesInterruptions mod_rules_interruptions = 11; + optional KittehBoxRules kitteh_box_rules = 12; + optional AutomixRules automix_rules = 13; + optional AutomixTalkRules automix_talk_rules = 14; + optional MftRules mft_rules = 15; + map sub_rules = 16; + optional bool is_adaptor_only = 17; } + diff --git a/protocol/proto/state_restore/context_player_state.proto b/protocol/proto/state_restore/context_player_state.proto new file mode 100644 index 000000000..74b66a652 --- /dev/null +++ b/protocol/proto/state_restore/context_player_state.proto @@ -0,0 +1,59 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "context_index.proto"; +import "restrictions.proto"; +import "play_origin.proto"; +import "state_restore/provided_track.proto"; +import "context_player_options.proto"; +import "prepare_play_options.proto"; +import "state_restore/playback_quality.proto"; + +message ContextPlayerState { + message ContextMetadataEntry { + optional string key = 1; + optional string value = 2; + } + + message PageMetadataEntry { + optional string key = 1; + optional string value = 2; + } + + message ModesEntry { + optional string key = 1; + optional string value = 2; + } + + optional uint64 timestamp = 1; + optional string context_uri = 2; + optional string context_url = 3; + optional Restrictions context_restrictions = 4; + optional PlayOrigin play_origin = 5; + optional ContextIndex index = 6; + optional ProvidedTrack track = 7; + optional bytes playback_id = 8; + optional PlaybackQuality playback_quality = 9; + optional double playback_speed = 10; + optional uint64 position_as_of_timestamp = 11; + optional uint64 duration = 12; + optional bool is_playing = 13; + optional bool is_paused = 14; + optional bool is_buffering = 15; + optional bool is_system_initiated = 16; + optional ContextPlayerOptions options = 17; + optional Restrictions restrictions = 18; + repeated string suppressions = 19; + repeated ProvidedTrack prev_tracks = 20; + repeated ProvidedTrack next_tracks = 21; + repeated ContextPlayerState.ContextMetadataEntry context_metadata = 22; + repeated ContextPlayerState.PageMetadataEntry page_metadata = 23; + optional string session_id = 24; + optional uint64 queue_revision = 25; + optional AudioStream audio_stream = 26; + repeated string signals = 27; + repeated ContextPlayerState.ModesEntry modes = 28; + optional string session_command_id = 29; +} + diff --git a/protocol/proto/state_restore/explicit_content_rules.proto b/protocol/proto/state_restore/explicit_content_rules.proto index 271ad6ead..8dafae433 100644 --- a/protocol/proto/state_restore/explicit_content_rules.proto +++ b/protocol/proto/state_restore/explicit_content_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/kitteh_box_rules.proto b/protocol/proto/state_restore/kitteh_box_rules.proto new file mode 100644 index 000000000..08de7d307 --- /dev/null +++ b/protocol/proto/state_restore/kitteh_box_rules.proto @@ -0,0 +1,30 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +message KittehBoxRules { + message NodeAspectsEntry { + optional string key = 1; + optional bytes value = 2; + } + + enum Transition { + ADVANCE = 0; + SKIP_NEXT = 1; + SKIP_PREV = 2; + } + + enum Position { + BETWEEN_TRACKS = 0; + ON_DELIMITER = 1; + ON_NODE_TRACK = 2; + } + + repeated KittehBoxRules.NodeAspectsEntry node_aspects = 1; + required KittehBoxRules.Position pos = 2; + required KittehBoxRules.Transition last_transition = 3; + required int32 context_iteration = 4; + required bool pending_skip_to = 5; + optional int64 page_index = 6; +} + diff --git a/protocol/proto/state_restore/mft_context_history.proto b/protocol/proto/state_restore/mft_context_history.proto index 48e772055..8b9d7a308 100644 --- a/protocol/proto/state_restore/mft_context_history.proto +++ b/protocol/proto/state_restore/mft_context_history.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -17,3 +17,4 @@ message MftContextHistoryEntry { message MftContextHistory { map lookup = 1; } + diff --git a/protocol/proto/state_restore/mft_context_switch_rules.proto b/protocol/proto/state_restore/mft_context_switch_rules.proto index d01e9298c..876d65c8e 100644 --- a/protocol/proto/state_restore/mft_context_switch_rules.proto +++ b/protocol/proto/state_restore/mft_context_switch_rules.proto @@ -1,3 +1,5 @@ +// Extracted from: Spotify 1.2.52.442 (windows) + syntax = "proto2"; package spotify.player.proto.state_restore; diff --git a/protocol/proto/state_restore/mft_fallback_page_history.proto b/protocol/proto/state_restore/mft_fallback_page_history.proto index 54d15e8de..7daca14ae 100644 --- a/protocol/proto/state_restore/mft_fallback_page_history.proto +++ b/protocol/proto/state_restore/mft_fallback_page_history.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/mft_rules_core.proto b/protocol/proto/state_restore/mft_rules_core.proto index 055496249..8845778e1 100644 --- a/protocol/proto/state_restore/mft_rules_core.proto +++ b/protocol/proto/state_restore/mft_rules_core.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/mft_rules_inject_filler_tracks.proto b/protocol/proto/state_restore/mft_rules_inject_filler_tracks.proto index b5b8c6575..41eafd486 100644 --- a/protocol/proto/state_restore/mft_rules_inject_filler_tracks.proto +++ b/protocol/proto/state_restore/mft_rules_inject_filler_tracks.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/mft_state.proto b/protocol/proto/state_restore/mft_state.proto index 8f5f9561c..4494ae127 100644 --- a/protocol/proto/state_restore/mft_state.proto +++ b/protocol/proto/state_restore/mft_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -7,12 +7,12 @@ package spotify.player.proto.state_restore; option optimize_for = CODE_SIZE; message EventList { - repeated int64 event_times = 1; + repeated uint64 event_times = 1; } message LastEvent { required string uri = 1; - required int32 when = 2; + required uint64 when = 2; } message History { @@ -25,7 +25,7 @@ message MftState { required History social_track = 2; required History album = 3; required History artist = 4; - required EventList skip = 5; - required int32 time = 6; + optional EventList skip = 5; + required uint64 time = 6; required bool did_skip = 7; } diff --git a/protocol/proto/state_restore/mod_interruption_state.proto b/protocol/proto/state_restore/mod_interruption_state.proto index e09ffe138..31ca96d8b 100644 --- a/protocol/proto/state_restore/mod_interruption_state.proto +++ b/protocol/proto/state_restore/mod_interruption_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/mod_rules_interruptions.proto b/protocol/proto/state_restore/mod_rules_interruptions.proto index 1b965ccd4..6faa2a579 100644 --- a/protocol/proto/state_restore/mod_rules_interruptions.proto +++ b/protocol/proto/state_restore/mod_rules_interruptions.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -10,6 +10,12 @@ import "state_restore/provided_track.proto"; option optimize_for = CODE_SIZE; message ModRulesInterruptions { + enum InterruptionSource { + CONTEXT = 1; + SAS = 2; + NO_INTERRUPTIONS = 3; + } + optional ProvidedTrack seek_repeat_track = 1; required uint32 prng_seed = 2; required bool support_video = 3; @@ -20,8 +26,3 @@ message ModRulesInterruptions { required PlayerLicense license = 8; } -enum InterruptionSource { - Context_IS = 1; - SAS = 2; - NoInterruptions = 3; -} diff --git a/protocol/proto/state_restore/music_injection_rules.proto b/protocol/proto/state_restore/music_injection_rules.proto index 5ae18bce7..5670b5218 100644 --- a/protocol/proto/state_restore/music_injection_rules.proto +++ b/protocol/proto/state_restore/music_injection_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/playback_state.proto b/protocol/proto/state_restore/playback_state.proto new file mode 100644 index 000000000..1b995d1a3 --- /dev/null +++ b/protocol/proto/state_restore/playback_state.proto @@ -0,0 +1,15 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "state_restore/playback_quality.proto"; + +message PlaybackState { + optional int64 timestamp = 1; + optional int32 position_as_of_timestamp = 2; + optional int32 duration = 3; + optional bool is_buffering = 4; + optional PlaybackQuality playback_quality = 5; + optional double playback_speed = 6; +} + diff --git a/protocol/proto/state_restore/player_model.proto b/protocol/proto/state_restore/player_model.proto new file mode 100644 index 000000000..aa08495c9 --- /dev/null +++ b/protocol/proto/state_restore/player_model.proto @@ -0,0 +1,38 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "context_player_options.proto"; +import "state_restore/player_session_queue.proto"; + +message PlayerModel { + message ConfigurationEntry { + optional string key = 1; + optional string value = 2; + } + + enum AdvanceReason { + SKIP_TO_PREV_TRACK = 1; + SKIP_TO_NEXT_TRACK = 2; + EXTERNAL_ADVANCE = 3; + INTERRUPTED = 4; + SWITCHED_TO_VIDEO = 5; + SWITCHED_TO_AUDIO = 6; + } + + enum StartReason { + PLAY_CONTEXT = 1; + PLAY_CONTEXT_TRACK = 2; + STATE_RESTORE = 3; + REMOTE_TRANSFER = 4; + } + + required ContextPlayerOptions options = 1; + repeated PlayerModel.ConfigurationEntry configuration = 2; + required PlayerSessionQueue session_queue = 3; + required PlayerModel.AdvanceReason last_advance_reason = 4; + optional PlayerModel.StartReason last_start_reason = 5; + required string prev_state_id = 6; + optional string override_state_id = 7; +} + diff --git a/protocol/proto/state_restore/player_session.proto b/protocol/proto/state_restore/player_session.proto new file mode 100644 index 000000000..ee5d525f6 --- /dev/null +++ b/protocol/proto/state_restore/player_session.proto @@ -0,0 +1,39 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "context_track.proto"; +import "context_player_options.proto"; +import "logging_params.proto"; +import "play_origin.proto"; +import "player_license.proto"; +import "prepare_play_options.proto"; +import "state_restore/context_loader.proto"; +import "state_restore/context_player_rules.proto"; +import "state_restore/playback_state.proto"; +import "state_restore/player_session_fake.proto"; +import "state_restore/provided_track.proto"; + +message PlayerSession { + required PreparePlayOptions prepare_play_options = 1; + optional PlaybackState playback_state = 2; + optional ProvidedTrack track = 3; + optional ContextTrack track_to_skip_to = 4; + optional bytes given_playback_id = 5; + required LoggingParams next_command_logging_params = 6; + required LoggingParams curr_command_logging_params = 7; + required PlayOrigin play_origin = 8; + required bool is_playing = 9; + required bool is_paused = 10; + required bool is_system_initiated = 11; + required bool is_finished = 12; + required ContextPlayerOptions options = 13; + required uint64 playback_seed = 14; + required int32 num_advances = 15; + required bool did_skip_prev = 16; + required PlayerLicense license = 17; + required ContextPlayerRules rules = 18; + required ContextLoader loader = 19; + optional PlayerSessionFake fake = 100; +} + diff --git a/protocol/proto/state_restore/player_session_fake.proto b/protocol/proto/state_restore/player_session_fake.proto new file mode 100644 index 000000000..7f4051276 --- /dev/null +++ b/protocol/proto/state_restore/player_session_fake.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; + +package spotify.player.proto.state_restore; + +import "context.proto"; +import "state_restore/context_player_state.proto"; + +message PlayerSessionFake { + required ContextPlayerState player_state = 1; + required Context player_context = 2; + required bool is_finished = 3; +} + diff --git a/protocol/proto/state_restore/player_session_queue.proto b/protocol/proto/state_restore/player_session_queue.proto index 22ee79419..036c277e5 100644 --- a/protocol/proto/state_restore/player_session_queue.proto +++ b/protocol/proto/state_restore/player_session_queue.proto @@ -1,27 +1,26 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; +import "state_restore/player_session.proto"; + package spotify.player.proto.state_restore; option optimize_for = CODE_SIZE; -message SessionJson { - optional string json = 1; -} - message QueuedSession { - optional Trigger trigger = 1; - optional SessionJson session = 2; + enum Trigger { + DID_GO_PAST_TRACK = 1; + DID_GO_PAST_CONTEXT = 2; + } + + optional QueuedSession.Trigger trigger = 1; + optional PlayerSession session = 2; } message PlayerSessionQueue { - optional SessionJson active = 1; - repeated SessionJson pushed = 2; + optional PlayerSession active = 1; + repeated PlayerSession pushed = 2; repeated QueuedSession queued = 3; } -enum Trigger { - DID_GO_PAST_TRACK = 1; - DID_GO_PAST_CONTEXT = 2; -} diff --git a/protocol/proto/state_restore/provided_track.proto b/protocol/proto/state_restore/provided_track.proto index a61010e57..7332cb574 100644 --- a/protocol/proto/state_restore/provided_track.proto +++ b/protocol/proto/state_restore/provided_track.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/random_source.proto b/protocol/proto/state_restore/random_source.proto index f1ad10190..f2739c57c 100644 --- a/protocol/proto/state_restore/random_source.proto +++ b/protocol/proto/state_restore/random_source.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/remove_banned_tracks_rules.proto b/protocol/proto/state_restore/remove_banned_tracks_rules.proto index 9db5c70cd..99de63aa1 100644 --- a/protocol/proto/state_restore/remove_banned_tracks_rules.proto +++ b/protocol/proto/state_restore/remove_banned_tracks_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/resume_points_rules.proto b/protocol/proto/state_restore/resume_points_rules.proto index 6f2618a99..31d35a6d5 100644 --- a/protocol/proto/state_restore/resume_points_rules.proto +++ b/protocol/proto/state_restore/resume_points_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/state_restore/track_error_rules.proto b/protocol/proto/state_restore/track_error_rules.proto index e13b8562b..a241d88c1 100644 --- a/protocol/proto/state_restore/track_error_rules.proto +++ b/protocol/proto/state_restore/track_error_rules.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/status.proto b/protocol/proto/status.proto index 1293af571..017cc8261 100644 --- a/protocol/proto/status.proto +++ b/protocol/proto/status.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/status_code.proto b/protocol/proto/status_code.proto index abc8bd49c..08153b1ec 100644 --- a/protocol/proto/status_code.proto +++ b/protocol/proto/status_code.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,7 +8,10 @@ option objc_class_prefix = "ESP"; option java_package = "com.spotify.stream_reporting_esperanto.proto"; enum StatusCode { - SUCCESS = 0; - NO_PLAYBACK_ID = 1; + INVALID_STATUS_CODE = 0; + SUCCESS = 1; EVENT_SENDER_ERROR = 2; + INVALID_STREAM_HANDLE = 3; + PENDING_EVENTS_ERROR = 4; + IGNORED = 5; } diff --git a/protocol/proto/status_response.proto b/protocol/proto/status_response.proto index 78d15c9a0..271739576 100644 --- a/protocol/proto/status_response.proto +++ b/protocol/proto/status_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -11,5 +11,4 @@ option java_package = "com.spotify.stream_reporting_esperanto.proto"; message StatusResponse { StatusCode status_code = 1; - string reason = 2; } diff --git a/protocol/proto/storage-resolve.proto b/protocol/proto/storage-resolve.proto index 1cb3b673e..8ccd73a8e 100644 --- a/protocol/proto/storage-resolve.proto +++ b/protocol/proto/storage-resolve.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,7 +13,7 @@ message StorageResolveResponse { STORAGE = 1; RESTRICTED = 3; } - + repeated string cdnurl = 2; bytes fileid = 4; } diff --git a/protocol/proto/storylines.proto b/protocol/proto/storylines.proto index c9361966a..115094545 100644 --- a/protocol/proto/storylines.proto +++ b/protocol/proto/storylines.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/stream_end_request.proto b/protocol/proto/stream_end_request.proto index ed72fd512..762d09410 100644 --- a/protocol/proto/stream_end_request.proto +++ b/protocol/proto/stream_end_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -15,5 +15,6 @@ message StreamEndRequest { StreamHandle stream_handle = 1; string source_end = 2; PlayReason reason_end = 3; - MediaFormat format = 4; + google.protobuf.Timestamp client_timestamp = 5; + optional AudioFormat format = 4; } diff --git a/protocol/proto/stream_handle.proto b/protocol/proto/stream_handle.proto index b66ed4ce3..b293fa181 100644 --- a/protocol/proto/stream_handle.proto +++ b/protocol/proto/stream_handle.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -8,5 +8,6 @@ option objc_class_prefix = "ESP"; option java_package = "com.spotify.stream_reporting_esperanto.proto"; message StreamHandle { - string playback_id = 1; + reserved 1; + uint32 raw_handle = 2; } diff --git a/protocol/proto/stream_progress_request.proto b/protocol/proto/stream_progress_request.proto index 63fe9d80c..4c68e6905 100644 --- a/protocol/proto/stream_progress_request.proto +++ b/protocol/proto/stream_progress_request.proto @@ -1,10 +1,13 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.stream_reporting_esperanto.proto; +import "google/protobuf/timestamp.proto"; +import "audio_format.proto"; import "stream_handle.proto"; +import "playback_state.proto"; option objc_class_prefix = "ESP"; option java_package = "com.spotify.stream_reporting_esperanto.proto"; @@ -19,4 +22,12 @@ message StreamProgressRequest { bool is_fullscreen = 7; bool is_external = 8; double playback_speed = 9; + google.protobuf.Timestamp client_timestamp = 14; + PlaybackState playback_state = 15; + optional string media_id = 10; + optional bool content_is_downloaded = 11; + optional AudioFormat audio_format = 12; + optional string content_uri = 13; + optional bool is_audio_on = 16; + optional string video_surface = 17; } diff --git a/protocol/proto/stream_seek_request.proto b/protocol/proto/stream_seek_request.proto index 7d99169e4..32c6ac6b2 100644 --- a/protocol/proto/stream_seek_request.proto +++ b/protocol/proto/stream_seek_request.proto @@ -1,16 +1,20 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.stream_reporting_esperanto.proto; +import "google/protobuf/timestamp.proto"; import "stream_handle.proto"; option objc_class_prefix = "ESP"; option java_package = "com.spotify.stream_reporting_esperanto.proto"; message StreamSeekRequest { + reserved 2; StreamHandle stream_handle = 1; uint64 from_position = 3; uint64 to_position = 4; + google.protobuf.Timestamp client_timestamp = 5; + optional bool is_system_initiated = 6; } diff --git a/protocol/proto/stream_start_request.proto b/protocol/proto/stream_start_request.proto index 656016a64..3f762dd04 100644 --- a/protocol/proto/stream_start_request.proto +++ b/protocol/proto/stream_start_request.proto @@ -1,31 +1,37 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.stream_reporting_esperanto.proto; +import "google/protobuf/timestamp.proto"; import "media_type.proto"; import "play_reason.proto"; +import "playback_stack.proto"; +import "playback_stack_v2.proto"; import "streaming_rule.proto"; option objc_class_prefix = "ESP"; option java_package = "com.spotify.stream_reporting_esperanto.proto"; message StreamStartRequest { - string playback_id = 1; - string parent_playback_id = 2; + reserved 9; + reserved 10; + reserved 13; + reserved 14; + reserved 27; + reserved 25; + reserved 35; + bytes playback_id = 1; + bytes parent_playback_id = 2; string parent_play_track = 3; string video_session_id = 4; string play_context = 5; - string uri = 6; - string displayed_uri = 7; - string feature_identifier = 8; - string feature_version = 9; - string view_uri = 10; + string content_uri = 6; + string displayed_content_uri = 7; + PlaybackStack playback_stack = 8; string provider = 11; string referrer = 12; - string referrer_version = 13; - string referrer_vendor = 14; StreamingRule streaming_rule = 15; string connect_controller_device_id = 16; string page_instance_id = 17; @@ -33,12 +39,25 @@ message StreamStartRequest { string source_start = 19; PlayReason reason_start = 20; bool is_shuffle = 23; - bool is_incognito = 25; string media_id = 28; MediaType media_type = 29; uint64 playback_start_time = 30; uint64 start_position = 31; bool is_live = 32; - bool stream_was_offlined = 33; + bool content_is_downloaded = 33; bool client_offline = 34; + string feature_uuid = 36; + string decision_id = 37; + string custom_reporting_attribution = 38; + string play_context_decision_id = 39; + google.protobuf.Timestamp client_timestamp = 40; + bool is_video_on = 44; + string player_session_id = 47; + optional bool is_repeating_track = 41; + optional bool is_repeating_context = 42; + optional bool is_audio_on = 43; + optional string video_surface = 45; + optional PlaybackStackV2 playback_stack_v2 = 46; + optional string preview_impression_uri = 48; } + diff --git a/protocol/proto/stream_start_response.proto b/protocol/proto/stream_start_response.proto index 98af2976e..fd1f710ce 100644 --- a/protocol/proto/stream_start_response.proto +++ b/protocol/proto/stream_start_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/streaming_rule.proto b/protocol/proto/streaming_rule.proto index 9593fdefe..fbf573821 100644 --- a/protocol/proto/streaming_rule.proto +++ b/protocol/proto/streaming_rule.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -13,4 +13,5 @@ enum StreamingRule { STREAMING_RULE_PREVIEW = 2; STREAMING_RULE_WIFI = 3; STREAMING_RULE_SHUFFLE_MODE = 4; + STREAMING_RULE_TABLET_FREE = 5; } diff --git a/protocol/proto/suppressions.proto b/protocol/proto/suppressions.proto index 4ddfaefbc..f514b03fe 100644 --- a/protocol/proto/suppressions.proto +++ b/protocol/proto/suppressions.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sync/album_sync_state.proto b/protocol/proto/sync/album_sync_state.proto index 7ea902769..b06a35da3 100644 --- a/protocol/proto/sync/album_sync_state.proto +++ b/protocol/proto/sync/album_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sync/artist_sync_state.proto b/protocol/proto/sync/artist_sync_state.proto index 03ba32f37..93f7495f6 100644 --- a/protocol/proto/sync/artist_sync_state.proto +++ b/protocol/proto/sync/artist_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sync/episode_sync_state.proto b/protocol/proto/sync/episode_sync_state.proto index 7dce8424a..fa1511e67 100644 --- a/protocol/proto/sync/episode_sync_state.proto +++ b/protocol/proto/sync/episode_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sync/track_sync_state.proto b/protocol/proto/sync/track_sync_state.proto index 8873fad5f..f9f4be01b 100644 --- a/protocol/proto/sync/track_sync_state.proto +++ b/protocol/proto/sync/track_sync_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/sync_request.proto b/protocol/proto/sync_request.proto index b2d776251..18d5b650b 100644 --- a/protocol/proto/sync_request.proto +++ b/protocol/proto/sync_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/track_instance.proto b/protocol/proto/track_instance.proto index 952f28c87..fd501bfea 100644 --- a/protocol/proto/track_instance.proto +++ b/protocol/proto/track_instance.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -11,12 +11,11 @@ import "seek_to_position.proto"; option optimize_for = CODE_SIZE; message TrackInstance { + reserved 3; optional ContextTrack track = 1; optional uint64 id = 2; optional SeekToPosition seek_to_position = 7; optional bool initially_paused = 4; optional ContextIndex index = 5; optional string provider = 6; - - reserved 3; } diff --git a/protocol/proto/track_instantiator.proto b/protocol/proto/track_instantiator.proto index 3b8b8bafd..47ee739a0 100644 --- a/protocol/proto/track_instantiator.proto +++ b/protocol/proto/track_instantiator.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; diff --git a/protocol/proto/transfer_state.proto b/protocol/proto/transfer_state.proto index 200547c03..a90b048ec 100644 --- a/protocol/proto/transfer_state.proto +++ b/protocol/proto/transfer_state.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -6,6 +6,7 @@ package spotify.player.proto.transfer; import "context_player_options.proto"; import "playback.proto"; +import "play_history.proto"; import "session.proto"; import "queue.proto"; @@ -16,4 +17,5 @@ message TransferState { optional Playback playback = 2; optional Session current_session = 3; optional Queue queue = 4; + optional PlayHistory play_history = 5; } diff --git a/protocol/proto/tts-resolve.proto b/protocol/proto/tts-resolve.proto index adb508548..0d0bcf028 100644 --- a/protocol/proto/tts-resolve.proto +++ b/protocol/proto/tts-resolve.proto @@ -1,15 +1,11 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; -package spotify.narration_injection.proto; +package spotify.narration.proto; option optimize_for = CODE_SIZE; -service TtsResolveService { - rpc Resolve(ResolveRequest) returns (ResolveResponse); -} - message ResolveRequest { AudioFormat audio_format = 3; enum AudioFormat { @@ -20,17 +16,54 @@ message ResolveRequest { VORBIS = 4; MP3 = 5; } - + string language = 4; - + TtsVoice tts_voice = 5; enum TtsVoice { UNSET_TTS_VOICE = 0; VOICE1 = 1; VOICE2 = 2; VOICE3 = 3; + VOICE4 = 4; + VOICE5 = 5; + VOICE6 = 6; + VOICE7 = 7; + VOICE8 = 8; + VOICE9 = 9; + VOICE10 = 10; + VOICE11 = 11; + VOICE12 = 12; + VOICE13 = 13; + VOICE14 = 14; + VOICE15 = 15; + VOICE16 = 16; + VOICE17 = 17; + VOICE18 = 18; + VOICE19 = 19; + VOICE20 = 20; + VOICE21 = 21; + VOICE22 = 22; + VOICE23 = 23; + VOICE24 = 24; + VOICE25 = 25; + VOICE26 = 26; + VOICE27 = 27; + VOICE28 = 28; + VOICE29 = 29; + VOICE30 = 30; + VOICE31 = 31; + VOICE32 = 32; + VOICE33 = 33; + VOICE34 = 34; + VOICE35 = 35; + VOICE36 = 36; + VOICE37 = 37; + VOICE38 = 38; + VOICE39 = 39; + VOICE40 = 40; } - + TtsProvider tts_provider = 6; enum TtsProvider { UNSET_TTS_PROVIDER = 0; @@ -38,10 +71,11 @@ message ResolveRequest { READSPEAKER = 2; POLLY = 3; WELL_SAID = 4; + SONANTIC_DEPRECATED = 5; + SONANTIC_FAST = 6; } - + int32 sample_rate_hz = 7; - oneof prompt { string text = 1; string ssml = 2; @@ -50,4 +84,5 @@ message ResolveRequest { message ResolveResponse { string url = 1; + int64 expiry = 2; } diff --git a/protocol/proto/ucs.proto b/protocol/proto/ucs.proto index c5048f8c1..d3c829972 100644 --- a/protocol/proto/ucs.proto +++ b/protocol/proto/ucs.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -16,12 +16,11 @@ message UcsRequest { string request_orgin_version = 2; string reason = 3; } - + ResolveRequest resolve_request = 2; - + AccountAttributesRequest account_attributes_request = 3; message AccountAttributesRequest { - } } @@ -30,25 +29,23 @@ message UcsResponseWrapper { UcsResponse success = 1; Error error = 2; } - + message UcsResponse { int64 fetch_time_millis = 5; - oneof resolve_result { ResolveResponse resolve_success = 1; Error resolve_error = 2; } - oneof account_attributes_result { AccountAttributesResponse account_attributes_success = 3; Error account_attributes_error = 4; } } - + message AccountAttributesResponse { map account_attributes = 1; } - + message Error { int32 error_code = 1; string error_message = 2; diff --git a/protocol/proto/unfinished_episodes_request.proto b/protocol/proto/unfinished_episodes_request.proto index 68e5f9032..ffeb703b6 100644 --- a/protocol/proto/unfinished_episodes_request.proto +++ b/protocol/proto/unfinished_episodes_request.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto2"; @@ -21,6 +21,6 @@ message Episode { message Response { repeated Episode episode = 2; - + reserved 1; } diff --git a/protocol/proto/useraccount.proto b/protocol/proto/useraccount.proto index ca8fea909..fd73fe027 100644 --- a/protocol/proto/useraccount.proto +++ b/protocol/proto/useraccount.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; diff --git a/protocol/proto/your_library_config.proto b/protocol/proto/your_library_config.proto new file mode 100644 index 000000000..3030f34bb --- /dev/null +++ b/protocol/proto/your_library_config.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; + +package spotify.your_library.proto; + +message YourLibraryLabelAndImage { + string label = 1; + string image = 2; + bool include_empty = 3; +} + +message YourLibraryPseudoPlaylistConfig { + .spotify.your_library.proto.YourLibraryLabelAndImage liked_songs = 1; + .spotify.your_library.proto.YourLibraryLabelAndImage your_episodes = 2; + .spotify.your_library.proto.YourLibraryLabelAndImage new_episodes = 3; + .spotify.your_library.proto.YourLibraryLabelAndImage local_files = 4; + .spotify.your_library.proto.YourLibraryLabelAndImage cached_files = 5; + bool your_highlights = 6; + bool all_available_configs_provided = 99; +} + +message YourLibraryFilters { + enum Filter { + ALBUM = 0; + ARTIST = 1; + PLAYLIST = 2; + SHOW = 3; + BOOK = 4; + EVENT = 5; + AUTHOR = 7; + DOWNLOADED = 100; + WRITABLE = 101; + BY_YOU = 102; + BY_SPOTIFY = 103; + UNPLAYED = 104; + IN_PROGRESS = 105; + FINISHED = 106; + } + + repeated .spotify.your_library.proto.YourLibraryFilters.Filter filter = 1; +} + +message YourLibrarySortOrder { + enum SortOrder { + NAME = 0; + RECENTLY_ADDED = 1; + CREATOR = 2; + CUSTOM = 4; + RECENTLY_UPDATED = 5; + RECENTLY_PLAYED_OR_ADDED = 6; + RELEVANCE = 7; + EVENT_START_TIME = 8; + RELEASE_DATE = 9; + } + + .spotify.your_library.proto.YourLibrarySortOrder.SortOrder sort_order = 1; +} + diff --git a/protocol/proto/your_library_contains_request.proto b/protocol/proto/your_library_contains_request.proto index bbb43c204..ea1f746d5 100644 --- a/protocol/proto/your_library_contains_request.proto +++ b/protocol/proto/your_library_contains_request.proto @@ -1,14 +1,17 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; -import "your_library_pseudo_playlist_config.proto"; +import "your_library_config.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; +option java_package = "spotify.your_library.esperanto.proto"; message YourLibraryContainsRequest { repeated string requested_uri = 3; YourLibraryPseudoPlaylistConfig pseudo_playlist_config = 4; + int32 update_throttling = 5; } diff --git a/protocol/proto/your_library_contains_response.proto b/protocol/proto/your_library_contains_response.proto index 641d71a59..232f99396 100644 --- a/protocol/proto/your_library_contains_response.proto +++ b/protocol/proto/your_library_contains_response.proto @@ -1,10 +1,12 @@ -// Extracted from: Spotify 1.1.61.583 (Windows) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; +option java_multiple_files = true; option optimize_for = CODE_SIZE; +option java_package = "spotify.your_library.esperanto.proto"; message YourLibraryContainsResponseHeader { bool is_loading = 2; @@ -18,5 +20,6 @@ message YourLibraryContainsResponseEntity { message YourLibraryContainsResponse { YourLibraryContainsResponseHeader header = 1; repeated YourLibraryContainsResponseEntity entity = 2; + uint32 status_code = 98; string error = 99; } diff --git a/protocol/proto/your_library_decorate_request.proto b/protocol/proto/your_library_decorate_request.proto index 6b77a9766..9c35b1df8 100644 --- a/protocol/proto/your_library_decorate_request.proto +++ b/protocol/proto/your_library_decorate_request.proto @@ -1,14 +1,17 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; -import "your_library_pseudo_playlist_config.proto"; +import "your_library_config.proto"; +option java_package = "spotify.your_library.esperanto.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; message YourLibraryDecorateRequest { repeated string requested_uri = 3; YourLibraryPseudoPlaylistConfig pseudo_playlist_config = 6; + int32 update_throttling = 7; } diff --git a/protocol/proto/your_library_decorate_response.proto b/protocol/proto/your_library_decorate_response.proto index 125d5c33a..b6896df24 100644 --- a/protocol/proto/your_library_decorate_response.proto +++ b/protocol/proto/your_library_decorate_response.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -6,7 +6,9 @@ package spotify.your_library.proto; import "your_library_decorated_entity.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; +option java_package = "spotify.your_library.esperanto.proto"; message YourLibraryDecorateResponseHeader { bool is_loading = 2; @@ -15,5 +17,6 @@ message YourLibraryDecorateResponseHeader { message YourLibraryDecorateResponse { YourLibraryDecorateResponseHeader header = 1; repeated YourLibraryDecoratedEntity entity = 2; + uint32 status_code = 98; string error = 99; } diff --git a/protocol/proto/your_library_decorated_entity.proto b/protocol/proto/your_library_decorated_entity.proto index c31b45ebe..848ab09e4 100644 --- a/protocol/proto/your_library_decorated_entity.proto +++ b/protocol/proto/your_library_decorated_entity.proto @@ -1,26 +1,29 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; +import "policy/supported_link_types_in_playlists.proto"; + option optimize_for = CODE_SIZE; message YourLibraryEntityInfo { - string key = 1; + enum Pinnable { + YES = 0; + NO_IN_FOLDER = 1; + } + string name = 2; string uri = 3; string group_label = 5; string image_uri = 6; bool pinned = 7; - Pinnable pinnable = 8; - enum Pinnable { - YES = 0; - NO_IN_FOLDER = 1; - } - Offline.Availability offline_availability = 9; + int64 add_time = 11; + int64 last_played = 12; + bool has_curated_items = 13; } message Offline { @@ -31,20 +34,51 @@ message Offline { DOWNLOADING = 3; WAITING = 4; } + } message YourLibraryAlbumExtraInfo { + enum Type { + ALBUM = 0; + SINGLE = 1; + COMPILATION = 2; + EP = 3; + } + string artist_name = 1; + string artist_uri = 2; + Type type = 3; + bool is_premium_only = 4; + bool new_release = 5; } message YourLibraryArtistExtraInfo { - + bool has_liked_tracks_or_albums = 1; +} + +message NumberOfItemsForLinkType { + playlist.cosmos.proto.LinkType link_type = 1; + int32 num_items = 2; +} + +message YourLibraryPlaylistFolderInfo { + string uri = 1; + string name = 2; } message YourLibraryPlaylistExtraInfo { string creator_name = 1; + string creator_uri = 8; bool is_loading = 5; bool can_view = 6; + bool can_add = 9; + string row_id = 7; + string made_for_name = 10; + string made_for_uri = 11; + repeated NumberOfItemsForLinkType number_of_items_per_link_type = 12; + bool owned_by_self = 13; + YourLibraryPlaylistFolderInfo from_folder = 14; + string name_prefix = 15; } message YourLibraryShowExtraInfo { @@ -57,6 +91,8 @@ message YourLibraryShowExtraInfo { message YourLibraryFolderExtraInfo { int32 number_of_playlists = 2; int32 number_of_folders = 3; + string row_id = 4; + repeated YourLibraryDecoratedEntity entity = 5; } message YourLibraryLikedSongsExtraInfo { @@ -76,12 +112,53 @@ message YourLibraryLocalFilesExtraInfo { } message YourLibraryBookExtraInfo { + enum Access { + OPEN = 0; + LOCKED = 1; + CAPPED = 2; + } + + enum State { + NOT_STARTED = 0; + IN_PROGRESS = 1; + FINISHED = 2; + } + string author_name = 1; + Access access = 2; + int64 milliseconds_left = 3; + int32 percent_done = 4; + State state = 5; +} + +message YourLibraryCachedFilesExtraInfo { + int32 number_of_items = 1; + int32 duration_in_seconds = 2; +} + +message YourLibraryPreReleaseExtraInfo { + enum Type { + ALBUM = 0; + BOOK = 1; + } + + string artist_name = 1; + string artist_uri = 2; + Type type = 3; + YourLibraryAlbumExtraInfo.Type album_type = 4; +} + +message YourLibraryEventExtraInfo { + string location_name = 1; + int64 start_time = 2; + string city_name = 3; +} + +message YourLibraryAuthorExtraInfo { } message YourLibraryDecoratedEntity { YourLibraryEntityInfo entity_info = 1; - oneof entity { YourLibraryAlbumExtraInfo album = 2; YourLibraryArtistExtraInfo artist = 3; @@ -93,13 +170,10 @@ message YourLibraryDecoratedEntity { YourLibraryNewEpisodesExtraInfo new_episodes = 10; YourLibraryLocalFilesExtraInfo local_files = 11; YourLibraryBookExtraInfo book = 12; + YourLibraryCachedFilesExtraInfo cached_files = 13; + YourLibraryPreReleaseExtraInfo prerelease = 15; + YourLibraryEventExtraInfo event = 16; + YourLibraryAuthorExtraInfo author = 17; } } -message YourLibraryAvailableEntityTypes { - bool albums = 1; - bool artists = 2; - bool playlists = 3; - bool shows = 4; - bool books = 5; -} diff --git a/protocol/proto/your_library_entity.proto b/protocol/proto/your_library_entity.proto index 897fc6c1a..174136eca 100644 --- a/protocol/proto/your_library_entity.proto +++ b/protocol/proto/your_library_entity.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -9,24 +9,15 @@ import "collection_index.proto"; option optimize_for = CODE_SIZE; -message YourLibraryShowWrapper { - collection.proto.CollectionAlbumLikeEntry show = 1; - string uri = 2; -} - -message YourLibraryBookWrapper { - collection.proto.CollectionAlbumLikeEntry book = 1; - string uri = 2; -} - message YourLibraryEntity { - bool pinned = 1; - oneof entity { - collection.proto.CollectionAlbumLikeEntry album = 2; - collection.proto.CollectionArtistEntry artist = 3; - YourLibraryRootlistEntity rootlist_entity = 4; - YourLibraryShowWrapper show = 7; - YourLibraryBookWrapper book = 8; + collection.proto.CollectionAlbumEntry album = 1; + collection.proto.CollectionArtistEntry artist = 2; + YourLibraryRootlistEntity rootlist_entity = 3; + collection.proto.CollectionShowEntry show = 4; + collection.proto.CollectionBookEntry book = 5; + YourLibraryPreReleaseEntity prerelease = 6; + YourLibraryEventEntity event = 7; + collection.proto.CollectionAuthorEntry author = 9; } } diff --git a/protocol/proto/your_library_index.proto b/protocol/proto/your_library_index.proto index 835c0fa26..68ada3d25 100644 --- a/protocol/proto/your_library_index.proto +++ b/protocol/proto/your_library_index.proto @@ -1,4 +1,4 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; @@ -7,26 +7,50 @@ package spotify.your_library.proto; option optimize_for = CODE_SIZE; message YourLibraryRootlistPlaylist { - string image_uri = 1; - bool is_loading = 3; - int32 rootlist_index = 4; - bool can_view = 5; + string prefix = 1; + string image_uri = 2; + string creator_uri = 3; + string made_for_name = 4; + string made_for_uri = 5; + bool is_loading = 6; + int32 rootlist_index = 7; + string row_id = 8; + bool can_view = 9; + bool can_add = 10; + bool owned_by_self = 11; +} + +message YourLibraryPredefinedPlaylist { + string prefix = 1; + string image_uri = 2; + string creator_uri = 3; + string made_for_name = 4; + string made_for_uri = 5; + bool is_loading = 6; + bool can_view = 7; + bool can_add = 8; + bool owned_by_self = 9; } message YourLibraryRootlistFolder { int32 number_of_playlists = 1; int32 number_of_folders = 2; int32 rootlist_index = 3; + string row_id = 4; } -message YourLibraryRootlistCollection { - Kind kind = 1; +message YourLibraryRootlistPseudoPlaylist { enum Kind { LIKED_SONGS = 0; YOUR_EPISODES = 1; NEW_EPISODES = 2; LOCAL_FILES = 3; + CACHED_FILES = 4; + CONTENT_FEED = 5; + YOUR_HIGHLIGHTS = 6; } + + Kind kind = 1; } message YourLibraryRootlistEntity { @@ -34,10 +58,41 @@ message YourLibraryRootlistEntity { string name = 2; string creator_name = 3; int64 add_time = 4; - + int64 last_played = 5; oneof entity { - YourLibraryRootlistPlaylist playlist = 5; - YourLibraryRootlistFolder folder = 6; - YourLibraryRootlistCollection collection = 7; + YourLibraryRootlistPlaylist playlist = 6; + YourLibraryRootlistFolder folder = 7; + YourLibraryRootlistPseudoPlaylist pseudo_playlist = 8; + YourLibraryPredefinedPlaylist predefined_playlist = 9; + } +} + +message YourLibraryPreReleaseEntity { + enum Type { + ALBUM = 0; + BOOK = 1; } + + string entity_name = 1; + string uri = 2; + string creator_name = 3; + string creator_uri = 4; + string image_uri = 5; + int64 add_time = 6; + int64 release_time = 9; + Type type = 7; + string type_str = 8; } + +message YourLibraryEventEntity { + string uri = 1; + string event_name = 2; + repeated string artist_names = 3; + string location_name = 4; + string image_uri = 5; + int64 add_time = 6; + int64 event_time = 7; + int64 utc_event_time = 8; + string city_name = 9; +} + diff --git a/protocol/proto/your_library_request.proto b/protocol/proto/your_library_request.proto index 917a1addd..bbbdd5d8f 100644 --- a/protocol/proto/your_library_request.proto +++ b/protocol/proto/your_library_request.proto @@ -1,18 +1,59 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; -import "your_library_pseudo_playlist_config.proto"; +import "your_library_config.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; +option java_package = "spotify.your_library.esperanto.proto"; + +message YourLibraryTagFilter { + string tag_uri = 1; +} + +message CuratedItems { + enum CuratedItemsFilter { + NONE = 0; + GROUP_BY = 1; + ONLY_CURATED = 2; + ONLY_NOT_CURATED = 3; + } + + repeated string items = 1; + CuratedItemsFilter filter = 2; +} message YourLibraryRequestHeader { bool remaining_entities = 9; + bool total_count = 18; + string lower_bound = 10; + int32 skip = 11; + int32 length = 12; + string text_filter = 13; + YourLibraryFilters filters = 14; + YourLibrarySortOrder sort_order = 15; + bool all_playlists = 17; + repeated int64 fill_folders = 34; + bool separate_pinned_items = 22; + bool num_link_types_in_playlists = 25; + bool ignore_pinning = 26; + CuratedItems curated_items = 29; + bool include_events = 30; + bool include_prereleases = 31; + bool include_authors = 33; + oneof maybe_folder_id { + int64 folder_id = 16; + } + oneof maybe_tag_filter { + .spotify.your_library.proto.YourLibraryTagFilter tag_filter = 24; + } } message YourLibraryRequest { YourLibraryRequestHeader header = 1; YourLibraryPseudoPlaylistConfig pseudo_playlist_config = 4; + int32 update_throttling = 5; } diff --git a/protocol/proto/your_library_response.proto b/protocol/proto/your_library_response.proto index c354ff5bc..3297d7d41 100644 --- a/protocol/proto/your_library_response.proto +++ b/protocol/proto/your_library_response.proto @@ -1,23 +1,48 @@ -// Extracted from: Spotify 1.1.73.517 (macOS) +// Extracted from: Spotify 1.2.52.442 (windows) syntax = "proto3"; package spotify.your_library.proto; import "your_library_decorated_entity.proto"; +import "your_library_config.proto"; +option java_multiple_files = true; option optimize_for = CODE_SIZE; +option java_package = "spotify.your_library.esperanto.proto"; + +message YourLibraryTagPlaylist { + string name = 1; + string uri = 2; + string description = 3; + string image_uri = 4; + proto.Offline.Availability offline_availability = 5; + bool is_curated = 6; + bool is_loading = 7; +} + +message YourLibraryTagInfo { + string tag_name = 1; + bool is_added = 5; + YourLibraryTagPlaylist tag_playlist_info = 7; +} message YourLibraryResponseHeader { int32 remaining_entities = 9; + int32 total_count = 17; + int32 pin_count = 18; + int32 maximum_pinned_items = 19; bool is_loading = 12; - YourLibraryAvailableEntityTypes has = 13; - YourLibraryAvailableEntityTypes has_downloaded = 14; string folder_name = 15; + string parent_folder_uri = 20; + YourLibraryFilters available_filters = 16; + YourLibraryTagInfo tag_info = 21; } message YourLibraryResponse { YourLibraryResponseHeader header = 1; repeated YourLibraryDecoratedEntity entity = 2; + repeated YourLibraryDecoratedEntity pinned_entity = 3; + int32 status_code = 98; string error = 99; } diff --git a/protocol/src/conversion.rs b/protocol/src/conversion.rs new file mode 100644 index 000000000..13286e7ff --- /dev/null +++ b/protocol/src/conversion.rs @@ -0,0 +1,173 @@ +use crate::{ + context_player_options::ContextPlayerOptions, + play_origin::PlayOrigin, + player::{ + ContextPlayerOptions as PlayerContextPlayerOptions, + ModeRestrictions as PlayerModeRestrictions, PlayOrigin as PlayerPlayOrigin, + RestrictionReasons as PlayerRestrictionReasons, Restrictions as PlayerRestrictions, + Suppressions as PlayerSuppressions, + }, + restrictions::{ModeRestrictions, RestrictionReasons, Restrictions}, + suppressions::Suppressions, +}; +use std::collections::HashMap; + +fn hashmap_into, V>(map: HashMap) -> HashMap { + map.into_iter().map(|(k, v)| (k, v.into())).collect() +} + +impl From for PlayerContextPlayerOptions { + fn from(value: ContextPlayerOptions) -> Self { + PlayerContextPlayerOptions { + shuffling_context: value.shuffling_context.unwrap_or_default(), + repeating_context: value.repeating_context.unwrap_or_default(), + repeating_track: value.repeating_track.unwrap_or_default(), + modes: value.modes, + playback_speed: value.playback_speed, + special_fields: value.special_fields, + } + } +} + +impl From for Restrictions { + fn from(value: PlayerRestrictions) -> Self { + Restrictions { + disallow_pausing_reasons: value.disallow_pausing_reasons, + disallow_resuming_reasons: value.disallow_resuming_reasons, + disallow_seeking_reasons: value.disallow_seeking_reasons, + disallow_peeking_prev_reasons: value.disallow_peeking_prev_reasons, + disallow_peeking_next_reasons: value.disallow_peeking_next_reasons, + disallow_skipping_prev_reasons: value.disallow_skipping_prev_reasons, + disallow_skipping_next_reasons: value.disallow_skipping_next_reasons, + disallow_toggling_repeat_context_reasons: value + .disallow_toggling_repeat_context_reasons, + disallow_toggling_repeat_track_reasons: value.disallow_toggling_repeat_track_reasons, + disallow_toggling_shuffle_reasons: value.disallow_toggling_shuffle_reasons, + disallow_set_queue_reasons: value.disallow_set_queue_reasons, + disallow_interrupting_playback_reasons: value.disallow_interrupting_playback_reasons, + disallow_transferring_playback_reasons: value.disallow_transferring_playback_reasons, + disallow_remote_control_reasons: value.disallow_remote_control_reasons, + disallow_inserting_into_next_tracks_reasons: value + .disallow_inserting_into_next_tracks_reasons, + disallow_inserting_into_context_tracks_reasons: value + .disallow_inserting_into_context_tracks_reasons, + disallow_reordering_in_next_tracks_reasons: value + .disallow_reordering_in_next_tracks_reasons, + disallow_reordering_in_context_tracks_reasons: value + .disallow_reordering_in_context_tracks_reasons, + disallow_removing_from_next_tracks_reasons: value + .disallow_removing_from_next_tracks_reasons, + disallow_removing_from_context_tracks_reasons: value + .disallow_removing_from_context_tracks_reasons, + disallow_updating_context_reasons: value.disallow_updating_context_reasons, + disallow_add_to_queue_reasons: value.disallow_add_to_queue_reasons, + disallow_setting_playback_speed: value.disallow_setting_playback_speed_reasons, + disallow_setting_modes: hashmap_into(value.disallow_setting_modes), + disallow_signals: hashmap_into(value.disallow_signals), + special_fields: value.special_fields, + } + } +} + +impl From for PlayerRestrictions { + fn from(value: Restrictions) -> Self { + PlayerRestrictions { + disallow_pausing_reasons: value.disallow_pausing_reasons, + disallow_resuming_reasons: value.disallow_resuming_reasons, + disallow_seeking_reasons: value.disallow_seeking_reasons, + disallow_peeking_prev_reasons: value.disallow_peeking_prev_reasons, + disallow_peeking_next_reasons: value.disallow_peeking_next_reasons, + disallow_skipping_prev_reasons: value.disallow_skipping_prev_reasons, + disallow_skipping_next_reasons: value.disallow_skipping_next_reasons, + disallow_toggling_repeat_context_reasons: value + .disallow_toggling_repeat_context_reasons, + disallow_toggling_repeat_track_reasons: value.disallow_toggling_repeat_track_reasons, + disallow_toggling_shuffle_reasons: value.disallow_toggling_shuffle_reasons, + disallow_set_queue_reasons: value.disallow_set_queue_reasons, + disallow_interrupting_playback_reasons: value.disallow_interrupting_playback_reasons, + disallow_transferring_playback_reasons: value.disallow_transferring_playback_reasons, + disallow_remote_control_reasons: value.disallow_remote_control_reasons, + disallow_inserting_into_next_tracks_reasons: value + .disallow_inserting_into_next_tracks_reasons, + disallow_inserting_into_context_tracks_reasons: value + .disallow_inserting_into_context_tracks_reasons, + disallow_reordering_in_next_tracks_reasons: value + .disallow_reordering_in_next_tracks_reasons, + disallow_reordering_in_context_tracks_reasons: value + .disallow_reordering_in_context_tracks_reasons, + disallow_removing_from_next_tracks_reasons: value + .disallow_removing_from_next_tracks_reasons, + disallow_removing_from_context_tracks_reasons: value + .disallow_removing_from_context_tracks_reasons, + disallow_updating_context_reasons: value.disallow_updating_context_reasons, + disallow_add_to_queue_reasons: value.disallow_add_to_queue_reasons, + disallow_setting_playback_speed_reasons: value.disallow_setting_playback_speed, + disallow_setting_modes: hashmap_into(value.disallow_setting_modes), + disallow_signals: hashmap_into(value.disallow_signals), + disallow_playing_reasons: vec![], + disallow_stopping_reasons: vec![], + special_fields: value.special_fields, + } + } +} + +impl From for ModeRestrictions { + fn from(value: PlayerModeRestrictions) -> Self { + ModeRestrictions { + values: hashmap_into(value.values), + special_fields: value.special_fields, + } + } +} + +impl From for PlayerModeRestrictions { + fn from(value: ModeRestrictions) -> Self { + PlayerModeRestrictions { + values: hashmap_into(value.values), + special_fields: value.special_fields, + } + } +} + +impl From for RestrictionReasons { + fn from(value: PlayerRestrictionReasons) -> Self { + RestrictionReasons { + reasons: value.reasons, + special_fields: value.special_fields, + } + } +} + +impl From for PlayerRestrictionReasons { + fn from(value: RestrictionReasons) -> Self { + PlayerRestrictionReasons { + reasons: value.reasons, + special_fields: value.special_fields, + } + } +} + +impl From for PlayerPlayOrigin { + fn from(value: PlayOrigin) -> Self { + PlayerPlayOrigin { + feature_identifier: value.feature_identifier.unwrap_or_default(), + feature_version: value.feature_version.unwrap_or_default(), + view_uri: value.view_uri.unwrap_or_default(), + external_referrer: value.external_referrer.unwrap_or_default(), + referrer_identifier: value.referrer_identifier.unwrap_or_default(), + device_identifier: value.device_identifier.unwrap_or_default(), + feature_classes: value.feature_classes, + restriction_identifier: value.restriction_identifier.unwrap_or_default(), + special_fields: value.special_fields, + } + } +} + +impl From for PlayerSuppressions { + fn from(value: Suppressions) -> Self { + PlayerSuppressions { + providers: value.providers, + special_fields: value.special_fields, + } + } +} diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index 224043e76..05aef10fd 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -1,4 +1,6 @@ // This file is parsed by build.rs // Each included module will be compiled from the matching .proto definition. +mod conversion; + include!(concat!(env!("OUT_DIR"), "/mod.rs"));