fix: desktop client: generate PO token from user_syncid when authenticated

This commit is contained in:
ThetaDev 2025-03-16 01:56:29 +01:00
parent c34227e763
commit 1e1b0cdf45
2 changed files with 33 additions and 14 deletions

View file

@ -293,8 +293,10 @@ struct OauthToken {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
struct AuthCookie { struct AuthCookie {
cookie: String, cookie: String,
#[serde(alias = "account_syncid", skip_serializing_if = "Option::is_none")]
channel_syncid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
account_syncid: Option<String>, user_syncid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
session_index: Option<String>, session_index: Option<String>,
} }
@ -319,8 +321,9 @@ impl AuthCookie {
fn new(cookie: String) -> Self { fn new(cookie: String) -> Self {
Self { Self {
cookie, cookie,
account_syncid: None, channel_syncid: None,
session_index: None, session_index: None,
user_syncid: None,
} }
} }
} }
@ -1591,6 +1594,17 @@ impl RustyPipe {
.ok_or(Error::Auth(AuthError::NoLogin)) .ok_or(Error::Auth(AuthError::NoLogin))
} }
fn user_auth_datasync_id(&self) -> Result<String, Error> {
self.inner
.cache
.auth_cookie
.read()
.unwrap()
.as_ref()
.and_then(|c| c.user_syncid.as_ref().map(|id| id.to_owned()))
.ok_or(Error::Auth(AuthError::NoLogin))
}
/// Set the user authentication cookie /// Set the user authentication cookie
/// ///
/// The cookie is used for authenticated requests with browser-based clients /// The cookie is used for authenticated requests with browser-based clients
@ -1685,17 +1699,17 @@ impl RustyPipe {
))?; ))?;
// datasyncid is of the form "channel_syncid||user_syncid" for secondary channel // datasyncid is of the form "channel_syncid||user_syncid" for secondary channel
// and just "user_syncid||" for primary channel. We only want the channel_syncid // and just "user_syncid||" for primary channel.
let (channel_syncid, user_syncid) = let (p1, p2) =
datasync_id datasync_id
.split_once("||") .split_once("||")
.ok_or(Error::Extraction(ExtractionError::InvalidData( .ok_or(Error::Extraction(ExtractionError::InvalidData(
"datasyncId does not contain || seperator".into(), "datasyncId does not contain || seperator".into(),
)))?; )))?;
auth_cookie.account_syncid = if user_syncid.is_empty() { (auth_cookie.channel_syncid, auth_cookie.user_syncid) = if p2.is_empty() {
None (None, Some(p1.to_owned()))
} else { } else {
Some(channel_syncid.to_owned()) (Some(p1.to_owned()), Some(p2.to_owned()))
}; };
auth_cookie.session_index = Some( auth_cookie.session_index = Some(
@ -2129,7 +2143,7 @@ impl RustyPipeQuery {
if let Some(session_index) = auth_cookie.session_index { if let Some(session_index) = auth_cookie.session_index {
r = r.header("X-Goog-AuthUser", session_index); r = r.header("X-Goog-AuthUser", session_index);
} }
if let Some(account_syncid) = auth_cookie.account_syncid { if let Some(account_syncid) = auth_cookie.channel_syncid {
r = r.header("X-Goog-PageId", account_syncid); r = r.header("X-Goog-PageId", account_syncid);
} }
cookie = Some(auth_cookie.cookie); cookie = Some(auth_cookie.cookie);

View file

@ -139,22 +139,27 @@ impl RustyPipeQuery {
async fn get_player_po_token(&self, video_id: &str) -> Result<PlayerPoToken, Error> { async fn get_player_po_token(&self, video_id: &str) -> Result<PlayerPoToken, Error> {
if let Some(bg) = &self.client.inner.botguard { if let Some(bg) = &self.client.inner.botguard {
let visitor_data = self.get_visitor_data(false).await?; let (ident, visitor_data) = if self.opts.auth == Some(true) {
(self.client.user_auth_datasync_id()?, None)
} else {
let visitor_data = self.get_visitor_data(false).await?;
(visitor_data.to_owned(), Some(visitor_data))
};
if bg.po_token_cache { if bg.po_token_cache {
let session_token = self.get_session_po_token(&visitor_data).await?; let session_token = self.get_session_po_token(&ident).await?;
Ok(PlayerPoToken { Ok(PlayerPoToken {
visitor_data: Some(visitor_data), visitor_data,
session_po_token: Some(session_token), session_po_token: Some(session_token),
content_po_token: None, content_po_token: None,
}) })
} else { } else {
let (po_tokens, valid_until) = let (po_tokens, valid_until) = self.get_po_tokens(&[video_id, &ident]).await?;
self.get_po_tokens(&[video_id, &visitor_data]).await?;
let mut po_tokens = po_tokens.into_iter(); let mut po_tokens = po_tokens.into_iter();
let po_token = po_tokens.next().unwrap(); let po_token = po_tokens.next().unwrap();
let session_po_token = po_tokens.next().unwrap(); let session_po_token = po_tokens.next().unwrap();
Ok(PlayerPoToken { Ok(PlayerPoToken {
visitor_data: Some(visitor_data), visitor_data,
session_po_token: Some(PoToken { session_po_token: Some(PoToken {
po_token: session_po_token, po_token: session_po_token,
valid_until, valid_until,