fix: improve deobfuscator (support multiple nsig name matches, error if mapping all streams fails)
Since YouTube keeps changing the nsig function signature and a generic regex may match at multiple places, I changed the extraction logic to search for multiple matches if necessary and test the extracted deobfuscation functions. I also found out that if the deobfuscation fails for all streams, fetching the player still returns a successful result with no streams, suggesting that the video is not available. So I changed the mapper to throw an ExtractionError if no streams are mapped successfully.
This commit is contained in:
parent
11a0038350
commit
8152ce6b08
4 changed files with 414 additions and 331 deletions
|
|
@ -551,6 +551,24 @@ impl<'a> Iterator for SplitTokens<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Applies function to the elements of iterator and returns the first successful result
|
||||
/// or the last error if the function fails on all elements. If the iterator is empty, e_empty
|
||||
/// is returned.
|
||||
pub fn find_map_or_last_err<I, T, P, O, E>(mut iter: I, e_empty: E, mut f: P) -> Result<O, E>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
P: FnMut(T) -> Result<O, E>,
|
||||
{
|
||||
let res = iter.try_fold(e_empty, |_, itm| match f(itm) {
|
||||
Ok(o) => Err(o),
|
||||
Err(e) => Ok(e),
|
||||
});
|
||||
match res {
|
||||
Ok(e) => Err(e),
|
||||
Err(o) => Ok(o),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use std::{fs::File, io::BufReader, path::PathBuf};
|
||||
|
|
@ -730,4 +748,27 @@ pub(crate) mod tests {
|
|||
let res = country_from_name(name);
|
||||
assert_eq!(res, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn t_find_map_or_last_err() {
|
||||
// Success
|
||||
let res = find_map_or_last_err([1, 2, 3].into_iter(), 0, |x: i32| {
|
||||
if x > 2 {
|
||||
Ok(true)
|
||||
} else {
|
||||
Err(x)
|
||||
}
|
||||
});
|
||||
assert_eq!(res, Ok(true));
|
||||
|
||||
// Error
|
||||
let res = find_map_or_last_err([1, 2, 3].into_iter(), 0, |x: i32| Err::<(), _>(x));
|
||||
assert_eq!(res, Err(3));
|
||||
|
||||
// Empty iterator
|
||||
assert_eq!(
|
||||
find_map_or_last_err(std::iter::empty(), 0, |_: i32| Ok(true)),
|
||||
Err(0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue