refactor: remove bail macros

This commit is contained in:
ThetaDev 2023-05-04 22:18:38 +02:00
parent 6a99540ef5
commit 25025ef701
6 changed files with 108 additions and 141 deletions

View file

@ -376,35 +376,26 @@ fn map_url(
deobf: &Deobfuscator, deobf: &Deobfuscator,
last_nsig: &mut [String; 2], last_nsig: &mut [String; 2],
) -> MapResult<Option<(String, bool)>> { ) -> MapResult<Option<(String, bool)>> {
let (url_base, mut url_params) = match url { let x = match url {
Some(url) => ok_or_bail!( Some(url) => util::url_to_params(url).map_err(|_| format!("Could not parse url `{url}`")),
util::url_to_params(url),
MapResult {
c: None,
warnings: vec![format!("Could not parse url `{url}`")]
}
),
None => match signature_cipher { None => match signature_cipher {
Some(signature_cipher) => match cipher_to_url_params(signature_cipher, deobf) { Some(signature_cipher) => cipher_to_url_params(signature_cipher, deobf).map_err(|e| {
Ok(res) => res, format!("Could not deobfuscate signatureCipher `{signature_cipher}`: {e}")
Err(e) => { }),
return MapResult { None => Err("stream contained neither url or cipher".to_owned()),
c: None,
warnings: vec![format!(
"Could not deobfuscate signatureCipher `{signature_cipher}`: {e}"
)],
};
}
},
None => {
return MapResult {
c: None,
warnings: vec!["stream contained neither url nor cipher".to_owned()],
}
}
}, },
}; };
let (url_base, mut url_params) = match x {
Ok(x) => x,
Err(e) => {
return MapResult {
c: None,
warnings: vec![e],
}
}
};
let mut warnings = vec![]; let mut warnings = vec![];
let mut throttled = false; let mut throttled = false;
deobf_nsig(&mut url_params, deobf, last_nsig).unwrap_or_else(|e| { deobf_nsig(&mut url_params, deobf, last_nsig).unwrap_or_else(|e| {
@ -414,21 +405,17 @@ fn map_url(
throttled = true; throttled = true;
}); });
MapResult { match Url::parse_with_params(url_base.as_str(), url_params.iter()) {
c: Some(( Ok(url) => MapResult {
ok_or_bail!( c: Some((url.to_string(), throttled)),
Url::parse_with_params(url_base.as_str(), url_params.iter()), warnings,
MapResult { },
c: None, Err(_) => MapResult {
warnings: vec![format!( c: None,
"url could not be joined. url: `{url_base}` params: {url_params:?}" warnings: vec![format!(
)], "url could not be joined. url: `{url_base}` params: {url_params:?}"
} )],
) },
.to_string(),
throttled,
)),
warnings,
} }
} }
@ -437,16 +424,27 @@ fn map_video_stream(
deobf: &Deobfuscator, deobf: &Deobfuscator,
last_nsig: &mut [String; 2], last_nsig: &mut [String; 2],
) -> MapResult<Option<VideoStream>> { ) -> MapResult<Option<VideoStream>> {
let (mtype, codecs) = some_or_bail!( let (mtype, codecs) = match parse_mime(&f.mime_type) {
parse_mime(&f.mime_type), Some(x) => x,
MapResult { None => {
c: None, return MapResult {
warnings: vec![format!( c: None,
"Invalid mime type `{}` in video format {:?}", warnings: vec![format!(
&f.mime_type, &f "Invalid mime type `{}` in video format {:?}",
)] &f.mime_type, &f
)],
}
} }
); };
let format = match get_video_format(mtype) {
Some(f) => f,
None => {
return MapResult {
c: None,
warnings: vec![format!("invalid video format. itag: {}", f.itag)],
}
}
};
let map_res = map_url(&f.url, &f.signature_cipher, deobf, last_nsig); let map_res = map_url(&f.url, &f.signature_cipher, deobf, last_nsig);
match map_res.c { match map_res.c {
@ -469,13 +467,7 @@ fn map_video_stream(
hdr: f.color_info.unwrap_or_default().primaries hdr: f.color_info.unwrap_or_default().primaries
== player::Primaries::ColorPrimariesBt2020, == player::Primaries::ColorPrimariesBt2020,
mime: f.mime_type.to_owned(), mime: f.mime_type.to_owned(),
format: some_or_bail!( format,
get_video_format(mtype),
MapResult {
c: None,
warnings: vec![format!("invalid video format. itag: {}", f.itag)]
}
),
codec: get_video_codec(codecs), codec: get_video_codec(codecs),
throttled, throttled,
}), }),
@ -495,16 +487,27 @@ fn map_audio_stream(
) -> MapResult<Option<AudioStream>> { ) -> MapResult<Option<AudioStream>> {
static LANG_PATTERN: Lazy<Regex> = Lazy::new(|| Regex::new(r#"^([a-z]{2,3})\."#).unwrap()); static LANG_PATTERN: Lazy<Regex> = Lazy::new(|| Regex::new(r#"^([a-z]{2,3})\."#).unwrap());
let (mtype, codecs) = some_or_bail!( let (mtype, codecs) = match parse_mime(&f.mime_type) {
parse_mime(&f.mime_type), Some(x) => x,
MapResult { None => {
c: None, return MapResult {
warnings: vec![format!( c: None,
"Invalid mime type `{}` in video format {:?}", warnings: vec![format!(
&f.mime_type, &f "Invalid mime type `{}` in video format {:?}",
)] &f.mime_type, &f
)],
}
} }
); };
let format = match get_audio_format(mtype) {
Some(f) => f,
None => {
return MapResult {
c: None,
warnings: vec![format!("invalid audio format. itag: {}", f.itag)],
}
}
};
let map_res = map_url(&f.url, &f.signature_cipher, deobf, last_nsig); let map_res = map_url(&f.url, &f.signature_cipher, deobf, last_nsig);
match map_res.c { match map_res.c {
@ -519,13 +522,7 @@ fn map_audio_stream(
init_range: f.init_range, init_range: f.init_range,
duration_ms: f.approx_duration_ms, duration_ms: f.approx_duration_ms,
mime: f.mime_type.to_owned(), mime: f.mime_type.to_owned(),
format: some_or_bail!( format,
get_audio_format(mtype),
MapResult {
c: None,
warnings: vec![format!("invalid audio format. itag: {}", f.itag)]
}
),
codec: get_audio_codec(codecs), codec: get_audio_codec(codecs),
channels: f.audio_channels, channels: f.audio_channels,
loudness_db: f.loudness_db, loudness_db: f.loudness_db,
@ -559,7 +556,7 @@ fn parse_mime(mime: &str) -> Option<(&str, Vec<&str>)> {
static PATTERN: Lazy<Regex> = static PATTERN: Lazy<Regex> =
Lazy::new(|| Regex::new(r#"(\w+/\w+);\scodecs="([a-zA-Z-0-9.,\s]*)""#).unwrap()); Lazy::new(|| Regex::new(r#"(\w+/\w+);\scodecs="([a-zA-Z-0-9.,\s]*)""#).unwrap());
let captures = some_or_bail!(PATTERN.captures(mime), None); let captures = PATTERN.captures(mime)?;
Some(( Some((
captures.get(1).unwrap().as_str(), captures.get(1).unwrap().as_str(),
captures captures

View file

@ -1,9 +1,6 @@
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs, clippy::todo, clippy::dbg_macro)] #![warn(missing_docs, clippy::todo, clippy::dbg_macro)]
#[macro_use]
mod macros;
mod deobfuscate; mod deobfuscate;
mod serializer; mod serializer;
mod util; mod util;

View file

@ -1,23 +0,0 @@
/// Returns an unwrapped Option if Some() otherwise returns the passed expression
macro_rules! some_or_bail {
($opt:expr, $ret:expr $(,)?) => {{
match $opt {
Some(stuff) => stuff,
None => {
return $ret;
}
}
}};
}
/// Returns an unwrapped Result if Ok() otherwise returns the passed expression
macro_rules! ok_or_bail {
($result:expr, $ret:expr $(,)?) => {{
match $result {
Ok(stuff) => stuff,
Err(_) => {
return $ret;
}
}
}};
}

View file

@ -193,40 +193,43 @@ pub fn retry_delay(
/// Also strips google analytics tracking parameters /// Also strips google analytics tracking parameters
/// (`utm_source`, `utm_medium`, `utm_campaign`, `utm_content`) because google analytics is bad. /// (`utm_source`, `utm_medium`, `utm_campaign`, `utm_content`) because google analytics is bad.
pub fn sanitize_yt_url(url: &str) -> String { pub fn sanitize_yt_url(url: &str) -> String {
let mut parsed_url = ok_or_bail!(Url::parse(url), url.to_owned()); fn sanitize_yt_url_inner(url: &str) -> Option<String> {
let mut parsed_url = Url::parse(url).ok()?;
// Convert redirect url // Convert redirect url
if parsed_url.host_str().unwrap_or_default() == "www.youtube.com" if parsed_url.host_str().unwrap_or_default() == "www.youtube.com"
&& parsed_url.path() == "/redirect" && parsed_url.path() == "/redirect"
{ {
if let Some((_, url)) = parsed_url.query_pairs().find(|(k, _)| k == "q") { if let Some((_, url)) = parsed_url.query_pairs().find(|(k, _)| k == "q") {
parsed_url = ok_or_bail!(Url::parse(url.as_ref()), url.to_string()); parsed_url = Url::parse(url.as_ref()).ok()?;
}
} }
// Remove GA tracking params
if parsed_url.query().is_some() {
let params = parsed_url
.query_pairs()
.filter_map(|(k, v)| match k.borrow() {
"utm_source" | "utm_medium" | "utm_campaign" | "utm_content" => None,
_ => Some((k.to_string(), v.to_string())),
})
.collect::<Vec<_>>();
// Set empty query string if there are no parameters to prevent urls from ending with /?
if params.is_empty() {
parsed_url.set_query(None);
} else {
parsed_url
.query_pairs_mut()
.clear()
.extend_pairs(params)
.finish();
}
}
Some(parsed_url.to_string())
} }
// Remove GA tracking params sanitize_yt_url_inner(url).unwrap_or_else(|| url.to_string())
if parsed_url.query().is_some() {
let params = parsed_url
.query_pairs()
.filter_map(|(k, v)| match k.borrow() {
"utm_source" | "utm_medium" | "utm_campaign" | "utm_content" => None,
_ => Some((k.to_string(), v.to_string())),
})
.collect::<Vec<_>>();
// Set empty query string if there are no parameters to prevent urls from ending with /?
if params.is_empty() {
parsed_url.set_query(None);
} else {
parsed_url
.query_pairs_mut()
.clear()
.extend_pairs(params)
.finish();
}
}
parsed_url.to_string()
} }
pub trait TryRemove<T> { pub trait TryRemove<T> {
@ -298,7 +301,7 @@ where
filtered.push(c); filtered.push(c);
} }
} }
(ok_or_bail!(buf.parse::<u64>(), None), exp, filtered) (buf.parse::<u64>().ok()?, exp, filtered)
}; };
let lookup_token = |token: &str| match token { let lookup_token = |token: &str| match token {
@ -318,14 +321,7 @@ where
.sum::<i32>(); .sum::<i32>();
} }
F::try_from(some_or_bail!( F::try_from(num.checked_mul((10_u64).checked_pow(exp.try_into().ok()?)?)?).ok()
num.checked_mul(some_or_bail!(
(10_u64).checked_pow(ok_or_bail!(exp.try_into(), None)),
None
)),
None
))
.ok()
} }
/// Replace all html control characters to make a string safe for inserting into HTML. /// Replace all html control characters to make a string safe for inserting into HTML.

View file

@ -98,11 +98,11 @@ pub fn string_from_pb<P: IntoIterator<Item = u8>>(pb: P, field: u32) -> Option<S
5 => 4, 5 => 4,
// string // string
2 => { 2 => {
let len = some_or_bail!(parse_varint(&mut pb), None); let len = parse_varint(&mut pb)?;
if this_field == field { if this_field == field {
let mut buf = Vec::new(); let mut buf = Vec::new();
for _ in 0..len { for _ in 0..len {
buf.push(some_or_bail!(pb.next(), None)); buf.push(pb.next()?);
} }
return String::from_utf8(buf).ok(); return String::from_utf8(buf).ok();
} else { } else {

View file

@ -1,5 +1,5 @@
// This code is used to test the deobfuscation javascript extraction. // This code is used to test the deobfuscation javascript extraction.
// Since YouTube's player code is copyrighted, I can just copy-paste it // Since YouTube's player code is copyrighted, I can't just copy-paste it
// into my project. // into my project.
/* /*