diff --git a/.github/RELEASE-TEMPLATE.md b/.github/RELEASE-TEMPLATE.md new file mode 100644 index 0000000..76e8b07 --- /dev/null +++ b/.github/RELEASE-TEMPLATE.md @@ -0,0 +1,14 @@ +### 🆕 New Features + * none + +### 🛠️ Bug Fixes + * none + +### 🔣 Dependencies + * none + +### ‼️ Breaking Changes + * none + +### 🔄 Other Changes + * none diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3b61fba --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: Build +on: + workflow_call: + workflow_dispatch: + +permissions: + actions: read + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@main + with: + submodules: recursive + token: ${{ secrets.SUBMODULE_TOKEN }} + - name: Set up Node.js + uses: actions/setup-node@main + with: + node-version: 'latest' + cache: 'npm' + - name: Install dependencies + run: npm install + - name: Build + run: npm run build + - name: Upload artifact + uses: actions/upload-artifact@master + with: + name: output + path: | + .github/RELEASE-TEMPLATE.md + CHANGELOG.md + modules + dist diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml new file mode 100644 index 0000000..9c2a38a --- /dev/null +++ b/.github/workflows/debug.yml @@ -0,0 +1,33 @@ +name: Debug +on: + workflow_call: + workflow_dispatch: + +permissions: + actions: read + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@main + with: + submodules: recursive + token: ${{ secrets.SUBMODULE_TOKEN }} + ref: dev + - name: Set up Node.js + uses: actions/setup-node@main + with: + node-version: 'latest' + cache: 'npm' + - name: Install dependencies + run: npm install + - name: Build + run: npm run build:debug + - name: Upload artifact + uses: actions/upload-artifact@master + with: + name: dist + path: dist diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..5329bed --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,38 @@ +name: Deploy +on: + push: + # Sequence of patterns matched against refs/heads + branches: + - dev + +permissions: + actions: read + contents: read + +jobs: + debug: + uses: ./.github/workflows/debug.yml + secrets: inherit + deploy: + needs: debug + runs-on: ubuntu-latest + steps: + - name: Download artifact + uses: actions/download-artifact@master + with: + name: dist + path: dist + - name: Deploy + uses: exuanbo/actions-deploy-gist@main + with: + token: ${{ secrets.GIST_TOKEN }} + gist_id: 45827a0c304016dadad59d48333b24aa + gist_description: " iRingo: ✈ TestFlight β" + file_path: dist/request.js + - name: Deploy + uses: exuanbo/actions-deploy-gist@main + with: + token: ${{ secrets.GIST_TOKEN }} + gist_id: 45827a0c304016dadad59d48333b24aa + gist_description: " iRingo: ✈ TestFlight β" + file_path: dist/response.js diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml new file mode 100644 index 0000000..fd5caf3 --- /dev/null +++ b/.github/workflows/draft.yml @@ -0,0 +1,32 @@ +name: Draft +on: + push: + # Sequence of patterns matched against refs/heads + branches: + - main + +permissions: + actions: read + contents: write + +jobs: + build: + uses: ./.github/workflows/build.yml + secrets: inherit + draft: + needs: build + runs-on: ubuntu-latest + steps: + - name: Download artifact + uses: actions/download-artifact@master + with: + name: output + - name: Publish Draft + uses: softprops/action-gh-release@v2 + with: + body_path: .github/RELEASE-TEMPLATE.md + token: ${{ secrets.GITHUB_TOKEN }} + files: | + dist/*.js + modules/* + draft: true diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 0000000..14c0e69 --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,33 @@ +name: Pre-Release +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - 'v*.*.*-alpha*' + - 'v*.*.*-beta*' + +permissions: + actions: read + contents: write + +jobs: + build: + uses: ./.github/workflows/build.yml + secrets: inherit + pre-release: + needs: build + runs-on: ubuntu-latest + steps: + - name: Download artifact + uses: actions/download-artifact@master + with: + name: output + - name: Publish Pre-Release + uses: softprops/action-gh-release@v2 + with: + body_path: CHANGELOG.md + token: ${{ secrets.GITHUB_TOKEN }} + files: | + dist/*.js + modules/* + prerelease: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..56a5e6e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,32 @@ +name: Release +on: + push: + # Sequence of patterns matched against refs/tags + tags: + - 'v*.*.*-rc*' + +permissions: + actions: read + contents: write + +jobs: + build: + uses: ./.github/workflows/build.yml + secrets: inherit + release: + needs: build + runs-on: ubuntu-latest + steps: + - name: Download artifact + uses: actions/download-artifact@master + with: + name: output + - name: Publish Release + uses: softprops/action-gh-release@v2 + with: + body_path: CHANGELOG.md + token: ${{ secrets.GITHUB_TOKEN }} + files: | + dist/*.js + modules/* + make_latest: "true" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6bba59 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..868a2ec --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/utils"] + path = src/utils + url = https://github.com/NanoCat-Me/utils.git diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..64f09c7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ + * 首次发布 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf7ad91 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# TestFlight \ No newline at end of file diff --git a/archive/js/TestFlight.request.v2.0.beta.js b/archive/js/TestFlight.request.v2.0.beta.js new file mode 100644 index 0000000..0024bf7 --- /dev/null +++ b/archive/js/TestFlight.request.v2.0.beta.js @@ -0,0 +1,548 @@ +/* +README:https://github.com/VirgilClyne/iRingo +*/ +const $ = new Env(" iRingo: ✈ TestFlight v2.0.0(1) request.beta"); +const URL = new URLs(); +const DataBase = { + "Location":{ + "Settings":{"Switch":"true","PEP":{"GCC":"US"},"Services":{"PlaceData":"CN","Directions":"AUTO","Traffic":"AUTO","RAP":"XX","Tiles":"AUTO"},"Geo_manifest":{"Dynamic":{"Config":{"Country_code":{"default":"AUTO","iOS":"CN","iPadOS":"CN","watchOS":"US","macOS":"CN"}}}},"Config":{"Announcements":{"Environment:":{"default":"AUTO","iOS":"CN","iPadOS":"CN","watchOS":"XX","macOS":"CN"}},"Defaults":{"LagunaBeach":true,"DrivingMultiWaypointRoutesEnabled":true,"GEOAddressCorrection":true,"LookupMaxParametersCount":true,"LocalitiesAndLandmarks":true,"POIBusyness":true,"PedestrianAR":true,"6694982d2b14e95815e44e970235e230":true,"OpticalHeading":true,"UseCLPedestrianMapMatchedLocations":true,"TransitPayEnabled":true,"WiFiQualityNetworkDisabled":false,"WiFiQualityTileDisabled":false}}} + }, + "Weather":{ + "Settings":{"Switch":"true","NextHour":{"Switch":true},"AQI":{"Switch":true,"Mode":"WAQI Public","Location":"Station","Auth":null,"Scale":"EPA_NowCast.2204"},"Map":{"AQI":false}}, + "Configs":{ + "Availability":["currentWeather","forecastDaily","forecastHourly","history","weatherChange","forecastNextHour","severeWeather","airQuality"], + "Pollutants":{"co":"CO","no":"NO","no2":"NO2","so2":"SO2","o3":"OZONE","nox":"NOX","pm25":"PM2.5","pm10":"PM10","other":"OTHER"} + } + }, + "Siri":{ + "Settings":{"Switch":"true","CountryCode":"SG","Domains":["web","itunes","app_store","movies","restaurants","maps"],"Functions":["flightutilities","lookup","mail","messages","news","safari","siri","spotlight","visualintelligence"],"Safari_Smart_History":true}, + "Configs":{ + "VisualIntelligence":{"enabled_domains":["pets","media","books","art","nature","landmarks"],"supported_domains":["OBJECT_2D","SCULPTURE","ART","CATS","DOGS","LANDMARK","ALBUM","SKYLINE","BIRDS","NATURE","ANIMALS","INSECTS","BOOK","MEDIA","NATURAL_LANDMARK"]} + } + }, + "TV":{ + "Settings": { + "Switch": true,"Third-Party": true,"Tabs":["WatchNow","Originals","Store","Movies","TV","Sports","Kids","Library","Search"], + "CountryCode":{"Configs":"AUTO","Settings":"AUTO","View":["SG","TW"],"WatchNow":"AUTO","Channels":"AUTO","Originals":"TW","Movies":"AUTO","TV":"AUTO","Sports":"US","Kids":"US","Persons":"SG","Search":"TW","Others":"AUTO"} + }, + "Configs":{ + "Locale":[["AU","en-AU"],["CA","en-CA"],["GB","en-GB"],["KR","ko-KR"],["HK","yue-Hant"],["JP","ja-JP"],["MO","zh-Hant"],["TW","zh-Hant"],["US","en-US"],["SG","zh-Hans"]], + "Tabs": [ + { "title": "立即观看", "type": "WatchNow", "universalLinks": ["https://tv.apple.com/watch-now"], "destinationType": "Target", "target": { "id": "tahoma_watchnow", "type": "Root", "url": "https://tv.apple.com/watch-now" } }, + { "title": "原创内容", "type": "Originals", "universalLinks": ["https://tv.apple.com/channel/tvs.sbd.4000", "https://tv.apple.com/atv"], "destinationType": "Target", "target": { "id": "tvs.sbd.4000", "type": "Brand", "url": "https://tv.apple.com/us/channel/tvs.sbd.4000" } }, + { "title": "电影", "type": "Movies", "universalLinks": ["https://tv.apple.com/movies"], "destinationType": "Target", "target": { "id": "tahoma_movies", "type": "Root", "url": "https://tv.apple.com/movies" } }, + { "title": "电视节目", "type": "TV", "universalLinks": ["https://tv.apple.com/tv-shows"], "destinationType": "Target", "target": { "id": "tahoma_tvshows", "type": "Root", "url": "https://tv.apple.com/tv-shows" } }, + { "title": "商店", "type": "Store", "universalLinks": ["https://tv.apple.com/store"], "destinationType": "SubTabs", + "subTabs": [ + { "title": "电影", "type": "Movies", "universalLinks": ["https://tv.apple.com/movies"], "destinationType": "Target", "target": { "id": "tahoma_movies", "type": "Root", "url": "https://tv.apple.com/movies" } }, + { "title": "电视节目", "type": "TV", "universalLinks": ["https://tv.apple.com/tv-shows"], "destinationType": "Target", "target": { "id": "tahoma_tvshows", "type": "Root", "url": "https://tv.apple.com/tv-shows" } } + ] + }, + { "title": "体育节目", "type": "Sports", "universalLinks": ["https://tv.apple.com/sports"], "destinationType": "Target", "target": { "id": "tahoma_sports", "type": "Root", "url": "https://tv.apple.com/sports" } }, + { "title": "儿童", "type": "Kids", "universalLinks": ["https://tv.apple.com/kids"], "destinationType": "Target", "target": { "id": "tahoma_kids", "type": "Root", "url": "https://tv.apple.com/kids" } }, + { "title": "资料库", "type": "Library", "destinationType": "Client" }, + { "title": "搜索", "type": "Search", "universalLinks": ["https://tv.apple.com/search"], "destinationType": "Target", "target": { "id": "tahoma_search", "type": "Root", "url": "https://tv.apple.com/search" } } + ], + "i18n": { + "WatchNow": [["en", "Watch Now"], ["zh", "立即观看"], ["zh-Hans", "立即观看"], ["zh-Hant", "立即觀看"]], + "Originals": [["en", "Originals"], ["zh", "原创内容"], ["zh-Hans", "原创内容"], ["zh-Hant", "原創內容"]], + "Movies": [["en", "Movies"], ["zh", "电影"], ["zh-Hans", "电影"], ["zh-Hant", "電影"]], + "TV": [["en", "TV"], ["zh", "电视节目"], ["zh-Hans", "电视节目"], ["zh-Hant", "電視節目"]], + "Store": [["en", "Store"], ["zh", "商店"], ["zh-Hans", "商店"], ["zh-Hant", "商店"]], + "Sports": [["en", "Sports"], ["zh", "体育节目"], ["zh-Hans", "体育节目"], ["zh-Hant", "體育節目"]], + "Kids": [["en", "Kids"], ["zh", "儿童"], ["zh-Hans", "儿童"], ["zh-Hant", "兒童"]], + "Library": [["en", "Library"], ["zh", "资料库"], ["zh-Hans", "资料库"], ["zh-Hant", "資料庫"]], + "Search": [["en", "Search"], ["zh", "搜索"], ["zh-Hans", "搜索"], ["zh-Hant", "蒐索"]] + } + } + }, + "News":{ + "Settings":{"Switch":"true","CountryCode":"US","newsPlusUser":"true"} + }, + "TestFlight":{ + "Settings":{"Switch":"true","CountryCode":"US","MultiAccount":"false","Universal":"true"} + }, + "Default": { + "Settings":{"Switch":"true"}, + "Configs":{ + "Storefront":[["AE","143481"],["AF","143610"],["AG","143540"],["AI","143538"],["AL","143575"],["AM","143524"],["AO","143564"],["AR","143505"],["AT","143445"],["AU","143460"],["AZ","143568"],["BA","143612"],["BB","143541"],["BD","143490"],["BE","143446"],["BF","143578"],["BG","143526"],["BH","143559"],["BJ","143576"],["BM","143542"],["BN","143560"],["BO","143556"],["BR","143503"],["BS","143539"],["BT","143577"],["BW","143525"],["BY","143565"],["BZ","143555"],["CA","143455"],["CD","143613"],["CG","143582"],["CH","143459"],["CI","143527"],["CL","143483"],["CM","143574"],["CN","143465"],["CO","143501"],["CR","143495"],["CV","143580"],["CY","143557"],["CZ","143489"],["DE","143443"],["DK","143458"],["DM","143545"],["DO","143508"],["DZ","143563"],["EC","143509"],["EE","143518"],["EG","143516"],["ES","143454"],["FI","143447"],["FJ","143583"],["FM","143591"],["FR","143442"],["GA","143614"],["GB","143444"],["GD","143546"],["GF","143615"],["GH","143573"],["GM","143584"],["GR","143448"],["GT","143504"],["GW","143585"],["GY","143553"],["HK","143463"],["HN","143510"],["HR","143494"],["HU","143482"],["ID","143476"],["IE","143449"],["IL","143491"],["IN","143467"],["IQ","143617"],["IS","143558"],["IT","143450"],["JM","143511"],["JO","143528"],["JP","143462"],["KE","143529"],["KG","143586"],["KH","143579"],["KN","143548"],["KP","143466"],["KR","143466"],["KW","143493"],["KY","143544"],["KZ","143517"],["TC","143552"],["TD","143581"],["TJ","143603"],["TH","143475"],["TM","143604"],["TN","143536"],["TO","143608"],["TR","143480"],["TT","143551"],["TW","143470"],["TZ","143572"],["LA","143587"],["LB","143497"],["LC","143549"],["LI","143522"],["LK","143486"],["LR","143588"],["LT","143520"],["LU","143451"],["LV","143519"],["LY","143567"],["MA","143620"],["MD","143523"],["ME","143619"],["MG","143531"],["MK","143530"],["ML","143532"],["MM","143570"],["MN","143592"],["MO","143515"],["MR","143590"],["MS","143547"],["MT","143521"],["MU","143533"],["MV","143488"],["MW","143589"],["MX","143468"],["MY","143473"],["MZ","143593"],["NA","143594"],["NE","143534"],["NG","143561"],["NI","143512"],["NL","143452"],["NO","143457"],["NP","143484"],["NR","143606"],["NZ","143461"],["OM","143562"],["PA","143485"],["PE","143507"],["PG","143597"],["PH","143474"],["PK","143477"],["PL","143478"],["PT","143453"],["PW","143595"],["PY","143513"],["QA","143498"],["RO","143487"],["RS","143500"],["RU","143469"],["RW","143621"],["SA","143479"],["SB","143601"],["SC","143599"],["SE","143456"],["SG","143464"],["SI","143499"],["SK","143496"],["SL","143600"],["SN","143535"],["SR","143554"],["ST","143598"],["SV","143506"],["SZ","143602"],["UA","143492"],["UG","143537"],["US","143441"],["UY","143514"],["UZ","143566"],["VC","143550"],["VE","143502"],["VG","143543"],["VN","143471"],["VU","143609"],["XK","143624"],["YE","143571"],["ZA","143472"],["ZM","143622"],["ZW","143605"]] + } + } +}; + +// 构造回复数据 +let $response = undefined; + +/***************** Processing *****************/ +(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", DataBase); + $.log(`⚠ ${$.name}`, `Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings?.Switch) { + case "true": + default: + let url = URL.parse($request?.url); + const METHOD = $request?.method, HOST = url?.host, PATH = url?.path, PATHs = PATH.split("/"); + // 解析格式 + const FORMAT = ($request?.headers?.["Content-Type"] ?? $request?.headers?.["content-type"])?.split(";")?.[0]; + $.log(`⚠ ${$.name}`, `METHOD: ${METHOD}`, `HOST: ${HOST}`, `PATH: ${PATH}`, `PATHs: ${PATHs}`, `FORMAT: ${FORMAT}`, ""); + // 创建空数据 + let body = {}; + // 方法判断 + switch (METHOD) { + case "POST": + case "PUT": + case "PATCH": + case "DELETE": + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + case "text/html": + default: + break; + case "text/xml": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + //body = await PLIST("plist2json", $request.body); + //$.log(body); + //$request.body = await PLIST("json2plist", body); + break; + case "text/json": + case "application/json": + body = JSON.parse($request.body); + switch (HOST) { + case "testflight.apple.com": + switch (PATH) { + case "v1/session/authenticate": + /* + if (Settings.storeCookies) { // 使用Cookies + $.log(`🚧 ${$.name}, storeCookies`, ""); + if (Caches?.dsId && Caches?.storeCookies) { // 有 DS ID和iTunes Store Cookie + $.log(`🚧 ${$.name}, 有Caches, DS ID和iTunes Store Cookie`, ""); + if (body.dsId !== Caches?.dsId) { // DS ID不相等,覆盖iTunes Store Cookie + $.log(`🚧 ${$.name}, DS ID不相等,覆盖DS ID和iTunes Store Cookie`, ""); + body.dsId = Caches.dsId; + body.deviceModel = Caches.deviceModel; + body.storeCookies = Caches.storeCookies; + body.deviceVendorId = Caches.deviceVendorId; + body.deviceName = Caches.deviceName; + } else $.setjson({ ...Caches, ...body }, "@iRingo.TestFlight.Caches"); // DS ID相等,刷新缓存 + } else $.setjson({ ...Caches, ...body }, "@iRingo.TestFlight.Caches"); // Caches空 + } + */ + if (Settings.CountryCode !== "AUTO") body.storeFrontIdentifier = body.storeFrontIdentifier.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + case "v1/devices": + case "v1/devices/apns": + case "v1/devices/add": + case "v1/devices/remove": + break; + default: + // v2.x + switch (PATHs?.[0]) { + case "v1": + switch (PATHs?.[1]) { + case "accounts": + switch (PATHs?.[2]) { + case "settings": + switch (PATHs?.[3]) { + case "notifications": + switch (PATHs?.[4]) { + case "apps": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/settings/notifications/apps/`, ""); + break; + }; + break; + }; + break; + case Caches?.data?.accountId: // UUID + default: + switch (PATHs?.[3]) { + case "apps": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/`, ""); + break; + }; + break; + }; + break; + case "apps": + switch (PATHs?.[3]) { + case "install": + switch (PATHs?.[4]) { + case undefined: + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/apps/install`, ""); + break; + case "status": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/apps/install/status`, ""); + break; + }; + break; + }; + break; + }; + break; + case "v2": + switch (PATHs?.[1]) { + case "accounts": + switch (PATHs?.[2]) { + case Caches?.data?.accountId: // UUID + default: + switch (PATHs?.[3]) { + case "apps": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/`, ""); + switch (PATHs?.[5]) { + case "builds": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/${PATHs?.[4]}/builds/`, ""); + switch (PATHs?.[7]) { + case undefined: + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/${PATHs?.[4]}/builds/${PATHs?.[6]}`, ""); + break; + case "install": + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/${PATHs?.[4]}/builds/${PATHs?.[6]}/install`, ""); + if (Settings.CountryCode !== "AUTO") body.storefrontId = body.storefrontId.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + case "v3": + switch (PATHs?.[1]) { + case "accounts": + switch (PATHs?.[2]) { + case Caches?.data?.accountId: // UUID + default: + switch (PATHs?.[3]) { + case undefined: + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}`, ""); + break; + case "apps": + switch (PATHs?.[4]) { + case undefined: + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps`, ""); + break; + default: + $.log(`🚧 ${$.name}, ${PATHs?.[0]}/accounts/${PATHs?.[2]}/apps/${PATHs?.[4]}`, ""); + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + // v1.x + /* + if (/\/accounts\//i.test(url.path)) { + $.log(`🚧 ${$.name}, accounts`, ""); + if (/\/settings\//i.test(url.path)) { + $.log(`🚧 ${$.name}, settings`, ""); + if (/\/notifications\/apps\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, notifications/apps`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + } else if (/\/apps/i.test(url.path)) { // app info mod + $.log(`🚧 ${$.name}, /apps`, ""); + if (/\/apps$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /apps`, ""); + } else if (/\/apps\/\d+\/builds\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids`, ""); + } else if (/\/apps\/\d+\/platforms\/\w+\/trains$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains`, ""); + } else if (/\/apps\/\d+\/platforms\/\w+\/trains\/[\d.]+\/builds$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains/builds`, ""); + } else if (/\/apps\/\d+\/builds\/\d+\/install$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install`, ""); + if (Settings.CountryCode !== "AUTO") body.storefrontId = body.storefrontId.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + } else if (/\/apps\/\d+\/builds\/\d+\/install\/status$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install/status`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + }; + }; + */ + break; + }; + break; + }; + $request.body = JSON.stringify(body); + break; + case "application/x-protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + break; + }; + //break; // 不中断,继续处理URL + case "GET": + case "HEAD": + case "OPTIONS": + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "v1/properties/testflight": + //$request.headers["X-Apple-Rosetta-Available"] = Settings.Rosetta; + break; + case `v1/messages/${Caches?.data?.accountId}`: + case `v1/messages/${Caches?.data?.accountId}/read`: + $.log(`🚧 ${$.name}, "accountId"相同,更新`, ""); + Caches.headers = { + "X-Request-Id": $request.headers["x-request-id"], + "X-Session-Id": $request.headers["x-session-id"], + "X-Session-Digest": $request.headers["x-session-digest"] + }; + $.setjson(Caches, "@iRingo.TestFlight.Caches"); + break; + default: + // headers auth mod + switch (Settings.MultiAccount) { // MultiAccount + case "true": + $.log(`🚧 ${$.name}, 启用多账号支持`, ""); + if (Caches?.data) { // Caches.data存在` + $.log(`🚧 ${$.name}, data存在`, ""); + switch (/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.exec(url.path)?.[0]) { + case Caches?.data?.accountId: // url.path有UUID且与accountId相同 + $.log(`🚧 ${$.name}, accountId相同,更新`, ""); + Caches.headers = { + "X-Request-Id": $request.headers["x-request-id"], + "X-Session-Id": $request.headers["x-session-id"], + "X-Session-Digest": $request.headers["x-session-digest"] + }; + $.setjson(Caches, "@iRingo.TestFlight.Caches"); + break; + case undefined: // url.path没有UUID + $.log(`🚧 ${$.name}, url.path没有UUID`, ""); + if ($request.headers["x-session-id"] !== Caches.headers["X-Session-Id"]) { // sessionId不同 + $.log(`🚧 ${$.name}, sessionId不同,替换`, ""); + if ($request?.headers?.["if-none-match"]) $request.headers["if-none-match"] = `\"${$request.headers["if-none-match"].replace(/\"/g, "")}_\"` + $request.headers["x-request-id"] = Caches.headers["X-Request-Id"]; + $request.headers["x-session-id"] = Caches.headers["X-Session-Id"]; + $request.headers["x-session-digest"] = Caches.headers["X-Session-Digest"]; + } + break; + default: // url.path有UUID但与accountId不同 + $.log(`🚧 ${$.name}, accountId不同,替换`, ""); + url.path = url.path.replace(/\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\//i, `/${Caches.data.accountId}/`); + if ($request?.headers?.["if-none-match"]) $request.headers["if-none-match"] = `\"${$request.headers["if-none-match"].replace(/\"/g, "")}_\"` + $request.headers["x-request-id"] = Caches.data["X-Request-Id"]; + $request.headers["x-session-id"] = Caches.data["X-Session-Id"]; + $request.headers["x-session-digest"] = Caches.data["X-Session-Digest"]; + break; + } + } else { // Caches空 + $.log(`🚧 ${$.name}, Caches空,写入`, ""); + Caches.headers = { + "X-Request-Id": $request.headers["x-request-id"], + "X-Session-Id": $request.headers["x-session-id"], + "X-Session-Digest": $request.headers["x-session-digest"] + }; + Caches.data = { + "accountId": /[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.exec(url.path)?.[0], + "sessionId": $request.headers["x-session-id"] + }; + $.setjson(Caches, "@iRingo.TestFlight.Caches"); + }; + //break; // 不中断,继续处理 + case "false": + default: + // v1.x + /* + if (/\/accounts\//i.test(url.path)) { + $.log(`🚧 ${$.name}, accounts`, ""); + if (/\/settings\//i.test(url.path)) { + $.log(`🚧 ${$.name}, settings`, ""); + if (/\/notifications\/apps\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, notifications/apps`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + } else if (/\/apps/i.test(url.path)) { // app info mod + $.log(`🚧 ${$.name}, /apps`, ""); + if (/\/apps$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /apps`, ""); + } else if (/\/apps\/\d+\/builds\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids`, ""); + } else if (/\/apps\/\d+\/platforms\/\w+\/trains$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains`, ""); + } else if (/\/apps\/\d+\/platforms\/\w+\/trains\/[\d.]+\/builds$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains/builds`, ""); + } else if (/\/apps\/\d+\/builds\/\d+\/install$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install`, ""); + //let install = JSON.parse($request.body); + //if (Settings.CountryCode !== "AUTO") install.storefrontId = install.storefrontId.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + //$request.body = JSON.stringify(install); + } else if (/\/apps\/\d+\/builds\/\d+\/install\/status$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install/status`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + }; + } else if (/\/ru\//i.test(url.path)) { + $.log(`🚧 ${$.name}, /ru/`, ""); + if (/\/app$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app`, ""); + } else if (/\/accept$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /accept`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + } else if (/\/invites\//i.test(url.path)) { + $.log(`🚧 ${$.name}, /invites/`, ""); + if (/\/app$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app`, ""); + } else if (/\/accept$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /accept`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + } else if (/\/messages\//i.test(url.path)) { + $.log(`🚧 ${$.name}, /messages/`, ""); + if (/\/read$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /read`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + }; + */ + break; + }; + break; + }; + break; + }; + if ($request?.headers?.Host) $request.headers.Host = url.host; + $request.url = URL.stringify(url); + $.log(`🚧 ${$.name}, 调试信息`, `$request.url: ${$request.url}`, ""); + break; + case "CONNECT": + case "TRACE": + break; + }; + break; + case "false": + break; + }; +})() + .catch((e) => $.logErr(e)) + .finally(() => { + switch ($response) { + default: { // 有构造回复数据,返回构造的回复数据 + const FORMAT = ($response?.headers?.["Content-Type"] ?? $response?.headers?.["content-type"])?.split(";")?.[0]; + $.log(`🎉 ${$.name}, finally`, `echo $response`, `FORMAT: ${FORMAT}`, ""); + //$.log(`🚧 ${$.name}, finally`, `echo $response: ${JSON.stringify($response)}`, ""); + if ($response?.headers?.["Content-Encoding"]) $response.headers["Content-Encoding"] = "identity"; + if ($response?.headers?.["content-encoding"]) $response.headers["content-encoding"] = "identity"; + if ($.isQuanX()) { + $response.status = "HTTP/1.1 200 OK"; + delete $response?.headers?.["Content-Length"]; + delete $response?.headers?.["content-length"]; + delete $response?.headers?.["Transfer-Encoding"]; + switch (FORMAT) { + case undefined: // 视为无body + // 返回普通数据 + $.done({ status: $response.status, headers: $response.headers }); + break; + case "application/x-www-form-urlencoded": + case "text/plain": + case "text/html": + case "text/xml": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + case "text/json": + case "application/json": + default: + // 返回普通数据 + $.done({ status: $response.status, headers: $response.headers, body: $response.body }); + break; + case "application/x-protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + // 返回二进制数据 + //$.log(`${$response.bodyBytes.byteLength}---${$response.bodyBytes.buffer.byteLength}`); + $.done({ status: $response.status, headers: $response.headers, bodyBytes: $response.bodyBytes }); + break; + }; + } else $.done({ response: $response }); + break; + }; + case undefined: { // 无构造回复数据,发送修改的请求数据 + const FORMAT = ($request?.headers?.["Content-Type"] ?? $request?.headers?.["content-type"])?.split(";")?.[0]; + $.log(`🎉 ${$.name}, finally`, `$request`, `FORMAT: ${FORMAT}`, ""); + //$.log(`🚧 ${$.name}, finally`, `$request: ${JSON.stringify($request)}`, ""); + if ($.isQuanX()) { + switch (FORMAT) { + case undefined: // 视为无body + // 返回普通数据 + $.done({ url: $request.url, headers: $request.headers }) + break; + case "application/x-www-form-urlencoded": + case "text/plain": + case "text/html": + case "text/xml": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + case "text/json": + case "application/json": + default: + // 返回普通数据 + $.done({ url: $request.url, headers: $request.headers, body: $request.body }) + break; + case "application/x-protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + // 返回二进制数据 + //$.log(`${$request.bodyBytes.byteLength}---${$request.bodyBytes.buffer.byteLength}`); + $.done({ url: $request.url, headers: $request.headers, bodyBytes: $request.bodyBytes.buffer.slice($request.bodyBytes.byteOffset, $request.bodyBytes.byteLength + $request.bodyBytes.byteOffset) }); + break; + }; + } else $.done($request); + break; + }; + }; + }) + +/***************** Function *****************/ +/** + * Set Environment Variables + * @author VirgilClyne + * @param {String} name - Persistent Store Key + * @param {String} platform - Platform Name + * @param {Object} database - Default DataBase + * @return {Object} { Settings, Caches, Configs } + */ +function setENV(name, platform, database) { + $.log(`⚠ ${$.name}, Set Environment Variables`, ""); + let { Settings, Caches, Configs } = getENV(name, platform, database); + /***************** Prase *****************/ + $.log(`🎉 ${$.name}, Set Environment Variables`, `Settings: ${typeof Settings}`, `Settings内容: ${JSON.stringify(Settings)}`, ""); + /***************** Caches *****************/ + /***************** Configs *****************/ + Configs.Storefront = new Map(Configs.Storefront); + return { Settings, Caches, Configs }; +}; + +/***************** Env *****************/ +// prettier-ignore +// https://github.com/chavyleung/scripts/blob/master/Env.min.js +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} + +// https://github.com/DualSubs/URL/blob/main/URLs.embedded.min.js +function URLs(s){return new class{constructor(s=[]){this.name="URL v1.0.2",this.opts=s,this.json={scheme:"",host:"",path:"",params:{}}}parse(s){let t=s.match(/(?.+):\/\/(?[^/]+)\/?(?[^?]+)?\??(?.*)?/)?.groups??null;return t?.path||(t.path=""),t?.params&&(t.params=Object.fromEntries(t.params.split("&").map((s=>s.split("="))))),t}stringify(s=this.json){return s?.params?s.scheme+"://"+s.host+"/"+s.path+"?"+Object.entries(s.params).map((s=>s.join("="))).join("&"):s.scheme+"://"+s.host+"/"+s.path}}(s)} + +/** + * Get Environment Variables + * @link https://github.com/VirgilClyne/VirgilClyne/blob/main/function/getENV/getENV.min.js + * @author VirgilClyne + * @param {String} t - Persistent Store Key + * @param {String} e - Platform Name + * @param {Object} n - Default Database + * @return {Object} { Settings, Caches, Configs } + */ +function getENV(t,e,n){let i=$.getjson(t,n),s={};if("undefined"!=typeof $argument&&Boolean($argument)){let t=Object.fromEntries($argument.split("&").map((t=>t.split("="))));for(let e in t)l(s,e,t[e])}let g={...n?.Default?.Settings,...n?.[e]?.Settings,...i?.[e]?.Settings,...s},f={...n?.Default?.Configs,...n?.[e]?.Configs,...i?.[e]?.Configs},o=i?.[e]?.Caches||{};return"string"==typeof o&&(o=JSON.parse(o)),{Settings:g,Caches:o,Configs:f};function l(t,e,n){e.split(".").reduce(((t,i,s)=>t[i]=e.split(".").length===++s?n:t[i]||{}),t)}} diff --git a/archive/js/TestFlight.response.v2.0.beta.js b/archive/js/TestFlight.response.v2.0.beta.js new file mode 100644 index 0000000..0510959 --- /dev/null +++ b/archive/js/TestFlight.response.v2.0.beta.js @@ -0,0 +1,411 @@ +/* +README:https://github.com/VirgilClyne/iRingo +*/ +const $ = new Env(" iRingo: ✈ TestFlight v2.0.0(1) response.beta"); +const URL = new URLs(); +const DataBase = { + "Location":{ + "Settings":{"Switch":"true","PEP":{"GCC":"US"},"Services":{"PlaceData":"CN","Directions":"AUTO","Traffic":"AUTO","RAP":"XX","Tiles":"AUTO"},"Geo_manifest":{"Dynamic":{"Config":{"Country_code":{"default":"AUTO","iOS":"CN","iPadOS":"CN","watchOS":"US","macOS":"CN"}}}},"Config":{"Announcements":{"Environment:":{"default":"AUTO","iOS":"CN","iPadOS":"CN","watchOS":"XX","macOS":"CN"}},"Defaults":{"LagunaBeach":true,"DrivingMultiWaypointRoutesEnabled":true,"GEOAddressCorrection":true,"LookupMaxParametersCount":true,"LocalitiesAndLandmarks":true,"POIBusyness":true,"PedestrianAR":true,"6694982d2b14e95815e44e970235e230":true,"OpticalHeading":true,"UseCLPedestrianMapMatchedLocations":true,"TransitPayEnabled":true,"WiFiQualityNetworkDisabled":false,"WiFiQualityTileDisabled":false}}} + }, + "Weather":{ + "Settings":{"Switch":"true","NextHour":{"Switch":true},"AQI":{"Switch":true,"Mode":"WAQI Public","Location":"Station","Auth":null,"Scale":"EPA_NowCast.2204"},"Map":{"AQI":false}}, + "Configs":{ + "Availability":["currentWeather","forecastDaily","forecastHourly","history","weatherChange","forecastNextHour","severeWeather","airQuality"], + "Pollutants":{"co":"CO","no":"NO","no2":"NO2","so2":"SO2","o3":"OZONE","nox":"NOX","pm25":"PM2.5","pm10":"PM10","other":"OTHER"} + } + }, + "Siri":{ + "Settings":{"Switch":"true","CountryCode":"SG","Domains":["web","itunes","app_store","movies","restaurants","maps"],"Functions":["flightutilities","lookup","mail","messages","news","safari","siri","spotlight","visualintelligence"],"Safari_Smart_History":true}, + "Configs":{ + "VisualIntelligence":{"enabled_domains":["pets","media","books","art","nature","landmarks"],"supported_domains":["OBJECT_2D","SCULPTURE","ART","CATS","DOGS","LANDMARK","ALBUM","SKYLINE","BIRDS","NATURE","ANIMALS","INSECTS","BOOK","MEDIA","NATURAL_LANDMARK"]} + } + }, + "TV":{ + "Settings": { + "Switch": true,"Third-Party": true,"Tabs":["WatchNow","Originals","Store","Movies","TV","Sports","Kids","Library","Search"], + "CountryCode":{"Configs":"AUTO","Settings":"AUTO","View":["SG","TW"],"WatchNow":"AUTO","Channels":"AUTO","Originals":"TW","Movies":"AUTO","TV":"AUTO","Sports":"US","Kids":"US","Persons":"SG","Search":"TW","Others":"AUTO"} + }, + "Configs":{ + "Locale":[["AU","en-AU"],["CA","en-CA"],["GB","en-GB"],["KR","ko-KR"],["HK","yue-Hant"],["JP","ja-JP"],["MO","zh-Hant"],["TW","zh-Hant"],["US","en-US"],["SG","zh-Hans"]], + "Tabs": [ + { "title": "立即观看", "type": "WatchNow", "universalLinks": ["https://tv.apple.com/watch-now"], "destinationType": "Target", "target": { "id": "tahoma_watchnow", "type": "Root", "url": "https://tv.apple.com/watch-now" } }, + { "title": "原创内容", "type": "Originals", "universalLinks": ["https://tv.apple.com/channel/tvs.sbd.4000", "https://tv.apple.com/atv"], "destinationType": "Target", "target": { "id": "tvs.sbd.4000", "type": "Brand", "url": "https://tv.apple.com/us/channel/tvs.sbd.4000" } }, + { "title": "电影", "type": "Movies", "universalLinks": ["https://tv.apple.com/movies"], "destinationType": "Target", "target": { "id": "tahoma_movies", "type": "Root", "url": "https://tv.apple.com/movies" } }, + { "title": "电视节目", "type": "TV", "universalLinks": ["https://tv.apple.com/tv-shows"], "destinationType": "Target", "target": { "id": "tahoma_tvshows", "type": "Root", "url": "https://tv.apple.com/tv-shows" } }, + { "title": "商店", "type": "Store", "universalLinks": ["https://tv.apple.com/store"], "destinationType": "SubTabs", + "subTabs": [ + { "title": "电影", "type": "Movies", "universalLinks": ["https://tv.apple.com/movies"], "destinationType": "Target", "target": { "id": "tahoma_movies", "type": "Root", "url": "https://tv.apple.com/movies" } }, + { "title": "电视节目", "type": "TV", "universalLinks": ["https://tv.apple.com/tv-shows"], "destinationType": "Target", "target": { "id": "tahoma_tvshows", "type": "Root", "url": "https://tv.apple.com/tv-shows" } } + ] + }, + { "title": "体育节目", "type": "Sports", "universalLinks": ["https://tv.apple.com/sports"], "destinationType": "Target", "target": { "id": "tahoma_sports", "type": "Root", "url": "https://tv.apple.com/sports" } }, + { "title": "儿童", "type": "Kids", "universalLinks": ["https://tv.apple.com/kids"], "destinationType": "Target", "target": { "id": "tahoma_kids", "type": "Root", "url": "https://tv.apple.com/kids" } }, + { "title": "资料库", "type": "Library", "destinationType": "Client" }, + { "title": "搜索", "type": "Search", "universalLinks": ["https://tv.apple.com/search"], "destinationType": "Target", "target": { "id": "tahoma_search", "type": "Root", "url": "https://tv.apple.com/search" } } + ], + "i18n": { + "WatchNow": [["en", "Watch Now"], ["zh", "立即观看"], ["zh-Hans", "立即观看"], ["zh-Hant", "立即觀看"]], + "Originals": [["en", "Originals"], ["zh", "原创内容"], ["zh-Hans", "原创内容"], ["zh-Hant", "原創內容"]], + "Movies": [["en", "Movies"], ["zh", "电影"], ["zh-Hans", "电影"], ["zh-Hant", "電影"]], + "TV": [["en", "TV"], ["zh", "电视节目"], ["zh-Hans", "电视节目"], ["zh-Hant", "電視節目"]], + "Store": [["en", "Store"], ["zh", "商店"], ["zh-Hans", "商店"], ["zh-Hant", "商店"]], + "Sports": [["en", "Sports"], ["zh", "体育节目"], ["zh-Hans", "体育节目"], ["zh-Hant", "體育節目"]], + "Kids": [["en", "Kids"], ["zh", "儿童"], ["zh-Hans", "儿童"], ["zh-Hant", "兒童"]], + "Library": [["en", "Library"], ["zh", "资料库"], ["zh-Hans", "资料库"], ["zh-Hant", "資料庫"]], + "Search": [["en", "Search"], ["zh", "搜索"], ["zh-Hans", "搜索"], ["zh-Hant", "蒐索"]] + } + } + }, + "News":{ + "Settings":{"Switch":"true","CountryCode":"US","newsPlusUser":"true"} + }, + "TestFlight":{ + "Settings":{"Switch":"true","CountryCode":"US","MultiAccount":"false","Universal":"true"} + }, + "Default": { + "Settings":{"Switch":"true"}, + "Configs":{ + "Storefront":[["AE","143481"],["AF","143610"],["AG","143540"],["AI","143538"],["AL","143575"],["AM","143524"],["AO","143564"],["AR","143505"],["AT","143445"],["AU","143460"],["AZ","143568"],["BA","143612"],["BB","143541"],["BD","143490"],["BE","143446"],["BF","143578"],["BG","143526"],["BH","143559"],["BJ","143576"],["BM","143542"],["BN","143560"],["BO","143556"],["BR","143503"],["BS","143539"],["BT","143577"],["BW","143525"],["BY","143565"],["BZ","143555"],["CA","143455"],["CD","143613"],["CG","143582"],["CH","143459"],["CI","143527"],["CL","143483"],["CM","143574"],["CN","143465"],["CO","143501"],["CR","143495"],["CV","143580"],["CY","143557"],["CZ","143489"],["DE","143443"],["DK","143458"],["DM","143545"],["DO","143508"],["DZ","143563"],["EC","143509"],["EE","143518"],["EG","143516"],["ES","143454"],["FI","143447"],["FJ","143583"],["FM","143591"],["FR","143442"],["GA","143614"],["GB","143444"],["GD","143546"],["GF","143615"],["GH","143573"],["GM","143584"],["GR","143448"],["GT","143504"],["GW","143585"],["GY","143553"],["HK","143463"],["HN","143510"],["HR","143494"],["HU","143482"],["ID","143476"],["IE","143449"],["IL","143491"],["IN","143467"],["IQ","143617"],["IS","143558"],["IT","143450"],["JM","143511"],["JO","143528"],["JP","143462"],["KE","143529"],["KG","143586"],["KH","143579"],["KN","143548"],["KP","143466"],["KR","143466"],["KW","143493"],["KY","143544"],["KZ","143517"],["TC","143552"],["TD","143581"],["TJ","143603"],["TH","143475"],["TM","143604"],["TN","143536"],["TO","143608"],["TR","143480"],["TT","143551"],["TW","143470"],["TZ","143572"],["LA","143587"],["LB","143497"],["LC","143549"],["LI","143522"],["LK","143486"],["LR","143588"],["LT","143520"],["LU","143451"],["LV","143519"],["LY","143567"],["MA","143620"],["MD","143523"],["ME","143619"],["MG","143531"],["MK","143530"],["ML","143532"],["MM","143570"],["MN","143592"],["MO","143515"],["MR","143590"],["MS","143547"],["MT","143521"],["MU","143533"],["MV","143488"],["MW","143589"],["MX","143468"],["MY","143473"],["MZ","143593"],["NA","143594"],["NE","143534"],["NG","143561"],["NI","143512"],["NL","143452"],["NO","143457"],["NP","143484"],["NR","143606"],["NZ","143461"],["OM","143562"],["PA","143485"],["PE","143507"],["PG","143597"],["PH","143474"],["PK","143477"],["PL","143478"],["PT","143453"],["PW","143595"],["PY","143513"],["QA","143498"],["RO","143487"],["RS","143500"],["RU","143469"],["RW","143621"],["SA","143479"],["SB","143601"],["SC","143599"],["SE","143456"],["SG","143464"],["SI","143499"],["SK","143496"],["SL","143600"],["SN","143535"],["SR","143554"],["ST","143598"],["SV","143506"],["SZ","143602"],["UA","143492"],["UG","143537"],["US","143441"],["UY","143514"],["UZ","143566"],["VC","143550"],["VE","143502"],["VG","143543"],["VN","143471"],["VU","143609"],["XK","143624"],["YE","143571"],["ZA","143472"],["ZM","143622"],["ZW","143605"]] + } + } +}; + +/***************** Processing *****************/ +(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", DataBase); + $.log(`⚠ ${$.name}`, `Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings?.Switch) { + case "true": + default: + let url = URL.parse($request?.url); + const METHOD = $request?.method, HOST = url?.host, PATH = url?.path, PATHs = PATH.split("/"); + // 解析格式 + const FORMAT = ($response?.headers?.["Content-Type"] ?? $response?.headers?.["content-type"])?.split(";")?.[0]; + $.log(`⚠ ${$.name}`, `METHOD: ${METHOD}`, `HOST: ${HOST}`, `PATH: ${PATH}`, `PATHs: ${PATHs}`, `FORMAT: ${FORMAT}`, ""); + // 创建空数据 + let body = {}; + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + case "text/html": + default: + break; + case "text/xml": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + break; + case "text/json": + case "application/json": + body = JSON.parse($response.body); + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "v1/session/authenticate": + switch (Settings.MultiAccount) { // MultiAccount + case "true": + $.log(`🚧 ${$.name}, 启用多账号支持`, ""); + if (Caches?.data) { //有data + $.log(`🚧 ${$.name}, 有Caches.data`, ""); + if (body?.data?.accountId === Caches?.data?.accountId) { // Account ID相等,刷新缓存 + $.log(`🚧 ${$.name}, Account ID相等,刷新缓存`, ""); + Caches.headers = { + "X-Request-Id": $request.headers["x-request-id"], + "X-Session-Id": $request.headers["x-session-id"], + "X-Session-Digest": $request.headers["x-session-digest"] + }; + Caches.data = body.data; + $.setjson(Caches, "@iRingo.TestFlight.Caches"); + } else { // Account ID不相等,Rewrite + $.log(`🚧 ${$.name}, Account ID不相等,覆盖accountId和sessionId`, ""); + //body.data = Caches.data; + } + } else { // Caches空 + $.log(`🚧 ${$.name}, Caches空,写入`, ""); + Caches.headers = { + "X-Request-Id": $request.headers["x-request-id"], + "X-Session-Id": $request.headers["x-session-id"], + "X-Session-Digest": $request.headers["x-session-digest"] + }; + Caches.data = body.data; + $.setjson(Caches, "@iRingo.TestFlight.Caches"); + }; + //break; // 不中断,继续处理 + case "false": + default: + break; + }; + break; + case "v1/devices": + case "v1/devices/apns": + case "v1/devices/add": + case "v1/devices/remove": + break; + case `v1/messages/${Caches?.data?.accountId}`: + case `v1/messages/${Caches?.data?.accountId}/read`: + break; + default: + if (/\/accounts\//i.test(url.path)) { + $.log(`🚧 ${$.name}, accounts`, ""); + if (/\/settings\//i.test(url.path)) { + $.log(`🚧 ${$.name}, settings`, ""); + if (/\/notifications\/apps\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, notifications/apps`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + } else if (/\/apps/i.test(url.path)) { // app info mod + $.log(`🚧 ${$.name}, /apps`, ""); + if (/\/apps$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /apps`, ""); + switch (Settings.Universal) { // 通用 + case "true": + $.log(`🚧 ${$.name}, 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + $.log(`🚧 ${$.name}, 数据无错误`, ""); + body.data = body.data.map(app => { + if (app.previouslyTested !== false) { // 不是前测试人员 + $.log(`🚧 ${$.name}, 不是前测试人员`, ""); + app.platforms = app.platforms.map(platform => { + platform.build = modBuild(platform.build); + return platform + }); + } + return app + }); + }; + break; + case "false": + default: + break; + }; + } else if (/\/apps\/\d+\/builds\/\d+$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids`, ""); + switch (Settings.Universal) { // 通用 + case "true": + $.log(`🚧 ${$.name}, 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + $.log(`🚧 ${$.name}, 数据无错误`, ""); + // 当前Bulid + body.data.currentBuild = modBuild(body.data.currentBuild); + // Build列表 + body.data.builds = body.data.builds.map(build => modBuild(build)); + }; + break; + case "false": + default: + break; + }; + } else if (/\/apps\/\d+\/platforms\/\w+\/trains$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains`, ""); + } else if (/\/apps\/\d+\/platforms\/\w+\/trains\/[\d.]+\/builds$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/platforms/trains/builds`, ""); + switch (Settings.Universal) { // 通用 + case "true": + $.log(`🚧 ${$.name}, 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + $.log(`🚧 ${$.name}, 数据无错误`, ""); + // 当前Bulid + body.data = body.data.map(data => modBuild(data)); + }; + break; + case "false": + default: + break; + }; + } else if (/\/apps\/\d+\/builds\/\d+\/install$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install`, ""); + } else if (/\/apps\/\d+\/builds\/\d+\/install\/status$/i.test(url.path)) { + $.log(`🚧 ${$.name}, /app/bulids/install/status`, ""); + } else $.log(`🚧 ${$.name}, unknown`, ""); + }; + }; + break; + }; + break; + }; + $response.body = JSON.stringify(body); + break; + case "application/x-protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + break; + }; + break; + case "false": + break; + }; +})() + .catch((e) => $.logErr(e)) + .finally(() => { + switch ($response) { + default: { // 有回复数据,返回回复数据 + const FORMAT = ($response?.headers?.["Content-Type"] ?? $response?.headers?.["content-type"])?.split(";")?.[0]; + $.log(`🎉 ${$.name}, finally`, `$response`, `FORMAT: ${FORMAT}`, ""); + //$.log(`🚧 ${$.name}, finally`, `$response: ${JSON.stringify($response)}`, ""); + if ($response?.headers?.["Content-Encoding"]) $response.headers["Content-Encoding"] = "identity"; + if ($response?.headers?.["content-encoding"]) $response.headers["content-encoding"] = "identity"; + if ($.isQuanX()) { + switch (FORMAT) { + case undefined: // 视为无body + // 返回普通数据 + $.done({ headers: $response.headers }); + break; + case "application/x-www-form-urlencoded": + case "text/plain": + case "text/html": + case "text/xml": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + case "text/json": + case "application/json": + default: + // 返回普通数据 + $.done({ headers: $response.headers, body: $response.body }); + break; + case "application/x-protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + // 返回二进制数据 + //$.log(`${$response.bodyBytes.byteLength}---${$response.bodyBytes.buffer.byteLength}`); + $.done({ headers: $response.headers, bodyBytes: $response.bodyBytes.buffer.slice($response.bodyBytes.byteOffset, $response.bodyBytes.byteLength + $response.bodyBytes.byteOffset) }); + break; + }; + } else $.done($response); + break; + }; + case undefined: { // 无回复数据 + break; + }; + }; + }) + +/***************** Function *****************/ +/** + * Set Environment Variables + * @author VirgilClyne + * @param {String} name - Persistent Store Key + * @param {String} platform - Platform Name + * @param {Object} database - Default DataBase + * @return {Object} { Settings, Caches, Configs } + */ +function setENV(name, platform, database) { + $.log(`⚠ ${$.name}, Set Environment Variables`, ""); + let { Settings, Caches, Configs } = getENV(name, platform, database); + /***************** Prase *****************/ + $.log(`🎉 ${$.name}, Set Environment Variables`, `Settings: ${typeof Settings}`, `Settings内容: ${JSON.stringify(Settings)}`, ""); + /***************** Caches *****************/ + /***************** Configs *****************/ + Configs.Storefront = new Map(Configs.Storefront); + return { Settings, Caches, Configs }; +}; + +/** + * mod Build + * @author VirgilClyne + * @param {Object} build - Build + * @return {Object} + */ +function modBuild(build) { + switch (build.platform || build.name) { + case "ios": + $.log(`🚧 ${$.name}, ios`, ""); + build = Build(build); + break; + case "osx": + $.log(`🚧 ${$.name}, osx`, ""); + if (build.macBuildCompatibility.runsOnAppleSilicon === true) { // 是苹果芯片 + $.log(`🚧 ${$.name}, runsOnAppleSilicon`, ""); + build = Build(build); + } + break; + case "appletvos": + $.log(`🚧 ${$.name}, appletvos`, ""); + break; + default: + $.log(`🚧 ${$.name}, unknown platform: ${build.platform || build.name}`, ""); + break; + }; + return build + + function Build(build) { + if (build.universal === true) { + build.compatible = true; + build.platformCompatible = true; + build.hardwareCompatible = true; + build.osCompatible = true; + if (build?.permission) build.permission = "install"; + if (build?.deviceFamilyInfo) { + build.deviceFamilyInfo = [ + { + "number": 1, + "name": "iOS", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_1.png" + }, + { + "number": 2, + "name": "iPad", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_2.png" + }, + { + "number": 3, + "name": "Apple TV", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_3.png" + } + ]; + } + if (build?.compatibilityData?.compatibleDeviceFamilies) { + build.compatibilityData.compatibleDeviceFamilies = [ + { + "name": "iPad", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPhone", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPod", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "Mac", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + } + ]; + } + }; + return build + }; +}; + +/***************** Env *****************/ +// prettier-ignore +// https://github.com/chavyleung/scripts/blob/master/Env.min.js +function Env(t,e){class s{constructor(t){this.env=t}send(t,e="GET"){t="string"==typeof t?{url:t}:t;let s=this.get;return"POST"===e&&(s=this.post),new Promise((e,a)=>{s.call(this,t,(t,s,r)=>{t?a(t):e(s)})})}get(t){return this.send.call(this.env,t)}post(t){return this.send.call(this.env,t,"POST")}}return new class{constructor(t,e){this.name=t,this.http=new s(this),this.data=null,this.dataFile="box.dat",this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=(new Date).getTime(),Object.assign(this,e),this.log("",`\ud83d\udd14${this.name}, \u5f00\u59cb!`)}getEnv(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"!=typeof module&&module.exports?"Node.js":"undefined"!=typeof $task?"Quantumult X":"undefined"!=typeof $loon?"Loon":"undefined"!=typeof $rocket?"Shadowrocket":void 0}isNode(){return"Node.js"===this.getEnv()}isQuanX(){return"Quantumult X"===this.getEnv()}isSurge(){return"Surge"===this.getEnv()}isLoon(){return"Loon"===this.getEnv()}isShadowrocket(){return"Shadowrocket"===this.getEnv()}isStash(){return"Stash"===this.getEnv()}toObj(t,e=null){try{return JSON.parse(t)}catch{return e}}toStr(t,e=null){try{return JSON.stringify(t)}catch{return e}}getjson(t,e){let s=e;const a=this.getdata(t);if(a)try{s=JSON.parse(this.getdata(t))}catch{}return s}setjson(t,e){try{return this.setdata(JSON.stringify(t),e)}catch{return!1}}getScript(t){return new Promise(e=>{this.get({url:t},(t,s,a)=>e(a))})}runScript(t,e){return new Promise(s=>{let a=this.getdata("@chavy_boxjs_userCfgs.httpapi");a=a?a.replace(/\n/g,"").trim():a;let r=this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout");r=r?1*r:20,r=e&&e.timeout?e.timeout:r;const[i,o]=a.split("@"),n={url:`http://${o}/v1/scripting/evaluate`,body:{script_text:t,mock_type:"cron",timeout:r},headers:{"X-Key":i,Accept:"*/*"},timeout:r};this.post(n,(t,e,a)=>s(a))}).catch(t=>this.logErr(t))}loaddata(){if(!this.isNode())return{};{this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e);if(!s&&!a)return{};{const a=s?t:e;try{return JSON.parse(this.fs.readFileSync(a))}catch(t){return{}}}}}writedata(){if(this.isNode()){this.fs=this.fs?this.fs:require("fs"),this.path=this.path?this.path:require("path");const t=this.path.resolve(this.dataFile),e=this.path.resolve(process.cwd(),this.dataFile),s=this.fs.existsSync(t),a=!s&&this.fs.existsSync(e),r=JSON.stringify(this.data);s?this.fs.writeFileSync(t,r):a?this.fs.writeFileSync(e,r):this.fs.writeFileSync(t,r)}}lodash_get(t,e,s){const a=e.replace(/\[(\d+)\]/g,".$1").split(".");let r=t;for(const t of a)if(r=Object(r)[t],void 0===r)return s;return r}lodash_set(t,e,s){return Object(t)!==t?t:(Array.isArray(e)||(e=e.toString().match(/[^.[\]]+/g)||[]),e.slice(0,-1).reduce((t,s,a)=>Object(t[s])===t[s]?t[s]:t[s]=Math.abs(e[a+1])>>0==+e[a+1]?[]:{},t)[e[e.length-1]]=s,t)}getdata(t){let e=this.getval(t);if(/^@/.test(t)){const[,s,a]=/^@(.*?)\.(.*?)$/.exec(t),r=s?this.getval(s):"";if(r)try{const t=JSON.parse(r);e=t?this.lodash_get(t,a,""):e}catch(t){e=""}}return e}setdata(t,e){let s=!1;if(/^@/.test(e)){const[,a,r]=/^@(.*?)\.(.*?)$/.exec(e),i=this.getval(a),o=a?"null"===i?null:i||"{}":"{}";try{const e=JSON.parse(o);this.lodash_set(e,r,t),s=this.setval(JSON.stringify(e),a)}catch(e){const i={};this.lodash_set(i,r,t),s=this.setval(JSON.stringify(i),a)}}else s=this.setval(t,e);return s}getval(t){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.read(t);case"Quantumult X":return $prefs.valueForKey(t);case"Node.js":return this.data=this.loaddata(),this.data[t];default:return this.data&&this.data[t]||null}}setval(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":return $persistentStore.write(t,e);case"Quantumult X":return $prefs.setValueForKey(t,e);case"Node.js":return this.data=this.loaddata(),this.data[e]=t,this.writedata(),!0;default:return this.data&&this.data[e]||null}}initGotEnv(t){this.got=this.got?this.got:require("got"),this.cktough=this.cktough?this.cktough:require("tough-cookie"),this.ckjar=this.ckjar?this.ckjar:new this.cktough.CookieJar,t&&(t.headers=t.headers?t.headers:{},void 0===t.headers.Cookie&&void 0===t.cookieJar&&(t.cookieJar=this.ckjar))}get(t,e=(()=>{})){switch(t.headers&&(delete t.headers["Content-Type"],delete t.headers["Content-Length"],delete t.headers["content-type"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient.get(t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let s=require("iconv-lite");this.initGotEnv(t),this.got(t).on("redirect",(t,e)=>{try{if(t.headers["set-cookie"]){const s=t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString();s&&this.ckjar.setCookieSync(s,null),e.cookieJar=this.ckjar}}catch(t){this.logErr(t)}}).then(t=>{const{statusCode:a,statusCode:r,headers:i,rawBody:o}=t,n=s.decode(o,this.encoding);e(null,{status:a,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:a,response:r}=t;e(a,r,r&&s.decode(r.rawBody,this.encoding))})}}post(t,e=(()=>{})){const s=t.method?t.method.toLocaleLowerCase():"post";switch(t.body&&t.headers&&!t.headers["Content-Type"]&&!t.headers["content-type"]&&(t.headers["content-type"]="application/x-www-form-urlencoded"),t.headers&&(delete t.headers["Content-Length"],delete t.headers["content-length"]),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:this.isSurge()&&this.isNeedRewrite&&(t.headers=t.headers||{},Object.assign(t.headers,{"X-Surge-Skip-Scripting":!1})),$httpClient[s](t,(t,s,a)=>{!t&&s&&(s.body=a,s.statusCode=s.status?s.status:s.statusCode,s.status=s.statusCode),e(t,s,a)});break;case"Quantumult X":t.method=s,this.isNeedRewrite&&(t.opts=t.opts||{},Object.assign(t.opts,{hints:!1})),$task.fetch(t).then(t=>{const{statusCode:s,statusCode:a,headers:r,body:i,bodyBytes:o}=t;e(null,{status:s,statusCode:a,headers:r,body:i,bodyBytes:o},i,o)},t=>e(t&&t.error||"UndefinedError"));break;case"Node.js":let a=require("iconv-lite");this.initGotEnv(t);const{url:r,...i}=t;this.got[s](r,i).then(t=>{const{statusCode:s,statusCode:r,headers:i,rawBody:o}=t,n=a.decode(o,this.encoding);e(null,{status:s,statusCode:r,headers:i,rawBody:o,body:n},n)},t=>{const{message:s,response:r}=t;e(s,r,r&&a.decode(r.rawBody,this.encoding))})}}time(t,e=null){const s=e?new Date(e):new Date;let a={"M+":s.getMonth()+1,"d+":s.getDate(),"H+":s.getHours(),"m+":s.getMinutes(),"s+":s.getSeconds(),"q+":Math.floor((s.getMonth()+3)/3),S:s.getMilliseconds()};/(y+)/.test(t)&&(t=t.replace(RegExp.$1,(s.getFullYear()+"").substr(4-RegExp.$1.length)));for(let e in a)new RegExp("("+e+")").test(t)&&(t=t.replace(RegExp.$1,1==RegExp.$1.length?a[e]:("00"+a[e]).substr((""+a[e]).length)));return t}queryStr(t){let e="";for(const s in t){let a=t[s];null!=a&&""!==a&&("object"==typeof a&&(a=JSON.stringify(a)),e+=`${s}=${a}&`)}return e=e.substring(0,e.length-1),e}msg(e=t,s="",a="",r){const i=t=>{switch(typeof t){case void 0:return t;case"string":switch(this.getEnv()){case"Surge":case"Stash":default:return{url:t};case"Loon":case"Shadowrocket":return t;case"Quantumult X":return{"open-url":t};case"Node.js":return}case"object":switch(this.getEnv()){case"Surge":case"Stash":case"Shadowrocket":default:{let e=t.url||t.openUrl||t["open-url"];return{url:e}}case"Loon":{let e=t.openUrl||t.url||t["open-url"],s=t.mediaUrl||t["media-url"];return{openUrl:e,mediaUrl:s}}case"Quantumult X":{let e=t["open-url"]||t.url||t.openUrl,s=t["media-url"]||t.mediaUrl,a=t["update-pasteboard"]||t.updatePasteboard;return{"open-url":e,"media-url":s,"update-pasteboard":a}}case"Node.js":return}default:return}};if(!this.isMute)switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(e,s,a,i(r));break;case"Quantumult X":$notify(e,s,a,i(r));break;case"Node.js":}if(!this.isMuteLog){let t=["","==============\ud83d\udce3\u7cfb\u7edf\u901a\u77e5\ud83d\udce3=============="];t.push(e),s&&t.push(s),a&&t.push(a),console.log(t.join("\n")),this.logs=this.logs.concat(t)}}log(...t){t.length>0&&(this.logs=[...this.logs,...t]),console.log(t.join(this.logSeparator))}logErr(t,e){switch(this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t);break;case"Node.js":this.log("",`\u2757\ufe0f${this.name}, \u9519\u8bef!`,t.stack)}}wait(t){return new Promise(e=>setTimeout(e,t))}done(t={}){const e=(new Date).getTime(),s=(e-this.startTime)/1e3;switch(this.log("",`\ud83d\udd14${this.name}, \u7ed3\u675f! \ud83d\udd5b ${s} \u79d2`),this.log(),this.getEnv()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":case"Quantumult X":default:$done(t);break;case"Node.js":process.exit(1)}}}(t,e)} + +// https://github.com/DualSubs/URL/blob/main/URLs.embedded.min.js +function URLs(s){return new class{constructor(s=[]){this.name="URL v1.0.2",this.opts=s,this.json={scheme:"",host:"",path:"",params:{}}}parse(s){let t=s.match(/(?.+):\/\/(?[^/]+)\/?(?[^?]+)?\??(?.*)?/)?.groups??null;return t?.path||(t.path=""),t?.params&&(t.params=Object.fromEntries(t.params.split("&").map((s=>s.split("="))))),t}stringify(s=this.json){return s?.params?s.scheme+"://"+s.host+"/"+s.path+"?"+Object.entries(s.params).map((s=>s.join("="))).join("&"):s.scheme+"://"+s.host+"/"+s.path}}(s)} + +/** + * Get Environment Variables + * @link https://github.com/VirgilClyne/VirgilClyne/blob/main/function/getENV/getENV.min.js + * @author VirgilClyne + * @param {String} t - Persistent Store Key + * @param {String} e - Platform Name + * @param {Object} n - Default Database + * @return {Object} { Settings, Caches, Configs } + */ +function getENV(t,e,n){let i=$.getjson(t,n),s={};if("undefined"!=typeof $argument&&Boolean($argument)){let t=Object.fromEntries($argument.split("&").map((t=>t.split("="))));for(let e in t)l(s,e,t[e])}let g={...n?.Default?.Settings,...n?.[e]?.Settings,...i?.[e]?.Settings,...s},f={...n?.Default?.Configs,...n?.[e]?.Configs,...i?.[e]?.Configs},o=i?.[e]?.Caches||{};return"string"==typeof o&&(o=JSON.parse(o)),{Settings:g,Caches:o,Configs:f};function l(t,e,n){e.split(".").reduce(((t,i,s)=>t[i]=e.split(".").length===++s?n:t[i]||{}),t)}} diff --git a/modules/TestFlight.plugin b/modules/TestFlight.plugin new file mode 100644 index 0000000..8ca5bd8 --- /dev/null +++ b/modules/TestFlight.plugin @@ -0,0 +1,18 @@ +#!name= iRingo: ✈ TestFlight +#!desc=1.自定义TestFlight登录商店地区 2.多账户保存及切换(需配置BoxJs使用) 3.让通用应用在任意苹果处理器设备上可安装 +#!openUrl=http://boxjs.com/#/app/iRingo.TestFlight +#!author=VirgilClyne[https://github.com/VirgilClyne] +#!homepage=https://github.com/NSRingo +#!manual=https://github.com/NSRingo/TestFlight +#!icon=https://developer.apple.com/assets/elements/icons/testflight/testflight-128x128.png +#!tag= iRingo + +[General] +skip-proxy = iosapps.itunes.apple.com + +[Script] +http-request ^https?:\/\/testflight\.apple\.com\/ script-path=https://github.com/NSRingo/TestFlight/releases/latest/download/request.js, requires-body=true, tag=✈ TestFlight.request, argument= +http-response ^https?:\/\/testflight\.apple\.com\/ script-path=https://github.com/NSRingo/TestFlight/releases/latest/download/response.js, requires-body=true, tag=✈ TestFlight.response, argument= + +[MITM] +hostname = testflight.apple.com diff --git a/modules/TestFlight.sgmodule b/modules/TestFlight.sgmodule new file mode 100644 index 0000000..b82d3bd --- /dev/null +++ b/modules/TestFlight.sgmodule @@ -0,0 +1,18 @@ +#!name= iRingo: ✈ TestFlight +#!desc=1.自定义TestFlight登录商店地区\n2.多账户保存及切换(需配置BoxJs使用)\n3.让通用应用在任意苹果处理器设备上可安装 +#!openUrl=http://boxjs.com/#/app/iRingo.TestFlight +#!author=VirgilClyne[https://github.com/VirgilClyne] +#!homepage=https://github.com/NSRingo +#!manual=https://github.com/NSRingo/TestFlight +#!icon=https://developer.apple.com/assets/elements/icons/testflight/testflight-128x128.png +#!category= iRingo + +[General] +skip-proxy = %APPEND% iosapps.itunes.apple.com + +[Script] +✈ TestFlight.request = type=http-request, pattern=^https?:\/\/testflight\.apple\.com\/, requires-body=1, script-path=https://github.com/NSRingo/TestFlight/releases/latest/download/request.js, argument= +✈ TestFlight.response = type=http-response, pattern=^https?:\/\/testflight\.apple\.com\/, requires-body=1, script-path=https://github.com/NSRingo/TestFlight/releases/latest/download/response.js, argument= + +[MITM] +hostname = %APPEND% testflight.apple.com diff --git a/modules/TestFlight.snippet b/modules/TestFlight.snippet new file mode 100644 index 0000000..446f1c5 --- /dev/null +++ b/modules/TestFlight.snippet @@ -0,0 +1,16 @@ +#!name= iRingo: ✈ TestFlight +#!desc=1.自定义TestFlight登录商店地区 2.多账户保存及切换(需配置BoxJs使用) 3.让通用应用在任意苹果处理器设备上可安装 +#!openUrl=http://boxjs.com/#/app/iRingo.TestFlight +#!author=VirgilClyne[https://github.com/VirgilClyne] +#!homepage=https://github.com/NSRingo +#!manual=https://github.com/NSRingo/TestFlight +#!icon=https://developer.apple.com/assets/elements/icons/testflight/testflight-128x128.png +#!category= iRingo + +#[rewrite_local] +# ✈ TestFlight +^https?:\/\/testflight\.apple\.com\/ url script-request-body https://github.com/NSRingo/TestFlight/releases/latest/download/request.js +^https?:\/\/testflight\.apple\.com\/ url script-response-body https://github.com/NSRingo/TestFlight/releases/latest/download/response.js + +#[mitm] +hostname = testflight.apple.com diff --git a/modules/TestFlight.stoverride b/modules/TestFlight.stoverride new file mode 100644 index 0000000..04acba3 --- /dev/null +++ b/modules/TestFlight.stoverride @@ -0,0 +1,34 @@ +name: " iRingo: ✈ TestFlight" +desc: |- + 1.自定义TestFlight登录商店地区 + 2.多账户保存及切换(需配置BoxJs使用) + 3.让通用应用在任意苹果处理器设备上可安装 +openUrl: "http://boxjs.com/#/app/iRingo.TestFlight" +author: "VirgilClyne" +homepage: "https://github.com/NSRingo" +manual: "https://github.com/NSRingo/TestFlight" +icon: "https://developer.apple.com/assets/elements/icons/testflight/testflight-128x128.png" +category: " iRingo" + +http: + mitm: + - "testflight.apple.com" + script: + - match: ^https?:\/\/testflight\.apple\.com\/ + name: TestFlight.request + type: request + require-body: true + argument: + - match: ^https?:\/\/testflight\.apple\.com\/ + name: TestFlight.response + type: response + require-body: true + argument: + +script-providers: + TestFlight.request: + url: https://github.com/NSRingo/TestFlight/releases/latest/download/request.js + interval: 86400 + TestFlight.response: + url: https://github.com/NSRingo/TestFlight/releases/latest/download/response.js + interval: 86400 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a6debad --- /dev/null +++ b/package-lock.json @@ -0,0 +1,839 @@ +{ + "name": "testflight", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "testflight", + "license": "Apache-2.0", + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.9.6" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "25.0.8", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", + "integrity": "sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", + "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz", + "integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/magic-string": { + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/terser": { + "version": "5.34.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.1.tgz", + "integrity": "sha512-FsJZ7iZLd/BXkz+4xrRTGJ26o/6VTjQytUk8b8OxkwcD2I+79VPJlz7qss1+zE7h8GNIScFqXcDyJ/KqBYZFVA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..fdf9506 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "testflight", + "type": "module", + "repository": { + "type": "git", + "url": "https://github.com/NSRingo/TestFlight.git" + }, + "directories": { + "example": "example" + }, + "scripts": { + "build": "rollup -c", + "build:debug": "rollup --config --configDebug" + }, + "browserslist": [ + "iOS >= 15" + ], + "keywords": [], + "author": "VirgilClyne", + "license": "Apache-2.0", + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.9.6" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..f9b9f57 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,7 @@ +import defaultConfig from './rollup.default.config.js'; +import debugConfig from './rollup.debug.config.js'; + +export default commandLineArgs => { + if (commandLineArgs.configDebug === true) return debugConfig; + else return defaultConfig; +}; diff --git a/rollup.debug.config.js b/rollup.debug.config.js new file mode 100644 index 0000000..3ec4673 --- /dev/null +++ b/rollup.debug.config.js @@ -0,0 +1,24 @@ +import json from '@rollup/plugin-json'; +import commonjs from "@rollup/plugin-commonjs"; +import { nodeResolve } from '@rollup/plugin-node-resolve'; + +export default [ + { + input: 'src/request.debug.js', + output: { + file: 'dist/request.js', + //format: 'es', + banner: `/* README: https://github.com/NSRingo */\nconsole.log(' iRingo: ✈ TestFlight β Request')\nconsole.log('${new Date().toLocaleString('zh-CN', {timeZone: 'PRC'})}')`, + }, + plugins: [json(), commonjs(), nodeResolve()] + }, + { + input: 'src/response.debug.js', + output: { + file: 'dist/response.js', + //format: 'es', + banner: `/* README: https://github.com/NSRingo */\nconsole.log(' iRingo: ✈ TestFlight β Response')\nconsole.log('${new Date().toLocaleString('zh-CN', {timeZone: 'PRC'})}')`, + }, + plugins: [json(), commonjs(), nodeResolve()] + } +]; diff --git a/rollup.default.config.js b/rollup.default.config.js new file mode 100644 index 0000000..b40ca42 --- /dev/null +++ b/rollup.default.config.js @@ -0,0 +1,25 @@ +import json from '@rollup/plugin-json'; +import commonjs from "@rollup/plugin-commonjs"; +import terser from '@rollup/plugin-terser'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; + +export default [ + { + input: 'src/request.js', + output: { + file: 'dist/request.js', + format: 'es', + banner: `/* README: https://github.com/NSRingo */\nconsole.log(' iRingo: ✈ TestFlight Request')\nconsole.log('${new Date().toLocaleString('zh-CN', {timeZone: 'PRC'})}')`, + }, + plugins: [json(), commonjs(), nodeResolve(), terser()] + }, + { + input: 'src/response.js', + output: { + file: 'dist/response.js', + format: 'es', + banner: `/* README: https://github.com/NSRingo */\nconsole.log(' iRingo: ✈ TestFlight Response')\nconsole.log('${new Date().toLocaleString('zh-CN', {timeZone: 'PRC'})}')`, + }, + plugins: [json(), commonjs(), nodeResolve(), terser()] + } +]; diff --git a/src/function/database.mjs b/src/function/database.mjs new file mode 100644 index 0000000..3ad94c8 --- /dev/null +++ b/src/function/database.mjs @@ -0,0 +1,13 @@ +export default { + "Testflight": { + "Settings": { + "Switch": "true", + "CountryCode": "US", + "MultiAccount": "false", + "Universal": "true" + }, + "Configs": { + "Storefront": {"AE":"143481","AF":"143610","AG":"143540","AI":"143538","AL":"143575","AM":"143524","AO":"143564","AR":"143505","AT":"143445","AU":"143460","AZ":"143568","BA":"143612","BB":"143541","BD":"143490","BE":"143446","BF":"143578","BG":"143526","BH":"143559","BJ":"143576","BM":"143542","BN":"143560","BO":"143556","BR":"143503","BS":"143539","BT":"143577","BW":"143525","BY":"143565","BZ":"143555","CA":"143455","CD":"143613","CG":"143582","CH":"143459","CI":"143527","CL":"143483","CM":"143574","CN":"143465","CO":"143501","CR":"143495","CV":"143580","CY":"143557","CZ":"143489","DE":"143443","DK":"143458","DM":"143545","DO":"143508","DZ":"143563","EC":"143509","EE":"143518","EG":"143516","ES":"143454","FI":"143447","FJ":"143583","FM":"143591","FR":"143442","GA":"143614","GB":"143444","GD":"143546","GF":"143615","GH":"143573","GM":"143584","GR":"143448","GT":"143504","GW":"143585","GY":"143553","HK":"143463","HN":"143510","HR":"143494","HU":"143482","ID":"143476","IE":"143449","IL":"143491","IN":"143467","IQ":"143617","IS":"143558","IT":"143450","JM":"143511","JO":"143528","JP":"143462","KE":"143529","KG":"143586","KH":"143579","KN":"143548","KP":"143466","KR":"143466","KW":"143493","KY":"143544","KZ":"143517","TC":"143552","TD":"143581","TJ":"143603","TH":"143475","TM":"143604","TN":"143536","TO":"143608","TR":"143480","TT":"143551","TW":"143470","TZ":"143572","LA":"143587","LB":"143497","LC":"143549","LI":"143522","LK":"143486","LR":"143588","LT":"143520","LU":"143451","LV":"143519","LY":"143567","MA":"143620","MD":"143523","ME":"143619","MG":"143531","MK":"143530","ML":"143532","MM":"143570","MN":"143592","MO":"143515","MR":"143590","MS":"143547","MT":"143521","MU":"143533","MV":"143488","MW":"143589","MX":"143468","MY":"143473","MZ":"143593","NA":"143594","NE":"143534","NG":"143561","NI":"143512","NL":"143452","NO":"143457","NP":"143484","NR":"143606","NZ":"143461","OM":"143562","PA":"143485","PE":"143507","PG":"143597","PH":"143474","PK":"143477","PL":"143478","PT":"143453","PW":"143595","PY":"143513","QA":"143498","RO":"143487","RS":"143500","RU":"143469","RW":"143621","SA":"143479","SB":"143601","SC":"143599","SE":"143456","SG":"143464","SI":"143499","SK":"143496","SL":"143600","SN":"143535","SR":"143554","ST":"143598","SV":"143506","SZ":"143602","UA":"143492","UG":"143537","US":"143441","UY":"143514","UZ":"143566","VC":"143550","VE":"143502","VG":"143543","VN":"143471","VU":"143609","XK":"143624","YE":"143571","ZA":"143472","ZM":"143622","ZW":"143605"} + } + } +} diff --git a/src/function/setENV.mjs b/src/function/setENV.mjs new file mode 100644 index 0000000..6b05b81 --- /dev/null +++ b/src/function/setENV.mjs @@ -0,0 +1,24 @@ +import getStorage from '../utils/getStorage.mjs' +import { _, log } from "../utils/utils.mjs"; + +/** + * Set Environment Variables + * @author VirgilClyne + * @param {String} name - Persistent Store Key + * @param {Array} platforms - Platform Names + * @param {Object} database - Default DataBase + * @return {Object} { Settings, Caches, Configs } + */ +export default function setENV(name, platforms, database) { + log(`☑️ Set Environment Variables`, ""); + let { Settings, Caches, Configs } = getStorage(name, platforms, database); + /***************** Settings *****************/ + log(`✅ Set Environment Variables, Settings: ${typeof Settings}, Settings内容: ${JSON.stringify(Settings)}`, ""); + /***************** Caches *****************/ + //log(`✅ Set Environment Variables, Caches: ${typeof Caches}, Caches内容: ${JSON.stringify(Caches)}`, ""); + /***************** Configs *****************/ + //Configs.Storefront = new Map(Configs.Storefront); + if (Configs.Locale) Configs.Locale = new Map(Configs.Locale); + if (Configs.i18n) for (let type in Configs.i18n) Configs.i18n[type] = new Map(Configs.i18n[type]); + return { Settings, Caches, Configs }; +}; diff --git a/src/request.debug.js b/src/request.debug.js new file mode 100644 index 0000000..a1e4d90 --- /dev/null +++ b/src/request.debug.js @@ -0,0 +1,302 @@ +import { $platform, URL, _, Storage, fetch, notification, log, logError, wait, done, getScript, runScript } from "./utils/utils.mjs"; +import database from "./function/database.mjs"; +import setENV from "./function/setENV.mjs"; +// 构造回复数据 +let $response = undefined; +/***************** Processing *****************/ +// 解构URL +const url = new URL($request.url); +log(`⚠ url: ${url.toJSON()}`, ""); +// 获取连接参数 +const METHOD = $request.method, HOST = url.hostname, PATH = url.pathname, PATHs = url.paths;; +log(`⚠ METHOD: ${METHOD}, HOST: ${HOST}, PATH: ${PATH}` , ""); +// 解析格式 +const FORMAT = ($request.headers?.["Content-Type"] ?? $request.headers?.["content-type"])?.split(";")?.[0]; +log(`⚠ FORMAT: ${FORMAT}`, ""); +!(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", database); + log(`⚠ Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings.Switch) { + case true: + default: + // 创建空数据 + let body = {}; + // 方法判断 + switch (METHOD) { + case "POST": + case "PUT": + case "PATCH": + case "DELETE": + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + default: + break; + case "application/x-mpegURL": + case "application/x-mpegurl": + case "application/vnd.apple.mpegurl": + case "audio/mpegurl": + //body = M3U8.parse($request.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$request.body = M3U8.stringify(body); + break; + case "text/xml": + case "text/html": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + //body = XML.parse($request.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$request.body = XML.stringify(body); + break; + case "text/vtt": + case "application/vtt": + //body = VTT.parse($request.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$request.body = VTT.stringify(body); + break; + case "text/json": + case "application/json": + body = JSON.parse($request.body ?? "{}"); + log(`🚧 body: ${JSON.stringify(body)}`, ""); + switch (HOST) { + case "testflight.apple.com": + switch (PATH) { + case "/v1/session/authenticate": + /* + if (Settings.storeCookies) { // 使用Cookies + log(`🚧 storeCookies`, ""); + if (Caches?.dsId && Caches?.storeCookies) { // 有 DS ID和iTunes Store Cookie + log(`🚧 有Caches, DS ID和iTunes Store Cookie`, ""); + if (body.dsId !== Caches?.dsId) { // DS ID不相等,覆盖iTunes Store Cookie + log(`🚧 DS ID不相等,覆盖DS ID和iTunes Store Cookie`, ""); + body.dsId = Caches.dsId; + body.deviceModel = Caches.deviceModel; + body.storeCookies = Caches.storeCookies; + body.deviceVendorId = Caches.deviceVendorId; + body.deviceName = Caches.deviceName; + } else Storage.setItem("@iRingo.TestFlight.Caches", { ...Caches, ...body }); // DS ID相等,刷新缓存 + } else Storage.setItem("@iRingo.TestFlight.Caches", { ...Caches, ...body }); // Caches空 + } + */ + if (Settings.CountryCode !== "AUTO") body.storeFrontIdentifier = body.storeFrontIdentifier.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + case "/v1/properties/testflight": + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + switch (PATHs[2]) { + case "settings": + break; + case Caches?.data?.accountId: // UUID + default: + switch (PATHs[3]) { + case "apps": + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/`, ""); + switch (PATHs[4]) { + default: + switch (PATHs[5]) { + case "builds": + switch (PATHs[7]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}`, ""); + break; + case "install": + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}/install`, ""); + if (Settings.CountryCode !== "AUTO") body.storefrontId = body.storefrontId.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}/${PATHs[7]}`, ""); + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + $request.body = JSON.stringify(body); + break; + case "application/protobuf": + case "application/x-protobuf": + case "application/vnd.google.protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + break; + }; + //break; // 不中断,继续处理URL + case "GET": + case "HEAD": + case "OPTIONS": + case undefined: // QX牛逼,script-echo-response不返回method + default: + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "/v1/session/authenticate": + break; + case "v1/properties/testflight": + //$request.headers["X-Apple-Rosetta-Available"] = Settings.Rosetta; + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + // headers auth mod + switch (Settings.MultiAccount) { // MultiAccount + case true: + log(`⚠ 启用多账号支持`, ""); + const IfNoneMatch = $request?.headers?.["If-None-Match"] ?? $request?.headers?.["if-none-match"]; + const XRequestId = $request?.headers?.["X-Request-Id"] ?? $request?.headers?.["x-request-id"]; + const XSessionId = $request?.headers?.["X-Session-Id"] ?? $request?.headers?.["x-session-id"]; + const XSessionDigest = $request?.headers?.["X-Session-Digest"] ?? $request?.headers?.["x-session-digest"]; + if (Caches.data) { // Caches.data存在 + log(`⚠ Caches.data存在,读取`, ""); + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + case "messages": + case "apps": + default: + switch (PATHs[2]) { + case "settings": + case undefined: + default: + switch (/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.test(PATHs[2])) { + case true: // PATHs[2]是UUID + log(`⚠ PATHs[2]是UUID,替换url.pathname`, ""); + url.pathname = PATH.replace(/\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\//i, `/${Caches.data.accountId}/`); + //break; // 不中断,继续处理 + case false: // PATHs[2]不是UUID + if (XSessionId !== Caches.headers["X-Session-Id"]) { // sessionId不同 + log(`⚠ sessionId不同,替换$request.headers`, ""); + if (IfNoneMatch) { + delete $request.headers?.["If-None-Match"]; + delete $request.headers?.["if-none-match"]; + }; + if (XRequestId) { + if ($request.headers?.["X-Request-Id"]) $request.headers["X-Request-Id"] = Caches.headers["X-Request-Id"]; + if ($request.headers?.["x-request-id"]) $request.headers["x-request-id"] = Caches.headers["X-Request-Id"]; + }; + if (XSessionId) { + if ($request.headers?.["X-Session-Id"]) $request.headers["X-Session-Id"] = Caches.headers["X-Session-Id"]; + if ($request.headers?.["x-session-id"]) $request.headers["x-session-id"] = Caches.headers["X-Session-Id"]; + }; + if (XSessionDigest) { + if ($request.headers?.["X-Session-Digest"]) $request.headers["X-Session-Digest"] = Caches.headers["X-Session-Digest"]; + if ($request.headers?.["x-session-digest"]) $request.headers["x-session-digest"] = Caches.headers["X-Session-Digest"]; + }; + }; + }; + break; + case Caches?.data?.accountId: // PATHs[2]有UUID且与accountId相同 + log(`⚠ PATHs[2]与accountId相同,更新Caches`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + break; + }; + break; + case "tc": // termsAndConditions + break; + }; + break; + }; + break; + } else { // Caches空 + log(`⚠ Caches空,新写入`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + if (/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.test(PATHs[2])) { + Caches.data = { + "accountId": PATHs[2], + "sessionId": XSessionId + }; + }; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + }; + break; + case false: + default: + break; + }; + break; + }; + break; + }; + break; + case "CONNECT": + case "TRACE": + break; + }; + $request.url = url.toString(); + log(`🚧 调试信息`, `$request.url: ${$request.url}`, ""); + break; + case false: + break; + }; +})() + .catch((e) => logError(e)) + .finally(() => { + switch ($response) { + default: // 有构造回复数据,返回构造的回复数据 + //log(`🚧 finally`, `echo $response: ${JSON.stringify($response, null, 2)}`, ""); + if ($response.headers?.["Content-Encoding"]) $response.headers["Content-Encoding"] = "identity"; + if ($response.headers?.["content-encoding"]) $response.headers["content-encoding"] = "identity"; + switch ($platform) { + default: + done({ response: $response }); + break; + case "Quantumult X": + if (!$response.status) $response.status = "HTTP/1.1 200 OK"; + delete $response.headers?.["Content-Length"]; + delete $response.headers?.["content-length"]; + delete $response.headers?.["Transfer-Encoding"]; + done($response); + break; + }; + break; + case undefined: // 无构造回复数据,发送修改的请求数据 + //log(`🚧 finally`, `$request: ${JSON.stringify($request, null, 2)}`, ""); + done($request); + break; + }; + }) diff --git a/src/request.js b/src/request.js new file mode 100644 index 0000000..73d9410 --- /dev/null +++ b/src/request.js @@ -0,0 +1,270 @@ +import { $platform, URL, _, Storage, fetch, notification, log, logError, wait, done, getScript, runScript } from "./utils/utils.mjs"; +import database from "./function/database.mjs"; +import setENV from "./function/setENV.mjs"; +// 构造回复数据 +let $response = undefined; +/***************** Processing *****************/ +// 解构URL +const url = new URL($request.url); +log(`⚠ url: ${url.toJSON()}`, ""); +// 获取连接参数 +const METHOD = $request.method, HOST = url.hostname, PATH = url.pathname, PATHs = url.paths;; +log(`⚠ METHOD: ${METHOD}, HOST: ${HOST}, PATH: ${PATH}` , ""); +// 解析格式 +const FORMAT = ($request.headers?.["Content-Type"] ?? $request.headers?.["content-type"])?.split(";")?.[0]; +log(`⚠ FORMAT: ${FORMAT}`, ""); +!(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", database); + log(`⚠ Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings.Switch) { + case true: + default: + // 创建空数据 + let body = {}; + // 方法判断 + switch (METHOD) { + case "POST": + case "PUT": + case "PATCH": + case "DELETE": + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + default: + break; + case "application/x-mpegURL": + case "application/x-mpegurl": + case "application/vnd.apple.mpegurl": + case "audio/mpegurl": + break; + case "text/xml": + case "text/html": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + break; + case "text/vtt": + case "application/vtt": + break; + case "text/json": + case "application/json": + body = JSON.parse($request.body ?? "{}"); + switch (HOST) { + case "testflight.apple.com": + switch (PATH) { + case "/v1/session/authenticate": + if (Settings.CountryCode !== "AUTO") body.storeFrontIdentifier = body.storeFrontIdentifier.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + case "/v1/properties/testflight": + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + switch (PATHs[2]) { + case "settings": + break; + case Caches?.data?.accountId: // UUID + default: + switch (PATHs[3]) { + case "apps": + switch (PATHs[4]) { + default: + switch (PATHs[5]) { + case "builds": + switch (PATHs[7]) { + case undefined: + break; + case "install": + if (Settings.CountryCode !== "AUTO") body.storefrontId = body.storefrontId.replace(/\d{6}/, Configs.Storefront.get(Settings.CountryCode)); + break; + default: + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + $request.body = JSON.stringify(body); + break; + case "application/protobuf": + case "application/x-protobuf": + case "application/vnd.google.protobuf": + case "application/grpc": + case "application/grpc+proto": + case "applecation/octet-stream": + break; + }; + //break; // 不中断,继续处理URL + case "GET": + case "HEAD": + case "OPTIONS": + case undefined: // QX牛逼,script-echo-response不返回method + default: + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "/v1/session/authenticate": + break; + case "v1/properties/testflight": + //$request.headers["X-Apple-Rosetta-Available"] = Settings.Rosetta; + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + // headers auth mod + switch (Settings.MultiAccount) { // MultiAccount + case true: + log(`⚠ 启用多账号支持`, ""); + const IfNoneMatch = $request?.headers?.["If-None-Match"] ?? $request?.headers?.["if-none-match"]; + const XRequestId = $request?.headers?.["X-Request-Id"] ?? $request?.headers?.["x-request-id"]; + const XSessionId = $request?.headers?.["X-Session-Id"] ?? $request?.headers?.["x-session-id"]; + const XSessionDigest = $request?.headers?.["X-Session-Digest"] ?? $request?.headers?.["x-session-digest"]; + if (Caches.data) { // Caches.data存在 + log(`⚠ Caches.data存在,读取`, ""); + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + case "messages": + case "apps": + default: + switch (PATHs[2]) { + case "settings": + case undefined: + default: + switch (/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.test(PATHs[2])) { + case true: // PATHs[2]是UUID + log(`⚠ PATHs[2]是UUID,替换url.pathname`, ""); + url.pathname = PATH.replace(/\/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}\//i, `/${Caches.data.accountId}/`); + //break; // 不中断,继续处理 + case false: // PATHs[2]不是UUID + if (XSessionId !== Caches.headers["X-Session-Id"]) { // sessionId不同 + log(`⚠ sessionId不同,替换$request.headers`, ""); + if (IfNoneMatch) { + delete $request.headers?.["If-None-Match"]; + delete $request.headers?.["if-none-match"]; + }; + if (XRequestId) { + if ($request.headers?.["X-Request-Id"]) $request.headers["X-Request-Id"] = Caches.headers["X-Request-Id"]; + if ($request.headers?.["x-request-id"]) $request.headers["x-request-id"] = Caches.headers["X-Request-Id"]; + }; + if (XSessionId) { + if ($request.headers?.["X-Session-Id"]) $request.headers["X-Session-Id"] = Caches.headers["X-Session-Id"]; + if ($request.headers?.["x-session-id"]) $request.headers["x-session-id"] = Caches.headers["X-Session-Id"]; + }; + if (XSessionDigest) { + if ($request.headers?.["X-Session-Digest"]) $request.headers["X-Session-Digest"] = Caches.headers["X-Session-Digest"]; + if ($request.headers?.["x-session-digest"]) $request.headers["x-session-digest"] = Caches.headers["X-Session-Digest"]; + }; + }; + }; + break; + case Caches?.data?.accountId: // PATHs[2]有UUID且与accountId相同 + log(`⚠ PATHs[2]与accountId相同,更新Caches`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + break; + }; + break; + case "tc": // termsAndConditions + break; + }; + break; + }; + break; + } else { // Caches空 + log(`⚠ Caches空,新写入`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + if (/[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}/.test(PATHs[2])) { + Caches.data = { + "accountId": PATHs[2], + "sessionId": XSessionId + }; + }; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + }; + break; + case false: + default: + break; + }; + break; + }; + break; + }; + break; + case "CONNECT": + case "TRACE": + break; + }; + $request.url = url.toString(); + log(`🚧 调试信息`, `$request.url: ${$request.url}`, ""); + break; + case false: + break; + }; +})() + .catch((e) => logError(e)) + .finally(() => { + switch ($response) { + default: // 有构造回复数据,返回构造的回复数据 + if ($response.headers?.["Content-Encoding"]) $response.headers["Content-Encoding"] = "identity"; + if ($response.headers?.["content-encoding"]) $response.headers["content-encoding"] = "identity"; + switch ($platform) { + default: + done({ response: $response }); + break; + case "Quantumult X": + if (!$response.status) $response.status = "HTTP/1.1 200 OK"; + delete $response.headers?.["Content-Length"]; + delete $response.headers?.["content-length"]; + delete $response.headers?.["Transfer-Encoding"]; + done($response); + break; + }; + break; + case undefined: // 无构造回复数据,发送修改的请求数据 + done($request); + break; + }; + }) diff --git a/src/response.debug.js b/src/response.debug.js new file mode 100644 index 0000000..2903597 --- /dev/null +++ b/src/response.debug.js @@ -0,0 +1,424 @@ +import { $platform, URL, _, Storage, fetch, notification, log, logError, wait, done, getScript, runScript } from "./utils/utils.mjs"; +import database from "./function/database.mjs"; +import setENV from "./function/setENV.mjs"; +/***************** Processing *****************/ +// 解构URL +const url = new URL($request.url); +log(`⚠ url: ${url.toJSON()}`, ""); +// 获取连接参数 +const METHOD = $request.method, HOST = url.hostname, PATH = url.pathname, PATHs = url.paths; +log(`⚠ METHOD: ${METHOD}, HOST: ${HOST}, PATH: ${PATH}` , ""); +// 解析格式 +const FORMAT = ($response.headers?.["Content-Type"] ?? $response.headers?.["content-type"])?.split(";")?.[0]; +log(`⚠ FORMAT: ${FORMAT}`, ""); +!(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", database); + log(`⚠ Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings.Switch) { + case true: + default: + // 创建空数据 + let body = {}; + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + default: + break; + case "application/x-mpegURL": + case "application/x-mpegurl": + case "application/vnd.apple.mpegurl": + case "audio/mpegurl": + //body = M3U8.parse($response.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$response.body = M3U8.stringify(body); + break; + case "text/xml": + case "text/html": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + //body = XML.parse($response.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$response.body = XML.stringify(body); + break; + case "text/vtt": + case "application/vtt": + //body = VTT.parse($response.body); + //log(`🚧 body: ${JSON.stringify(body)}`, ""); + //$response.body = VTT.stringify(body); + break; + case "text/json": + case "application/json": + body = JSON.parse($response.body ?? "{}"); + log(`🚧 body: ${JSON.stringify(body)}`, ""); + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "/v1/session/authenticate": + switch (Settings.MultiAccount) { // MultiAccount + case true: + log(`⚠ 启用多账号支持`, ""); + const XRequestId = $request?.headers?.["X-Request-Id"] ?? $request?.headers?.["x-request-id"]; + const XSessionId = $request?.headers?.["X-Session-Id"] ?? $request?.headers?.["x-session-id"]; + const XSessionDigest = $request?.headers?.["X-Session-Digest"] ?? $request?.headers?.["x-session-digest"]; + if (Caches?.data) { //有data + log(`⚠ 有Caches.data`, ""); + if (body?.data?.accountId === Caches?.data?.accountId) { // Account ID相等,刷新缓存 + log(`⚠ Account ID相等,刷新缓存`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Caches.data = body.data; + Caches.data.termsAndConditions = null; + Caches.data.hasNewTermsAndConditions = false; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + } + /* + else { // Account ID不相等,覆盖 + log(`⚠ Account ID不相等,覆盖data(accountId和sessionId)`, ""); + body.data = Caches.data; + } + */ + } else { // Caches空 + log(`⚠ Caches空,写入`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Caches.data = body.data; + Caches.data.termsAndConditions = null; + Caches.data.hasNewTermsAndConditions = false; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + }; + break; + case false: + default: + break; + }; + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + switch (PATHs[2]) { + case "settings": + switch (PATHs[3]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/settings`, ""); + break; + case "notifications": + switch (PATHs[4]) { + case "apps": + log(`🚧 /${PATHs[0]}/accounts/settings/notifications/apps/`, ""); + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/settings/${PATHs[3]}/`, ""); + break; + }; + break; + case Caches?.data?.accountId: // UUID + default: + switch (PATHs[3]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}`, ""); + break; + case "apps": + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/`, ""); + switch (PATHs[4]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps`, ""); + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + body.data = body.data.map(app => { + if (app.previouslyTested !== false) { // 不是前测试人员 + log(`🚧 不是前测试人员`, ""); + app.platforms = app.platforms.map(platform => { + platform.build = modBuild(platform.build); + return platform + }); + } + return app + }); + }; + break; + case false: + default: + break; + }; + break; + default: + switch (PATHs[5]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}`, ""); + break; + case "builds": + switch (PATHs[7]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}`, ""); + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + // 当前Bulid + body.data.currentBuild = modBuild(body.data.currentBuild); + // Build列表 + body.data.builds = body.data.builds.map(build => modBuild(build)); + }; + break; + case false: + default: + break; + }; + break; + case "install": + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}/install`, ""); + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/builds/${PATHs[6]}/${PATHs[7]}`, ""); + break; + }; + break; + case "platforms": + switch (PATHs[6]) { + case "ios": + case "osx": + case "appletvos": + default: + switch (PATHs[7]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}`, ""); + break; + case "trains": + switch (PATHs[9]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}/trains/${PATHs[8]}`, ""); + break; + case "builds": + switch (PATHs[10]) { + case undefined: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}/trains/${PATHs[8]}/builds`, ""); + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + // 当前Bulid + body.data = body.data.map(data => modBuild(data)); + }; + break; + case false: + default: + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}/trains/${PATHs[8]}/builds/${PATHs[10]}`, ""); + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}/trains/${PATHs[8]}/${PATHs[9]}`, ""); + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/platforms/${PATHs[6]}/${PATHs[7]}`, ""); + break; + }; + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/apps/${PATHs[4]}/${PATHs[5]}`, ""); + break; + }; + break; + }; + break; + default: + log(`🚧 /${PATHs[0]}/accounts/${PATHs[2]}/${PATHs[3]}/`, ""); + break; + }; + break; + }; + break; + case "apps": + switch (PATHs[3]) { + case "install": + switch (PATHs[4]) { + case undefined: + log(`🚧 /${PATHs[0]}/apps/install`, ""); + break; + case "status": + log(`🚧 /${PATHs[0]}/apps/install/status`, ""); + break; + default: + log(`🚧 /${PATHs[0]}/apps/install/${PATHs[4]}`, ""); + break; + }; + break; + }; + break; + case "messages": + switch (PATHs[2]) { + case Caches?.data?.accountId: // UUID + default: + log(`🚧 /${PATHs[0]}/messages/${PATHs[2]}`, ""); + switch (PATHs[3]) { + case undefined: + log(`🚧 /${PATHs[0]}/messages/${PATHs[2]}`, ""); + break; + case "read": + log(`🚧 /${PATHs[0]}/messages/${PATHs[2]}/read`, ""); + break; + default: + log(`🚧 /${PATHs[0]}/messages/${PATHs[2]}/${PATHs[3]}`, ""); + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + $response.body = JSON.stringify(body); + break; + case "application/protobuf": + case "application/x-protobuf": + case "application/vnd.google.protobuf": + case "application/grpc": + case "application/grpc+proto": + case "application/octet-stream": + break; + }; + break; + case false: + break; + }; +})() + .catch((e) => logError(e)) + .finally(() => done($response)) + +/***************** Function *****************/ +/** + * mod Build + * @author VirgilClyne + * @param {Object} build - Build + * @return {Object} + */ +function modBuild(build) { + switch (build.platform || build.name) { + case "ios": + log(`🚧 ios`, ""); + build = Build(build); + break; + case "osx": + log(`🚧 osx`, ""); + if (build?.macBuildCompatibility?.runsOnAppleSilicon === true) { // 是苹果芯片 + log(`🚧 runsOnAppleSilicon`, ""); + build = Build(build); + }; + break; + case "appletvos": + log(`🚧 appletvos`, ""); + break; + default: + log(`🚧 unknown platform: ${build.platform || build.name}`, ""); + break; + }; + return build + + function Build(build) { + //if (build.universal === true) { + build.compatible = true; + build.platformCompatible = true; + build.hardwareCompatible = true; + build.osCompatible = true; + if (build?.permission) build.permission = "install"; + if (build?.deviceFamilyInfo) { + build.deviceFamilyInfo = [ + { + "number": 1, + "name": "iOS", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_1.png" + }, + { + "number": 2, + "name": "iPad", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_2.png" + }, + { + "number": 3, + "name": "Apple TV", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_3.png" + } + ]; + }; + if (build?.compatibilityData?.compatibleDeviceFamilies) { + build.compatibilityData.compatibleDeviceFamilies = [ + { + "name": "iPad", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPhone", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPod", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "Mac", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + } + ]; + }; + if (build.macBuildCompatibility) { + build.macBuildCompatibility.runsOnIntel = true; + build.macBuildCompatibility.runsOnAppleSilicon = true; + /* + build.macBuildCompatibility = { + "macArchitectures": ["AppleSilicon", "Intel"], + "rosettaCompatible": true, + "runsOnIntel": true, + "runsOnAppleSilicon": true, + "requiresRosetta": false + }; + */ + }; + //}; + return build + }; +}; diff --git a/src/response.js b/src/response.js new file mode 100644 index 0000000..e35c8f3 --- /dev/null +++ b/src/response.js @@ -0,0 +1,383 @@ +import { $platform, URL, _, Storage, fetch, notification, log, logError, wait, done, getScript, runScript } from "./utils/utils.mjs"; +import database from "./function/database.mjs"; +import setENV from "./function/setENV.mjs"; +/***************** Processing *****************/ +// 解构URL +const url = new URL($request.url); +log(`⚠ url: ${url.toJSON()}`, ""); +// 获取连接参数 +const METHOD = $request.method, HOST = url.hostname, PATH = url.pathname, PATHs = url.paths; +log(`⚠ METHOD: ${METHOD}, HOST: ${HOST}, PATH: ${PATH}` , ""); +// 解析格式 +const FORMAT = ($response.headers?.["Content-Type"] ?? $response.headers?.["content-type"])?.split(";")?.[0]; +log(`⚠ FORMAT: ${FORMAT}`, ""); +!(async () => { + const { Settings, Caches, Configs } = setENV("iRingo", "TestFlight", database); + log(`⚠ Settings.Switch: ${Settings?.Switch}`, ""); + switch (Settings.Switch) { + case true: + default: + // 创建空数据 + let body = {}; + // 格式判断 + switch (FORMAT) { + case undefined: // 视为无body + break; + case "application/x-www-form-urlencoded": + case "text/plain": + default: + break; + case "application/x-mpegURL": + case "application/x-mpegurl": + case "application/vnd.apple.mpegurl": + case "audio/mpegurl": + break; + case "text/xml": + case "text/html": + case "text/plist": + case "application/xml": + case "application/plist": + case "application/x-plist": + break; + case "text/vtt": + case "application/vtt": + break; + case "text/json": + case "application/json": + body = JSON.parse($response.body ?? "{}"); + // 主机判断 + switch (HOST) { + case "testflight.apple.com": + // 路径判断 + switch (PATH) { + case "/v1/session/authenticate": + switch (Settings.MultiAccount) { // MultiAccount + case true: + log(`⚠ 启用多账号支持`, ""); + const XRequestId = $request?.headers?.["X-Request-Id"] ?? $request?.headers?.["x-request-id"]; + const XSessionId = $request?.headers?.["X-Session-Id"] ?? $request?.headers?.["x-session-id"]; + const XSessionDigest = $request?.headers?.["X-Session-Digest"] ?? $request?.headers?.["x-session-digest"]; + if (Caches?.data) { //有data + log(`⚠ 有Caches.data`, ""); + if (body?.data?.accountId === Caches?.data?.accountId) { // Account ID相等,刷新缓存 + log(`⚠ Account ID相等,刷新缓存`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Caches.data = body.data; + Caches.data.termsAndConditions = null; + Caches.data.hasNewTermsAndConditions = false; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + } + } else { // Caches空 + log(`⚠ Caches空,写入`, ""); + Caches.headers = { + "X-Request-Id": XRequestId, + "X-Session-Id": XSessionId, + "X-Session-Digest": XSessionDigest + }; + Caches.data = body.data; + Caches.data.termsAndConditions = null; + Caches.data.hasNewTermsAndConditions = false; + Storage.setItem("@iRingo.TestFlight.Caches", Caches); + }; + break; + case false: + default: + break; + }; + break; + case "/v1/devices": + case "/v1/devices/apns": + case "/v1/devices/add": + case "/v1/devices/remove": + break; + default: + switch (PATHs[0]) { + case "v1": + case "v2": + case "v3": + switch (PATHs[1]) { + case "accounts": + switch (PATHs[2]) { + case "settings": + switch (PATHs[3]) { + case undefined: + break; + case "notifications": + switch (PATHs[4]) { + case "apps": + break; + }; + break; + default: + break; + }; + break; + case Caches?.data?.accountId: // UUID + default: + switch (PATHs[3]) { + case undefined: + break; + case "apps": + switch (PATHs[4]) { + case undefined: + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + body.data = body.data.map(app => { + if (app.previouslyTested !== false) { // 不是前测试人员 + log(`🚧 不是前测试人员`, ""); + app.platforms = app.platforms.map(platform => { + platform.build = modBuild(platform.build); + return platform + }); + } + return app + }); + }; + break; + case false: + default: + break; + }; + break; + default: + switch (PATHs[5]) { + case undefined: + break; + case "builds": + switch (PATHs[7]) { + case undefined: + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + // 当前Bulid + body.data.currentBuild = modBuild(body.data.currentBuild); + // Build列表 + body.data.builds = body.data.builds.map(build => modBuild(build)); + }; + break; + case false: + default: + break; + }; + break; + case "install": + break; + default: + break; + }; + break; + case "platforms": + switch (PATHs[6]) { + case "ios": + case "osx": + case "appletvos": + default: + switch (PATHs[7]) { + case undefined: + break; + case "trains": + switch (PATHs[9]) { + case undefined: + break; + case "builds": + switch (PATHs[10]) { + case undefined: + switch (Settings.Universal) { // 通用 + case true: + log(`🚧 启用通用应用支持`, ""); + if (body.error === null) { // 数据无错误 + log(`🚧 数据无错误`, ""); + // 当前Bulid + body.data = body.data.map(data => modBuild(data)); + }; + break; + case false: + default: + break; + }; + break; + default: + break; + }; + break; + default: + break; + }; + break; + default: + break; + }; + break; + }; + break; + default: + break; + }; + break; + }; + break; + default: + break; + }; + break; + }; + break; + case "apps": + switch (PATHs[3]) { + case "install": + switch (PATHs[4]) { + case undefined: + break; + case "status": + break; + default: + break; + }; + break; + }; + break; + case "messages": + switch (PATHs[2]) { + case Caches?.data?.accountId: // UUID + default: + switch (PATHs[3]) { + case undefined: + break; + case "read": + break; + default: + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + break; + }; + $response.body = JSON.stringify(body); + break; + case "application/protobuf": + case "application/x-protobuf": + case "application/vnd.google.protobuf": + case "application/grpc": + case "application/grpc+proto": + case "application/octet-stream": + break; + }; + break; + case false: + break; + }; +})() + .catch((e) => logError(e)) + .finally(() => done($response)) + +/***************** Function *****************/ +/** + * mod Build + * @author VirgilClyne + * @param {Object} build - Build + * @return {Object} + */ +function modBuild(build) { + switch (build.platform || build.name) { + case "ios": + log(`🚧 ios`, ""); + build = Build(build); + break; + case "osx": + log(`🚧 osx`, ""); + if (build?.macBuildCompatibility?.runsOnAppleSilicon === true) { // 是苹果芯片 + log(`🚧 runsOnAppleSilicon`, ""); + build = Build(build); + }; + break; + case "appletvos": + log(`🚧 appletvos`, ""); + break; + default: + log(`🚧 unknown platform: ${build.platform || build.name}`, ""); + break; + }; + return build + + function Build(build) { + //if (build.universal === true) { + build.compatible = true; + build.platformCompatible = true; + build.hardwareCompatible = true; + build.osCompatible = true; + if (build?.permission) build.permission = "install"; + if (build?.deviceFamilyInfo) { + build.deviceFamilyInfo = [ + { + "number": 1, + "name": "iOS", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_1.png" + }, + { + "number": 2, + "name": "iPad", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_2.png" + }, + { + "number": 3, + "name": "Apple TV", + "iconUrl": "https://itunesconnect-mr.itunes.apple.com/itc/img/device-icons/device_family_icon_3.png" + } + ]; + }; + if (build?.compatibilityData?.compatibleDeviceFamilies) { + build.compatibilityData.compatibleDeviceFamilies = [ + { + "name": "iPad", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPhone", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "iPod", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + }, + { + "name": "Mac", + "minimumSupportedDevice": null, + "unsupportedDevices": [] + } + ]; + }; + if (build.macBuildCompatibility) { + build.macBuildCompatibility.runsOnIntel = true; + build.macBuildCompatibility.runsOnAppleSilicon = true; + /* + build.macBuildCompatibility = { + "macArchitectures": ["AppleSilicon", "Intel"], + "rosettaCompatible": true, + "runsOnIntel": true, + "runsOnAppleSilicon": true, + "requiresRosetta": false + }; + */ + }; + //}; + return build + }; +}; diff --git a/src/utils b/src/utils new file mode 160000 index 0000000..40e91e8 --- /dev/null +++ b/src/utils @@ -0,0 +1 @@ +Subproject commit 40e91e80011968370ba7ef400ff768dabf5cf583