From 0bfbde3b801dfbd3b0ce2fbef0a877da78a5f732 Mon Sep 17 00:00:00 2001 From: Anton Bobov Date: Mon, 3 Aug 2026 23:35:17 +0500 Subject: add rustore-apk-get script --- rustore-apk-get | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100755 rustore-apk-get (limited to 'rustore-apk-get') diff --git a/rustore-apk-get b/rustore-apk-get new file mode 100755 index 0000000..5479c5d --- /dev/null +++ b/rustore-apk-get @@ -0,0 +1,139 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# See https://github.com/ImranR98/Obtainium/blob/main/lib/app_sources/rustore.dart + +# @describe Download apk from https://rustore.ru +# @meta require-tools curl,jq,fzf,xxh64sum +# @flag -u --update download file if it exists but hash not match +# @flag -v --verbose verbose output +# @flag --whats-new show whats new before download +# @flag --save-json save package info JSON +# @flag --extract extract ZIP on download +# @option -q --query search string +# @option -o --output=`_default_output` Output directory/file +# @arg package_name Application package name + +BASE_URL=https://backapi.rustore.ru +PAGE_SIZE=10 + +_default_output() { + pwd +} + +_curl() { + curl --retry 3 --header 'ruStoreVerCode: 1105002' "$@" +} + +_curl_silent() { + _curl --silent "$@" +} + +select_package_name_from_query() { + local delimiter=$'\t' + _curl_silent --get \ + --data-urlencode "query=$argc_query" \ + --data-urlencode "pageSize=$PAGE_SIZE" \ + "$BASE_URL/applicationData/apps" | + jq -r '.body.content[] | [.packageName,.appName,.shortDescription] | @tsv' | + column -t -s "$delimiter" -o "$delimiter" | + fzf --delimiter "$delimiter" --accept-nth 1 +} + +get_app_info_by_package() { + _curl_silent --get "$BASE_URL/applicationData/overallInfo/$1" | jq .body +} + +download_apk() { + local app_info="$1" + local app_id + local package_name + local version_name + app_id=$(jq -r .appId <<<"$app_info") + package_name=$(jq -r .packageName <<<"$app_info") + version_name=$(jq -r .versionName <<<"$app_info") + local output_file + local output_file_hash + + if [ -d "${argc_output?}" ]; then + output_file="$argc_output/$package_name-$version_name.apk" + else + output_file="$argc_output" + fi + output_file_hash="${output_file}.xxh64sum" + + local existing_file_hash + + if [ -f "$output_file" ] && [ -f "$output_file_hash" ]; then + if [ -z "${argc_update:-}" ]; then + echo "File already exists: $output_file" + exit 1 + else + existing_file_hash=$(cat "$output_file_hash") + fi + fi + + local download_info + download_info=$(_curl_silent --request POST --json '{"appId":'"$app_id"'}' "$BASE_URL/applicationData/v2/download-link" | jq .body.downloadUrls[0]) + + local download_url + local expected_hash + download_url=$(jq -r .url <<<"$download_info") + expected_hash=$(jq -r .hash <<<"$download_info") + + [ "${existing_file_hash:-}" == "$expected_hash" ] && return + + [ -n "${argc_whats_new:-}" ] && jq -r '"News: \(.whatsNew)"' <<<"$app_info" + + temp_file_zip=$(mktemp) + temp_file_apk=$(mktemp) + trap 'rm -f "$temp_file_zip" "$temp_file_apk"' EXIT + + _curl --progress-bar --output "$temp_file_zip" "$download_url" + + existing_file_hash=$(xxh64sum "$temp_file_zip" | cut -d ' ' -f 1) + + if [ "$existing_file_hash" == "$expected_hash" ]; then + unzip -p "$temp_file_zip" "*.apk" >"$temp_file_apk" + mv "$temp_file_apk" "$output_file" + echo "$expected_hash" >"$output_file_hash" + else + echo "Downloaded file hash not match expected" + exit 2 + fi +} + +main() { + local package_name="${argc_package_name:-}" + if [[ "$package_name" == http* ]]; then + package_name=$(echo "$package_name" | grep -oP '(?<=/app/)[^/?]+') + fi + if [ -z "$package_name" ] && [ -n "${argc_query:-}" ]; then + package_name=$(select_package_name_from_query) + fi + + [ -z "$package_name" ] && exit 1 + + local app_info + app_info=$(get_app_info_by_package "$package_name") + + local app_id + app_id=$(jq -r .appId <<<"$app_info") + + if [ -z "${app_id:-}" ]; then + echo "No application ID specified or found" + exit 1 + fi + + if [ "${argc_verbose:-}" == 1 ]; then + jq -r '{appName,versionName,appVerUpdatedAt,shortDescription,whatsNew} | to_entries[] | [.key,.value] | @tsv' <<<"$app_info" | + column -t -s $'\t' + else + jq -r '"\(.appName) - v\(.versionName) [\(.appVerUpdatedAt | strptime("%Y-%m-%dT%H:%M:%S%Z") | strftime("%d.%m.%Y"))]"' <<<"$app_info" + fi + + download_apk "$app_info" +} + +eval "$(argc --argc-eval "$0" "$@")" -- cgit v1.2.3