├── .github └── workflows │ ├── ipa.yml │ └── ipa_shell.yml └── README.md /.github/workflows/ipa.yml: -------------------------------------------------------------------------------- 1 | # vim: expandtab tabstop=2 shiftwidth=2 2 | name: IPA Down 3 | 4 | env: 5 | PYTHONIOENCODING: utf-8 6 | 7 | # Allow Release 8 | permissions: write-all 9 | 10 | on: 11 | workflow_dispatch: 12 | inputs: 13 | appleId: 14 | description: 'Apple ID Account' 15 | required: true 16 | appleIdPwd: 17 | description: 'Apple ID Password' 18 | required: true 19 | operation: 20 | description: 'Operation to do, choices: lookup, historyver, download, historyver_id, download_id' 21 | 22 | appBundleId: 23 | description: 'AppStore Bundle-ID (needed when using non-*_id operations)' 24 | required: false 25 | appCountry: 26 | description: 'AppStore Country (needed when using non-*_id operations)' 27 | required: false 28 | default: 'VN' 29 | 30 | appVerId: 31 | description: 'App Version Id Number (for downloading history versions)' 32 | required: false 33 | 34 | appId: 35 | description: 'App Id Number (needed when using *_id operations)' 36 | required: false 37 | 38 | debug_enabled: 39 | description: 'Run the build with RDP debugging enabled' 40 | required: false 41 | default: false 42 | itunes_debug_enabled: 43 | description: 'Run the build with ngrok debugging enabled' 44 | required: false 45 | default: false 46 | 47 | jobs: 48 | download_ipa: 49 | name: 'IPATool Operations' 50 | runs-on: "windows-latest" 51 | steps: 52 | - name: Masking inputs 53 | run: | 54 | SECRET_VALUE=$(cat $GITHUB_EVENT_PATH | jq -r '.inputs.appleId' ) 55 | echo "::add-mask::$SECRET_VALUE" 56 | SECRET_VALUE=$(cat $GITHUB_EVENT_PATH | jq -r '.inputs.appleIdPwd' ) 57 | echo "::add-mask::$SECRET_VALUE" 58 | shell: bash 59 | 60 | - name: Set up git repository 61 | uses: actions/checkout@v4 62 | 63 | - name: Setup ipatool-py 64 | run: | 65 | git clone -b itunes_server https://github.com/NyaMisty/ipatool-py 66 | pip3 install -r ipatool-py/requirements.txt 67 | mkdir -p ipaDown 68 | shell: bash 69 | 70 | - name: Setup iTunes Header Service 71 | uses: Yakov5776/actions-iTunes-header@master 72 | if: ${{ github.event.inputs.operation != 'lookup' }} 73 | with: 74 | apple_id: ${{ github.event.inputs.appleId }} 75 | apple_id_pwd: ${{ github.event.inputs.appleIdPwd }} 76 | ngrok_token: ${{ secrets.NGROK_AUTH_TOKEN }} 77 | 78 | - name: Execute operation 79 | id: operation 80 | run: | 81 | # available operations: lookup, historyver, download, historyver_id, download_id 82 | op=${{ github.event.inputs.operation }} 83 | if [[ "$op" == "lookup" ]]; then 84 | if [[ "${{ github.event.inputs.appBundleId }}" != "" ]]; then 85 | python3 ipatool-py/main.py --json lookup --get-verid -b ${{ github.event.inputs.appBundleId }} -c ${{ github.event.inputs.appCountry }} 86 | else 87 | python3 ipatool-py/main.py --json lookup --get-verid -i ${{ github.event.inputs.appId }} -c ${{ github.event.inputs.appCountry }} 88 | fi 89 | elif [[ "$op" == historyver* ]]; then 90 | if [[ "$op" == "historyver" ]]; then 91 | python3 ipatool-py/main.py --json lookup -b ${{ github.event.inputs.appBundleId }} -c ${{ github.event.inputs.appCountry }} \ 92 | historyver -s http://127.0.0.1:9000 93 | elif [[ "$op" == "historyver_id" ]]; then 94 | python3 ipatool-py/main.py --json historyver -s http://127.0.0.1:9000 --appId ${{ github.event.inputs.id }} 95 | fi 96 | elif [[ "$op" == download* ]]; then 97 | if [[ "${{ github.event.inputs.appVerId }}" == "" ]]; then 98 | appVerCmd="" 99 | else 100 | appVerCmd="--appVerId ${{ github.event.inputs.appVerId }}" 101 | fi 102 | 103 | if [[ "$op" == "download" ]]; then 104 | output=$(python3 ipatool-py/main.py --json lookup -b ${{ github.event.inputs.appBundleId }} -c ${{ github.event.inputs.appCountry }} \ 105 | download -o ipaDown -s http://127.0.0.1:9000 $appVerCmd) 106 | elif [[ "$op" == "download_id" ]]; then 107 | output=$(python3 ipatool-py/main.py --json download -o ipaDown -s http://127.0.0.1:9000 --appId ${{ github.event.inputs.id }} $appVerCmd) 108 | fi 109 | echo "Got Downloading JSON result: $output" 110 | echo "needIPARelease=1" >> $GITHUB_ENV 111 | echo "appName=$(echo "$output" | jq -r '.appName')" >> $GITHUB_ENV 112 | echo "appBundleId=$(echo "$output" | jq -r '.appBundleId')" >> $GITHUB_ENV 113 | echo "appVer=$(echo "$output" | jq -r '.appVer')" >> $GITHUB_ENV 114 | echo "appId=$(echo "$output" | jq -r '.appId')" >> $GITHUB_ENV 115 | echo "appVerId=$(echo "$output" | jq -r '.appVerId')" >> $GITHUB_ENV 116 | else 117 | echo "Unknown Operation: $op" 118 | fi 119 | shell: bash 120 | 121 | - name: "Upload package" 122 | uses: NyaMisty/upload-artifact-as-is@master 123 | with: 124 | path: ipaDown\* 125 | 126 | - name: Split ipa 127 | if: ${{ env.needIPARelease == '1' }} 128 | run: | 129 | mkdir -p ipaDown_split 130 | (cd ipaDown; find . -name "*.ipa" -size +1879048192b -exec split --bytes=1879048192 --suffix-length=3 --numeric-suffix {} ../ipaDown_split/{}. \;) 131 | (cd ipaDown; find . -name "*.ipa" -not -size +1879048192b -exec cp -r {} ../ipaDown_split \;) 132 | shell: bash 133 | 134 | - name: Pushing to release 135 | if: ${{ env.needIPARelease == '1' }} 136 | uses: ncipollo/release-action@v1 137 | with: 138 | name: "IPADown: ${{ env.appName }} - ${{ env.appVer }}" 139 | body: >- 140 | ${{ format(fromJSON('"appName: {0}\nappBundleId: {1}\nappVer: {2}\nappId: {3}\nappVerId: {4}\n"'), 141 | env.appName, 142 | env.appBundleId, 143 | env.appVer, 144 | env.appId, 145 | env.appVerId 146 | ) }} 147 | commit: ${{ github.sha }} 148 | tag: "${{ env.appBundleId }}-${{ env.appId }}-${{ env.appVerId }}" 149 | artifacts: ipaDown_split\* 150 | allowUpdates: true 151 | removeArtifacts: true 152 | replacesArtifacts: true 153 | -------------------------------------------------------------------------------- /.github/workflows/ipa_shell.yml: -------------------------------------------------------------------------------- 1 | # vim: expandtab tabstop=2 shiftwidth=2 2 | name: IPA Download Shell 3 | 4 | env: 5 | PYTHONIOENCODING: utf-8 6 | 7 | # Allow Release 8 | permissions: write-all 9 | 10 | on: 11 | workflow_dispatch: 12 | inputs: 13 | appleId: 14 | description: 'Apple ID Account' 15 | required: true 16 | appleIdPwd: 17 | description: 'Apple ID Password' 18 | required: true 19 | itunes_debug_enabled: 20 | description: 'Run the build with ngrok debugging enabled' 21 | required: false 22 | default: false 23 | 24 | jobs: 25 | ipadown_shell: 26 | name: 'IPA Download Shell' 27 | runs-on: "windows-latest" 28 | steps: 29 | - name: Masking inputs 30 | run: | 31 | SECRET_VALUE=$(cat $GITHUB_EVENT_PATH | jq -r '.inputs.appleId' ) 32 | echo "::add-mask::$SECRET_VALUE" 33 | SECRET_VALUE=$(cat $GITHUB_EVENT_PATH | jq -r '.inputs.appleIdPwd' ) 34 | echo "::add-mask::$SECRET_VALUE" 35 | shell: bash 36 | 37 | - name: Set up git repository 38 | uses: actions/checkout@v2 39 | 40 | - name: Setup ipatool-py 41 | run: | 42 | git clone https://github.com/NyaMisty/ipatool-py 43 | mkdir -p ipaDown 44 | shell: bash 45 | 46 | - name: Setup iTunes Header Service 47 | uses: NyaMisty/actions-iTunes-header@master 48 | with: 49 | apple_id: ${{ github.event.inputs.appleId }} 50 | apple_id_pwd: ${{ github.event.inputs.appleIdPwd }} 51 | ngrok_token: ${{ secrets.NGROK_AUTH_TOKEN }} 52 | 53 | #- uses: NyaMisty/reverse-rdp-windows-github-actions-ng@master 54 | # if: ${{ always() && github.event_name == 'workflow_dispatch' && github.event.inputs.itunes_debug_enabled }} 55 | # with: 56 | # ngrok-token: ${{ secrets.NGROK_AUTH_TOKEN }} 57 | # password: Aa123456 58 | # foreground: false 59 | 60 | # Enable tmate debugging of manually-triggered workflows if the input option was provided 61 | - name: Setup tmate session 62 | uses: mxschmitt/action-tmate@v3 63 | 64 | - name: "Upload package" 65 | uses: NyaMisty/upload-artifact-as-is@master 66 | with: 67 | path: ipaDown\* 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # action-ipadown 2 | 3 | Download old versions of app using Github Actions, without computers! 4 | 5 | **Warning: NOT supporting 2FA accounts currently** 6 | 7 | ## Use Cases 8 | 9 | - Buy & Download App 10 | - Download Old Versions of App 11 | - Query Version History of App 12 | - Lookup app information based on bundleID or appID 13 | 14 | ## Usage 15 | 16 | 1. Fork this repo 17 | 2. Enable Actions in forked repo 18 | - Click Actions in toolbar 19 | - Click `I understand my workflows, go ahead and enable them` 20 | ![image](https://user-images.githubusercontent.com/5344431/167505409-ef077008-2450-4e2d-9d43-2067244ac931.png) 21 | 3. Run Action 22 | - Click `IPA Down` in left list: 23 | ![image](https://user-images.githubusercontent.com/5344431/167505630-1a741d9c-69de-470c-978e-1b8944dcfd3b.png) 24 | - Click `Run workflow` at right: 25 | ![image](https://user-images.githubusercontent.com/5344431/167505748-52e0bba9-b9ec-44e1-9370-4452d3c3c66b.png) 26 | - Enter Apple ID, Password, Operation and corresponding parameters (like bundleID) 27 | - Click `Run workflow` 28 | - Find output files in Actions artifact or Release 29 | ![image](https://user-images.githubusercontent.com/5344431/167506938-c3e3529c-ee91-4661-a251-a12a2d0576cb.png) 30 | - If the actions fails at `Setup iTunes Header Service`, please retry 1~2 times before submitting issue 31 | 32 | ## Operations 33 | 34 | There are currently five operations: lookup, historyver, download, historyver_id, download_id 35 | 36 | - lookup: query information of app based on bundleID 37 | - historyver: query history appVerID by bundleID (with historyver_id querys by appID) 38 | - download: download IPA by bundleID (download_id uses appID) & appVerID (optional, defaults to newest version) 39 | 40 | To use these operations, enter your app informations like this: 41 | - Using Bundle ID: 42 | ![image](https://user-images.githubusercontent.com/5344431/167506427-1503417c-112f-4c45-b82b-7887f05b0dac.png) 43 | - Using appID: 44 | ![image](https://user-images.githubusercontent.com/5344431/167506645-d29db175-ab38-45d3-b224-6cc94131e61d.png) 45 | - Also giving appVerID: 46 | ![image](https://user-images.githubusercontent.com/5344431/167506870-8dcaa565-3bd1-424e-a9d2-eed00bd4cffb.png) 47 | 48 | ## Credits 49 | 50 | - ipatool-py: https://github.com/NyaMisty/ipatool-py 51 | - actions-iTunes-header: https://github.com/NyaMisty/actions-iTunes-header 52 | --------------------------------------------------------------------------------