[
  {
    "path": ".gitignore",
    "content": ".githubtoken\n.tgtoken\nworking/\nexternal/\n"
  },
  {
    "path": "README.md",
    "content": "# dumpyara\n\n**[Telegram channel (feed)](https://t.me/android_dumps)**  \n**[Telegram group for dump requests](https://t.me/dumprequests)**\n\n**Script requirements**:\n\n      Linux or Mac\n      \n***For setting up requirements***:\n\n      bash setup.sh\n\n**Usage**:\n\n      bash dumpyara.sh \"<OTAlink> OR <OTA file path>\" yourGithubToken\n\nYou can also place your github oauth token in a file called `.githubtoken` and telegram bot token in a file called `.tgtoken` in the root of this repository, if you wish it is ignored by git.  \nBefore you start, make sure that dumpyara scripts are mapped to your own org or account, otherwise you'll only dump, not push.  \n\n**Supported image types**:  \ncheck [here](https://github.com/AndroidDumps/Firmware_extractor/blob/master/extractor.sh#L3)  \n\nIf you're a member of AndroidDumps org, use a token with following permissions: `admin:org, public_repo`\n"
  },
  {
    "path": "dumpyara.sh",
    "content": "#!/usr/bin/env bash\n\n# Add logging definition to make output clearer\n## Info\nLOGI() {\n    echo -e \"[\\033[32mINFO\\033[0m]: ${1}\"\n}\n\n## Warning\nLOGW() {\n    echo -e \"[\\033[33mWARNING\\033[0m]: ${1}\"\n}\n\n## Error\nLOGE() {\n    echo -e \"[\\033[31mERROR\\033[0m]: ${1}\"\n}\n\n## Fatal\nLOGF() {\n    echo -e \"[\\033[41mFATAL\\033[0m]: ${1}\"\n    exit 1\n}\n\n[[ $# = 0 ]] && \\\n    LOGF \"No input provided.\"\n\nPWD=\"$(cd $(dirname ${BASH_SOURCE[0]}); pwd -P)\"\n\n# Create input & working directory if it does not exist\nmkdir -p \"${PWD}\"/working\n\n# GitHub token\nif [[ -n $2 ]]; then\n    GIT_OAUTH_TOKEN=$2\nelif [[ -f \".githubtoken\" ]]; then\n    GIT_OAUTH_TOKEN=$(< .githubtoken)\nelse\n    LOGW \"GitHub token not found. Dumping just locally...\"\nfi\n\n# Check whether input is a string or a file\nif echo \"${1}\" | grep -e '^\\(https\\?\\|ftp\\)://.*$' > /dev/null; then\n    # Set 'URL' to appended string\n    URL=\"${1}\"\n\n    # Override '${URL}' with best possible mirror of it\n    case \"${URL}\" in\n        # For Xiaomi: replace '${URL}' with (one of) the fastest mirror\n        *\"d.miui.com\"*)\n            # Do not run this loop in case we're already using one of the reccomended mirrors\n            if ! echo \"${URL}\" | rg -q 'cdnorg|bkt-sgp-miui-ota-update-alisgp'; then\n                # Set '${URL_ORIGINAL}' and '${FILE_PATH}' in case we might need to roll back\n                URL_ORIGINAL=$(echo \"${URL}\" | sed -E 's|(https://[^/]+).*|\\1|')\n                FILE_PATH=$(echo \"${URL#*d.miui.com/}\" | sed 's/?.*//')\n\n                # Array of different possible mirrors\n                MIRRORS=(\n                    \"https://cdnorg.d.miui.com\"\n                    \"https://bkt-sgp-miui-ota-update-alisgp.oss-ap-southeast-1.aliyuncs.com\"\n                    \"https://bn.d.miui.com\"\n                    \"${URL_ORIGINAL}\"\n                )\n\n                # Check back and forth for the best available mirror\n                for URLS in \"${MIRRORS[@]}\"; do\n                    # Change mirror's domain with one(s) from array\n                    URL=${URLS}/${FILE_PATH}\n\n                    # Be sure that the mirror is available. Once found, break the loop \n                    if [ \"$(curl -I -sS \"${URL}\" | head -n1 | cut -d' ' -f2)\" == \"404\" ]; then\n                        LOGW \"${URLS} is not available. Trying with other mirror(s)...\"\n                    else\n                        LOGI \"Found best available mirror.\"\n                        break\n                    fi\n                done\n            fi\n            ;;\n            # For Pixeldrain: replace the link with a direct one\n            *\"pixeldrain.com/u\"*)\n                LOGI \"Replacing with best available mirror.\"\n                URL=\"https://pd.cybar.xyz/${URL##*/}\"\n            ;;\n            *\"pixeldrain.com/d\"*)\n                LOGI \"Replacing with direct download link.\"\n                URL=\"https://pixeldrain.com/api/filesystem/${URL##*/}\"\n            ;;\n        esac\n    \n    # Sanitize file name and path\n    FILENAME=\"$(basename \"${URL}\")\"\n    SAFE_FILENAME=$(echo \"${FILENAME}\" | inline-detox)\n    DEST_PATH=\"${PWD}/working/${SAFE_FILENAME}\"\n\n    # Start downloading from 'aria2c' and, if failed, 'wget'\n    LOGI \"Started downloading file from link... ($(date +%R:%S))\"\n\n    aria2c -q -s16 -x16 --check-certificate=false -d \"${PWD}/working\" -o \"${SAFE_FILENAME}\" \"${URL}\" || {\n        rm -fv \"${DEST_PATH}\"\n        wget -q --no-check-certificate -O \"${DEST_PATH}\" \"${URL}\" || \\\n            LOGF \"Failed to download file. Aborting.\"\n    }\n\n    LOGI \"Finished downloading file. ($(date +%R:%S))\"\n\n    # Set 'INPUT' variable for rest of script\n    INPUT=\"${DEST_PATH}\"\nelse\n    # Otherwise, check if it's a file or directory\n    if [[ -e ${1} ]]; then\n        INPUT=${1}\n    else\n        LOGF \"Invalid input. Aborting.\"\n    fi\nfi\n\nORG=AndroidDumps #your GitHub org name\nEXTENSION=$(echo \"${INPUT##*.}\" | inline-detox)\nUNZIP_DIR=$(basename ${INPUT/.$EXTENSION/})\nWORKING=${PWD}/working/${UNZIP_DIR}\n\n# Delete previously dumped project\nif [[ -d \"${WORKING}\" ]]; then\n    rm -rf \"${WORKING}\"\nfi\n\n# Copy over directory to 'WORKING'\nif [[ -d \"${INPUT}\" ]]; then\n    LOGI 'Directory detected. Copying...'\n    cp -a \"${INPUT}\" \"${WORKING}\"\nfi\n\n# clone other repo's\nif [[ -d \"${PWD}/external/Firmware_extractor\" ]]; then\n    git -C \"${PWD}\"/external/Firmware_extractor pull --recurse-submodules --rebase\nelse\n    LOGI \"Cloning 'Fimrware_extractor' to 'external/'...\"\n    git clone -q --recurse-submodules https://github.com/AndroidDumps/Firmware_extractor \"${PWD}\"/external/Firmware_extractor\nfi\n\n# Extract input via 'Firmware_extractor'\n[[ ! -d \"${INPUT}\" ]] && \\\n    bash \"$PWD\"/external/Firmware_extractor/extractor.sh \"${INPUT}\" \"${WORKING}\" || LOGF \"Extraction failed. Aborting.\"\n\n# Retrive 'extract-ikconfig' from torvalds/linux\nif ! [[ -f \"${PWD}\"/external/extract-ikconfig ]]; then\n    curl -s -Lo \"${PWD}\"/external/extract-ikconfig https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/scripts/extract-ikconfig\n    chmod +x \"${PWD}\"/external/extract-ikconfig\nfi\n\n# Set path for tools\nUNPACKBOOTIMG=\"${PWD}\"/external/Firmware_extractor/tools/unpackbootimg\nVMLINUX_TO_ELF=\"uvx -q --from git+https://github.com/marin-m/vmlinux-to-elf@master\"\nEXTRACT_IKCONFIG=\"${PWD}\"/external/extract-ikconfig\nFSCK_EROFS=\"${PWD}\"/external/Firmware_extractor/tools/fsck.erofs\n\n# Initialize images extraction\ncd \"${WORKING}\" || exit\n\n# Create an array of partitions that need to be extracted\nPARTITIONS=(system systemex system_ext system_other vendor cust odm odm_ext oem factory \n    product modem xrom oppo_product opproduct reserve india my_preload my_odm my_stock\n    my_operator my_country my_product my_company my_engineering my_heytap my_custom my_manifest my_carrier my_region \n    my_bigball my_version special_preload vendor_dlkm odm_dlkm system_dlkm mi_ext radio\n    product_h preas preavs preload\n)\n\n# Extract the images\nLOGI \"Extracting partitions...\"\nfor partition in \"${PARTITIONS[@]}\"; do\n    # Proceed only if the image from 'PARTITIONS' array exists\n    if [[ -f \"${partition}\".img ]]; then\n        # Try to extract file through '7z'\n        ${FSCK_EROFS} --extract=\"${partition}\" \"${partition}\".img >> /dev/null 2>&1 || {\n                # Try to extract file through '7z'\n                7z -snld x \"${partition}\".img -y -o\"${partition}\"/ > /dev/null || {\n                LOGE \"'${partition}' extraction via '7z' failed.\"\n\n                # Only abort if we're at the first occourence\n                if [[ \"${partition}\" == \"${PARTITIONS[0]}\" ]]; then\n                    LOGF \"Aborting dumping considering it's a crucial partition.\"\n                fi\n            }\n        }\n\n        # Clean-up\n        rm -f \"${partition}\".img\n    fi\ndone\n\n# Also extract 'fsg.mbn' from 'radio.img'\nif [ -f \"fsg.mbn\" ]; then\n    LOGI \"Extracting 'fsg.mbn' via '7zz'...\"\n    mkdir \"radio/fsg\"\n\n    # Thankfully, 'fsg.mbn' is a simple EXT2 partition\n    7zz -snld x \"fsg.mbn\" -o\"radio/fsg\" > /dev/null\n\n    # Remove 'fsg.mbn'\n    rm -rf \"fsg.mbn\"\nfi\n\n# Extract and decompile device-tree blobs\nfor image in boot vendor_boot vendor_kernel_boot; do\n    if [[ -f \"${image}\".img ]]; then\n        # Create working directories\n        mkdir -p \"${image}/dtb\" \"${image}/dts\"\n\n        # Unpack image's content\n        LOGI \"Extracting '${image}' content...\"\n        ${UNPACKBOOTIMG} -i \"${image}.img\" -o \"${image}/\" > /dev/null || \\\n            LOGE \"Extraction via 'unpackbootimg' unsuccessful.\"\n\n        ## Retrive image's ramdisk, and extract it\n        unlz4 \"${image}\"/\"${image}\".img-*ramdisk \"${image}/ramdisk.lz4\" >> /dev/null 2>&1\n        7z -snld x \"${image}/ramdisk.lz4\" -o\"${image}/ramdisk\" >> /dev/null 2>&1  || \\\n            LOGI \"Failed to extract ramdisk.\"\n\n        ## Clean-up\n        rm -rf \"${image}/ramdisk.lz4\"\n        rm -rf \"${image}/${image}\".img-*ramdisk\n\n        # Extract 'dtb' via 'extract-dtb'\n        LOGI \"Trying to extract device-tree(s) from '${image}'...\" \n        uvx extract-dtb \"${image}.img\" -o \"${image}/dtb\" >> /dev/null 2>&1 || \\\n            LOGE \"Failed to extract device-tree blobs.\"\n\n        # Remove '00_kernel'\n        rm -rf \"${image}/dtb/00_kernel\"\n\n        # Decompile blobs to 'dts' via 'dtc'\n        for dtb in $(find \"${image}/dtb\" -type f); do\n            dtc -q -I dtb -O dts \"${dtb}\" >> \"${image}/dts/$(basename \"${dtb}\" | sed 's/\\.dtb/.dts/')\" || \\\n                LOGE \"Failed to decompile device-tree blobs.\"\n        done\n    fi\n\n    # If no device-tree were extracted or decompiled, delete the directories\n    if ! ls -A ${image}/dtb >> /dev/null 2>&1; then\n        rm -rf \"${image}/dtb\" \"${image}/dts\"\n    fi\ndone\n\n# Extract 'boot.img'-related content\nif [[ -f boot.img ]]; then\n    # Extract 'ikconfig'\n    LOGI \"Extracting 'ikconfig'...\"\n    ${EXTRACT_IKCONFIG} boot.img > ikconfig || {\n        LOGE \"Failed to generate 'ikconfig'\"\n    }\n\n    # Generate non-stack symbols\n    LOGI \"Generating 'boot.img-kallsyms'...\"\n    ${VMLINUX_TO_ELF} kallsyms-finder boot.img >> /dev/null 2>&1 > boot/boot.img-kallsyms || \\\n        LOGE \"Failed to generate 'boot.img-kallsyms'\"\n\n    # Generate analyzable '.elf'\n    LOGI \"Extracting 'boot.img-elf'...\"\n    ${VMLINUX_TO_ELF} vmlinux-to-elf boot.img boot/boot.img-elf >> /dev/null 2>&1 > /dev/null ||\n        LOGE \"Failed to generate 'boot.img-elf'\"\nfi\n\n# Extract 'dtbo.img' separately\nif [[ -f dtbo.img ]]; then\n    # Create working directories\n    mkdir -p \"dtbo/dts\"\n\n    # Extract 'dtb' via 'extract-dtb'\n    LOGI \"Trying to extract device-tree(s) from 'dtbo'...\" \n    uvx extract-dtb \"dtbo.img\" -o \"dtbo/\"  >> /dev/null 2>&1 || \\\n        LOGE \"Failed to extract device-tree blobs.\"\n\n    # Remove '00_kernel'\n    rm -rf \"dtbo/00_kernel\"\n\n    # Decompile blobs to 'dts' via 'dtc'\n    for dtb in $(find \"dtbo\" -type f -name \"*.dtb\"); do\n        dtc -q -I dtb -O dts \"${dtb}\" >> \"dtbo/dts/$(basename \"${dtb}\" | sed 's/\\.dtb/.dts/')\" || \\\n            LOGE \"Failed to decompile device-tree blobs.\"\n    done\nfi\n\n# Generate 'board-info.txt'\nLOGI \"Generating 'board-info.txt'...\"\n\n## Generic\nif [ -f vendor/build.prop ]; then\n    strings ./vendor/build.prop | grep \"ro.vendor.build.date.utc\" | sed \"s|ro.vendor.build.date.utc|require version-vendor|g\" >> ./board-info.txt\nfi\n\n## Qualcomm-specific\nif [[ $(find . -wholename \"modem\") ]] && [[ $(find . -wholename \"*./tz*\") ]]; then\n    find ./modem -type f -exec strings {} \\; | rg \"QC_IMAGE_VERSION_STRING=MPSS.\" | sed \"s|QC_IMAGE_VERSION_STRING=MPSS.||g\" | cut -c 4- | sed -e 's/^/require version-baseband=/' >> board-info.txt\n    find ./tz* -type f -exec strings {} \\; | rg \"QC_IMAGE_VERSION_STRING\" | sed \"s|QC_IMAGE_VERSION_STRING|require version-trustzone|g\" >> board-info.txt\nfi\n\n## Sort 'board-info.txt' content\nif [ -f board-info.txt ]; then\n    sort -u -o board-info.txt board-info.txt\nfi\n\n# Generate 'all_files.txt'\nLOGI \"Generating 'all_files.txt'...\"\nfind . -type f ! -name all_files.txt \\\n     -printf '%P\\n' | sort | grep -v \".git/\" > ./all_files.txt\n\n# 'flavor' property (e.g. caiman-user)\nflavor=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.flavor=).*\" {vendor,system,system/system}/build.prop)\n[[ -z ${flavor} ]] && flavor=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.flavor=).*\" vendor/build*.prop)\n[[ -z ${flavor} ]] && flavor=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.flavor=).*\" {vendor,system,system/system}/build*.prop)\n[[ -z ${flavor} ]] && flavor=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.flavor=).*\" {system,system/system}/build*.prop)\n[[ -z ${flavor} ]] && flavor=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.type=).*\" {system,system/system}/build*.prop)\n\n# 'release' property (e.g. 15)\nrelease=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.release=).*\" {my_manifest,vendor,system,system/system}/build*.prop)\n[[ -z ${release} ]] && release=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.version.release=).*\" vendor/build*.prop)\n[[ -z ${release} ]] && release=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.version.release=).*\" {system,system/system}/build*.prop)\nrelease=$(echo \"$release\" | head -1)\n\n# 'id' property (e.g. AP4A.241205.013)\nid=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.id=).*\" my_manifest/build*.prop)\n[[ -z ${id} ]] && id=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.id=).*\" system/system/build_default.prop)\n[[ -z ${id} ]] && id=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.id=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${id} ]] && id=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.id=).*\" {vendor,system,system/system}/build*.prop)\n[[ -z ${id} ]] && id=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.id=).*\" vendor/build*.prop)\n[[ -z ${id} ]] && id=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.id=).*\" {system,system/system}/build*.prop)\nid=$(echo \"$id\" | head -1)\n\n# 'incremental' property (e.g. 12621605)\nincremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.incremental=).*\" my_manifest/build*.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.incremental=).*\" system/system/build_default.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.incremental=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.incremental=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.version.incremental=).*\" my_manifest/build*.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.version.incremental=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.version.incremental=).*\" vendor/build*.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.version.incremental=).*\" {system,system/system}/build*.prop | head -1)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.version.incremental=).*\" my_product/build*.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.version.incremental=).*\" my_product/build*.prop)\n[[ -z ${incremental} ]] && incremental=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.version.incremental=).*\" my_product/build*.prop)\nincremental=$(echo \"$incremental\" | head -1)\n\n# 'tags' property (e.g. release-keys)\ntags=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.tags=).*\" {vendor,system,system/system}/build*.prop)\n[[ -z ${tags} ]] && tags=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.tags=).*\" vendor/build*.prop)\n[[ -z ${tags} ]] && tags=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.tags=).*\" {system,system/system}/build*.prop)\ntags=$(echo \"$tags\" | head -1)\n\n# 'platform' property (e.g. zumapro)\nplatform=$(rg -m1 -INoP --no-messages \"(?<=^ro.board.platform=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${platform} ]] && platform=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.board.platform=).*\" vendor/build*.prop)\n[[ -z ${platform} ]] && platform=$(rg -m1 -INoP --no-messages rg\"(?<=^ro.system.board.platform=).*\" {system,system/system}/build*.prop)\nplatform=$(echo \"$platform\" | head -1)\n\n# 'manufacturer' property (e.g. google)\nmanufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.manufacturer=).*\" odm/etc/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" odm/etc/fingerprint/build.default.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" my_product/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" my_manifest/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" system/system/build_default.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand.sub=).*\" my_product/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand.sub=).*\" system/system/euclid/my_product/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.manufacturer=).*\" vendor/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.manufacturer=).*\" my_manifest/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.manufacturer=).*\" system/system/build_default.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.manufacturer=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.manufacturer=).*\" vendor/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.product.manufacturer=).*\" {system,system/system}/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.manufacturer=).*\" {system,system/system}/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.manufacturer=).*\" my_manifest/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.manufacturer=).*\" system/system/build_default.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.manufacturer=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.manufacturer=).*\" vendor/odm/etc/build*.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" {oppo_product,my_product}/build*.prop | head -1)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.manufacturer=).*\" vendor/euclid/*/build.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.product.manufacturer=).*\" vendor/euclid/*/build.prop)\n[[ -z ${manufacturer} ]] && manufacturer=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.manufacturer=).*\" vendor/euclid/product/build*.prop)\nmanufacturer=$(echo \"$manufacturer\" | head -1)\n\n# 'fingerprint' property (e.g. google/caiman/caiman:15/AP4A.241205.013/12621605:user/release-keys)\nfingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.odm.build.fingerprint=).*\" odm/etc/*build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" my_manifest/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" system/system/build_default.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" odm/etc/fingerprint/build.default.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" vendor/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fingerprint=).*\" my_manifest/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fingerprint=).*\" system/system/build_default.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fingerprint=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fingerprint=).*\"  {system,system/system}/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.build.fingerprint=).*\" product/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.fingerprint=).*\" {system,system/system}/build*.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fingerprint=).*\" my_product/build.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.fingerprint=).*\" my_product/build.prop)\n[[ -z ${fingerprint} ]] && fingerprint=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.fingerprint=).*\" my_product/build.prop)\nfingerprint=$(echo \"$fingerprint\" | head -1)\n\n# 'codename' property (e.g. caiman)\ncodename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.device=).*\" odm/etc/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.device=).*\" system/system/build_default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" odm/etc/fingerprint/build.default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" my_manifest/build*.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" system/system/build_default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.device=).*\" system/system/build_default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.device=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.device=).*\" system/system/build_default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.device=).*\" vendor/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.device=).*\" vendor/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.device.oem=).*\" odm/build.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.device.oem=).*\" vendor/euclid/odm/build.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.device=).*\" my_manifest/build*.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.device=).*\" {system,system/system}/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.device=).*\" vendor/euclid/*/build.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.device=).*\" vendor/euclid/*/build.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.device=).*\" system/system/build_default.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.model=).*\" vendor/euclid/*/build.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.device=).*\" {oppo_product,my_product}/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.device=).*\" oppo_product/build*.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.device=).*\" my_product/build*.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.device=).*\" my_product/build*.prop)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.fota.version=).*\" {system,system/system}/build*.prop | cut -d - -f1 | head -1)\n[[ -z ${codename} ]] && codename=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.product=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${codename} ]] && codename=$(echo \"$fingerprint\" | cut -d / -f3 | cut -d : -f1)\n\n# 'brand' property (e.g. google)\nbrand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" odm/etc/\"${codename}\"_build.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" odm/etc/build*.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" system/system/build_default.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" odm/etc/fingerprint/build.default.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" my_product/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" system/system/build_default.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" {vendor,system,system/system}/build*.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand.sub=).*\" my_product/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand.sub=).*\" system/system/euclid/my_product/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.brand=).*\" my_manifest/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.brand=).*\" system/system/build_default.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.brand=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.vendor.brand=).*\" vendor/build*.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.product.brand=).*\" vendor/build*.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.brand=).*\" {system,system/system}/build*.prop | head -1)\n[[ -z ${brand} || ${brand} == \"OPPO\" ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.system.brand=).*\" vendor/euclid/*/build.prop | head -1)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.product.brand=).*\" vendor/euclid/product/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" my_manifest/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" vendor/euclid/my_manifest/build.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.odm.brand=).*\" vendor/odm/etc/build*.prop)\n[[ -z ${brand} ]] && brand=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.brand=).*\" {oppo_product,my_product}/build*.prop | head -1)\n[[ -z ${brand} ]] && brand=$(echo \"$fingerprint\" | cut -d / -f1)\n[[ -z ${brand} ]] && brand=\"$manufacturer\"\n\n# 'description' property (e.g. caiman-user 15 AP4A.241205.013 12621605 release-keys)\ndescription=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.description=).*\" {system,system/system}/build.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.build.description=).*\" {system,system/system}/build*.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.description=).*\" vendor/build.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.vendor.build.description=).*\" vendor/build*.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.build.description=).*\" product/build.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.product.build.description=).*\" product/build*.prop)\n[[ -z ${description} ]] && description=$(rg -m1 -INoP --no-messages \"(?<=^ro.system.build.description=).*\" {system,system/system}/build*.prop)\n[[ -z ${description} ]] && description=\"$flavor $release $id $incremental $tags\"\n\n# Generate dummy device tree\nmkdir -p \"${WORKING}/aosp-device-tree\"\nLOGI \"Generating dummy device tree...\"\nuvx aospdtgen . --output \"${WORKING}/aosp-device-tree\" >> /dev/null 2>&1 || \\\n    LOGE \"Failed to generate AOSP device tree\" && rm -rf \"${WORKING}/aosp-device-tree\"\n\nis_ab=$(grep -oP \"(?<=^ro.build.ab_update=).*\" -hs {system,system/system,vendor}/build*.prop | head -1)\n[[ -z \"${is_ab}\" ]] && is_ab=\"false\"\nbranch=$(echo \"$description\" | tr ' ' '-')\nrepo=$(echo \"$brand\"_\"$codename\"_dump | tr '[:upper:]' '[:lower:]' | tr -d '\\r\\n')\nplatform=$(echo \"$platform\" | tr '[:upper:]' '[:lower:]' | tr -dc '[:print:]' | tr '_' '-' | cut -c 1-35)\ntop_codename=$(echo \"$codename\" | tr '[:upper:]' '[:lower:]' | tr -dc '[:print:]' | tr '_' '-' | cut -c 1-35)\nmanufacturer=$(echo \"$manufacturer\" | tr '[:upper:]' '[:lower:]' | tr -dc '[:print:]' | tr '_' '-' | cut -c 1-35)\nprintf \"# %s\\n- manufacturer: %s\\n- platform: %s\\n- codename: %s\\n- flavor: %s\\n- release: %s\\n- id: %s\\n- incremental: %s\\n- tags: %s\\n- fingerprint: %s\\n- is_ab: %s\\n- brand: %s\\n- branch: %s\\n- repo: %s\\n\" \"$description\" \"$manufacturer\" \"$platform\" \"$codename\" \"$flavor\" \"$release\" \"$id\" \"$incremental\" \"$tags\" \"$fingerprint\" \"$is_ab\" \"$brand\" \"$branch\" \"$repo\" > \"${WORKING}\"/README.md\ncat \"${WORKING}\"/README.md\n\nif [[ -n $GIT_OAUTH_TOKEN ]]; then\n    GITPUSH=(git push https://\"$GIT_OAUTH_TOKEN\"@github.com/\"$ORG\"/\"${repo,,}\".git \"$branch\")\n    curl --silent --fail \"https://raw.githubusercontent.com/$ORG/$repo/$branch/all_files.txt\" 2> /dev/null && echo \"Firmware already dumped!\" && exit 1\n    git init\n    if [[ -z \"$(git config --get user.email)\" ]]; then\n        git config user.email AndroidDumps@github.com\n    fi\n    if [[ -z \"$(git config --get user.name)\" ]]; then\n        git config user.name AndroidDumps\n    fi\n    curl -s -X POST -H \"Authorization: token ${GIT_OAUTH_TOKEN}\" -d '{ \"name\": \"'\"$repo\"'\" }' \"https://api.github.com/orgs/${ORG}/repos\" #create new repo\n    curl -s -X PUT -H \"Authorization: token ${GIT_OAUTH_TOKEN}\" -H \"Accept: application/vnd.github.mercy-preview+json\" -d '{ \"names\": [\"'\"$manufacturer\"'\",\"'\"$platform\"'\",\"'\"$top_codename\"'\"]}' \"https://api.github.com/repos/${ORG}/${repo}/topics\"\n    git remote add origin https://github.com/$ORG/\"${repo,,}\".git\n    git checkout -b \"$branch\"\n    find . -size +97M -printf '%P\\n' -o -name \"*sensetime*\" -printf '%P\\n' -o -name \"*.lic\" -printf '%P\\n' >| .gitignore\n    git add --all\n    git commit -asm \"Add ${description}\"\n    git update-ref -d HEAD\n    git reset system/ vendor/ product/\n    git checkout -b \"$branch\"\n    git commit -asm \"Add extras for ${description}\" && \"${GITPUSH[@]}\"\n    git add vendor/\n    git commit -asm \"Add vendor for ${description}\" && \"${GITPUSH[@]}\"\n    git add system/system/app/ || git add system/app/\n    git commit -asm \"Add system app for ${description}\" && \"${GITPUSH[@]}\"\n    git add system/system/priv-app/ || git add system/priv-app/\n    git commit -asm \"Add system priv-app for ${description}\" && \"${GITPUSH[@]}\"\n    git add system/\n    git commit -asm \"Add system for ${description}\" && \"${GITPUSH[@]}\"\n    git add product/app/\n    git commit -asm \"Add product app for ${description}\" && \"${GITPUSH[@]}\"\n    git add product/priv-app/\n    git commit -asm \"Add product priv-app for ${description}\" && \"${GITPUSH[@]}\"\n    git add product/\n    git commit -asm \"Add product for ${description}\" && \"${GITPUSH[@]}\"\nelse\n    LOGI \"Dump done locally.\"\n    exit 1\nfi\n\n# Telegram channel\nTG_TOKEN=$(< \"$PWD\"/.tgtoken)\nif [[ -n \"$TG_TOKEN\" ]]; then\n    CHAT_ID=\"@android_dumps\"\n    commit_head=$(git log --format=format:%H | head -n 1)\n    commit_link=\"https://github.com/$ORG/$repo/commit/$commit_head\"\n    echo -e \"Sending telegram notification\"\n    printf \"<b>Brand: %s</b>\" \"$brand\" >| \"$PWD\"/working/tg.html\n    {\n        printf \"\\n<b>Device: %s</b>\" \"$codename\"\n        printf \"\\n<b>Version:</b> %s\" \"$release\"\n        printf \"\\n<b>Fingerprint:</b> %s\" \"$fingerprint\"\n        printf \"\\n<b>GitHub:</b>\"\n        printf \"\\n<a href=\\\"%s\\\">Commit</a>\" \"$commit_link\"\n        printf \"\\n<a href=\\\"https://github.com/%s/%s/tree/%s/\\\">%s</a>\" \"$ORG\" \"$repo\" \"$branch\" \"$codename\"\n    } >> \"$PWD\"/working/tg.html\n    TEXT=$(< \"$PWD\"/working/tg.html)\n    curl -s \"https://api.telegram.org/bot${TG_TOKEN}/sendmessage\" --data \"text=${TEXT}&chat_id=${CHAT_ID}&parse_mode=HTML&disable_web_page_preview=True\" > /dev/null\n    rm -rf \"$PWD\"/working/tg.html\nfi\n"
  },
  {
    "path": "setup.sh",
    "content": "#!/bin/bash\n\n# Add logging definition to make output clearer\n## Info\nLOGI() {\n    echo -e \"[\\033[32mINFO\\033[0m]: ${1}\"\n}\n\n## Warning\nLOGW() {\n    echo -e \"[\\033[33mWARNING\\033[0m]: ${1}\"\n}\n\n## Error\nLOGE() {\n    echo -e \"[\\033[31mERROR\\033[0m]: ${1}\"\n}\n\n## Fatal\nLOGF() {\n    echo -e \"[\\033[41mFATAL\\033[0m]: ${1}\"\n    exit 1\n}\n\n# Determine which command to use for privilege escalation\nif command -v sudo > /dev/null 2>&1; then\n    sudo_cmd=\"sudo\"\nelif command -v doas > /dev/null 2>&1; then\n    sudo_cmd=\"doas\"\nelse\n    LOGW \"Neither 'sudo' nor 'doas' found; resorting to 'su'.\"\n    # Create a separated function in order to handle 'su'\n    su_cmd() { \n        su -c \"$*\" \n    }\n    sudo_cmd=\"su_cmd\"\nfi\n\n# 'apt' (Debian)\nif command -v apt > /dev/null 2>&1; then\n    # Perform repositories updates to prevent dead mirrors\n    LOGI \"Updating repositories...\"\n    $sudo_cmd apt update > /dev/null 2>&1\n\n    # Install required packages in form of a 'for' loop\n    for package in unace unrar zip unzip p7zip-full p7zip-rar sharutils rar uudeview mpack arj cabextract device-tree-compiler liblzma-dev python3-pip brotli liblz4-tool axel gawk aria2 detox cpio rename liblz4-dev curl ripgrep; do\n        LOGI \"Installing '${package}'...\"\n        if ! $sudo_cmd apt install  -y \"${package}\" > /dev/null 2>&1; then\n            LOGE \"Failed installing '${package}'.\"\n            case ${package} in\n                liblz4-tool)\n                    $sudo_cmd apt install lz4 -y > /dev/null 2>&1 || \\\n                        LOGE \"Failed installing 'lz4'.\"\n                ;;\n            esac\n        fi\n    done\n# 'dnf' (Fedora)\nelif command -v dnf > /dev/null 2>&1; then\n    # Install required packages in form of a 'for' loop\n    for package in unace unrar zip unzip sharutils uudeview arj cabextract file-roller dtc python3-pip brotli axel aria2 detox cpio lz4 python3-devel xz-devel p7zip p7zip-plugins ripgrep; do\n        LOGI \"Installing '${package}'...\"\n        $sudo_cmd dnf install -y \"${package}\" > /dev/null 2>&1 || \\\n            LOGE \"Failed installing '${package}'.\"\n    done\n# 'pacman' (Arch Linux)\nelif command -v pacman > /dev/null 2>&1; then\n    # Install required packages in form of a 'for' loop\n    for package in unace unrar zip unzip p7zip sharutils uudeview arj cabextract file-roller dtc python-pip brotli axel gawk aria2 detox cpio lz4 ripgrep; do\n        LOGI \"Installing '${package}'...\"\n        $sudo_cmd pacman -Sy --noconfirm --needed \"${package}\" > /dev/null 2>&1 || \\\n            LOGE \"Failed installing '${package}'.\"\n    done\nfi\n\n# Install 'uv' through pipx\nLOGI \"Installing 'uv'...\"\ncurl -LsSf https://astral.sh/uv/install.sh | sh > /dev/null 2>&1 \n\n# Finish\nLOGI \"Set-up finished. You may now execute 'dumpyara.sh'.\"\n"
  }
]