fix: remove leading zero-width-space from comments, ensure space after links

This commit is contained in:
ThetaDev 2024-12-18 19:31:24 +01:00
parent 8cadbc1a4c
commit 162959ca45
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6
3 changed files with 41 additions and 5 deletions

View file

@ -250,6 +250,7 @@ fn extract_js_fn(js: &str, offset: usize, name: &str) -> Result<String, DeobfErr
} }
} }
// Looking for variable names
if let Token::Ident(id) = &token { if let Token::Ident(id) = &token {
if !period_before { if !period_before {
let id_str = id.to_string(); let id_str = id.to_string();

View file

@ -1,4 +1,4 @@
use std::convert::TryFrom; use std::{borrow::Cow, convert::TryFrom};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use serde_with::{serde_as, DefaultOnError, DeserializeAs, VecSkipError}; use serde_with::{serde_as, DefaultOnError, DeserializeAs, VecSkipError};
@ -402,10 +402,41 @@ impl<'de> DeserializeAs<'de, TextComponents> for AttributedText {
.next() .next()
.map(Verification::from) .map(Verification::from)
.unwrap_or_default(); .unwrap_or_default();
let mut components: Vec<TextComponent> = Vec::with_capacity(runs.len() + 1);
fn process_txt_before(components: &[TextComponent], txt_before: Cow<'_, str>) -> String {
// YouTube sometimes inserts zero-width spaces at the start of comments
let txt_before = match txt_before.strip_prefix('\u{200b}') {
Some(t) => Cow::Borrowed(t),
None => txt_before,
};
// Ensure that text after link components always begins with a space
if !txt_before
.chars()
.next()
.map(|c| c.is_whitespace())
.unwrap_or_default()
&& components
.last()
.map(|c| {
!matches!(c, TextComponent::Text { .. })
&& !c
.as_str()
.chars()
.last()
.map(|c| c.is_whitespace())
.unwrap_or_default()
})
.unwrap_or_default()
{
format!(" {txt_before}")
} else {
txt_before.into_owned()
}
}
let mut components = Vec::with_capacity(runs.len() + 1);
for run in runs { for run in runs {
let txt_before = take_chars(run.start_index); let txt_before = process_txt_before(&components, take_chars(run.start_index).into());
let txt_run = take_chars(run.start_index + run.length); let txt_run = take_chars(run.start_index + run.length);
if !txt_before.is_empty() { if !txt_before.is_empty() {
@ -461,7 +492,7 @@ impl<'de> DeserializeAs<'de, TextComponents> for AttributedText {
}) })
} }
let end = chars.as_str(); let end = process_txt_before(&components, chars.as_str().into());
if !end.is_empty() { if !end.is_empty() {
components.push(TextComponent::new(end)); components.push(TextComponent::new(end));
} }
@ -683,6 +714,10 @@ impl From<TextComponent> for String {
} }
impl TextComponents { impl TextComponents {
pub fn is_empty(&self) -> bool {
self.0.iter().all(|c| c.as_str().is_empty())
}
/// Return the string representation of the first text component /// Return the string representation of the first text component
pub fn first_str(&self) -> &str { pub fn first_str(&self) -> &str {
self.0 self.0

View file

@ -30,7 +30,7 @@ use rustypipe::validate;
#[case::desktop(ClientType::Desktop)] #[case::desktop(ClientType::Desktop)]
#[case::tv(ClientType::Tv)] #[case::tv(ClientType::Tv)]
#[case::mobile(ClientType::Mobile)] #[case::mobile(ClientType::Mobile)]
// #[case::android(ClientType::Android)] #[case::android(ClientType::Android)]
#[case::ios(ClientType::Ios)] #[case::ios(ClientType::Ios)]
#[tokio::test] #[tokio::test]
async fn get_player_from_client(#[case] client_type: ClientType, rp: RustyPipe) { async fn get_player_from_client(#[case] client_type: ClientType, rp: RustyPipe) {