diff --git a/connect/src/spirc.rs b/connect/src/spirc.rs index 95b48a8c..911c58ed 100644 --- a/connect/src/spirc.rs +++ b/connect/src/spirc.rs @@ -4,7 +4,7 @@ use crate::{ authentication::Credentials, dealer::{ manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply}, - protocol::{Command, Message, Request}, + protocol::{Command, FallbackWrapper, Message, Request}, }, session::UserAttributes, Error, Session, SpotifyId, @@ -81,7 +81,7 @@ struct SpircTask { connect_state_volume_update: BoxedStreamResult, connect_state_logout_request: BoxedStreamResult, playlist_update: BoxedStreamResult, - session_update: BoxedStreamResult, + session_update: BoxedStreamResult>, connect_state_command: BoxedStream, user_attributes_update: BoxedStreamResult, user_attributes_mutation: BoxedStreamResult, @@ -191,7 +191,7 @@ impl Spirc { let session_update = session .dealer() - .listen_for("social-connect/v2/session_update", Message::from_json)?; + .listen_for("social-connect/v2/session_update", Message::try_from_json)?; let user_attributes_update = session .dealer() @@ -1552,7 +1552,24 @@ impl SpircTask { Ok(()) } - fn handle_session_update(&mut self, mut session_update: SessionUpdate) { + fn handle_session_update(&mut self, session_update: FallbackWrapper) { + // we know that this enum value isn't present in our current proto definitions, by that + // the json parsing fails because the enum isn't known as proto representation + const WBC: &str = "WIFI_BROADCAST_CHANGED"; + + let mut session_update = match session_update { + FallbackWrapper::Inner(update) => update, + FallbackWrapper::Fallback(value) => { + let fallback_inner = value.to_string(); + if fallback_inner.contains(WBC) { + log::debug!("Received SessionUpdate::{WBC}"); + } else { + log::warn!("SessionUpdate couldn't be parse correctly: {value:?}"); + } + return; + } + }; + let reason = session_update.reason.enum_value(); let mut session = match session_update.session.take() { diff --git a/core/src/dealer/mod.rs b/core/src/dealer/mod.rs index d5bff5b1..4d79f67c 100644 --- a/core/src/dealer/mod.rs +++ b/core/src/dealer/mod.rs @@ -357,7 +357,7 @@ impl DealerShared { } } - warn!("No subscriber for msg.uri: {}", msg.uri); + debug!("No subscriber for msg.uri: {}", msg.uri); } fn dispatch_request( diff --git a/core/src/dealer/protocol.rs b/core/src/dealer/protocol.rs index c774a119..f8fdc8e9 100644 --- a/core/src/dealer/protocol.rs +++ b/core/src/dealer/protocol.rs @@ -5,9 +5,8 @@ pub use request::*; use std::collections::HashMap; use std::io::{Error as IoError, Read}; -use crate::Error; -use base64::prelude::BASE64_STANDARD; -use base64::{DecodeError, Engine}; +use crate::{deserialize_with::json_proto, Error}; +use base64::{prelude::BASE64_STANDARD, DecodeError, Engine}; use flate2::read::GzDecoder; use log::LevelFilter; use serde::Deserialize; @@ -99,17 +98,19 @@ pub struct Message { pub uri: String, } +#[derive(Deserialize)] +#[serde(untagged)] +pub enum FallbackWrapper { + Inner(#[serde(deserialize_with = "json_proto")] T), + Fallback(JsonValue), +} + impl Message { - pub fn from_json(value: Self) -> Result { - use protobuf_json_mapping::*; + pub fn try_from_json( + value: Self, + ) -> Result, Error> { match value.payload { - PayloadValue::Json(json) => match parse_from_str::(&json) { - Ok(message) => Ok(message), - Err(_) => match parse_from_str_with_options(&json, &IGNORE_UNKNOWN) { - Ok(message) => Ok(message), - Err(why) => Err(Error::failed_precondition(why)), - }, - }, + PayloadValue::Json(json) => Ok(serde_json::from_str(&json)?), other => Err(ProtocolError::UnexpectedData(other).into()), } } diff --git a/core/src/deserialize_with.rs b/core/src/deserialize_with.rs index 11687f9b..0e735cbb 100644 --- a/core/src/deserialize_with.rs +++ b/core/src/deserialize_with.rs @@ -35,11 +35,7 @@ where D: Deserializer<'de>, { let v: Value = Deserialize::deserialize(de)?; - parse_value_to_msg(&v).map_err(|why| { - warn!("deserialize_json_proto: {v}"); - error!("deserialize_json_proto: {why}"); - Error::custom(why) - }) + parse_value_to_msg(&v).map_err(Error::custom) } pub fn option_json_proto<'de, T, D>(de: D) -> Result, D::Error>