From 2a574267ae4c04360242f1516f4caec98025b635 Mon Sep 17 00:00:00 2001 From: Felix Prillwitz Date: Tue, 24 Dec 2024 09:39:49 +0100 Subject: [PATCH] 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"));