diff --git a/USAGE b/USAGE index f83534d..926b950 100644 --- a/USAGE +++ b/USAGE @@ -27,13 +27,15 @@ Options: -e, --email Google account email address (required if download source is Google Play) -t, --aas-token - Google aas token (required if download source is Google Play) + Google aas token (required if download source is Google Play) --accept-tos Accept Google Play Terms of Service -s, --sleep-duration Sleep duration (in ms) before download requests [default: 0] -r, --parallel The number of parallel APK fetches to run at a time [default: 4] + -x, --xapk + Download a xapk file instead of an apk file. This only applies to APKPure and not all apps have a xapk available. -h, --help Print help -V, --version diff --git a/src/apkpure.rs b/src/apkpure.rs index d7676bd..7ae20a7 100644 --- a/src/apkpure.rs +++ b/src/apkpure.rs @@ -30,17 +30,16 @@ pub async fn download_apps( parallel: usize, sleep_duration: u64, outpath: &Path, + xapk_bundle: bool ) { let mp = Rc::new(MultiProgress::new()); let http_client = Rc::new(reqwest::Client::new()); let headers = http_headers(); - let re = Rc::new(Regex::new(crate::consts::APKPURE_DOWNLOAD_URL_REGEX).unwrap()); futures_util::stream::iter( apps.into_iter().map(|app| { let (app_id, app_version) = app; let http_client = Rc::clone(&http_client); - let re = Rc::clone(&re); let headers = headers.clone(); let mp = Rc::clone(&mp); let mp_log = Rc::clone(&mp); @@ -63,13 +62,19 @@ pub async fn download_apps( .get(versions_url) .headers(headers) .send().await.unwrap(); - if let Some(app_version) = app_version { - let regex_string = format!("[[:^digit:]]{}:(?s:.)+?{}", regex::escape(&app_version), crate::consts::APKPURE_DOWNLOAD_URL_REGEX); - let re = Regex::new(®ex_string).unwrap(); - download_from_response(versions_response, Box::new(Box::new(re)), app_string, outpath, mp).await; - } else { - download_from_response(versions_response, Box::new(re), app_string, outpath, mp).await; - } + + let download_url_regex = match xapk_bundle { + true => format!("(XAPKJ)..{}", crate::consts::APKPURE_DOWNLOAD_URL_REGEX), + false => format!("[^X](APKJ)..{}", crate::consts::APKPURE_DOWNLOAD_URL_REGEX) + }; + + let regex_string = if let Some(app_version) = app_version { + format!("[[:^digit:]]{}:(?s:.)+?{}", regex::escape(&app_version) , download_url_regex) } + else { + format!("[[:^digit:]]:(?s:.)+?{}" , download_url_regex)}; + + let re = Regex::new(®ex_string).unwrap(); + download_from_response(versions_response, Box::new(Box::new(re)), app_string, outpath, mp).await; } }) ).buffer_unordered(parallel).collect::>().await; diff --git a/src/cli.rs b/src/cli.rs index d6a1133..f6c5475 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -119,7 +119,7 @@ pub fn app() -> Command { ) .arg( Arg::new("google_aas_token") - .help("Google aas token (required if download source is Google Play)") + .help("Google aas token (required if download source is Google Play)") .short('t') .long("aas-token") .action(ArgAction::Set) @@ -156,4 +156,11 @@ pub fn app() -> Command { .index(1) .required_unless_present("google_oauth_token"), ) + .arg( + Arg::new("xapk") + .help("Download a xapk file instead of an apk file. This only applies to APKPure and not all apps have a xapk available.") + .short('x') + .long("xapk") + .action(ArgAction::SetTrue) + ) } diff --git a/src/consts.rs b/src/consts.rs index 0c39a13..bd0c7bd 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,5 +1,5 @@ pub const APKPURE_VERSIONS_URL_FORMAT: &str = "https://api.pureapk.com/m/v3/cms/app_version?hl=en-US&package_name="; -pub const APKPURE_DOWNLOAD_URL_REGEX: &str = r"(X?APKJ)..(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))"; +pub const APKPURE_DOWNLOAD_URL_REGEX: &str = r"(https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))"; pub const FDROID_REPO: &str = "https://f-droid.org/repo"; pub const FDROID_INDEX_FINGERPRINT: &[u8] = &[67, 35, 141, 81, 44, 30, 94, 178, 214, 86, 159, 74, 58, 251, 245, 82, 52, 24, 184, 46, 10, 62, 209, 85, 39, 112, 171, 185, 169, 201, 204, 171]; pub const FDROID_SIGNATURE_BLOCK_FILE_REGEX: &str = r"^META-INF/.*\.(DSA|EC|RSA)$"; diff --git a/src/main.rs b/src/main.rs index 390a801..2e6856c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -299,7 +299,11 @@ async fn main() { match download_source { DownloadSource::APKPure => { - apkpure::download_apps(list, parallel, sleep_duration, &outpath.unwrap()).await; + if let Some(true) = matches.get_one::("xapk") { + apkpure::download_apps(list, parallel, sleep_duration, &outpath.unwrap(), true).await; + } else { + apkpure::download_apps(list, parallel, sleep_duration, &outpath.unwrap(), false).await; + } } DownloadSource::GooglePlay => { let mut email = matches.get_one::("google_email").map(|v| v.to_string());