mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 18:03:55 +01:00
Compare commits
123 Commits
v4.13.0-de
...
v4.17.0-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64680c718b | ||
|
|
007702825b | ||
|
|
596c2b0f8d | ||
|
|
773fd81dfd | ||
|
|
68b61b4725 | ||
|
|
10efb20e35 | ||
|
|
d5a13684f6 | ||
|
|
e2dd1bdaf3 | ||
|
|
98c33f03dd | ||
|
|
d73e5b77df | ||
|
|
2f7e1f601a | ||
|
|
bcdc7a4589 | ||
|
|
0679a47b22 | ||
|
|
5a08620356 | ||
|
|
42ed29b4c0 | ||
|
|
8475cc2b09 | ||
|
|
d76f4c96a4 | ||
|
|
eebe82b2f4 | ||
|
|
59273999e9 | ||
|
|
c3d457d7de | ||
|
|
17dfc161c1 | ||
|
|
e3e1efea33 | ||
|
|
ef8aa22779 | ||
|
|
fb9db0eec4 | ||
|
|
33adf53ef1 | ||
|
|
9131e387b5 | ||
|
|
1928e89085 | ||
|
|
35973c721a | ||
|
|
31b18fec39 | ||
|
|
db15b68dc8 | ||
|
|
82d44f691d | ||
|
|
fee2218303 | ||
|
|
1f0b4cdcb4 | ||
|
|
1fd30c1b44 | ||
|
|
fa94ddd510 | ||
|
|
94cf815e4a | ||
|
|
8a3b0610b4 | ||
|
|
b920355d9c | ||
|
|
8b49012130 | ||
|
|
4c7b018878 | ||
|
|
5ddd957313 | ||
|
|
bb0dcbe83d | ||
|
|
163736fb26 | ||
|
|
0c6db43bde | ||
|
|
317e9a80eb | ||
|
|
464e6a3673 | ||
|
|
2e9142eda4 | ||
|
|
b4c6d0a7d2 | ||
|
|
c0ee85e12a | ||
|
|
2d326072e2 | ||
|
|
586770aa3a | ||
|
|
9f314c2425 | ||
|
|
c8b3456738 | ||
|
|
e8cb6ee028 | ||
|
|
3e796eb7c2 | ||
|
|
303d2de81d | ||
|
|
0ab7344295 | ||
|
|
ff8fe46685 | ||
|
|
a104eeaf68 | ||
|
|
18b09168cc | ||
|
|
f7209f0a53 | ||
|
|
1fb3fc4857 | ||
|
|
e03c14cc01 | ||
|
|
bed29d00dc | ||
|
|
d36982e245 | ||
|
|
13031f0534 | ||
|
|
b5b6ef5d6f | ||
|
|
5b1e07d861 | ||
|
|
e3220cc10a | ||
|
|
02db9378ea | ||
|
|
f83e314dff | ||
|
|
d5e383b78a | ||
|
|
395e18d830 | ||
|
|
887684e7c7 | ||
|
|
2f7d751f9f | ||
|
|
4886a95713 | ||
|
|
58719239cf | ||
|
|
fcb68cc65e | ||
|
|
16217f012e | ||
|
|
d6f20ee67d | ||
|
|
bccd62e593 | ||
|
|
1322403698 | ||
|
|
a64270514f | ||
|
|
f5de555adf | ||
|
|
4c2ec2870c | ||
|
|
a73e2458e9 | ||
|
|
96e6f43ca0 | ||
|
|
f667d5a238 | ||
|
|
ff2c4564a0 | ||
|
|
b568207e49 | ||
|
|
70470a9162 | ||
|
|
9922f47a49 | ||
|
|
ed532eb528 | ||
|
|
74f3f82927 | ||
|
|
6544cd5fc6 | ||
|
|
4e323aa206 | ||
|
|
c1cee281ff | ||
|
|
0779f9fc5e | ||
|
|
0ee5cf98ab | ||
|
|
6bb848b991 | ||
|
|
188b66ffe7 | ||
|
|
a276425d83 | ||
|
|
e556c3f692 | ||
|
|
cb30248eab | ||
|
|
c5ce742ab4 | ||
|
|
bdd2f7cb0f | ||
|
|
b7600f448d | ||
|
|
5c4bf7676d | ||
|
|
fcd2f9b4c4 | ||
|
|
aa3487aa92 | ||
|
|
ada642f4a7 | ||
|
|
eac758588a | ||
|
|
5d047eae77 | ||
|
|
ed92bf1be6 | ||
|
|
c6318e890f | ||
|
|
7f3b1c54da | ||
|
|
3d0d94b6c8 | ||
|
|
b84e6afebd | ||
|
|
3eab130276 | ||
|
|
95f8e9b3a9 | ||
|
|
d7be94a193 | ||
|
|
e4e20bec6c | ||
|
|
b8bd63a34c |
5
.github/workflows/open_pull_request.yml
vendored
5
.github/workflows/open_pull_request.yml
vendored
@@ -25,7 +25,8 @@ jobs:
|
||||
pr_body: |
|
||||
This pull request will ${{ env.MESSAGE }}.
|
||||
|
||||
## Dependencies before merge
|
||||
## Before merging this PR
|
||||
|
||||
- [ ] https://github.com/revanced/revanced-integrations
|
||||
- [ ] Remember about https://github.com/revanced/revanced-integrations
|
||||
- [ ] Pull translations from Crowdin
|
||||
pr_draft: true
|
||||
|
||||
4
.github/workflows/pull_strings.yml
vendored
4
.github/workflows/pull_strings.yml
vendored
@@ -8,6 +8,8 @@ on:
|
||||
jobs:
|
||||
pull:
|
||||
name: Pull strings
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -30,6 +32,6 @@ jobs:
|
||||
github_user_name: revanced-bot
|
||||
github_user_email: github@revanced.app
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
|
||||
1
.github/workflows/push_strings.yml
vendored
1
.github/workflows/push_strings.yml
vendored
@@ -24,6 +24,5 @@ jobs:
|
||||
config: crowdin.yml
|
||||
upload_sources: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
|
||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -46,5 +49,5 @@ jobs:
|
||||
|
||||
- name: Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npm exec semantic-release
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"README.md",
|
||||
"CHANGELOG.md",
|
||||
"gradle.properties",
|
||||
"patches.json"
|
||||
]
|
||||
],
|
||||
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
||||
397
CHANGELOG.md
397
CHANGELOG.md
@@ -1,3 +1,400 @@
|
||||
# [4.17.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.7...v4.17.0-dev.8) (2024-10-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Twitter:** Add `Change link sharing domain` patch ([#3753](https://github.com/ReVanced/revanced-patches/issues/3753)) ([9269a07](https://github.com/ReVanced/revanced-patches/commit/9269a076b674ecdcf478bca842238f6e30869f44))
|
||||
|
||||
# [4.17.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.6...v4.17.0-dev.7) (2024-10-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitter - Unlock downloads:** Make it work with latest versions ([#3782](https://github.com/ReVanced/revanced-patches/issues/3782)) ([5189122](https://github.com/ReVanced/revanced-patches/commit/5189122006b0f72d5bfb50422021c3b0f3a9ae4a))
|
||||
* **YouTube - Spoof video streams:** Fix playback for Android VR by removing invalid body as well ([#3769](https://github.com/ReVanced/revanced-patches/issues/3769)) ([5150a15](https://github.com/ReVanced/revanced-patches/commit/5150a15ad4ca73a747f0a89f933db7f2d686ec2d))
|
||||
|
||||
# [4.17.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.5...v4.17.0-dev.6) (2024-10-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add option to hide `Use template`, `Upcoming`, `Green screen` buttons ([#3752](https://github.com/ReVanced/revanced-patches/issues/3752)) ([f71c406](https://github.com/ReVanced/revanced-patches/commit/f71c4068bc646d02954b59fac4756f1419c55dbe))
|
||||
|
||||
# [4.17.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.4...v4.17.0-dev.5) (2024-10-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Backdrops - Pro unlock:** Support latest versions by removing version constraint ([a62b506](https://github.com/ReVanced/revanced-patches/commit/a62b50691c49d1ce529a7c9c4e49da0d0dd46df2))
|
||||
|
||||
# [4.17.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.3...v4.17.0-dev.4) (2024-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide layout components:** Adjust settings text ([#3745](https://github.com/ReVanced/revanced-patches/issues/3745)) ([13998bb](https://github.com/ReVanced/revanced-patches/commit/13998bbf95ac3cde8bf24754d60258d0ff9bc4f4))
|
||||
|
||||
# [4.17.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.2...v4.17.0-dev.3) (2024-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide layout components:** Add option to hide Yoodles (YouTube Doodles) ([#3743](https://github.com/ReVanced/revanced-patches/issues/3743)) ([b8c8916](https://github.com/ReVanced/revanced-patches/commit/b8c89164cf3911ac3842df9b0d2ec42b52213505))
|
||||
|
||||
# [4.17.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.17.0-dev.1...v4.17.0-dev.2) (2024-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Willhaben:** Add `Hide ads` patch ([#3740](https://github.com/ReVanced/revanced-patches/issues/3740)) ([1fe3a52](https://github.com/ReVanced/revanced-patches/commit/1fe3a523e99ccfe556d88800686e34ac6ed77b2c))
|
||||
|
||||
# [4.17.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.16.1-dev.1...v4.17.0-dev.1) (2024-10-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add option to hide like fountain ([#3731](https://github.com/ReVanced/revanced-patches/issues/3731)) ([00a99dd](https://github.com/ReVanced/revanced-patches/commit/00a99dd13be6e5c44fa691d74c92b23ce6ba659d))
|
||||
|
||||
## [4.16.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.16.0...v4.16.1-dev.1) (2024-10-01)
|
||||
|
||||
# [4.16.0](https://github.com/ReVanced/revanced-patches/compare/v4.15.0...v4.16.0) (2024-09-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Soundcloud:** Support latest versions ([#3702](https://github.com/ReVanced/revanced-patches/issues/3702)) ([099ac5e](https://github.com/ReVanced/revanced-patches/commit/099ac5ea2cf55633a7c6a7e6f8e963599bcd5784))
|
||||
* **Twitter - Open links with app chooser:** Fix incorrect version in compatibility list ([#3683](https://github.com/ReVanced/revanced-patches/issues/3683)) ([adafe85](https://github.com/ReVanced/revanced-patches/commit/adafe85d77f6a0031a5523b9b7da69475959d78d))
|
||||
* **YouTube - SponsorBlock:** Fade out SB buttons without overlapping other buttons ([#3719](https://github.com/ReVanced/revanced-patches/issues/3719)) ([bf96108](https://github.com/ReVanced/revanced-patches/commit/bf9610894f0a9f9e751e2eed5b825c5d327a722c))
|
||||
* **YouTube:** Show video chapter titles without clipping when overlay buttons are enabled ([#3674](https://github.com/ReVanced/revanced-patches/issues/3674)) ([4b88c31](https://github.com/ReVanced/revanced-patches/commit/4b88c316ed90c56e83e2aee266561833b36fc37d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Google Photos:** Restore hidden 'Back up while charging' toggle ([#3678](https://github.com/ReVanced/revanced-patches/issues/3678)) ([f9e19ce](https://github.com/ReVanced/revanced-patches/commit/f9e19ce6e9185fdf31b2b0d5f2934f6e8a544b8e))
|
||||
* **YouTube - Disable precise seeking gesture:** Hide "pull up" label that shows up when swiping ([#3668](https://github.com/ReVanced/revanced-patches/issues/3668)) ([3fa8af9](https://github.com/ReVanced/revanced-patches/commit/3fa8af9fe534b59ad093c36f1927f56f549a330d))
|
||||
* **YouTube - Hide Shorts components:** Add `Hide save music`, `Hide stickers` ([#3710](https://github.com/ReVanced/revanced-patches/issues/3710)) ([8c99321](https://github.com/ReVanced/revanced-patches/commit/8c99321df4db696156330fc90dd547c1345d880e))
|
||||
* **YouTube - Hide Shorts components:** Add patch option to hide Shorts app shortcut (long press app icon) ([#3699](https://github.com/ReVanced/revanced-patches/issues/3699)) ([0d4e1f5](https://github.com/ReVanced/revanced-patches/commit/0d4e1f5d03cf3dcc06fd41165e26a1ce901b976b))
|
||||
* **YouTube - Hide Shorts components:** Add patch option to hide Shorts from app launcher widget Beta ([#3707](https://github.com/ReVanced/revanced-patches/issues/3707)) ([838f183](https://github.com/ReVanced/revanced-patches/commit/838f1834a5df547ce2c3217b874c0594b6878a67))
|
||||
|
||||
# [4.16.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.6...v4.16.0-dev.7) (2024-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Fade out SB buttons without overlapping other buttons ([#3719](https://github.com/ReVanced/revanced-patches/issues/3719)) ([bf96108](https://github.com/ReVanced/revanced-patches/commit/bf9610894f0a9f9e751e2eed5b825c5d327a722c))
|
||||
|
||||
# [4.16.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.5...v4.16.0-dev.6) (2024-09-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add `Hide save music`, `Hide stickers` ([#3710](https://github.com/ReVanced/revanced-patches/issues/3710)) ([8c99321](https://github.com/ReVanced/revanced-patches/commit/8c99321df4db696156330fc90dd547c1345d880e))
|
||||
|
||||
# [4.16.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.4...v4.16.0-dev.5) (2024-09-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Disable precise seeking gesture:** Hide "pull up" label that shows up when swiping ([#3668](https://github.com/ReVanced/revanced-patches/issues/3668)) ([3fa8af9](https://github.com/ReVanced/revanced-patches/commit/3fa8af9fe534b59ad093c36f1927f56f549a330d))
|
||||
|
||||
# [4.16.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.3...v4.16.0-dev.4) (2024-09-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Soundcloud:** Support latest versions ([#3702](https://github.com/ReVanced/revanced-patches/issues/3702)) ([099ac5e](https://github.com/ReVanced/revanced-patches/commit/099ac5ea2cf55633a7c6a7e6f8e963599bcd5784))
|
||||
|
||||
# [4.16.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.2...v4.16.0-dev.3) (2024-09-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Google Photos:** Restore hidden 'Back up while charging' toggle ([#3678](https://github.com/ReVanced/revanced-patches/issues/3678)) ([f9e19ce](https://github.com/ReVanced/revanced-patches/commit/f9e19ce6e9185fdf31b2b0d5f2934f6e8a544b8e))
|
||||
|
||||
# [4.16.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.16.0-dev.1...v4.16.0-dev.2) (2024-09-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add patch option to hide Shorts from app launcher widget Beta ([#3707](https://github.com/ReVanced/revanced-patches/issues/3707)) ([838f183](https://github.com/ReVanced/revanced-patches/commit/838f1834a5df547ce2c3217b874c0594b6878a67))
|
||||
|
||||
# [4.16.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.15.1-dev.2...v4.16.0-dev.1) (2024-09-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Add patch option to hide Shorts app shortcut (long press app icon) ([#3699](https://github.com/ReVanced/revanced-patches/issues/3699)) ([0d4e1f5](https://github.com/ReVanced/revanced-patches/commit/0d4e1f5d03cf3dcc06fd41165e26a1ce901b976b))
|
||||
|
||||
## [4.15.1-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.15.1-dev.1...v4.15.1-dev.2) (2024-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Show video chapter titles without clipping when overlay buttons are enabled ([#3674](https://github.com/ReVanced/revanced-patches/issues/3674)) ([4b88c31](https://github.com/ReVanced/revanced-patches/commit/4b88c316ed90c56e83e2aee266561833b36fc37d))
|
||||
|
||||
## [4.15.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.15.0...v4.15.1-dev.1) (2024-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Twitter - Open links with app chooser:** Fix incorrect version in compatibility list ([#3683](https://github.com/ReVanced/revanced-patches/issues/3683)) ([adafe85](https://github.com/ReVanced/revanced-patches/commit/adafe85d77f6a0031a5523b9b7da69475959d78d))
|
||||
|
||||
# [4.15.0](https://github.com/ReVanced/revanced-patches/compare/v4.14.1...v4.15.0) (2024-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok - Playback speed:** Prevent crash by fixing invalid patch ([82d53cb](https://github.com/ReVanced/revanced-patches/commit/82d53cbc3bbfa585ba4337fdfaec9f0f19c802e6))
|
||||
* **TikTok - Settings:** Prevent crash by fixing invalid patch ([8074032](https://github.com/ReVanced/revanced-patches/commit/8074032fad3eff1c03296a882d2e2820da99b592))
|
||||
* **Twitter - Open links with app chooser:** Constrain patch to last working version `10.48.0-release` ([b9955d5](https://github.com/ReVanced/revanced-patches/commit/b9955d5ff6e456593b01f0f25d80ff660d02082a))
|
||||
* **YouTube - Spoof video streams:** Change default client type to Android VR ([74c8637](https://github.com/ReVanced/revanced-patches/commit/74c8637943347078955f51325bc6af92a35d4463))
|
||||
* **YouTube - Spoof video streams:** Change default client type to Android VR ([#3672](https://github.com/ReVanced/revanced-patches/issues/3672)) ([a3306f6](https://github.com/ReVanced/revanced-patches/commit/a3306f6717a09b734354f00363a96abad0ae14e7))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok:** Bump patches to support the latest version 36.5.4 ([e5dcb72](https://github.com/ReVanced/revanced-patches/commit/e5dcb72597092fb32003f11fdf6f861ede4e7ff3))
|
||||
|
||||
# [4.15.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.2-dev.2...v4.15.0-dev.1) (2024-09-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **TikTok:** Bump patches to support the latest version 36.5.4 ([e5dcb72](https://github.com/ReVanced/revanced-patches/commit/e5dcb72597092fb32003f11fdf6f861ede4e7ff3))
|
||||
|
||||
## [4.14.2-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.14.2-dev.1...v4.14.2-dev.2) (2024-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof video streams:** Change default client type to Android VR ([74c8637](https://github.com/ReVanced/revanced-patches/commit/74c8637943347078955f51325bc6af92a35d4463))
|
||||
* **YouTube - Spoof video streams:** Change default client type to Android VR ([#3672](https://github.com/ReVanced/revanced-patches/issues/3672)) ([a3306f6](https://github.com/ReVanced/revanced-patches/commit/a3306f6717a09b734354f00363a96abad0ae14e7))
|
||||
|
||||
## [4.14.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.1...v4.14.2-dev.1) (2024-09-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **TikTok - Playback speed:** Prevent crash by fixing invalid patch ([82d53cb](https://github.com/ReVanced/revanced-patches/commit/82d53cbc3bbfa585ba4337fdfaec9f0f19c802e6))
|
||||
* **TikTok - Settings:** Prevent crash by fixing invalid patch ([8074032](https://github.com/ReVanced/revanced-patches/commit/8074032fad3eff1c03296a882d2e2820da99b592))
|
||||
* **Twitter - Open links with app chooser:** Constrain patch to last working version `10.48.0-release` ([b9955d5](https://github.com/ReVanced/revanced-patches/commit/b9955d5ff6e456593b01f0f25d80ff660d02082a))
|
||||
|
||||
## [4.14.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1) (2024-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([4413533](https://github.com/ReVanced/revanced-patches/commit/441353306572340131030e1c4fee1ab6acb63cd9))
|
||||
|
||||
## [4.14.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.14.0...v4.14.1-dev.1) (2024-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Check environment:** Only use fields available since Android 8 ([#3655](https://github.com/ReVanced/revanced-patches/issues/3655)) ([4413533](https://github.com/ReVanced/revanced-patches/commit/441353306572340131030e1c4fee1ab6acb63cd9))
|
||||
|
||||
# [4.14.0](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.14.0) (2024-09-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([98956e8](https://github.com/ReVanced/revanced-patches/commit/98956e8f1a41347bb435720bbf984969469a7110))
|
||||
* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([66e7e33](https://github.com/ReVanced/revanced-patches/commit/66e7e33efce9b702fdfcc2b9803e9da8491c1f08))
|
||||
* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([0f5a771](https://github.com/ReVanced/revanced-patches/commit/0f5a771a5cff5684b4a8fd317f4938fe2cf3cbbe))
|
||||
* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([005be82](https://github.com/ReVanced/revanced-patches/commit/005be82d71b2a42387b1b57035930b20f4663794))
|
||||
* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([df80b9f](https://github.com/ReVanced/revanced-patches/commit/df80b9f92f0d981b9a40b7756d74f8ccc3dcb1e9))
|
||||
* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([37b3dd1](https://github.com/ReVanced/revanced-patches/commit/37b3dd1e789f8bb16fa1b9dd582e39c89dbe730c))
|
||||
* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([dfa94d7](https://github.com/ReVanced/revanced-patches/commit/dfa94d70f65150d6ef24ea6378b8e6a317055186))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([5998029](https://github.com/ReVanced/revanced-patches/commit/59980292809cc0626bf49a160eeb05a1523c4eda))
|
||||
* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([fbcbdaf](https://github.com/ReVanced/revanced-patches/commit/fbcbdafa4938a35b5fdec46aae7b250a84b9c139))
|
||||
* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([d0a8599](https://github.com/ReVanced/revanced-patches/commit/d0a8599f76ce653e5d7c98069ad3c58b9ab9c5eb))
|
||||
* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([46d11f3](https://github.com/ReVanced/revanced-patches/commit/46d11f3530fcdae9ed08b7e93aac235638a92dff))
|
||||
* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([98ead49](https://github.com/ReVanced/revanced-patches/commit/98ead493380932cb105530f4ba992673fd364d82))
|
||||
* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([33fc090](https://github.com/ReVanced/revanced-patches/commit/33fc09061431d4aa457d743c09a0de31ec566df1))
|
||||
* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([f5fb351](https://github.com/ReVanced/revanced-patches/commit/f5fb3512cfafe214ba6a6d25ba0825ae1884a0ff))
|
||||
* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([1a49d1f](https://github.com/ReVanced/revanced-patches/commit/1a49d1f3c2a343d05d0abc07c143add486246fd0))
|
||||
* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([12f6f19](https://github.com/ReVanced/revanced-patches/commit/12f6f1966ad04631451940f7b64d785c3ef481a0))
|
||||
* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([0684ab5](https://github.com/ReVanced/revanced-patches/commit/0684ab5f183631de5720352049cfd293daa58eb0))
|
||||
|
||||
# [4.14.0-dev.15](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.14...v4.14.0-dev.15) (2024-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Fix issues related to playback by replace streaming data ([#3582](https://github.com/ReVanced/revanced-patches/issues/3582)) ([dfa94d7](https://github.com/ReVanced/revanced-patches/commit/dfa94d70f65150d6ef24ea6378b8e6a317055186))
|
||||
|
||||
# [4.14.0-dev.14](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.13...v4.14.0-dev.14) (2024-09-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Make working patches compatible with latest versions ([#3556](https://github.com/ReVanced/revanced-patches/issues/3556)) ([12f6f19](https://github.com/ReVanced/revanced-patches/commit/12f6f1966ad04631451940f7b64d785c3ef481a0))
|
||||
|
||||
# [4.14.0-dev.13](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.12...v4.14.0-dev.13) (2024-09-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide Shorts components:** Hide 'Use this sound' button ([#3647](https://github.com/ReVanced/revanced-patches/issues/3647)) ([33fc090](https://github.com/ReVanced/revanced-patches/commit/33fc09061431d4aa457d743c09a0de31ec566df1))
|
||||
|
||||
# [4.14.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.11...v4.14.0-dev.12) (2024-09-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Soundcloud - Hide ads:** Support latest version ([#3628](https://github.com/ReVanced/revanced-patches/issues/3628)) ([66e7e33](https://github.com/ReVanced/revanced-patches/commit/66e7e33efce9b702fdfcc2b9803e9da8491c1f08))
|
||||
|
||||
# [4.14.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.10...v4.14.0-dev.11) (2024-09-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Sync for Reddit:** Rename patch to `Use /user/ endpoint` ([98ead49](https://github.com/ReVanced/revanced-patches/commit/98ead493380932cb105530f4ba992673fd364d82))
|
||||
|
||||
# [4.14.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.9...v4.14.0-dev.10) (2024-09-12)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Sync for Reddit:** Add `Fix /user/ endpoint` patch ([46d11f3](https://github.com/ReVanced/revanced-patches/commit/46d11f3530fcdae9ed08b7e93aac235638a92dff))
|
||||
|
||||
# [4.14.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.8...v4.14.0-dev.9) (2024-09-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube:** Add donation link to settings about screen ([#3626](https://github.com/ReVanced/revanced-patches/issues/3626)) ([0684ab5](https://github.com/ReVanced/revanced-patches/commit/0684ab5f183631de5720352049cfd293daa58eb0))
|
||||
|
||||
# [4.14.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.7...v4.14.0-dev.8) (2024-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Add summary text to 'view my segments' button ([df80b9f](https://github.com/ReVanced/revanced-patches/commit/df80b9f92f0d981b9a40b7756d74f8ccc3dcb1e9))
|
||||
|
||||
# [4.14.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.6...v4.14.0-dev.7) (2024-09-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Check environment` patch ([#3610](https://github.com/ReVanced/revanced-patches/issues/3610)) ([fbcbdaf](https://github.com/ReVanced/revanced-patches/commit/fbcbdafa4938a35b5fdec46aae7b250a84b9c139))
|
||||
|
||||
# [4.14.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.5...v4.14.0-dev.6) (2024-09-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Change data directory location` patch ([#3602](https://github.com/ReVanced/revanced-patches/issues/3602)) ([5998029](https://github.com/ReVanced/revanced-patches/commit/59980292809cc0626bf49a160eeb05a1523c4eda))
|
||||
|
||||
# [4.14.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.4...v4.14.0-dev.5) (2024-09-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Pixiv - Hide ads:** Fix for latest version ([#3616](https://github.com/ReVanced/revanced-patches/issues/3616)) ([98956e8](https://github.com/ReVanced/revanced-patches/commit/98956e8f1a41347bb435720bbf984969469a7110))
|
||||
|
||||
# [4.14.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.3...v4.14.0-dev.4) (2024-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - ReturnYouTubeDislike:** Show estimated like count for videos with hidden likes ([#3601](https://github.com/ReVanced/revanced-patches/issues/3601)) ([005be82](https://github.com/ReVanced/revanced-patches/commit/005be82d71b2a42387b1b57035930b20f4663794))
|
||||
|
||||
# [4.14.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.2...v4.14.0-dev.3) (2024-08-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Keyword filter:** Add syntax to match whole keywords and not substrings ([#3592](https://github.com/ReVanced/revanced-patches/issues/3592)) ([f5fb351](https://github.com/ReVanced/revanced-patches/commit/f5fb3512cfafe214ba6a6d25ba0825ae1884a0ff))
|
||||
|
||||
# [4.14.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.14.0-dev.1...v4.14.0-dev.2) (2024-08-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Duolingo:** Add `Disable ads` and `Enable debug menu` patch ([#3422](https://github.com/ReVanced/revanced-patches/issues/3422)) ([d0a8599](https://github.com/ReVanced/revanced-patches/commit/d0a8599f76ce653e5d7c98069ad3c58b9ab9c5eb))
|
||||
|
||||
# [4.14.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.2...v4.14.0-dev.1) (2024-08-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Spoof client:** Allow forcing AVC codec with iOS ([#3570](https://github.com/ReVanced/revanced-patches/issues/3570)) ([1a49d1f](https://github.com/ReVanced/revanced-patches/commit/1a49d1f3c2a343d05d0abc07c143add486246fd0))
|
||||
|
||||
## [4.13.4-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.4-dev.1...v4.13.4-dev.2) (2024-08-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - SponsorBlock:** Handle if the user enters an invalid number into any SB settings ([37b3dd1](https://github.com/ReVanced/revanced-patches/commit/37b3dd1e789f8bb16fa1b9dd582e39c89dbe730c))
|
||||
|
||||
## [4.13.4-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.3...v4.13.4-dev.1) (2024-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SwissID:** Rename `Remove Google Play Integrity Integrity check` to `Remove Google Play Integrity check` ([#3558](https://github.com/ReVanced/revanced-patches/issues/3558)) ([0f5a771](https://github.com/ReVanced/revanced-patches/commit/0f5a771a5cff5684b4a8fd317f4938fe2cf3cbbe))
|
||||
|
||||
## [4.13.3](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Remove translated string that breaks patching ([a48c2db](https://github.com/ReVanced/revanced-patches/commit/a48c2db53d84767c8fd5d569f9ce1c46c2bfd9a1))
|
||||
|
||||
## [4.13.3-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.2...v4.13.3-dev.1) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube:** Remove translated string that breaks patching ([a48c2db](https://github.com/ReVanced/revanced-patches/commit/a48c2db53d84767c8fd5d569f9ce1c46c2bfd9a1))
|
||||
|
||||
## [4.13.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([b2b8454](https://github.com/ReVanced/revanced-patches/commit/b2b8454aa992bcb217fb03eb4de5532e0a9bd354))
|
||||
|
||||
## [4.13.2-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.1...v4.13.2-dev.1) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - GmsCore Support:** Fix patch exception by using correct patch offset ([#3543](https://github.com/ReVanced/revanced-patches/issues/3543)) ([b2b8454](https://github.com/ReVanced/revanced-patches/commit/b2b8454aa992bcb217fb03eb4de5532e0a9bd354))
|
||||
|
||||
## [4.13.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Check watch history domain name resolution:** Add compatibility field ([6c598f0](https://github.com/ReVanced/revanced-patches/commit/6c598f084ed90ee1318e4c66d8c1751c797b8e3b))
|
||||
|
||||
## [4.13.1-dev.1](https://github.com/ReVanced/revanced-patches/compare/v4.13.0...v4.13.1-dev.1) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Check watch history domain name resolution:** Add compatibility field ([6c598f0](https://github.com/ReVanced/revanced-patches/commit/6c598f084ed90ee1318e4c66d8c1751c797b8e3b))
|
||||
|
||||
# [4.13.0](https://github.com/ReVanced/revanced-patches/compare/v4.12.0...v4.13.0) (2024-08-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - GmsCore support:** Fix notifications not working by using the correct permissions ([19ddae2](https://github.com/ReVanced/revanced-patches/commit/19ddae2d15e513e18eb1556c468cd94bd197685b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Google Photos:** Add `Spoof features` patch ([#3459](https://github.com/ReVanced/revanced-patches/issues/3459)) ([7c218cd](https://github.com/ReVanced/revanced-patches/commit/7c218cd168aa72eb99bcb47d12dfa45616e8ad88))
|
||||
* **SCB Easy:** Remove broken `Remove debugging detection` patch ([#3518](https://github.com/ReVanced/revanced-patches/issues/3518)) ([f4e23cb](https://github.com/ReVanced/revanced-patches/commit/f4e23cbb8a24638318d8cee20a1991c51855d9d2))
|
||||
* **YouTube:** Add `Check watch history domain name resolution` patch ([#3537](https://github.com/ReVanced/revanced-patches/issues/3537)) ([2af1425](https://github.com/ReVanced/revanced-patches/commit/2af142525cda07a131335faadd4b3889979fd077))
|
||||
|
||||
# [4.13.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v4.13.0-dev.1...v4.13.0-dev.2) (2024-08-15)
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@ public final class app/revanced/patches/all/connectivity/wifi/spoof/SpoofWifiPat
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lkotlin/Triple;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/directory/ChangeDataDirectoryLocationPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/all/directory/ChangeDataDirectoryLocationPatch;
|
||||
public fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Integer;
|
||||
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
|
||||
public fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
|
||||
public synthetic fun transform (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/all/interaction/gestures/PredictiveBackGesturePatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -243,6 +251,18 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/duolingo/ad/DisableAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/duolingo/ad/DisableAdsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/duolingo/debug/EnableDebugMenuPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/duolingo/debug/EnableDebugMenuPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/facebook/ads/story/HideStoryAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/facebook/ads/story/HideStoryAdsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -301,6 +321,12 @@ public final class app/revanced/patches/googlephotos/misc/integrations/Integrati
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlephotos/misc/integrations/IntegrationsPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlephotos/preferences/RestoreHiddenBackUpWhileChargingTogglePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlephotos/preferences/RestoreHiddenBackUpWhileChargingTogglePatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/googlerecorder/restrictions/RemoveDeviceRestrictions;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -808,6 +834,12 @@ public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/s
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/slink/FixSLinksPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/syncforreddit/fix/user/UseUserEndpointPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/fix/user/UseUserEndpointPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch : app/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/reddit/customclients/syncforreddit/misc/integrations/IntegrationsPatch;
|
||||
}
|
||||
@@ -842,6 +874,12 @@ public final class app/revanced/patches/serviceportalbund/detection/root/RootDet
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public abstract class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public fun <init> (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1452,6 +1490,12 @@ public final class app/revanced/patches/twitter/misc/hook/patch/recommendation/H
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/hook/patch/recommendation/HideRecommendedUsersPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/ChangeLinkSharingDomainPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/twitter/misc/links/OpenLinksWithAppChooserPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1482,6 +1526,12 @@ public final class app/revanced/patches/warnwetter/misc/promocode/PromoCodeUnloc
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/willhaben/ads/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/willhaben/ads/HideAdsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/windyapp/misc/unlockpro/UnlockProPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
@@ -1850,6 +1900,10 @@ public final class app/revanced/patches/youtube/misc/backgroundplayback/Backgrou
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch : app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/check/CheckEnvironmentPatch;
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/debugging/DebuggingPatch : app/revanced/patcher/patch/ResourcePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/debugging/DebuggingPatch;
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
@@ -1880,6 +1934,12 @@ public final class app/revanced/patches/youtube/misc/fix/playback/SpoofSignature
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/SpoofVideoStreamsPatch;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch : app/revanced/patches/all/misc/transformation/BaseTransformInstructionsPatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/fix/playback/UserAgentClientSpoofPatch;
|
||||
public synthetic fun filterMap (Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;I)Ljava/lang/Object;
|
||||
@@ -1958,13 +2018,19 @@ public final class app/revanced/patches/youtube/misc/playercontrols/BottomContro
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsBytecodePatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/PlayerControlsBytecodePatch;
|
||||
public static field showPlayerControlsFingerprintResult Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
|
||||
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public final fun getShowPlayerControlsFingerprintResult ()Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;
|
||||
public final fun initializeBottomControl (Ljava/lang/String;)V
|
||||
public final fun initializeControl (Ljava/lang/String;)V
|
||||
public final fun injectVisibilityCheckCall (Ljava/lang/String;)V
|
||||
public final fun setShowPlayerControlsFingerprintResult (Lapp/revanced/patcher/fingerprint/MethodFingerprintResult;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/playercontrols/PlayerControlsResourcePatch : app/revanced/patcher/patch/ResourcePatch, java/io/Closeable {
|
||||
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/playercontrols/PlayerControlsResourcePatch;
|
||||
public final fun addBottomControls (Ljava/lang/String;)V
|
||||
public fun close ()V
|
||||
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
|
||||
public fun execute (Lapp/revanced/patcher/data/ResourceContext;)V
|
||||
}
|
||||
|
||||
public final class app/revanced/patches/youtube/misc/playeroverlay/PlayerOverlaysHookPatch : app/revanced/patcher/patch/BytecodePatch {
|
||||
@@ -2124,6 +2190,7 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static final fun containsWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
|
||||
public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
|
||||
public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;
|
||||
public static final fun findOpcodeIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
|
||||
public static final fun getException (Lapp/revanced/patcher/fingerprint/MethodFingerprint;)Lapp/revanced/patcher/patch/PatchException;
|
||||
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I
|
||||
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)I
|
||||
@@ -2132,6 +2199,8 @@ public final class app/revanced/util/BytecodeUtilsKt {
|
||||
public static synthetic fun indexOfFirstInstructionOrThrow$default (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)I
|
||||
public static final fun indexOfFirstWideLiteralInstructionValue (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
|
||||
public static final fun indexOfFirstWideLiteralInstructionValueOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
|
||||
public static final fun indexOfFirstWideLiteralInstructionValueReversed (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
|
||||
public static final fun indexOfFirstWideLiteralInstructionValueReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;J)I
|
||||
public static final fun indexOfIdResource (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
|
||||
public static final fun indexOfIdResourceOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
|
||||
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
|
||||
@@ -2159,6 +2228,7 @@ public final class app/revanced/util/ResourceUtilsKt {
|
||||
public static final fun copyXmlNode (Ljava/lang/String;Lapp/revanced/patcher/util/DomFileEditor;Lapp/revanced/patcher/util/DomFileEditor;)Ljava/lang/AutoCloseable;
|
||||
public static final fun doRecursively (Lorg/w3c/dom/Node;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun forEachChildElement (Lorg/w3c/dom/Node;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun insertFirst (Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)V
|
||||
public static final fun iterateXmlNodeChildren (Lapp/revanced/patcher/data/ResourceContext;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ dependencies {
|
||||
implementation(libs.guava)
|
||||
// Used in JsonGenerator.
|
||||
implementation(libs.gson)
|
||||
// Android API stubs defined here.
|
||||
compileOnly(project(":stub"))
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 4.13.0-dev.2
|
||||
version = 4.17.0-dev.8
|
||||
|
||||
321
package-lock.json
generated
321
package-lock.json
generated
@@ -8,8 +8,8 @@
|
||||
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.9.2",
|
||||
"semantic-release": "^24.0.0"
|
||||
"gradle-semantic-release-plugin": "^1.10.1",
|
||||
"semantic-release": "^24.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
@@ -235,13 +235,13 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "11.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz",
|
||||
"integrity": "sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==",
|
||||
"version": "11.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz",
|
||||
"integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.5.0"
|
||||
"@octokit/types": "^13.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
@@ -251,9 +251,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz",
|
||||
"integrity": "sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.2.tgz",
|
||||
"integrity": "sha512-XOWnPpH2kJ5VTwozsxGurw+svB2e61aWlmk5EVIYZPwFK5F9h4cyPyj9CIKRyMXMHSwpIsI3mPOdpMmrRhe7UQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -302,9 +302,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz",
|
||||
"integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz",
|
||||
"integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -315,9 +315,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "13.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz",
|
||||
"integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==",
|
||||
"version": "13.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.0.tgz",
|
||||
"integrity": "sha512-CrooV/vKCXqwLa+osmHLIMUb87brpgUqlqkPGc6iE2wCkUvTrHiXFMhAKoDDaAAYJrtKtrFTgSQTg5nObBEaew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -355,9 +355,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@pnpm/npm-conf": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz",
|
||||
"integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz",
|
||||
"integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -977,6 +977,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@saithodev/semantic-release-backmerge/node_modules/hosted-git-info": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
|
||||
"integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@saithodev/semantic-release-backmerge/node_modules/human-signals": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
|
||||
@@ -1372,9 +1385,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/github": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.1.1.tgz",
|
||||
"integrity": "sha512-sSmsBKGpAlTtXf9rUJf/si16p+FwPEsvsJRjl3KCwFP0WywaSpynvUhlYvE18n5rzkQNbGJnObAKIoo3xFMSjA==",
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.0.tgz",
|
||||
"integrity": "sha512-Uon6G6gJD8U1JNvPm7X0j46yxNRJ8Ui6SgK4Zw5Ktu8RgjEft3BGn+l/RX1TTzhhO3/uUcKuqM+/9/ETFxWS/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1399,7 +1412,7 @@
|
||||
"node": ">=20.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"semantic-release": ">=20.1.0"
|
||||
"semantic-release": ">=24.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/github/node_modules/@semantic-release/error": {
|
||||
@@ -1569,9 +1582,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/npm/node_modules/execa": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz",
|
||||
"integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==",
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz",
|
||||
"integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -1579,10 +1592,10 @@
|
||||
"cross-spawn": "^7.0.3",
|
||||
"figures": "^6.1.0",
|
||||
"get-stream": "^9.0.0",
|
||||
"human-signals": "^7.0.0",
|
||||
"human-signals": "^8.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"is-stream": "^4.0.1",
|
||||
"npm-run-path": "^5.2.0",
|
||||
"npm-run-path": "^6.0.0",
|
||||
"pretty-ms": "^9.0.0",
|
||||
"signal-exit": "^4.1.0",
|
||||
"strip-final-newline": "^4.0.0",
|
||||
@@ -1613,9 +1626,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/npm/node_modules/human-signals": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz",
|
||||
"integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz",
|
||||
"integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
@@ -1649,16 +1662,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/npm/node_modules/npm-run-path": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
|
||||
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
|
||||
"integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^4.0.0"
|
||||
"path-key": "^4.0.0",
|
||||
"unicorn-magic": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -1703,6 +1717,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/npm/node_modules/unicorn-magic": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
|
||||
"integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@semantic-release/release-notes-generator": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.1.tgz",
|
||||
@@ -2273,13 +2300,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
|
||||
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -2358,9 +2385,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/env-ci": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz",
|
||||
"integrity": "sha512-apikxMgkipkgTvMdRT9MNqWx5VLOci79F4VBd7Op/7OPjjoanjdAvn6fglMCCEf/1bAh8eOiuEVCUs4V3qP3nQ==",
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz",
|
||||
"integrity": "sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2549,9 +2576,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
|
||||
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
|
||||
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -2847,9 +2874,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/gradle-semantic-release-plugin": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.9.2.tgz",
|
||||
"integrity": "sha512-8qpf4GYFPQ+UMUymYBy/VchOOwLILAWzZMrZX1R0RR3JMgJBMN2R0tJn92R/3rXmxx4OAqwUFH6Np51eFoxr3w==",
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.10.1.tgz",
|
||||
"integrity": "sha512-Q4dLAFICjPouUyRRHEKK8cXNB75nraXoioYZDZlVQOg4sYKudnTDZ3ohLmV3k4cPGiiMCh1ckXETkx9JnuyKmA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -2925,16 +2952,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
|
||||
"integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.0.tgz",
|
||||
"integrity": "sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
"node": "^18.17.0 || >=20.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
@@ -2976,9 +3003,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
"integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -3191,9 +3218,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-unicode-supported": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz",
|
||||
"integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
|
||||
"integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -3497,9 +3524,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -3547,9 +3574,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -3610,6 +3637,19 @@
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-package-data/node_modules/hosted-git-info": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
|
||||
"integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"lru-cache": "^10.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-url": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz",
|
||||
@@ -3624,9 +3664,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-10.8.2.tgz",
|
||||
"integrity": "sha512-x/AIjFIKRllrhcb48dqUNAAZl0ig9+qMuN91RpZo3Cb2+zuibfh+KISl6+kVVyktDz230JKc208UkQwwMqyB+w==",
|
||||
"version": "10.8.3",
|
||||
"resolved": "https://registry.npmjs.org/npm/-/npm-10.8.3.tgz",
|
||||
"integrity": "sha512-0IQlyAYvVtQ7uOhDFYZCGK8kkut2nh8cpAdA9E6FvRSJaTgtZRZgNjlC5ZCct//L73ygrpY93CxXpRJDtNqPVg==",
|
||||
"bundleDependencies": [
|
||||
"@isaacs/string-locale-compare",
|
||||
"@npmcli/arborist",
|
||||
@@ -3719,13 +3759,13 @@
|
||||
"@sigstore/tuf": "^2.3.4",
|
||||
"abbrev": "^2.0.0",
|
||||
"archy": "~1.0.0",
|
||||
"cacache": "^18.0.3",
|
||||
"cacache": "^18.0.4",
|
||||
"chalk": "^5.3.0",
|
||||
"ci-info": "^4.0.0",
|
||||
"cli-columns": "^4.0.0",
|
||||
"fastest-levenshtein": "^1.0.16",
|
||||
"fs-minipass": "^3.0.3",
|
||||
"glob": "^10.4.2",
|
||||
"glob": "^10.4.5",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"hosted-git-info": "^7.0.2",
|
||||
"ini": "^4.1.3",
|
||||
@@ -3734,7 +3774,7 @@
|
||||
"json-parse-even-better-errors": "^3.0.2",
|
||||
"libnpmaccess": "^8.0.6",
|
||||
"libnpmdiff": "^6.1.4",
|
||||
"libnpmexec": "^8.1.3",
|
||||
"libnpmexec": "^8.1.4",
|
||||
"libnpmfund": "^5.0.12",
|
||||
"libnpmhook": "^10.0.5",
|
||||
"libnpmorg": "^6.0.6",
|
||||
@@ -3748,12 +3788,12 @@
|
||||
"minipass": "^7.1.1",
|
||||
"minipass-pipeline": "^1.2.4",
|
||||
"ms": "^2.1.2",
|
||||
"node-gyp": "^10.1.0",
|
||||
"node-gyp": "^10.2.0",
|
||||
"nopt": "^7.2.1",
|
||||
"normalize-package-data": "^6.0.2",
|
||||
"npm-audit-report": "^5.0.0",
|
||||
"npm-install-checks": "^6.3.0",
|
||||
"npm-package-arg": "^11.0.2",
|
||||
"npm-package-arg": "^11.0.3",
|
||||
"npm-pick-manifest": "^9.1.0",
|
||||
"npm-profile": "^10.0.0",
|
||||
"npm-registry-fetch": "^17.1.0",
|
||||
@@ -3764,7 +3804,7 @@
|
||||
"proc-log": "^4.2.0",
|
||||
"qrcode-terminal": "^0.12.0",
|
||||
"read": "^3.0.1",
|
||||
"semver": "^7.6.2",
|
||||
"semver": "^7.6.3",
|
||||
"spdx-expression-parse": "^4.0.0",
|
||||
"ssri": "^10.0.6",
|
||||
"supports-color": "^9.4.0",
|
||||
@@ -4335,7 +4375,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/cacache": {
|
||||
"version": "18.0.3",
|
||||
"version": "18.0.4",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4502,7 +4542,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/debug": {
|
||||
"version": "4.3.5",
|
||||
"version": "4.3.6",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
@@ -4586,7 +4626,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/foreground-child": {
|
||||
"version": "3.2.1",
|
||||
"version": "3.3.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4614,7 +4654,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/glob": {
|
||||
"version": "10.4.2",
|
||||
"version": "10.4.5",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -4629,9 +4669,6 @@
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
@@ -4815,16 +4852,13 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/npm/node_modules/jackspeak": {
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
},
|
||||
@@ -4910,7 +4944,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/libnpmexec": {
|
||||
"version": "8.1.3",
|
||||
"version": "8.1.4",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -5044,13 +5078,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/lru-cache": {
|
||||
"version": "10.2.2",
|
||||
"version": "10.4.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "14 || >=16.14"
|
||||
}
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/npm/node_modules/make-fetch-happen": {
|
||||
"version": "13.0.1",
|
||||
@@ -5262,7 +5293,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/node-gyp": {
|
||||
"version": "10.1.0",
|
||||
"version": "10.2.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
@@ -5273,9 +5304,9 @@
|
||||
"graceful-fs": "^4.2.6",
|
||||
"make-fetch-happen": "^13.0.0",
|
||||
"nopt": "^7.0.0",
|
||||
"proc-log": "^3.0.0",
|
||||
"proc-log": "^4.1.0",
|
||||
"semver": "^7.3.5",
|
||||
"tar": "^6.1.2",
|
||||
"tar": "^6.2.1",
|
||||
"which": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
@@ -5285,15 +5316,6 @@
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/node-gyp/node_modules/proc-log": {
|
||||
"version": "3.0.0",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/nopt": {
|
||||
"version": "7.2.1",
|
||||
"dev": true,
|
||||
@@ -5366,7 +5388,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/npm-package-arg": {
|
||||
"version": "11.0.2",
|
||||
"version": "11.0.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -5540,7 +5562,7 @@
|
||||
}
|
||||
},
|
||||
"node_modules/npm/node_modules/postcss-selector-parser": {
|
||||
"version": "6.1.0",
|
||||
"version": "6.1.2",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
@@ -5678,7 +5700,7 @@
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/npm/node_modules/semver": {
|
||||
"version": "7.6.2",
|
||||
"version": "7.6.3",
|
||||
"dev": true,
|
||||
"inBundle": true,
|
||||
"license": "ISC",
|
||||
@@ -6437,9 +6459,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
|
||||
"integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
|
||||
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
@@ -6481,9 +6503,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-ms": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz",
|
||||
"integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==",
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.1.0.tgz",
|
||||
"integrity": "sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6738,15 +6760,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/semantic-release": {
|
||||
"version": "24.0.0",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.0.0.tgz",
|
||||
"integrity": "sha512-v46CRPw+9eI3ZuYGF2oAjqPqsfbnfFTwLBgQsv/lch4goD09ytwOTESMN4QIrx/wPLxUGey60/NMx+ANQtWRsA==",
|
||||
"version": "24.1.2",
|
||||
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.2.tgz",
|
||||
"integrity": "sha512-hvEJ7yI97pzJuLsDZCYzJgmRxF8kiEJvNZhf0oiZQcexw+Ycjy4wbdsn/sVMURgNCu8rwbAXJdBRyIxM4pe32g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@semantic-release/commit-analyzer": "^13.0.0-beta.1",
|
||||
"@semantic-release/error": "^4.0.0",
|
||||
"@semantic-release/github": "^10.0.0",
|
||||
"@semantic-release/github": "^11.0.0",
|
||||
"@semantic-release/npm": "^12.0.0",
|
||||
"@semantic-release/release-notes-generator": "^14.0.0-beta.1",
|
||||
"aggregate-error": "^5.0.0",
|
||||
@@ -6759,7 +6781,7 @@
|
||||
"get-stream": "^6.0.0",
|
||||
"git-log-parser": "^1.2.0",
|
||||
"hook-std": "^3.0.0",
|
||||
"hosted-git-info": "^7.0.0",
|
||||
"hosted-git-info": "^8.0.0",
|
||||
"import-from-esm": "^1.3.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"marked": "^12.0.0",
|
||||
@@ -6851,9 +6873,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semantic-release/node_modules/execa": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz",
|
||||
"integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==",
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz",
|
||||
"integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -6861,10 +6883,10 @@
|
||||
"cross-spawn": "^7.0.3",
|
||||
"figures": "^6.1.0",
|
||||
"get-stream": "^9.0.0",
|
||||
"human-signals": "^7.0.0",
|
||||
"human-signals": "^8.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"is-stream": "^4.0.1",
|
||||
"npm-run-path": "^5.2.0",
|
||||
"npm-run-path": "^6.0.0",
|
||||
"pretty-ms": "^9.0.0",
|
||||
"signal-exit": "^4.1.0",
|
||||
"strip-final-newline": "^4.0.0",
|
||||
@@ -6895,9 +6917,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semantic-release/node_modules/human-signals": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz",
|
||||
"integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz",
|
||||
"integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
@@ -6931,16 +6953,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/semantic-release/node_modules/npm-run-path": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
|
||||
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
|
||||
"integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^4.0.0"
|
||||
"path-key": "^4.0.0",
|
||||
"unicorn-magic": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
@@ -6998,6 +7021,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/semantic-release/node_modules/unicorn-magic": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
|
||||
"integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
@@ -7239,9 +7275,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-license-ids": {
|
||||
"version": "3.0.18",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
|
||||
"integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
|
||||
"version": "3.0.20",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
|
||||
"integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
|
||||
"dev": true,
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
@@ -7365,9 +7401,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/supports-hyperlinks": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
|
||||
"integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz",
|
||||
"integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -7376,6 +7412,9 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/temp-dir": {
|
||||
@@ -7530,9 +7569,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "4.22.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz",
|
||||
"integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==",
|
||||
"version": "4.26.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz",
|
||||
"integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
@@ -7543,9 +7582,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/uglify-js": {
|
||||
"version": "3.19.0",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz",
|
||||
"integrity": "sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==",
|
||||
"version": "3.19.3",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
||||
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"@saithodev/semantic-release-backmerge": "^4.0.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.9.2",
|
||||
"semantic-release": "^24.0.0"
|
||||
"gradle-semantic-release-plugin": "^1.10.1",
|
||||
"semantic-release": "^24.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,3 +5,5 @@ buildCache {
|
||||
isEnabled = "CI" !in System.getenv()
|
||||
}
|
||||
}
|
||||
|
||||
include(":stub")
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package app.revanced.patches.all.directory
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.all.misc.transformation.BaseTransformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
|
||||
@Patch(
|
||||
name = "Change data directory location",
|
||||
description = "Changes the data directory in the application from " +
|
||||
"the app internal storage directory to /sdcard/android/data accessible by root-less devices." +
|
||||
"Using this patch can cause unexpected issues with some apps.",
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ChangeDataDirectoryLocationPatch : BaseTransformInstructionsPatch<Int>() {
|
||||
override fun filterMap(
|
||||
classDef: ClassDef,
|
||||
method: Method,
|
||||
instruction: Instruction,
|
||||
instructionIndex: Int,
|
||||
): Int? {
|
||||
val reference = instruction.getReference<MethodReference>() ?: return null
|
||||
|
||||
if (!MethodUtil.methodSignaturesMatch(reference, MethodCall.GetDir.reference)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return instructionIndex
|
||||
}
|
||||
|
||||
override fun transform(
|
||||
mutableMethod: MutableMethod,
|
||||
entry: Int,
|
||||
) = transformMethodCall(entry, mutableMethod)
|
||||
|
||||
private fun transformMethodCall(
|
||||
instructionIndex: Int,
|
||||
mutableMethod: MutableMethod,
|
||||
) {
|
||||
val getDirInstruction = mutableMethod.getInstruction<Instruction35c>(instructionIndex)
|
||||
val contextRegister = getDirInstruction.registerC
|
||||
val dataRegister = getDirInstruction.registerD
|
||||
|
||||
mutableMethod.replaceInstruction(
|
||||
instructionIndex,
|
||||
"invoke-virtual { v$contextRegister, v$dataRegister }, " +
|
||||
"Landroid/content/Context;->getExternalFilesDir(Ljava/lang/String;)Ljava/io/File;",
|
||||
)
|
||||
}
|
||||
|
||||
private enum class MethodCall(
|
||||
val reference: MethodReference,
|
||||
) {
|
||||
GetDir(
|
||||
ImmutableMethodReference(
|
||||
"Landroid/content/Context;",
|
||||
"getDir",
|
||||
listOf("Ljava/lang/String;", "I"),
|
||||
"Ljava/io/File;",
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -83,8 +83,9 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
"eu-rES" to "eu",
|
||||
"fa-rIR" to "fa",
|
||||
"fi-rFI" to "fi",
|
||||
"tl-rPH" to "tl",
|
||||
"fil-rPH" to "tl",
|
||||
"fr-rFR" to "fr",
|
||||
"ga-rIE" to "ga",
|
||||
"gl-rES" to "gl",
|
||||
"gu-rIN" to "gu",
|
||||
"hi-rIN" to "hi",
|
||||
@@ -139,7 +140,6 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
|
||||
"uz-rUZ" to "uz",
|
||||
"vi-rVN" to "vi",
|
||||
"zh-rCN" to "zh-rCN",
|
||||
"zh-rHK" to "zh-rHK",
|
||||
"zh-rTW" to "zh-rTW",
|
||||
"zu-rZA" to "zu",
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Pro unlock",
|
||||
compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers", ["4.52"])]
|
||||
compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ProUnlockPatch : BytecodePatch(
|
||||
@@ -34,4 +34,4 @@ object ProUnlockPatch : BytecodePatch(
|
||||
|
||||
} ?: throw ProUnlockFingerprint.exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package app.revanced.patches.duolingo.ad
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.duolingo.ad.fingerprints.InitializeMonetizationDebugSettingsFingerprint
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Disable ads",
|
||||
compatiblePackages = [CompatiblePackage("com.duolingo")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisableAdsPatch : BytecodePatch(
|
||||
setOf(InitializeMonetizationDebugSettingsFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Couple approaches to remove ads exist:
|
||||
//
|
||||
// MonetizationDebugSettings has a boolean value for "disableAds".
|
||||
// OnboardingState has a getter to check if the user has any "adFreeSessions".
|
||||
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
|
||||
//
|
||||
// MonetizationDebugSettings seems to be the most general setting to work fine.
|
||||
InitializeMonetizationDebugSettingsFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"const/4 v$register, 0x1"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package app.revanced.patches.duolingo.ad.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object InitializeMonetizationDebugSettingsFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf(
|
||||
"Z", // disableAds
|
||||
"Z", // useDebugBilling
|
||||
"Z", // showManageSubscriptions
|
||||
"Z", // alwaysShowSuperAds
|
||||
"Lcom/duolingo/debug/FamilyQuestOverride;",
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_BOOLEAN
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
package app.revanced.patches.duolingo.debug
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.duolingo.debug.fingerprints.InitializeBuildConfigProviderFingerprint
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Enable debug menu",
|
||||
compatiblePackages = [CompatiblePackage("com.duolingo", ["5.158.4"])],
|
||||
use = false
|
||||
)
|
||||
@Suppress("unused")
|
||||
object EnableDebugMenuPatch : BytecodePatch(
|
||||
setOf(InitializeBuildConfigProviderFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
InitializeBuildConfigProviderFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val insertIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"const/4 v$register, 0x1"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package app.revanced.patches.duolingo.debug.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
/**
|
||||
* The `BuildConfigProvider` class has two booleans:
|
||||
*
|
||||
* - `isChina`: (usually) compares "play" with "china"...except for builds in China
|
||||
* - `isDebug`: compares "release" with "debug" <-- we want to force this to `true`
|
||||
*/
|
||||
internal object InitializeBuildConfigProviderFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
strings = listOf(
|
||||
"debug",
|
||||
"release",
|
||||
"china",
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_BOOLEAN
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.revanced.patches.googlephotos.preferences
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.googlephotos.preferences.fingerprints.BackupPreferencesFingerprint
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Patch(
|
||||
name = "Restore hidden 'Back up while charging' toggle",
|
||||
description = "Restores a hidden toggle to only run backups when the device is charging.",
|
||||
compatiblePackages = [CompatiblePackage("com.google.android.apps.photos")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RestoreHiddenBackUpWhileChargingTogglePatch : BytecodePatch(
|
||||
setOf(BackupPreferencesFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true.
|
||||
BackupPreferencesFingerprint.result?.let {
|
||||
val chargingPrefStringIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
it.mutableMethod.apply {
|
||||
// Get the register of move-result.
|
||||
val resultRegister = getInstruction<OneRegisterInstruction>(chargingPrefStringIndex + 2).registerA
|
||||
// Insert const after move-result to override register as true.
|
||||
addInstruction(chargingPrefStringIndex + 3, "const/4 v$resultRegister, 0x1")
|
||||
}
|
||||
} ?: throw Exception("BackupPreferencesFingerprint result not found")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.googlephotos.preferences.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object BackupPreferencesFingerprint : MethodFingerprint(
|
||||
returnType = "Lcom/google/android/apps/photos/backup/data/BackupPreferences;",
|
||||
strings = listOf(
|
||||
"backup_prefs_had_backup_only_when_charging_enabled",
|
||||
),
|
||||
)
|
||||
@@ -13,16 +13,7 @@ import app.revanced.util.exception
|
||||
name = "Hide video ads",
|
||||
description = "Hides ads that appear while listening to or streaming music videos, podcasts, or songs.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -12,16 +12,7 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
@Patch(
|
||||
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Deprecated("This patch is no longer needed as the feature is now enabled by default.")
|
||||
|
||||
@@ -12,16 +12,7 @@ import app.revanced.util.exception
|
||||
name = "Enable exclusive audio playback",
|
||||
description = "Enables the option to play audio without video.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -14,16 +14,7 @@ import app.revanced.patches.music.interaction.permanentrepeat.fingerprints.Repea
|
||||
name = "Permanent repeat",
|
||||
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
],
|
||||
use = false
|
||||
)
|
||||
|
||||
@@ -14,16 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
name = "Hide category bar",
|
||||
description = "Hides the category bar at the top of the homepage.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
],
|
||||
use = false,
|
||||
)
|
||||
|
||||
@@ -17,16 +17,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
name = "Hide 'Get Music Premium' label",
|
||||
description = "Hides the \"Get Music Premium\" label from the account menu and settings.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -23,16 +23,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
name = "Remove upgrade button",
|
||||
description = "Removes the upgrade tab from the pivot bar.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -13,16 +13,7 @@ import app.revanced.patches.music.misc.androidauto.fingerprints.CheckCertificate
|
||||
name = "Bypass certificate checks",
|
||||
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -14,16 +14,7 @@ import app.revanced.util.resultOrThrow
|
||||
name = "Remove background playback restrictions",
|
||||
description = "Removes restrictions on background playback, including playing kids videos in the background.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
[
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
]
|
||||
)
|
||||
CompatiblePackage("com.google.android.apps.youtube.music")
|
||||
]
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -23,16 +23,7 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
|
||||
integrationsPatchDependency = IntegrationsPatch::class,
|
||||
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
|
||||
compatiblePackages = setOf(
|
||||
CompatiblePackage(
|
||||
"com.google.android.apps.youtube.music",
|
||||
setOf(
|
||||
"6.45.54",
|
||||
"6.51.53",
|
||||
"7.01.53",
|
||||
"7.02.52",
|
||||
"7.03.52",
|
||||
),
|
||||
),
|
||||
CompatiblePackage("com.google.android.apps.youtube.music"),
|
||||
),
|
||||
fingerprints = setOf(
|
||||
CastDynamiteModuleV2Fingerprint,
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
package app.revanced.patches.pixiv.ads
|
||||
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.pixiv.ads.fingerprints.IsNotPremiumFingerprint
|
||||
import app.revanced.patches.pixiv.ads.fingerprints.ShouldShowAdsFingerprint
|
||||
import app.revanced.util.exception
|
||||
|
||||
@Patch(
|
||||
name = "Hide ads",
|
||||
compatiblePackages = [CompatiblePackage("jp.pxv.android")]
|
||||
compatiblePackages = [CompatiblePackage("jp.pxv.android")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideAdsPatch : BytecodePatch(setOf(IsNotPremiumFingerprint)) {
|
||||
// Always return false in the "isNotPremium" method which normally returns !this.accountManager.isPremium.
|
||||
// However, this is not the method that controls the user's premium status.
|
||||
// Instead, this method is used to determine whether ads should be shown.
|
||||
object HideAdsPatch : BytecodePatch(setOf(ShouldShowAdsFingerprint)) {
|
||||
override fun execute(context: BytecodeContext) =
|
||||
IsNotPremiumFingerprint.result?.mutableClass?.virtualMethods?.first()?.addInstructions(
|
||||
ShouldShowAdsFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
"""
|
||||
) ?: throw IsNotPremiumFingerprint.exception
|
||||
}
|
||||
""",
|
||||
) ?: throw ShouldShowAdsFingerprint.exception
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package app.revanced.patches.pixiv.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
internal object IsNotPremiumFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
listOf("L"),
|
||||
strings = listOf("pixivAccountManager"),
|
||||
customFingerprint = custom@{ _, classDef ->
|
||||
// The "isNotPremium" method is the only method in the class.
|
||||
if (classDef.virtualMethods.count() != 1) return@custom false
|
||||
|
||||
classDef.virtualMethods.first().let { isNotPremiumMethod ->
|
||||
isNotPremiumMethod.parameterTypes.size == 0 && isNotPremiumMethod.returnType == "Z"
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.pixiv.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
|
||||
internal object ShouldShowAdsFingerprint : MethodFingerprint(
|
||||
"Z",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
classDef.type.endsWith("AdUtils;") && methodDef.name == "shouldShowAds"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,61 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.*
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthFriendRequestFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthSubredditInfoRequestHelperFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints.OAuthUnfriendRequestFingerprint
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
@Patch(
|
||||
name = "Use /user/ endpoint",
|
||||
description = "Replaces the deprecated endpoint for viewing user profiles /u with /user, that used to fix a bug.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.laurencedawson.reddit_sync"),
|
||||
CompatiblePackage("com.laurencedawson.reddit_sync.pro"),
|
||||
CompatiblePackage("com.laurencedawson.reddit_sync.dev"),
|
||||
],
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
object UseUserEndpointPatch : BytecodePatch(
|
||||
fingerprints = setOf(
|
||||
OAuthFriendRequestFingerprint,
|
||||
OAuthSubredditInfoRequestConstructorFingerprint,
|
||||
OAuthSubredditInfoRequestHelperFingerprint,
|
||||
OAuthUnfriendRequestFingerprint,
|
||||
OAuthUserIdRequestFingerprint,
|
||||
OAuthUserInfoRequestFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
arrayOf(
|
||||
OAuthFriendRequestFingerprint,
|
||||
OAuthSubredditInfoRequestConstructorFingerprint,
|
||||
OAuthSubredditInfoRequestHelperFingerprint,
|
||||
OAuthUnfriendRequestFingerprint,
|
||||
OAuthUserIdRequestFingerprint,
|
||||
OAuthUserInfoRequestFingerprint,
|
||||
).map(MethodFingerprint::resultOrThrow).map {
|
||||
it.scanResult.stringsScanResult!!.matches.first().index to it.mutableMethod
|
||||
}.forEach { (userPathStringIndex, method) ->
|
||||
val userPathStringInstruction = method.getInstruction<OneRegisterInstruction>(userPathStringIndex)
|
||||
val userPathStringRegister = userPathStringInstruction.registerA
|
||||
val fixedUserPathString = userPathStringInstruction.getReference<StringReference>()!!.string.replace("u/", "user/")
|
||||
|
||||
method.replaceInstruction(
|
||||
userPathStringIndex,
|
||||
"const-string v$userPathStringRegister, \"${fixedUserPathString}\"",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal abstract class BaseUserEndpointFingerprint(source: String, accessFlags: Int? = null) :
|
||||
MethodFingerprint(
|
||||
accessFlags = accessFlags,
|
||||
strings = listOf("u/"),
|
||||
customFingerprint = { _, classDef -> classDef.sourceFile == source },
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
internal object OAuthFriendRequestFingerprint : BaseUserEndpointFingerprint("OAuthFriendRequest.java")
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object OAuthSubredditInfoRequestConstructorFingerprint :
|
||||
BaseUserEndpointFingerprint(
|
||||
"OAuthSubredditInfoRequest.java",
|
||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object OAuthSubredditInfoRequestHelperFingerprint :
|
||||
BaseUserEndpointFingerprint(
|
||||
"OAuthSubredditInfoRequest.java",
|
||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
internal object OAuthUnfriendRequestFingerprint : BaseUserEndpointFingerprint("OAuthUnfriendRequest.java")
|
||||
@@ -0,0 +1,3 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
internal object OAuthUserIdRequestFingerprint : BaseUserEndpointFingerprint("OAuthUserIdRequest.java")
|
||||
@@ -0,0 +1,3 @@
|
||||
package app.revanced.patches.reddit.customclients.syncforreddit.fix.user.fingerprints
|
||||
|
||||
internal object OAuthUserInfoRequestFingerprint : BaseUserEndpointFingerprint("OAuthUserInfoRequest.java")
|
||||
@@ -0,0 +1,114 @@
|
||||
package app.revanced.patches.shared.misc.checks
|
||||
|
||||
import android.os.Build.*
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableLongEncodedValue
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableStringEncodedValue
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoBuildFingerprint
|
||||
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoFingerprint
|
||||
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.immutable.value.ImmutableLongEncodedValue
|
||||
import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.security.MessageDigest
|
||||
import kotlin.io.encoding.Base64
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
|
||||
abstract class BaseCheckEnvironmentPatch(
|
||||
private val mainActivityOnCreateFingerprint: MethodFingerprint,
|
||||
compatiblePackages: Set<CompatiblePackage>,
|
||||
integrationsPatch: BaseIntegrationsPatch,
|
||||
) : BytecodePatch(
|
||||
description = "Checks, if the application was patched by, otherwise warns the user.",
|
||||
compatiblePackages = compatiblePackages,
|
||||
dependencies = setOf(
|
||||
AddResourcesPatch::class,
|
||||
integrationsPatch::class,
|
||||
),
|
||||
fingerprints = setOf(
|
||||
PatchInfoFingerprint,
|
||||
PatchInfoBuildFingerprint,
|
||||
mainActivityOnCreateFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(BaseCheckEnvironmentPatch::class)
|
||||
|
||||
setPatchInfo()
|
||||
invokeCheck()
|
||||
}
|
||||
|
||||
private fun setPatchInfo() {
|
||||
PatchInfoFingerprint.setClassFields(
|
||||
"PATCH_TIME" to System.currentTimeMillis().encoded,
|
||||
)
|
||||
|
||||
fun setBuildInfo() {
|
||||
PatchInfoBuildFingerprint.setClassFields(
|
||||
"PATCH_BOARD" to BOARD.encodedAndHashed,
|
||||
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
|
||||
"PATCH_BRAND" to BRAND.encodedAndHashed,
|
||||
"PATCH_CPU_ABI" to CPU_ABI.encodedAndHashed,
|
||||
"PATCH_CPU_ABI2" to CPU_ABI2.encodedAndHashed,
|
||||
"PATCH_DEVICE" to DEVICE.encodedAndHashed,
|
||||
"PATCH_DISPLAY" to DISPLAY.encodedAndHashed,
|
||||
"PATCH_FINGERPRINT" to FINGERPRINT.encodedAndHashed,
|
||||
"PATCH_HARDWARE" to HARDWARE.encodedAndHashed,
|
||||
"PATCH_HOST" to HOST.encodedAndHashed,
|
||||
"PATCH_ID" to ID.encodedAndHashed,
|
||||
"PATCH_MANUFACTURER" to MANUFACTURER.encodedAndHashed,
|
||||
"PATCH_MODEL" to MODEL.encodedAndHashed,
|
||||
"PATCH_PRODUCT" to PRODUCT.encodedAndHashed,
|
||||
"PATCH_RADIO" to RADIO.encodedAndHashed,
|
||||
"PATCH_TAGS" to TAGS.encodedAndHashed,
|
||||
"PATCH_TYPE" to TYPE.encodedAndHashed,
|
||||
"PATCH_USER" to USER.encodedAndHashed,
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
Class.forName("android.os.Build")
|
||||
// This only works on Android,
|
||||
// because it uses Android APIs.
|
||||
setBuildInfo()
|
||||
} catch (_: ClassNotFoundException) { }
|
||||
}
|
||||
|
||||
private fun invokeCheck() = mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"invoke-static/range { p0 .. p0 },$INTEGRATIONS_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
|
||||
) ?: throw mainActivityOnCreateFingerprint.exception
|
||||
|
||||
private companion object {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/shared/checks/CheckEnvironmentPatch;"
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
private val String.encodedAndHashed
|
||||
get() = MutableStringEncodedValue(
|
||||
ImmutableStringEncodedValue(
|
||||
Base64.encode(
|
||||
MessageDigest.getInstance("SHA-1")
|
||||
.digest(this.toByteArray(StandardCharsets.UTF_8)),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private val Long.encoded get() = MutableLongEncodedValue(ImmutableLongEncodedValue(this))
|
||||
|
||||
private fun <T : MutableEncodedValue> MethodFingerprint.setClassFields(vararg fieldNameValues: Pair<String, T>) {
|
||||
val fieldNameValueMap = mapOf(*fieldNameValues)
|
||||
|
||||
resultOrThrow().mutableClass.fields.forEach { field ->
|
||||
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.shared.misc.checks.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object PatchInfoBuildFingerprint : MethodFingerprint(
|
||||
customFingerprint = { _, classDef -> classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo\$Build;" },
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.shared.misc.checks.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object PatchInfoFingerprint : MethodFingerprint(
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo;"
|
||||
},
|
||||
)
|
||||
@@ -18,7 +18,7 @@ import app.revanced.patches.shared.misc.gms.fingerprints.GooglePlayUtilityFinger
|
||||
import app.revanced.patches.shared.misc.gms.fingerprints.ServiceCheckFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction21c
|
||||
@@ -115,15 +115,16 @@ abstract class BaseGmsCoreSupportPatch(
|
||||
|
||||
// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
|
||||
mainActivityOnCreateFingerprint.result?.mutableMethod?.apply {
|
||||
val setContextIndex = indexOfFirstInstructionOrThrow {
|
||||
val reference = getReference<MethodReference>() ?: return@indexOfFirstInstructionOrThrow false
|
||||
// Temporary fix for patches with an integrations patch that hook the onCreate method as well.
|
||||
val setContextIndex = indexOfFirstInstruction {
|
||||
val reference = getReference<MethodReference>() ?: return@indexOfFirstInstruction false
|
||||
|
||||
reference.toString() == "Lapp/revanced/integrations/shared/Utils;->setContext(Landroid/content/Context;)V"
|
||||
}
|
||||
|
||||
// Add after setContext call, because this patch needs the context.
|
||||
addInstructions(
|
||||
setContextIndex + 1,
|
||||
if (setContextIndex < 0) 0 else setContextIndex + 1,
|
||||
"invoke-static/range { p0 .. p0 }, Lapp/revanced/integrations/shared/GmsCoreSupport;->" +
|
||||
"checkGmsCore(Landroid/app/Activity;)V",
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.getNode
|
||||
import app.revanced.util.insertFirst
|
||||
import org.w3c.dom.Node
|
||||
import java.io.Closeable
|
||||
|
||||
@@ -47,11 +48,7 @@ abstract class BaseSettingsResourcePatch(
|
||||
// It may be necessary to ask for the desired resourceValue in the future.
|
||||
AddResourcesPatch("values", resource)
|
||||
}.let { preferenceNode ->
|
||||
if (prepend && firstChild != null) {
|
||||
insertBefore(preferenceNode, firstChild)
|
||||
} else {
|
||||
appendChild(preferenceNode)
|
||||
}
|
||||
insertFirst(preferenceNode)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ object HideAdsPatch : BytecodePatch(
|
||||
|
||||
// Prevent verification of an HTTP header containing the user's current plan, which would contradict the previous patch.
|
||||
InterceptFingerprint.resultOrThrow().let { result ->
|
||||
val conditionIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val conditionIndex = result.scanResult.patternScanResult!!.endIndex + 1
|
||||
result.mutableMethod.addInstruction(
|
||||
conditionIndex,
|
||||
"return-object p1",
|
||||
|
||||
@@ -9,14 +9,9 @@ internal object InterceptFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC.value,
|
||||
parameters = listOf("L"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT_OBJECT
|
||||
),
|
||||
strings = listOf("SC-Mob-UserPlan", "Configuration"),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "ApiUserPlanInterceptor.java"
|
||||
},
|
||||
)
|
||||
|
||||
@@ -8,7 +8,4 @@ internal object UserConsumerPlanConstructorFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Ljava/lang/String;", "Z", "Ljava/lang/String;", "Ljava/util/List;", "Ljava/lang/String;", "Ljava/lang/String;"),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "UserConsumerPlan.kt"
|
||||
},
|
||||
)
|
||||
@@ -7,6 +7,7 @@ internal object CreateTrackingApiFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC.value,
|
||||
customFingerprint = { methodDef, classDef ->
|
||||
classDef.sourceFile == "DefaultTrackingApiFactory.kt" && methodDef.name == "create"
|
||||
methodDef.name == "create"
|
||||
},
|
||||
strings = listOf("backend", "boogaloo")
|
||||
)
|
||||
|
||||
@@ -15,7 +15,5 @@ internal object DownloadOperationsHeaderVerificationFingerprint : MethodFingerpr
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.CONST_STRING
|
||||
),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "DownloadOperations.kt"
|
||||
}
|
||||
strings = listOf("X-SC-Mime-Type", "X-SC-Preset", "X-SC-Quality")
|
||||
)
|
||||
@@ -14,7 +14,4 @@ internal object DownloadOperationsURLBuilderFingerprint : MethodFingerprint(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.FILLED_NEW_ARRAY
|
||||
),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "DownloadOperations.kt"
|
||||
}
|
||||
)
|
||||
@@ -3,12 +3,16 @@ package app.revanced.patches.soundcloud.shared.fingerprints
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
|
||||
internal object FeatureConstructorFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
parameters = listOf("Ljava/lang/String;", "Z", "Ljava/util/List;"),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.sourceFile == "Feature.kt"
|
||||
},
|
||||
opcodes = listOf(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
)
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patches.swissid.integritycheck.fingerprints.CheckIntegrityFi
|
||||
import app.revanced.util.resultOrThrow
|
||||
|
||||
@Patch(
|
||||
name = "Remove Google Play Integrity Integrity check",
|
||||
name = "Remove Google Play Integrity check",
|
||||
description = "Removes the Google Play Integrity check. With this it's possible to use SwissID on custom ROMS." +
|
||||
"If the device is rooted, root permissions must be hidden from the app.",
|
||||
compatiblePackages = [CompatiblePackage("com.swisssign.swissid.mobile")],
|
||||
|
||||
@@ -17,16 +17,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
@Patch(
|
||||
name = "Feed filter",
|
||||
description = "Removes ads, livestreams, stories, image videos " +
|
||||
"and videos with a specific amount of views or likes from the feed.",
|
||||
"and videos with a specific amount of views or likes from the feed.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["36.5.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["36.5.4"]),
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object FeedFilterPatch : BytecodePatch(
|
||||
setOf(FeedApiServiceLIZFingerprint, SettingsStatusLoadFingerprint)
|
||||
setOf(FeedApiServiceLIZFingerprint, SettingsStatusLoadFingerprint),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
FeedApiServiceLIZFingerprint.result?.mutableMethod?.apply {
|
||||
@@ -36,13 +36,13 @@ object FeedFilterPatch : BytecodePatch(
|
||||
addInstruction(
|
||||
returnFeedItemInstruction.location.index,
|
||||
"invoke-static { v$feedItemsRegister }, " +
|
||||
"Lapp/revanced/integrations/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
|
||||
"Lapp/revanced/integrations/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V",
|
||||
)
|
||||
} ?: throw FeedApiServiceLIZFingerprint.exception
|
||||
|
||||
SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableFeedFilter()V"
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableFeedFilter()V",
|
||||
) ?: throw SettingsStatusLoadFingerprint.exception
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints.OnClearDisplayEventFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints.OnRenderFirstFrameFingerprint
|
||||
import app.revanced.patches.tiktok.shared.fingerprints.OnRenderFirstFrameFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
@@ -19,16 +19,16 @@ import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
|
||||
name = "Remember clear display",
|
||||
description = "Remembers the clear display configurations in between videos.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["36.5.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["36.5.4"]),
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object RememberClearDisplayPatch : BytecodePatch(
|
||||
setOf(
|
||||
OnClearDisplayEventFingerprint,
|
||||
OnRenderFirstFrameFingerprint
|
||||
)
|
||||
OnRenderFirstFrameFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
OnClearDisplayEventFingerprint.result?.mutableMethod?.let {
|
||||
@@ -40,7 +40,7 @@ object RememberClearDisplayPatch : BytecodePatch(
|
||||
it.addInstructions(
|
||||
isEnabledIndex,
|
||||
"invoke-static { v$isEnabledRegister }, " +
|
||||
"Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V"
|
||||
"Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->rememberClearDisplayState(Z)V",
|
||||
)
|
||||
|
||||
// endregion
|
||||
@@ -54,22 +54,25 @@ object RememberClearDisplayPatch : BytecodePatch(
|
||||
"""
|
||||
# Create a new clearDisplayEvent and post it to the EventBus (https://github.com/greenrobot/EventBus)
|
||||
|
||||
# The state of clear display.
|
||||
invoke-static { }, Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->getClearDisplayState()Z
|
||||
move-result v3
|
||||
if-eqz v3, :clear_display_disabled
|
||||
|
||||
# Clear display type such as 0 = LONG_PRESS, 1 = SCREEN_RECORD etc.
|
||||
const/4 v1, 0x0
|
||||
|
||||
# Enter method (Such as "pinch", "swipe_exit", or an empty string (unknown, what it means)).
|
||||
const-string v2, ""
|
||||
|
||||
# Name of the clear display type which is equivalent to the clear display type.
|
||||
const-string v2, "long_press"
|
||||
const-string v3, "long_press"
|
||||
|
||||
# The state of clear display.
|
||||
invoke-static { }, Lapp/revanced/integrations/tiktok/cleardisplay/RememberClearDisplayPatch;->getClearDisplayState()Z
|
||||
move-result v4
|
||||
if-eqz v4, :clear_display_disabled
|
||||
|
||||
new-instance v0, $clearDisplayEventClass
|
||||
invoke-direct { v0, v1, v2, v3 }, $clearDisplayEventClass-><init>(ILjava/lang/String;Z)V
|
||||
invoke-direct { v0, v1, v2, v3, v4 }, $clearDisplayEventClass-><init>(ILjava/lang/String;Ljava/lang/String;Z)V
|
||||
invoke-virtual { v0 }, $clearDisplayEventClass->post()Lcom/ss/android/ugc/governance/eventbus/IEvent;
|
||||
""",
|
||||
ExternalLabel("clear_display_disabled", getInstruction(0))
|
||||
ExternalLabel("clear_display_disabled", getInstruction(0)),
|
||||
)
|
||||
} ?: throw OnRenderFirstFrameFingerprint.exception
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package app.revanced.patches.tiktok.interaction.cleardisplay.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
|
||||
}
|
||||
)
|
||||
@@ -13,14 +13,13 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint2
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint3
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadPathParentFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadUriFingerprint
|
||||
import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.SettingsPatch
|
||||
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch(
|
||||
@@ -28,9 +27,9 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
description = "Removes download restrictions and changes the default path to download to.",
|
||||
dependencies = [IntegrationsPatch::class, SettingsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["36.5.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["36.5.4"]),
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DownloadsPatch : BytecodePatch(
|
||||
@@ -38,9 +37,9 @@ object DownloadsPatch : BytecodePatch(
|
||||
ACLCommonShareFingerprint,
|
||||
ACLCommonShareFingerprint2,
|
||||
ACLCommonShareFingerprint3,
|
||||
DownloadPathParentFingerprint,
|
||||
SettingsStatusLoadFingerprint
|
||||
)
|
||||
DownloadUriFingerprint,
|
||||
SettingsStatusLoadFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
fun MethodFingerprint.getMethod() = result?.mutableMethod ?: throw exception
|
||||
@@ -52,7 +51,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
},
|
||||
ACLCommonShareFingerprint2 to {
|
||||
@@ -61,7 +60,7 @@ object DownloadsPatch : BytecodePatch(
|
||||
"""
|
||||
const/4 v0, 0x2
|
||||
return v0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
},
|
||||
// Download videos without watermark.
|
||||
@@ -76,48 +75,40 @@ object DownloadsPatch : BytecodePatch(
|
||||
return v0
|
||||
:noremovewatermark
|
||||
nop
|
||||
"""
|
||||
""",
|
||||
)
|
||||
},
|
||||
// Change the download path patch.
|
||||
DownloadPathParentFingerprint to {
|
||||
val targetIndex = indexOfFirstInstructionOrThrow { opcode == Opcode.INVOKE_STATIC }
|
||||
val downloadUriMethod = context
|
||||
.toMethodWalker(this)
|
||||
.nextMethod(targetIndex, true)
|
||||
.getMethod() as MutableMethod
|
||||
|
||||
val firstIndex = downloadUriMethod.indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_DIRECT && ((this as Instruction35c).reference as MethodReference).name == "<init>"
|
||||
DownloadUriFingerprint to {
|
||||
val firstIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "<init>"
|
||||
}
|
||||
val secondIndex = downloadUriMethod.indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_STATIC && ((this as Instruction35c).reference as MethodReference).returnType.contains(
|
||||
"Uri"
|
||||
)
|
||||
val secondIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.returnType?.contains("Uri") == true
|
||||
}
|
||||
|
||||
downloadUriMethod.addInstructions(
|
||||
addInstructions(
|
||||
secondIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
""",
|
||||
)
|
||||
|
||||
downloadUriMethod.addInstructions(
|
||||
addInstructions(
|
||||
firstIndex,
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
"""
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
|
||||
move-result-object v0
|
||||
""",
|
||||
)
|
||||
},
|
||||
SettingsStatusLoadFingerprint to {
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableDownload()V"
|
||||
"invoke-static {}, Lapp/revanced/integrations/tiktok/settings/SettingsStatus;->enableDownload()V",
|
||||
)
|
||||
}
|
||||
},
|
||||
).forEach { (fingerprint, patch) ->
|
||||
fingerprint.getMethod().patch()
|
||||
}
|
||||
|
||||
@@ -3,22 +3,18 @@ package app.revanced.patches.tiktok.interaction.downloads.fingerprints
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object DownloadPathParentFingerprint : MethodFingerprint(
|
||||
"L",
|
||||
internal object DownloadUriFingerprint : MethodFingerprint(
|
||||
"Landroid/net/Uri;",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
strings = listOf(
|
||||
"video/mp4"
|
||||
"/",
|
||||
"/Camera",
|
||||
"/Camera/",
|
||||
"video/mp4",
|
||||
),
|
||||
parameters = listOf(
|
||||
"L",
|
||||
"L"
|
||||
"Landroid/content/Context;",
|
||||
"Ljava/lang/String;",
|
||||
),
|
||||
opcodes = listOf(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -9,30 +9,33 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.GetSpeedFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.OnRenderFirstFrameFingerprint
|
||||
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SetSpeedFingerprint
|
||||
import app.revanced.patches.tiktok.shared.fingerprints.GetEnterFromFingerprint
|
||||
import app.revanced.patches.tiktok.shared.fingerprints.OnRenderFirstFrameFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction11x
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch(
|
||||
name = "Playback speed",
|
||||
description = "Enables the playback speed option for all videos and " +
|
||||
"retains the speed configurations in between videos.",
|
||||
"retains the speed configurations in between videos.",
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["36.5.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["36.5.4"]),
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object PlaybackSpeedPatch : BytecodePatch(
|
||||
setOf(
|
||||
GetSpeedFingerprint,
|
||||
OnRenderFirstFrameFingerprint,
|
||||
SetSpeedFingerprint
|
||||
)
|
||||
SetSpeedFingerprint,
|
||||
GetEnterFromFingerprint,
|
||||
),
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
SetSpeedFingerprint.result?.let { onVideoSwiped ->
|
||||
@@ -44,7 +47,7 @@ object PlaybackSpeedPatch : BytecodePatch(
|
||||
addInstruction(
|
||||
injectIndex,
|
||||
"invoke-static { v$register }," +
|
||||
" Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->rememberPlaybackSpeed(F)V"
|
||||
" Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->rememberPlaybackSpeed(F)V",
|
||||
)
|
||||
} ?: throw GetSpeedFingerprint.exception
|
||||
|
||||
@@ -53,29 +56,29 @@ object PlaybackSpeedPatch : BytecodePatch(
|
||||
OnRenderFirstFrameFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
# Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method.
|
||||
const/4 v0, 0x1
|
||||
invoke-virtual {p0, v0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getEnterFrom(Z)Ljava/lang/String;
|
||||
move-result-object v0
|
||||
|
||||
# Model of current video retrieved using getCurrentAweme method.
|
||||
invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme;
|
||||
move-result-object v1
|
||||
|
||||
# Desired playback speed retrieved using getPlaybackSpeed method.
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->getPlaybackSpeed()F
|
||||
move-result-object v2
|
||||
invoke-static { v0, v1, v2 }, ${onVideoSwiped.method}
|
||||
"""
|
||||
# Video playback location (e.g. home page, following page or search result page) retrieved using getEnterFrom method.
|
||||
const/4 v0, 0x1
|
||||
invoke-virtual {p0, v0}, ${GetEnterFromFingerprint.resultOrThrow().method}
|
||||
move-result-object v0
|
||||
|
||||
# Model of current video retrieved using getCurrentAweme method.
|
||||
invoke-virtual {p0}, Lcom/ss/android/ugc/aweme/feed/panel/BaseListFragmentPanel;->getCurrentAweme()Lcom/ss/android/ugc/aweme/feed/model/Aweme;
|
||||
move-result-object v1
|
||||
|
||||
# Desired playback speed retrieved using getPlaybackSpeed method.
|
||||
invoke-static {}, Lapp/revanced/integrations/tiktok/speed/PlaybackSpeedPatch;->getPlaybackSpeed()F
|
||||
move-result v2
|
||||
invoke-static { v0, v1, v2 }, ${onVideoSwiped.method}
|
||||
""",
|
||||
) ?: throw OnRenderFirstFrameFingerprint.exception
|
||||
|
||||
// Force enable the playback speed option for all videos.
|
||||
onVideoSwiped.mutableClass.methods.find { method -> method.returnType == "Z" }?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
) ?: throw PatchException("Failed to force enable the playback speed option.")
|
||||
} ?: throw SetSpeedFingerprint.exception
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
description = "Adds ReVanced settings to TikTok.",
|
||||
dependencies = [IntegrationsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
|
||||
]
|
||||
CompatiblePackage("com.ss.android.ugc.trill", ["36.5.4"]),
|
||||
CompatiblePackage("com.zhiliaoapp.musically", ["36.5.4"]),
|
||||
],
|
||||
)
|
||||
object SettingsPatch : BytecodePatch(
|
||||
setOf(
|
||||
@@ -34,21 +34,21 @@ object SettingsPatch : BytecodePatch(
|
||||
AddSettingsEntryFingerprint,
|
||||
SettingsEntryFingerprint,
|
||||
SettingsEntryInfoFingerprint,
|
||||
)
|
||||
),
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/tiktok/settings/AdPersonalizationActivityHook;"
|
||||
|
||||
private const val INITIALIZE_SETTINGS_METHOD_DESCRIPTOR =
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->initialize(" +
|
||||
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||
")Z"
|
||||
"Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;" +
|
||||
")Z"
|
||||
|
||||
private const val CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR =
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->createSettingsEntry(" +
|
||||
"Ljava/lang/String;" +
|
||||
"Ljava/lang/String;" +
|
||||
")Ljava/lang/Object;"
|
||||
"Ljava/lang/String;" +
|
||||
"Ljava/lang/String;" +
|
||||
")Ljava/lang/Object;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// Find the class name of classes which construct a settings entry
|
||||
@@ -70,8 +70,8 @@ object SettingsPatch : BytecodePatch(
|
||||
markIndex + 2,
|
||||
listOf(
|
||||
getUnitManager,
|
||||
addEntry
|
||||
)
|
||||
addEntry,
|
||||
),
|
||||
)
|
||||
|
||||
addInstructions(
|
||||
@@ -81,7 +81,8 @@ object SettingsPatch : BytecodePatch(
|
||||
const-string v1, "$settingsButtonInfoClass"
|
||||
invoke-static {v0, v1}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR
|
||||
move-result-object v0
|
||||
"""
|
||||
check-cast v0, ${SettingsEntryFingerprint.result!!.classDef}
|
||||
""",
|
||||
)
|
||||
} ?: throw AddSettingsEntryFingerprint.exception
|
||||
|
||||
@@ -102,12 +103,10 @@ object SettingsPatch : BytecodePatch(
|
||||
if-eqz v$usableRegister, :do_not_open
|
||||
return-void
|
||||
""",
|
||||
ExternalLabel("do_not_open", getInstruction(initializeSettingsIndex))
|
||||
ExternalLabel("do_not_open", getInstruction(initializeSettingsIndex)),
|
||||
)
|
||||
} ?: throw AdPersonalizationActivityOnCreateFingerprint.exception
|
||||
}
|
||||
|
||||
private fun String.toClassName(): String {
|
||||
return substring(1, this.length - 1).replace("/", ".")
|
||||
}
|
||||
}
|
||||
private fun String.toClassName(): String = substring(1, this.length - 1).replace("/", ".")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package app.revanced.patches.tiktok.shared.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object GetEnterFromFingerprint : MethodFingerprint(
|
||||
returnType = "Ljava/lang/String;",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Z"),
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;")
|
||||
},
|
||||
)
|
||||
@@ -1,9 +1,10 @@
|
||||
package app.revanced.patches.tiktok.interaction.speed.fingerprints
|
||||
package app.revanced.patches.tiktok.shared.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object OnRenderFirstFrameFingerprint : MethodFingerprint(
|
||||
strings = listOf("method_enable_viewpager_preload_duration"),
|
||||
customFingerprint = { methodDef, _ ->
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;") && methodDef.name == "onRenderFirstFrame"
|
||||
}
|
||||
methodDef.definingClass.endsWith("/BaseListFragmentPanel;")
|
||||
},
|
||||
)
|
||||
@@ -10,5 +10,5 @@ internal object BuildMediaOptionsSheetFingerprint : MethodFingerprint(
|
||||
Opcode.GOTO_16,
|
||||
Opcode.NEW_INSTANCE,
|
||||
),
|
||||
strings = listOf("resources.getString(R.string.post_video)"),
|
||||
strings = listOf("mediaEntity", "media_options_sheet"),
|
||||
)
|
||||
|
||||
@@ -5,6 +5,6 @@ import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object ShowDownloadVideoUpsellBottomSheetFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
strings = listOf("variantToDownload.url"),
|
||||
strings = listOf("mediaEntity", "url"),
|
||||
opcodes = listOf(Opcode.IF_EQZ)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package app.revanced.patches.twitter.misc.links
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
|
||||
import app.revanced.patches.twitter.misc.links.fingerprints.LinkBuilderFingerprint
|
||||
import app.revanced.patches.twitter.misc.links.fingerprints.LinkResourceGetterFingerprint
|
||||
import app.revanced.patches.twitter.misc.links.fingerprints.LinkSharingDomainFingerprint
|
||||
import app.revanced.util.exception
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.StringReference
|
||||
|
||||
@Patch(
|
||||
name = "Change link sharing domain",
|
||||
description = "Replaces the domain name of Twitter links when sharing them.",
|
||||
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||
)
|
||||
@Suppress("unused")
|
||||
object ChangeLinkSharingDomainPatch : BytecodePatch(
|
||||
setOf(
|
||||
LinkBuilderFingerprint,
|
||||
LinkResourceGetterFingerprint,
|
||||
LinkSharingDomainFingerprint,
|
||||
),
|
||||
) {
|
||||
private var domainName by stringPatchOption(
|
||||
key = "domainName",
|
||||
default = "fxtwitter.com",
|
||||
title = "Domain name",
|
||||
description = "The domain name to use when sharing links.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
// This method is used to build the link that is shared when the "Share via..." button is pressed.
|
||||
private const val FORMAT_METHOD_RESOURCE_REFERENCE =
|
||||
"Lapp/revanced/integrations/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
|
||||
"formatResourceLink([Ljava/lang/Object;)Ljava/lang/String;"
|
||||
|
||||
// This method is used to build the link that is shared when the "Copy link" button is pressed.
|
||||
private const val FORMAT_METHOD_REFERENCE =
|
||||
"Lapp/revanced/integrations/twitter/patches/links/ChangeLinkSharingDomainPatch;->" +
|
||||
"formatLink(JLjava/lang/String;)Ljava/lang/String;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
LinkSharingDomainFingerprint.result?.let {
|
||||
val replacementIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
val domainRegister = it.mutableMethod.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
|
||||
it.mutableMethod.replaceInstruction(
|
||||
replacementIndex,
|
||||
"const-string v$domainRegister, \"https://$domainName\"",
|
||||
)
|
||||
} ?: throw LinkSharingDomainFingerprint.exception
|
||||
|
||||
// Replace the domain name when copying a link with "Copy link" button.
|
||||
LinkBuilderFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { p0, p1, p2 }, $FORMAT_METHOD_REFERENCE
|
||||
move-result-object p0
|
||||
return-object p0
|
||||
""",
|
||||
)
|
||||
}
|
||||
} ?: throw LinkBuilderFingerprint.exception
|
||||
|
||||
// Used in the Share via... dialog.
|
||||
LinkResourceGetterFingerprint.result?.mutableMethod?.apply {
|
||||
val constWithParameterName = indexOfFirstInstructionOrThrow {
|
||||
getReference<StringReference>()?.string?.contains("id.toString()") == true
|
||||
}
|
||||
|
||||
// Format the link with the new domain name register (2 instructions above the const-string).
|
||||
val formatLinkCallIndex = constWithParameterName - 2
|
||||
val formatLinkCall = getInstruction<Instruction35c>(formatLinkCallIndex)
|
||||
|
||||
// Replace the original method call with the new method call.
|
||||
replaceInstruction(
|
||||
formatLinkCallIndex,
|
||||
"invoke-static { v${formatLinkCall.registerE} }, $FORMAT_METHOD_RESOURCE_REFERENCE",
|
||||
)
|
||||
} ?: throw LinkResourceGetterFingerprint.exception
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import app.revanced.util.exception
|
||||
name = "Open links with app chooser",
|
||||
description = "Instead of opening links directly, open them with an app chooser. " +
|
||||
"As a result you can select a browser to open the link with.",
|
||||
compatiblePackages = [CompatiblePackage("com.twitter.android")],
|
||||
compatiblePackages = [CompatiblePackage("com.twitter.android", ["10.48.0-release.0"])],
|
||||
use = false,
|
||||
)
|
||||
@Suppress("unused")
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.twitter.misc.links.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
// Returns a shareable link string based on a tweet ID and a username.
|
||||
internal object LinkBuilderFingerprint : MethodFingerprint(
|
||||
strings = listOf("/%1\$s/status/%2\$d"),
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.twitter.misc.links.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
// Gets Resource string for share link view available by pressing "Share via" button.
|
||||
internal object LinkResourceGetterFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("Landroid/content/res/Resources;"),
|
||||
strings = listOf("res.getString(R.string.t…lUsername, id.toString())"),
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
package app.revanced.patches.twitter.misc.links.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
|
||||
internal object LinkSharingDomainFingerprint : MethodFingerprint(
|
||||
strings = listOf("https://fxtwitter.com"),
|
||||
)
|
||||
@@ -0,0 +1,28 @@
|
||||
package app.revanced.patches.willhaben.ads
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.willhaben.ads.fingerprints.AdResolverFingerprint
|
||||
import app.revanced.patches.willhaben.ads.fingerprints.WHAdViewInjectorFingerprint
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Patch(
|
||||
name = "Hide ads",
|
||||
description = "Hides all in-app ads.",
|
||||
compatiblePackages = [CompatiblePackage("at.willhaben")]
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideAdsPatch : BytecodePatch(
|
||||
fingerprints = setOf(
|
||||
AdResolverFingerprint,
|
||||
WHAdViewInjectorFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) {
|
||||
arrayOf(AdResolverFingerprint, WHAdViewInjectorFingerprint).forEach {
|
||||
it.returnEarly()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package app.revanced.patches.willhaben.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object AdResolverFingerprint : MethodFingerprint(
|
||||
"L",
|
||||
parameters = listOf("L", "L"),
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
strings = listOf(
|
||||
"Google Ad is invalid ",
|
||||
"Google Native Ad is invalid ",
|
||||
"Criteo Ad is invalid ",
|
||||
"Amazon Ad is invalid "
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package app.revanced.patches.willhaben.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object WHAdViewInjectorFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
parameters = listOf("L", "L", "L", "Z"),
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
strings = listOf("successfulAdView"),
|
||||
customFingerprint = { _, classDef ->
|
||||
classDef.type == "Lat/willhaben/advertising/WHAdView;"
|
||||
}
|
||||
)
|
||||
@@ -51,8 +51,8 @@ object CopyVideoUrlBytecodePatch : BytecodePatch(emptySet()) {
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
BUTTONS_DESCRIPTORS.forEach { descriptor ->
|
||||
PlayerControlsBytecodePatch.initializeControl("$descriptor->initializeButton(Landroid/view/View;)V")
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$descriptor->changeVisibility(Z)V")
|
||||
PlayerControlsBytecodePatch.initializeBottomControl(descriptor)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(descriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
@@ -13,7 +13,7 @@ import app.revanced.util.copyResources
|
||||
@Patch(
|
||||
dependencies = [
|
||||
SettingsPatch::class,
|
||||
BottomControlsResourcePatch::class,
|
||||
PlayerControlsResourcePatch::class,
|
||||
AddResourcesPatch::class
|
||||
]
|
||||
)
|
||||
@@ -34,6 +34,6 @@ internal object CopyVideoUrlResourcePatch : ResourcePatch() {
|
||||
)
|
||||
)
|
||||
|
||||
BottomControlsResourcePatch.addControls("copyvideourl")
|
||||
PlayerControlsResourcePatch.addBottomControls("copyvideourl")
|
||||
}
|
||||
}
|
||||
@@ -58,8 +58,8 @@ object DownloadsPatch : BytecodePatch(
|
||||
private const val BUTTON_DESCRIPTOR = "Lapp/revanced/integrations/youtube/videoplayer/ExternalDownloadButton;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
PlayerControlsBytecodePatch.initializeControl("$BUTTON_DESCRIPTOR->initializeButton(Landroid/view/View;)V")
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$BUTTON_DESCRIPTOR->changeVisibility(Z)V")
|
||||
PlayerControlsBytecodePatch.initializeBottomControl(BUTTON_DESCRIPTOR)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(BUTTON_DESCRIPTOR)
|
||||
|
||||
// Main activity is used to launch downloader intent.
|
||||
MainActivityFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
|
||||
@@ -9,14 +9,14 @@ import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.TextPreference
|
||||
import app.revanced.patches.youtube.misc.playercontrols.BottomControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
|
||||
@Patch(
|
||||
dependencies = [
|
||||
BottomControlsResourcePatch::class,
|
||||
PlayerControlsResourcePatch::class,
|
||||
SettingsPatch::class,
|
||||
AddResourcesPatch::class,
|
||||
],
|
||||
@@ -42,6 +42,6 @@ internal object DownloadsResourcePatch : ResourcePatch() {
|
||||
ResourceGroup("drawable", "revanced_yt_download_button.xml"),
|
||||
)
|
||||
|
||||
BottomControlsResourcePatch.addControls("downloads")
|
||||
PlayerControlsResourcePatch.addBottomControls("downloads")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.IsSwipingUpFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.AllowSwipingUpGestureFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.ShowSwipingUpGuideFingerprint
|
||||
import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SwipingUpGestureParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import app.revanced.util.alsoResolve
|
||||
|
||||
@Patch(
|
||||
name = "Disable precise seeking gesture",
|
||||
@@ -52,11 +54,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
)
|
||||
@Suppress("unused")
|
||||
object DisablePreciseSeekingGesturePatch : BytecodePatch(
|
||||
setOf(IsSwipingUpFingerprint)
|
||||
setOf(SwipingUpGestureParentFingerprint)
|
||||
) {
|
||||
private const val INTEGRATIONS_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;->" +
|
||||
"disableGesture(Landroid/view/VelocityTracker;Landroid/view/MotionEvent;)V"
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/DisablePreciseSeekingGesturePatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
@@ -65,19 +66,37 @@ object DisablePreciseSeekingGesturePatch : BytecodePatch(
|
||||
SwitchPreference("revanced_disable_precise_seeking_gesture")
|
||||
)
|
||||
|
||||
IsSwipingUpFingerprint.result?.let {
|
||||
val addMovementIndex = it.scanResult.patternScanResult!!.startIndex - 1
|
||||
AllowSwipingUpGestureFingerprint.alsoResolve(
|
||||
context,
|
||||
SwipingUpGestureParentFingerprint
|
||||
).mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isGestureDisabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :disabled
|
||||
return-void
|
||||
""",
|
||||
ExternalLabel("disabled", getInstruction(0))
|
||||
)
|
||||
}
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val addMovementInstruction = getInstruction<FiveRegisterInstruction>(addMovementIndex)
|
||||
val trackerRegister = addMovementInstruction.registerC
|
||||
val eventRegister = addMovementInstruction.registerD
|
||||
|
||||
replaceInstruction(
|
||||
addMovementIndex,
|
||||
"invoke-static {v$trackerRegister, v$eventRegister}, $INTEGRATIONS_METHOD_DESCRIPTOR"
|
||||
)
|
||||
}
|
||||
} ?: throw IsSwipingUpFingerprint.exception
|
||||
ShowSwipingUpGuideFingerprint.alsoResolve(
|
||||
context,
|
||||
SwipingUpGestureParentFingerprint
|
||||
).mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isGestureDisabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :disabled
|
||||
const/4 v0, 0x0
|
||||
return v0
|
||||
""",
|
||||
ExternalLabel("disabled", getInstruction(0))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* Resolves using the class found in [SwipingUpGestureParentFingerprint].
|
||||
*/
|
||||
internal object AllowSwipingUpGestureFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "V",
|
||||
parameters = listOf("L"),
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object IsSwipingUpFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
parameters = listOf("Landroid/view/MotionEvent;", "J"),
|
||||
opcodes = listOf(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IGET_OBJECT
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
/**
|
||||
* Resolves using the class found in [SwipingUpGestureParentFingerprint].
|
||||
*/
|
||||
internal object ShowSwipingUpGuideFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.FINAL.value,
|
||||
returnType = "Z",
|
||||
parameters = emptyList(),
|
||||
literalSupplier = { 1L }
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package app.revanced.patches.youtube.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object SwipingUpGestureParentFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "Z",
|
||||
parameters = listOf(),
|
||||
literalSupplier = { 45379021 }
|
||||
)
|
||||
@@ -18,13 +18,18 @@ import app.revanced.patches.youtube.layout.hide.general.fingerprints.HideShowMor
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ParseElementFromBufferFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.PlayerOverlayFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.ShowWatermarkFingerprint
|
||||
import app.revanced.patches.youtube.layout.hide.general.fingerprints.YoodlesImageViewFingerprint
|
||||
import app.revanced.patches.youtube.misc.litho.filter.LithoFilterPatch
|
||||
import app.revanced.patches.youtube.misc.navigation.NavigationBarHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.findOpcodeIndicesReversed
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Patch(
|
||||
name = "Hide layout components",
|
||||
@@ -70,7 +75,12 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
)
|
||||
@Suppress("unused")
|
||||
object HideLayoutComponentsPatch : BytecodePatch(
|
||||
setOf(ParseElementFromBufferFingerprint, PlayerOverlayFingerprint, HideShowMoreButtonFingerprint),
|
||||
setOf(
|
||||
ParseElementFromBufferFingerprint,
|
||||
PlayerOverlayFingerprint,
|
||||
HideShowMoreButtonFingerprint,
|
||||
YoodlesImageViewFingerprint,
|
||||
),
|
||||
) {
|
||||
private const val LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/components/LayoutComponentsFilter;"
|
||||
@@ -89,7 +99,6 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
SwitchPreference("revanced_hide_channel_guidelines"),
|
||||
SwitchPreference("revanced_hide_channel_member_shelf"),
|
||||
SwitchPreference("revanced_hide_channel_watermark"),
|
||||
SwitchPreference("revanced_hide_chips_shelf"),
|
||||
SwitchPreference("revanced_hide_community_guidelines"),
|
||||
PreferenceScreen(
|
||||
key = "revanced_hide_description_components_screen",
|
||||
@@ -129,6 +138,7 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
SwitchPreference("revanced_hide_search_result_recommendations"),
|
||||
SwitchPreference("revanced_hide_search_result_shelf_header"),
|
||||
SwitchPreference("revanced_hide_show_more_button"),
|
||||
SwitchPreference("revanced_hide_doodles"),
|
||||
PreferenceScreen(
|
||||
key = "revanced_hide_keyword_content_screen",
|
||||
sorting = Sorting.UNSORTED,
|
||||
@@ -138,11 +148,14 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
SwitchPreference("revanced_hide_keyword_content_search"),
|
||||
TextPreference("revanced_hide_keyword_content_phrases", inputType = InputType.TEXT_MULTI_LINE),
|
||||
NonInteractivePreference("revanced_hide_keyword_content_about"),
|
||||
),
|
||||
),
|
||||
NonInteractivePreference(key = "revanced_hide_keyword_content_about_whole_words",
|
||||
tag = "app.revanced.integrations.youtube.settings.preference.HtmlPreference")
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
SettingsPatch.PreferenceScreen.GENERAL_LAYOUT.addPreferences(
|
||||
SwitchPreference("revanced_hide_chips_shelf"),
|
||||
SwitchPreference("revanced_hide_expandable_chip"),
|
||||
SwitchPreference("revanced_hide_gray_separator"),
|
||||
PreferenceScreen(
|
||||
@@ -224,5 +237,28 @@ object HideLayoutComponentsPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region 'Yoodles'
|
||||
|
||||
YoodlesImageViewFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
findOpcodeIndicesReversed{
|
||||
opcode == Opcode.INVOKE_VIRTUAL
|
||||
&& getReference<MethodReference>()?.name == "setImageDrawable"
|
||||
}.forEach { insertIndex ->
|
||||
val register = getInstruction<FiveRegisterInstruction>(insertIndex).registerD
|
||||
|
||||
addInstructionsWithLabels(
|
||||
insertIndex,
|
||||
"""
|
||||
invoke-static { v$register }, $LAYOUT_COMPONENTS_FILTER_CLASS_DESCRIPTOR->hideYoodles(Landroid/graphics/drawable/Drawable;)Landroid/graphics/drawable/Drawable;
|
||||
move-result-object v$register
|
||||
if-eqz v$register, :hide
|
||||
""",
|
||||
ExternalLabel("hide", getInstruction(insertIndex + 1)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,17 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
internal object HideLayoutComponentsResourcePatch : ResourcePatch() {
|
||||
internal var expandButtonDownId: Long = -1
|
||||
|
||||
var youTubeLogo = -1L
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
expandButtonDownId = ResourceMappingPatch[
|
||||
"layout",
|
||||
"expand_button_down",
|
||||
]
|
||||
|
||||
youTubeLogo = ResourceMappingPatch[
|
||||
"id",
|
||||
"youtube_logo"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.layout.hide.general.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patches.youtube.layout.hide.general.HideLayoutComponentsResourcePatch
|
||||
import app.revanced.util.patch.LiteralValueFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object YoodlesImageViewFingerprint : LiteralValueFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
parameters = listOf("L", "L"),
|
||||
returnType = "Landroid/view/View;",
|
||||
literalSupplier = { HideLayoutComponentsResourcePatch.youTubeLogo }
|
||||
)
|
||||
@@ -6,6 +6,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.booleanPatchOption
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||
import app.revanced.patches.youtube.layout.hide.shorts.fingerprints.*
|
||||
@@ -76,6 +77,20 @@ object HideShortsComponentsPatch : BytecodePatch(
|
||||
) {
|
||||
private const val FILTER_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/components/ShortsFilter;"
|
||||
|
||||
internal val hideShortsAppShortcut by booleanPatchOption(
|
||||
key = "hideShortsAppShortcut",
|
||||
default = false,
|
||||
title = "Hide Shorts app shortcut",
|
||||
description = "Permanently hides the shortcut to open Shorts when long pressing the app icon in your launcher."
|
||||
)
|
||||
|
||||
internal val hideShortsWidget by booleanPatchOption(
|
||||
key = "hideShortsWidget",
|
||||
default = false,
|
||||
title = "Hide Shorts widget",
|
||||
description = "Permanently hides the launcher widget Shorts button."
|
||||
)
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
// region Hide the Shorts shelf.
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.layout.hide.shorts.HideShortsComponentsPatch.hideShortsAppShortcut
|
||||
import app.revanced.patches.youtube.layout.hide.shorts.HideShortsComponentsPatch.hideShortsWidget
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
||||
|
||||
@Patch(dependencies = [SettingsPatch::class, ResourceMappingPatch::class, AddResourcesPatch::class])
|
||||
object HideShortsComponentsResourcePatch : ResourcePatch() {
|
||||
@@ -26,6 +29,7 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
|
||||
// since this Setting menu currently uses the ordering used here.
|
||||
|
||||
// Vertical row of buttons on right side of the screen.
|
||||
SwitchPreference("revanced_hide_shorts_like_fountain"),
|
||||
SwitchPreference("revanced_hide_shorts_like_button"),
|
||||
SwitchPreference("revanced_hide_shorts_dislike_button"),
|
||||
SwitchPreference("revanced_hide_shorts_comments_button"),
|
||||
@@ -38,8 +42,12 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
|
||||
SwitchPreference("revanced_hide_shorts_subscribe_button"),
|
||||
SwitchPreference("revanced_hide_shorts_paused_overlay_buttons"),
|
||||
SwitchPreference("revanced_hide_shorts_save_sound_button"),
|
||||
SwitchPreference("revanced_hide_shorts_use_template_button"),
|
||||
SwitchPreference("revanced_hide_shorts_upcoming_button"),
|
||||
SwitchPreference("revanced_hide_shorts_green_screen_button"),
|
||||
SwitchPreference("revanced_hide_shorts_shop_button"),
|
||||
SwitchPreference("revanced_hide_shorts_tagged_products"),
|
||||
SwitchPreference("revanced_hide_shorts_stickers"),
|
||||
SwitchPreference("revanced_hide_shorts_search_suggestions"),
|
||||
SwitchPreference("revanced_hide_shorts_super_thanks_button"),
|
||||
SwitchPreference("revanced_hide_shorts_location_label"),
|
||||
@@ -51,6 +59,28 @@ object HideShortsComponentsResourcePatch : ResourcePatch() {
|
||||
SwitchPreference("revanced_hide_shorts_navigation_bar"),
|
||||
)
|
||||
|
||||
if (hideShortsAppShortcut == true) {
|
||||
context.xmlEditor["res/xml/main_shortcuts.xml"].use { editor ->
|
||||
val shortsItem = editor.file.childNodes.findElementByAttributeValueOrThrow(
|
||||
"android:shortcutId",
|
||||
"shorts-shortcut",
|
||||
)
|
||||
|
||||
shortsItem.parentNode.removeChild(shortsItem)
|
||||
}
|
||||
}
|
||||
|
||||
if (hideShortsWidget == true) {
|
||||
context.xmlEditor["res/layout/appwidget_two_rows.xml"].use { editor ->
|
||||
val shortsItem = editor.file.childNodes.findElementByAttributeValueOrThrow(
|
||||
"android:id",
|
||||
"@id/button_shorts_container",
|
||||
)
|
||||
|
||||
shortsItem.parentNode.removeChild(shortsItem)
|
||||
}
|
||||
}
|
||||
|
||||
reelPlayerRightCellButtonHeight = ResourceMappingPatch[
|
||||
"dimen",
|
||||
"reel_player_right_cell_button_height",
|
||||
|
||||
@@ -10,7 +10,6 @@ import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.AppendTimeFingerprint
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.ControlsOverlayFingerprint
|
||||
import app.revanced.patches.youtube.layout.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint
|
||||
@@ -26,7 +25,10 @@ import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.video.videoid.VideoIdPatch
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.*
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
@@ -169,59 +171,14 @@ object SponsorBlockBytecodePatch : BytecodePatch(
|
||||
break
|
||||
}
|
||||
|
||||
/*
|
||||
* Voting & Shield button
|
||||
*/
|
||||
val controlsMethodResult = PlayerControlsBytecodePatch.showPlayerControlsFingerprintResult
|
||||
// Change visibility of the buttons.
|
||||
PlayerControlsBytecodePatch.initializeTopControl(INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR)
|
||||
|
||||
val controlsLayoutStubResourceId =
|
||||
ResourceMappingPatch["id", "controls_layout_stub"]
|
||||
val zoomOverlayResourceId =
|
||||
ResourceMappingPatch["id", "video_zoom_overlay_stub"]
|
||||
PlayerControlsBytecodePatch.initializeTopControl(INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR)
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall(INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR)
|
||||
|
||||
methods@ for (method in controlsMethodResult.mutableClass.methods) {
|
||||
val instructions = method.implementation?.instructions!!
|
||||
instructions@ for ((index, instruction) in instructions.withIndex()) {
|
||||
// search for method which inflates the controls layout view
|
||||
if (instruction.opcode != Opcode.CONST) continue@instructions
|
||||
|
||||
when ((instruction as NarrowLiteralInstruction).wideLiteral) {
|
||||
controlsLayoutStubResourceId -> {
|
||||
// replace the view with the YouTubeControlsOverlay
|
||||
val moveResultInstructionIndex = index + 5
|
||||
val inflatedViewRegister =
|
||||
(instructions[moveResultInstructionIndex] as OneRegisterInstruction).registerA
|
||||
// initialize with the player overlay object
|
||||
method.addInstructions(
|
||||
moveResultInstructionIndex + 1, // insert right after moving the view to the register and use that register
|
||||
"""
|
||||
invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
|
||||
invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Landroid/view/View;)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
zoomOverlayResourceId -> {
|
||||
val invertVisibilityMethod =
|
||||
context.toMethodWalker(method).nextMethod(index - 6, true).getMethod() as MutableMethod
|
||||
// change visibility of the buttons
|
||||
invertVisibilityMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static {p1}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V
|
||||
invoke-static {p1}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V
|
||||
""".trimIndent(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// change visibility of the buttons
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibility(Z)V")
|
||||
PlayerControlsBytecodePatch.injectVisibilityCheckCall("$INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibility(Z)V")
|
||||
|
||||
// append the new time to the player layout
|
||||
// Append the new time to the player layout.
|
||||
val appendTimeFingerprintResult = AppendTimeFingerprint.result!!
|
||||
val appendTimePatternScanStartIndex = appendTimeFingerprintResult.scanResult.patternScanResult!!.startIndex
|
||||
val targetRegister =
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package app.revanced.patches.youtube.layout.sponsorblock
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.IntentPreference
|
||||
import app.revanced.patches.youtube.misc.playercontrols.PlayerControlsResourcePatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsResourcePatch
|
||||
import app.revanced.util.ResourceGroup
|
||||
import app.revanced.util.copyResources
|
||||
import app.revanced.util.copyXmlNode
|
||||
import app.revanced.util.inputStreamFromBundledResource
|
||||
|
||||
@Patch(
|
||||
dependencies = [
|
||||
@@ -60,49 +58,6 @@ internal object SponsorBlockResourcePatch : ResourcePatch() {
|
||||
context.copyResources("sponsorblock", resourceGroup)
|
||||
}
|
||||
|
||||
// copy nodes from host resources to their real xml files
|
||||
|
||||
val hostingResourceStream =
|
||||
inputStreamFromBundledResource(
|
||||
"sponsorblock",
|
||||
"host/layout/youtube_controls_layout.xml",
|
||||
)!!
|
||||
|
||||
var modifiedControlsLayout = false
|
||||
val editor = context.xmlEditor["res/layout/youtube_controls_layout.xml"]
|
||||
"RelativeLayout".copyXmlNode(
|
||||
context.xmlEditor[hostingResourceStream],
|
||||
editor,
|
||||
).also {
|
||||
val document = editor.file
|
||||
|
||||
val children = document.getElementsByTagName("RelativeLayout").item(0).childNodes
|
||||
|
||||
// Replace the startOf with the voting button view so that the button does not overlap
|
||||
for (i in 1 until children.length) {
|
||||
val view = children.item(i)
|
||||
|
||||
// Replace the attribute for a specific node only
|
||||
if (!(
|
||||
view.hasAttributes() &&
|
||||
view.attributes.getNamedItem(
|
||||
"android:id",
|
||||
).nodeValue.endsWith("live_chat_overlay_button")
|
||||
)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
// voting button id from the voting button view from the youtube_controls_layout.xml host file
|
||||
val votingButtonId = "@+id/revanced_sb_voting_button"
|
||||
|
||||
view.attributes.getNamedItem("android:layout_toStartOf").nodeValue = votingButtonId
|
||||
|
||||
modifiedControlsLayout = true
|
||||
break
|
||||
}
|
||||
}.close()
|
||||
|
||||
if (!modifiedControlsLayout) throw PatchException("Could not modify controls layout")
|
||||
PlayerControlsResourcePatch.addTopControls("sponsorblock")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.revanced.patches.youtube.misc.check
|
||||
|
||||
import app.revanced.patches.shared.misc.checks.BaseCheckEnvironmentPatch
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint
|
||||
|
||||
@Suppress("unused")
|
||||
object CheckEnvironmentPatch :
|
||||
BaseCheckEnvironmentPatch(
|
||||
mainActivityOnCreateFingerprint = MainActivityOnCreateFingerprint,
|
||||
integrationsPatch = IntegrationsPatch,
|
||||
compatiblePackages = setOf(CompatiblePackage("com.google.android.youtube")),
|
||||
)
|
||||
@@ -3,6 +3,7 @@ package app.revanced.patches.youtube.misc.dns
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
|
||||
@@ -13,6 +14,37 @@ import app.revanced.util.resultOrThrow
|
||||
name = "Check watch history domain name resolution",
|
||||
description = "Checks if the device DNS server is preventing user watch history from being saved.",
|
||||
dependencies = [IntegrationsPatch::class],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.32.39",
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.39",
|
||||
"19.03.36",
|
||||
"19.04.38",
|
||||
"19.05.36",
|
||||
"19.06.39",
|
||||
"19.07.40",
|
||||
"19.08.36",
|
||||
"19.09.38",
|
||||
"19.10.39",
|
||||
"19.11.43",
|
||||
"19.12.41",
|
||||
"19.13.37",
|
||||
"19.14.43",
|
||||
"19.15.36",
|
||||
"19.16.39",
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
@Suppress("unused")
|
||||
internal object CheckWatchHistoryDomainNameResolutionPatch : BytecodePatch(
|
||||
|
||||
@@ -1,390 +1,11 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playback
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.backgroundplayback.BackgroundPlaybackPatch
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.TypeReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
@Patch(
|
||||
name = "Spoof client",
|
||||
description = "Spoofs the client to allow video playback.",
|
||||
dependencies = [
|
||||
SettingsPatch::class,
|
||||
AddResourcesPatch::class,
|
||||
UserAgentClientSpoofPatch::class,
|
||||
// Required since iOS livestream fix partially enables background playback.
|
||||
BackgroundPlaybackPatch::class,
|
||||
PlayerTypeHookPatch::class,
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
// This patch works with these versions,
|
||||
// but the dependent background playback patch does not.
|
||||
// "18.37.36",
|
||||
// "18.38.44",
|
||||
// "18.43.45",
|
||||
// "18.44.41",
|
||||
// "18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.39",
|
||||
"19.03.36",
|
||||
"19.04.38",
|
||||
"19.05.36",
|
||||
"19.06.39",
|
||||
"19.07.40",
|
||||
"19.08.36",
|
||||
"19.09.38",
|
||||
"19.10.39",
|
||||
"19.11.43",
|
||||
"19.12.41",
|
||||
"19.13.37",
|
||||
"19.14.43",
|
||||
"19.15.36",
|
||||
"19.16.39",
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
@Deprecated("This patch is obsolete.", replaceWith = ReplaceWith("SpoofVideoStreamsPatch"))
|
||||
object SpoofClientPatch : BytecodePatch(
|
||||
setOf(
|
||||
// Client type spoof.
|
||||
BuildInitPlaybackRequestFingerprint,
|
||||
BuildPlayerRequestURIFingerprint,
|
||||
SetPlayerRequestClientTypeFingerprint,
|
||||
CreatePlayerRequestBodyFingerprint,
|
||||
CreatePlayerRequestBodyWithModelFingerprint,
|
||||
CreatePlayerRequestBodyWithVersionReleaseFingerprint,
|
||||
|
||||
// Player gesture config.
|
||||
PlayerGestureConfigSyntheticFingerprint,
|
||||
|
||||
// Player speed menu item.
|
||||
CreatePlaybackSpeedMenuItemFingerprint,
|
||||
|
||||
// Video qualities missing.
|
||||
BuildRequestFingerprint,
|
||||
|
||||
// Livestream audio only background playback.
|
||||
PlayerResponseModelBackgroundAudioPlaybackFingerprint,
|
||||
)
|
||||
dependencies = setOf(SpoofVideoStreamsPatch::class),
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofClientPatch;"
|
||||
private const val CLIENT_INFO_CLASS_DESCRIPTOR =
|
||||
"Lcom/google/protos/youtube/api/innertube/InnertubeContext\$ClientInfo;"
|
||||
private const val REQUEST_CLASS_DESCRIPTOR =
|
||||
"Lorg/chromium/net/ExperimentalUrlRequest;"
|
||||
private const val REQUEST_BUILDER_CLASS_DESCRIPTOR =
|
||||
"Lorg/chromium/net/ExperimentalUrlRequest\$Builder;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreen(
|
||||
key = "revanced_spoof_client_screen",
|
||||
sorting = PreferenceScreen.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_client"),
|
||||
SwitchPreference("revanced_spoof_client_use_ios"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
||||
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
|
||||
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Get field references to be used below.
|
||||
|
||||
val (clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField) =
|
||||
SetPlayerRequestClientTypeFingerprint.resultOrThrow().let { result ->
|
||||
// Field in the player request object that holds the client info object.
|
||||
val clientInfoField = result.mutableMethod
|
||||
.getInstructions().find { instruction ->
|
||||
// requestMessage.clientInfo = clientInfoBuilder.build();
|
||||
instruction.opcode == Opcode.IPUT_OBJECT &&
|
||||
instruction.getReference<FieldReference>()?.type == CLIENT_INFO_CLASS_DESCRIPTOR
|
||||
}?.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoField")
|
||||
|
||||
// Client info object's client type field.
|
||||
val clientInfoClientTypeField = result.mutableMethod
|
||||
.getInstruction(result.scanResult.patternScanResult!!.endIndex)
|
||||
.getReference<FieldReference>() ?: throw PatchException("Could not find clientInfoClientTypeField")
|
||||
|
||||
// Client info object's client version field.
|
||||
val clientInfoClientVersionField = result.mutableMethod
|
||||
.getInstruction(result.scanResult.stringsScanResult!!.matches.first().index + 1)
|
||||
.getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoClientVersionField")
|
||||
|
||||
Triple(clientInfoField, clientInfoClientTypeField, clientInfoClientVersionField)
|
||||
}
|
||||
|
||||
val clientInfoClientModelField = CreatePlayerRequestBodyWithModelFingerprint.resultOrThrow().let {
|
||||
val getClientModelIndex =
|
||||
CreatePlayerRequestBodyWithModelFingerprint.indexOfBuildModelInstruction(it.method)
|
||||
|
||||
// The next IPUT_OBJECT instruction after getting the client model is setting the client model field.
|
||||
val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getClientModelIndex) {
|
||||
opcode == Opcode.IPUT_OBJECT
|
||||
}
|
||||
|
||||
it.mutableMethod.getInstruction(index).getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoClientModelField")
|
||||
}
|
||||
|
||||
val clientInfoOsVersionField = CreatePlayerRequestBodyWithVersionReleaseFingerprint.resultOrThrow().let {
|
||||
val getOsVersionIndex =
|
||||
CreatePlayerRequestBodyWithVersionReleaseFingerprint.indexOfBuildVersionReleaseInstruction(it.method)
|
||||
|
||||
// The next IPUT_OBJECT instruction after getting the client os version is setting the client os version field.
|
||||
val index = it.mutableMethod.indexOfFirstInstructionOrThrow(getOsVersionIndex) {
|
||||
opcode == Opcode.IPUT_OBJECT
|
||||
}
|
||||
|
||||
it.mutableMethod.getInstruction(index).getReference<FieldReference>()
|
||||
?: throw PatchException("Could not find clientInfoOsVersionField")
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Spoof client type for /player requests.
|
||||
|
||||
CreatePlayerRequestBodyFingerprint.resultOrThrow().let { result ->
|
||||
val setClientInfoMethodName = "patch_setClientInfo"
|
||||
val checkCastIndex = result.scanResult.patternScanResult!!.startIndex
|
||||
var clientInfoContainerClassName: String
|
||||
|
||||
result.mutableMethod.apply {
|
||||
val checkCastInstruction = getInstruction<OneRegisterInstruction>(checkCastIndex)
|
||||
val requestMessageInstanceRegister = checkCastInstruction.registerA
|
||||
clientInfoContainerClassName = checkCastInstruction.getReference<TypeReference>()!!.type
|
||||
|
||||
addInstruction(
|
||||
checkCastIndex + 1,
|
||||
"invoke-static { v$requestMessageInstanceRegister }," +
|
||||
" ${result.classDef.type}->$setClientInfoMethodName($clientInfoContainerClassName)V",
|
||||
)
|
||||
}
|
||||
|
||||
// Change client info to use the spoofed values.
|
||||
// Do this in a helper method, to remove the need of picking out multiple free registers from the hooked code.
|
||||
result.mutableClass.methods.add(
|
||||
ImmutableMethod(
|
||||
result.mutableClass.type,
|
||||
setClientInfoMethodName,
|
||||
listOf(ImmutableMethodParameter(clientInfoContainerClassName, null, "clientInfoContainer")),
|
||||
"V",
|
||||
AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(3),
|
||||
).toMutable().apply {
|
||||
addInstructions(
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isClientSpoofingEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :disabled
|
||||
|
||||
iget-object v0, p0, $clientInfoField
|
||||
|
||||
# Set client type to the spoofed value.
|
||||
iget v1, v0, $clientInfoClientTypeField
|
||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientTypeId(I)I
|
||||
move-result v1
|
||||
iput v1, v0, $clientInfoClientTypeField
|
||||
|
||||
# Set client model to the spoofed value.
|
||||
iget-object v1, v0, $clientInfoClientModelField
|
||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientModel(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $clientInfoClientModelField
|
||||
|
||||
# Set client version to the spoofed value.
|
||||
iget-object v1, v0, $clientInfoClientVersionField
|
||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getClientVersion(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $clientInfoClientVersionField
|
||||
|
||||
# Set client os version to the spoofed value.
|
||||
iget-object v1, v0, $clientInfoOsVersionField
|
||||
invoke-static { v1 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getOsVersion(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $clientInfoOsVersionField
|
||||
|
||||
:disabled
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix player gesture if spoofing to iOS.
|
||||
|
||||
PlayerGestureConfigSyntheticFingerprint.resultOrThrow().let {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val downAndOutLandscapeAllowedIndex = endIndex - 3
|
||||
val downAndOutPortraitAllowedIndex = endIndex - 9
|
||||
|
||||
arrayOf(
|
||||
downAndOutLandscapeAllowedIndex,
|
||||
downAndOutPortraitAllowedIndex,
|
||||
).forEach { index ->
|
||||
val gestureAllowedMethod = context.toMethodWalker(it.mutableMethod)
|
||||
.nextMethod(index, true)
|
||||
.getMethod() as MutableMethod
|
||||
|
||||
gestureAllowedMethod.apply {
|
||||
val isAllowedIndex = getInstructions().lastIndex
|
||||
val isAllowed = getInstruction<OneRegisterInstruction>(isAllowedIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
isAllowedIndex,
|
||||
"""
|
||||
invoke-static { v$isAllowed }, $INTEGRATIONS_CLASS_DESCRIPTOR->enablePlayerGesture(Z)Z
|
||||
move-result v$isAllowed
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix livestream audio only background play if spoofing to iOS.
|
||||
// This force enables audio background playback.
|
||||
|
||||
PlayerResponseModelBackgroundAudioPlaybackFingerprint.resultOrThrow().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->overrideBackgroundAudioPlayback()Z
|
||||
move-result v0
|
||||
if-eqz v0, :do_not_override
|
||||
return v0
|
||||
:do_not_override
|
||||
nop
|
||||
"""
|
||||
)
|
||||
|
||||
// endregion
|
||||
|
||||
// Fix playback speed menu item if spoofing to iOS.
|
||||
|
||||
CreatePlaybackSpeedMenuItemFingerprint.resultOrThrow().let {
|
||||
val scanResult = it.scanResult.patternScanResult!!
|
||||
if (scanResult.startIndex != 0) throw PatchException("Unexpected start index: ${scanResult.startIndex}")
|
||||
|
||||
it.mutableMethod.apply {
|
||||
// Find the conditional check if the playback speed menu item is not created.
|
||||
val shouldCreateMenuIndex =
|
||||
indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode.IF_EQZ }
|
||||
val shouldCreateMenuRegister = getInstruction<OneRegisterInstruction>(shouldCreateMenuIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
shouldCreateMenuIndex,
|
||||
"""
|
||||
invoke-static { v$shouldCreateMenuRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->forceCreatePlaybackSpeedMenu(Z)Z
|
||||
move-result v$shouldCreateMenuRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Fix video qualities missing, if spoofing to iOS by overriding the user agent.
|
||||
|
||||
BuildRequestFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val buildRequestIndex = getInstructions().lastIndex - 2
|
||||
val requestBuilderRegister = getInstruction<FiveRegisterInstruction>(buildRequestIndex).registerC
|
||||
|
||||
val newRequestBuilderIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
|
||||
|
||||
// Replace "requestBuilder.build(): Request" with "overrideUserAgent(requestBuilder, url): Request".
|
||||
replaceInstruction(
|
||||
buildRequestIndex,
|
||||
"invoke-static { v$requestBuilderRegister, v$urlRegister }, " +
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->" +
|
||||
"overrideUserAgent(${REQUEST_BUILDER_CLASS_DESCRIPTOR}Ljava/lang/String;)" +
|
||||
REQUEST_CLASS_DESCRIPTOR
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
@@ -1,239 +1,12 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playback
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.playertype.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.patches.youtube.video.information.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
|
||||
import app.revanced.util.exception
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
@Patch(
|
||||
description = "Spoofs the signature to prevent playback issues.",
|
||||
dependencies = [
|
||||
SettingsPatch::class,
|
||||
PlayerTypeHookPatch::class,
|
||||
PlayerResponseMethodHookPatch::class,
|
||||
VideoInformationPatch::class,
|
||||
SpoofSignatureResourcePatch::class,
|
||||
AddResourcesPatch::class,
|
||||
],
|
||||
)
|
||||
@Deprecated("This patch will be removed in the future.")
|
||||
@Deprecated("This patch is obsolete.", replaceWith = ReplaceWith("SpoofVideoStreamsPatch"))
|
||||
object SpoofSignaturePatch : BytecodePatch(
|
||||
setOf(
|
||||
PlayerResponseModelImplGeneralFingerprint,
|
||||
PlayerResponseModelImplLiveStreamFingerprint,
|
||||
PlayerResponseModelImplRecommendedLevelFingerprint,
|
||||
StoryboardRendererSpecFingerprint,
|
||||
StoryboardRendererDecoderSpecFingerprint,
|
||||
StoryboardRendererDecoderRecommendedLevelFingerprint,
|
||||
StoryboardThumbnailParentFingerprint,
|
||||
SpoofSignaturePatchScrubbedPreviewLayoutFingerprint,
|
||||
StatsQueryParameterFingerprint,
|
||||
ParamsMapPutFingerprint,
|
||||
),
|
||||
dependencies = setOf(SpoofVideoStreamsPatch::class),
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofSignaturePatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreen(
|
||||
key = "revanced_spoof_signature_verification_screen",
|
||||
sorting = Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_signature_verification_enabled"),
|
||||
SwitchPreference("revanced_spoof_signature_in_feed_enabled"),
|
||||
SwitchPreference("revanced_spoof_storyboard"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// Hook the player parameters.
|
||||
PlayerResponseMethodHookPatch += PlayerResponseMethodHookPatch.Hook.ProtoBufferParameter(
|
||||
"$INTEGRATIONS_CLASS_DESCRIPTOR->spoofParameter(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
|
||||
)
|
||||
|
||||
// Force the seekbar time and chapters to always show up.
|
||||
// This is used if the storyboard spec fetch fails, for viewing paid videos,
|
||||
// or if storyboard spoofing is turned off.
|
||||
StoryboardThumbnailParentFingerprint.result?.classDef?.let { classDef ->
|
||||
StoryboardThumbnailFingerprint.also {
|
||||
it.resolve(
|
||||
context,
|
||||
classDef,
|
||||
)
|
||||
}.result?.let {
|
||||
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
// Replace existing instruction to preserve control flow label.
|
||||
// The replaced return instruction always returns false
|
||||
// (it is the 'no thumbnails found' control path),
|
||||
// so there is no need to pass the existing return value to integrations.
|
||||
it.mutableMethod.replaceInstruction(
|
||||
endIndex,
|
||||
"""
|
||||
invoke-static {}, $INTEGRATIONS_CLASS_DESCRIPTOR->getSeekbarThumbnailOverrideValue()Z
|
||||
""",
|
||||
)
|
||||
// Since this is end of the method must replace one line then add the rest.
|
||||
it.mutableMethod.addInstructions(
|
||||
endIndex + 1,
|
||||
"""
|
||||
move-result v0
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
} ?: throw StoryboardThumbnailFingerprint.exception
|
||||
}
|
||||
|
||||
// If storyboard spoofing is turned off, then hide the empty seekbar thumbnail view.
|
||||
SpoofSignaturePatchScrubbedPreviewLayoutFingerprint.result?.apply {
|
||||
val endIndex = scanResult.patternScanResult!!.endIndex
|
||||
mutableMethod.apply {
|
||||
val imageViewFieldName = getInstruction<ReferenceInstruction>(endIndex).reference
|
||||
addInstructions(
|
||||
implementation!!.instructions.lastIndex,
|
||||
"""
|
||||
iget-object v0, p0, $imageViewFieldName # copy imageview field to a register
|
||||
invoke-static {v0}, $INTEGRATIONS_CLASS_DESCRIPTOR->seekbarImageViewCreated(Landroid/widget/ImageView;)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
} ?: throw SpoofSignaturePatchScrubbedPreviewLayoutFingerprint.exception
|
||||
|
||||
/**
|
||||
* Hook StoryBoard renderer url
|
||||
*/
|
||||
arrayOf(
|
||||
PlayerResponseModelImplGeneralFingerprint,
|
||||
PlayerResponseModelImplLiveStreamFingerprint,
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val getStoryBoardIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val getStoryBoardRegister =
|
||||
getInstruction<OneRegisterInstruction>(getStoryBoardIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
getStoryBoardIndex,
|
||||
"""
|
||||
invoke-static { v$getStoryBoardRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$getStoryBoardRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
} ?: throw fingerprint.exception
|
||||
}
|
||||
|
||||
// Hook recommended seekbar thumbnails quality level.
|
||||
StoryboardRendererDecoderRecommendedLevelFingerprint.result?.let {
|
||||
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val originalValueRegister = it.mutableMethod
|
||||
.getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
|
||||
|
||||
it.mutableMethod.addInstructions(
|
||||
moveOriginalRecommendedValueIndex + 1,
|
||||
"""
|
||||
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
|
||||
move-result v$originalValueRegister
|
||||
""",
|
||||
)
|
||||
} ?: throw StoryboardRendererDecoderRecommendedLevelFingerprint.exception
|
||||
|
||||
// Hook the recommended precise seeking thumbnails quality level.
|
||||
PlayerResponseModelImplRecommendedLevelFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val moveOriginalRecommendedValueIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val originalValueRegister =
|
||||
getInstruction<OneRegisterInstruction>(moveOriginalRecommendedValueIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveOriginalRecommendedValueIndex,
|
||||
"""
|
||||
invoke-static { v$originalValueRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getRecommendedLevel(I)I
|
||||
move-result v$originalValueRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
} ?: throw PlayerResponseModelImplRecommendedLevelFingerprint.exception
|
||||
|
||||
StoryboardRendererSpecFingerprint.result?.let {
|
||||
it.mutableMethod.apply {
|
||||
val storyBoardUrlParams = 0
|
||||
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
if-nez p$storyBoardUrlParams, :ignore
|
||||
invoke-static { p$storyBoardUrlParams }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object p$storyBoardUrlParams
|
||||
""",
|
||||
ExternalLabel("ignore", getInstruction(0)),
|
||||
)
|
||||
}
|
||||
} ?: throw StoryboardRendererSpecFingerprint.exception
|
||||
|
||||
// Hook the seekbar thumbnail decoder and use a NULL spec for live streams.
|
||||
StoryboardRendererDecoderSpecFingerprint.result?.let {
|
||||
val storyBoardUrlIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||
val storyboardUrlRegister =
|
||||
it.mutableMethod.getInstruction<OneRegisterInstruction>(storyBoardUrlIndex).registerA
|
||||
|
||||
it.mutableMethod.addInstructions(
|
||||
storyBoardUrlIndex + 1,
|
||||
"""
|
||||
invoke-static { v$storyboardUrlRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStoryboardDecoderRendererSpec(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$storyboardUrlRegister
|
||||
""",
|
||||
)
|
||||
} ?: throw StoryboardRendererDecoderSpecFingerprint.exception
|
||||
|
||||
// Fix stats not being tracked.
|
||||
// Due to signature spoofing "adformat" is present in query parameters made for /stats requests,
|
||||
// even though, for regular videos, it should not be.
|
||||
// This breaks stats tracking.
|
||||
// Replace the ad parameter with the video parameter in the query parameters.
|
||||
StatsQueryParameterFingerprint.result?.let {
|
||||
val putMethod = ParamsMapPutFingerprint.result?.method?.toString()
|
||||
?: throw ParamsMapPutFingerprint.exception
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val adParamIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
val videoParamIndex = adParamIndex + 3
|
||||
|
||||
// Replace the ad parameter with the video parameter.
|
||||
replaceInstruction(adParamIndex, getInstruction(videoParamIndex))
|
||||
|
||||
// Call paramsMap.put instead of paramsMap.putIfNotExist
|
||||
// because the key is already present in the map.
|
||||
val putAdParamIndex = adParamIndex + 1
|
||||
val putIfKeyNotExistsInstruction = getInstruction<FiveRegisterInstruction>(putAdParamIndex)
|
||||
replaceInstruction(
|
||||
putAdParamIndex,
|
||||
"invoke-virtual { " +
|
||||
"v${putIfKeyNotExistsInstruction.registerC}, " +
|
||||
"v${putIfKeyNotExistsInstruction.registerD}, " +
|
||||
"v${putIfKeyNotExistsInstruction.registerE} }, " +
|
||||
putMethod,
|
||||
)
|
||||
}
|
||||
} ?: throw StatsQueryParameterFingerprint.exception
|
||||
}
|
||||
override fun execute(context: BytecodeContext) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,18 +2,8 @@ package app.revanced.patches.youtube.misc.fix.playback
|
||||
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.ResourcePatch
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patches.shared.misc.mapping.ResourceMappingPatch
|
||||
|
||||
@Patch(dependencies = [ResourceMappingPatch::class])
|
||||
@Deprecated("This patch will be removed in the future.")
|
||||
object SpoofSignatureResourcePatch : ResourcePatch() {
|
||||
internal var scrubbedPreviewThumbnailResourceId: Long = -1
|
||||
|
||||
override fun execute(context: ResourceContext) {
|
||||
scrubbedPreviewThumbnailResourceId = ResourceMappingPatch[
|
||||
"id",
|
||||
"thumbnail",
|
||||
]
|
||||
}
|
||||
override fun execute(context: ResourceContext) {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playback
|
||||
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||
import app.revanced.patcher.patch.annotation.Patch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patches.all.misc.resources.AddResourcesPatch
|
||||
import app.revanced.patches.shared.misc.settings.preference.ListPreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
|
||||
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen
|
||||
import app.revanced.patches.shared.misc.settings.preference.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildInitPlaybackRequestFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildMediaDataSourceFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildPlayerRequestURIFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.BuildRequestFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.CreateStreamingDataFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufClassParseByteBufferFingerprint
|
||||
import app.revanced.patches.youtube.misc.settings.SettingsPatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.resultOrThrow
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
||||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
@Patch(
|
||||
name = "Spoof video streams",
|
||||
description = "Spoofs the client video streams to allow video playback.",
|
||||
dependencies = [
|
||||
SettingsPatch::class,
|
||||
AddResourcesPatch::class,
|
||||
UserAgentClientSpoofPatch::class,
|
||||
],
|
||||
compatiblePackages = [
|
||||
CompatiblePackage(
|
||||
"com.google.android.youtube",
|
||||
[
|
||||
"18.37.36",
|
||||
"18.38.44",
|
||||
"18.43.45",
|
||||
"18.44.41",
|
||||
"18.45.43",
|
||||
"18.48.39",
|
||||
"18.49.37",
|
||||
"19.01.34",
|
||||
"19.02.39",
|
||||
"19.03.36",
|
||||
"19.04.38",
|
||||
"19.05.36",
|
||||
"19.06.39",
|
||||
"19.07.40",
|
||||
"19.08.36",
|
||||
"19.09.38",
|
||||
"19.10.39",
|
||||
"19.11.43",
|
||||
"19.12.41",
|
||||
"19.13.37",
|
||||
"19.14.43",
|
||||
"19.15.36",
|
||||
"19.16.39",
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
object SpoofVideoStreamsPatch : BytecodePatch(
|
||||
setOf(
|
||||
BuildInitPlaybackRequestFingerprint,
|
||||
BuildPlayerRequestURIFingerprint,
|
||||
CreateStreamingDataFingerprint,
|
||||
BuildMediaDataSourceFingerprint,
|
||||
BuildRequestFingerprint,
|
||||
ProtobufClassParseByteBufferFingerprint,
|
||||
),
|
||||
) {
|
||||
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/youtube/patches/spoof/SpoofVideoStreamsPatch;"
|
||||
|
||||
override fun execute(context: BytecodeContext) {
|
||||
AddResourcesPatch(this::class)
|
||||
|
||||
SettingsPatch.PreferenceScreen.MISC.addPreferences(
|
||||
PreferenceScreen(
|
||||
key = "revanced_spoof_video_streams_screen",
|
||||
sorting = PreferenceScreen.Sorting.UNSORTED,
|
||||
preferences = setOf(
|
||||
SwitchPreference("revanced_spoof_video_streams"),
|
||||
ListPreference(
|
||||
"revanced_spoof_video_streams_client",
|
||||
summaryKey = null
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_spoof_video_streams_ios_force_avc",
|
||||
tag = "app.revanced.integrations.youtube.settings.preference.ForceAVCSpoofingPreference",
|
||||
),
|
||||
NonInteractivePreference("revanced_spoof_video_streams_about_android_vr"),
|
||||
NonInteractivePreference("revanced_spoof_video_streams_about_ios"),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// region Block /initplayback requests to fall back to /get_watch requests.
|
||||
|
||||
BuildInitPlaybackRequestFingerprint.resultOrThrow().let {
|
||||
val moveUriStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val targetRegister = getInstruction<OneRegisterInstruction>(moveUriStringIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
moveUriStringIndex + 1,
|
||||
"""
|
||||
invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String;
|
||||
move-result-object v$targetRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Block /get_watch requests to fall back to /player requests.
|
||||
|
||||
BuildPlayerRequestURIFingerprint.resultOrThrow().let {
|
||||
val invokeToStringIndex = it.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
it.mutableMethod.apply {
|
||||
val uriRegister = getInstruction<FiveRegisterInstruction>(invokeToStringIndex).registerC
|
||||
|
||||
addInstructions(
|
||||
invokeToStringIndex,
|
||||
"""
|
||||
invoke-static { v$uriRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->blockGetWatchRequest(Landroid/net/Uri;)Landroid/net/Uri;
|
||||
move-result-object v$uriRegister
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Get replacement streams at player requests.
|
||||
|
||||
BuildRequestFingerprint.resultOrThrow().mutableMethod.apply {
|
||||
val newRequestBuilderIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.name == "newUrlRequestBuilder"
|
||||
}
|
||||
val urlRegister = getInstruction<FiveRegisterInstruction>(newRequestBuilderIndex).registerD
|
||||
val freeRegister = getInstruction<OneRegisterInstruction>(newRequestBuilderIndex + 1).registerA
|
||||
|
||||
addInstructions(
|
||||
newRequestBuilderIndex,
|
||||
"""
|
||||
move-object v$freeRegister, p1
|
||||
invoke-static { v$urlRegister, v$freeRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->fetchStreams(Ljava/lang/String;Ljava/util/Map;)V
|
||||
""",
|
||||
)
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Replace the streaming data with the replacement streams.
|
||||
|
||||
CreateStreamingDataFingerprint.resultOrThrow().let { result ->
|
||||
result.mutableMethod.apply {
|
||||
val setStreamDataMethodName = "patch_setStreamingData"
|
||||
val resultMethodType = result.mutableClass.type
|
||||
val videoDetailsIndex = result.scanResult.patternScanResult!!.endIndex
|
||||
val videoDetailsRegister = getInstruction<TwoRegisterInstruction>(videoDetailsIndex).registerA
|
||||
val videoDetailsClass = getInstruction(videoDetailsIndex).getReference<FieldReference>()!!.type
|
||||
|
||||
addInstruction(
|
||||
videoDetailsIndex + 1,
|
||||
"invoke-direct { p0, v$videoDetailsRegister }, " +
|
||||
"$resultMethodType->$setStreamDataMethodName($videoDetailsClass)V",
|
||||
)
|
||||
|
||||
val protobufClass = ProtobufClassParseByteBufferFingerprint.resultOrThrow().mutableMethod.definingClass
|
||||
val setStreamingDataIndex = result.scanResult.patternScanResult!!.startIndex
|
||||
|
||||
val playerProtoClass = getInstruction(setStreamingDataIndex + 1)
|
||||
.getReference<FieldReference>()!!.definingClass
|
||||
|
||||
val setStreamingDataField = getInstruction(setStreamingDataIndex).getReference<FieldReference>()
|
||||
|
||||
val getStreamingDataField = getInstruction(
|
||||
indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.definingClass == playerProtoClass
|
||||
}
|
||||
).getReference<FieldReference>()
|
||||
|
||||
// Use a helper method to avoid the need of picking out multiple free registers from the hooked code.
|
||||
result.mutableClass.methods.add(
|
||||
ImmutableMethod(
|
||||
resultMethodType,
|
||||
setStreamDataMethodName,
|
||||
listOf(ImmutableMethodParameter(videoDetailsClass, null, "videoDetails")),
|
||||
"V",
|
||||
AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
null,
|
||||
null,
|
||||
MutableMethodImplementation(9),
|
||||
).toMutable().apply {
|
||||
addInstructionsWithLabels(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->isSpoofingEnabled()Z
|
||||
move-result v0
|
||||
if-eqz v0, :disabled
|
||||
|
||||
# Get video id.
|
||||
iget-object v2, p1, $videoDetailsClass->c:Ljava/lang/String;
|
||||
if-eqz v2, :disabled
|
||||
|
||||
# Get streaming data.
|
||||
invoke-static { v2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->getStreamingData(Ljava/lang/String;)Ljava/nio/ByteBuffer;
|
||||
move-result-object v3
|
||||
if-eqz v3, :disabled
|
||||
|
||||
# Parse streaming data.
|
||||
sget-object v4, $playerProtoClass->a:$playerProtoClass
|
||||
invoke-static { v4, v3 }, $protobufClass->parseFrom(${protobufClass}Ljava/nio/ByteBuffer;)$protobufClass
|
||||
move-result-object v5
|
||||
check-cast v5, $playerProtoClass
|
||||
|
||||
# Set streaming data.
|
||||
iget-object v6, v5, $getStreamingDataField
|
||||
if-eqz v6, :disabled
|
||||
iput-object v6, p0, $setStreamingDataField
|
||||
|
||||
:disabled
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region Remove /videoplayback request body to fix playback.
|
||||
// It is assumed, YouTube makes a request with a body tuned for Android.
|
||||
// Requesting streams intended for other platforms with a body tuned for Android could be the cause of 400 errors.
|
||||
// A proper fix may include modifying the request body to match the platforms expected body.
|
||||
|
||||
BuildMediaDataSourceFingerprint.resultOrThrow().let {
|
||||
it.mutableMethod.apply {
|
||||
val targetIndex = getInstructions().lastIndex
|
||||
|
||||
// Instructions are added just before the method returns,
|
||||
// so there's no concern of clobbering in-use registers.
|
||||
addInstructions(
|
||||
targetIndex,
|
||||
"""
|
||||
# Field a: Stream uri.
|
||||
# Field c: Http method.
|
||||
# Field d: Post data.
|
||||
move-object v0, p0 # method has over 15 registers and must copy p0 to a lower register.
|
||||
iget-object v1, v0, $definingClass->a:Landroid/net/Uri;
|
||||
iget v2, v0, $definingClass->c:I
|
||||
iget-object v3, v0, $definingClass->d:[B
|
||||
invoke-static { v1, v2, v3 }, $INTEGRATIONS_CLASS_DESCRIPTOR->removeVideoPlaybackPostBody(Landroid/net/Uri;I[B)[B
|
||||
move-result-object v1
|
||||
iput-object v1, v0, $definingClass->d:[B
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal object BuildMediaDataSourceFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||
returnType = "V",
|
||||
parameters = listOf(
|
||||
"Landroid/net/Uri;",
|
||||
"J",
|
||||
"I",
|
||||
"[B",
|
||||
"Ljava/util/Map;",
|
||||
"J",
|
||||
"J",
|
||||
"Ljava/lang/String;",
|
||||
"I",
|
||||
"Ljava/lang/Object;"
|
||||
)
|
||||
)
|
||||
@@ -3,13 +3,34 @@ package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object BuildRequestFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
returnType = "Lorg/chromium/net/UrlRequest;",
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
customFingerprint = { methodDef, _ ->
|
||||
// Different targets have slightly different parameters
|
||||
|
||||
// Earlier targets have parameters:
|
||||
//L
|
||||
//Ljava/util/Map;
|
||||
//[B
|
||||
//L
|
||||
//L
|
||||
//L
|
||||
//Lorg/chromium/net/UrlRequest$Callback;
|
||||
|
||||
// Later targets have parameters:
|
||||
//L
|
||||
//Ljava/util/Map;
|
||||
//[B
|
||||
//L
|
||||
//L
|
||||
//L
|
||||
//Lorg/chromium/net/UrlRequest\$Callback;
|
||||
//L
|
||||
|
||||
val parameterTypes = methodDef.parameterTypes
|
||||
(parameterTypes.size == 7 || parameterTypes.size == 8)
|
||||
&& parameterTypes[1] == "Ljava/util/Map;" // URL headers.
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
package app.revanced.patches.youtube.misc.fix.playback.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal object CreatePlaybackSpeedMenuItemFingerprint : MethodFingerprint(
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
returnType = "V",
|
||||
opcodes = listOf(
|
||||
Opcode.IGET_OBJECT, // First instruction of the method
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.IF_EQZ,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
null // MOVE_RESULT or MOVE_RESULT_OBJECT, Return value controls the creation of the playback speed menu item.
|
||||
),
|
||||
// 19.01 and earlier is missing the second parameter.
|
||||
// Since this fingerprint is somewhat weak, work around by checking for both method parameter signatures.
|
||||
customFingerprint = custom@{ methodDef, _ ->
|
||||
// 19.01 and earlier parameters are: "[L"
|
||||
// 19.02+ parameters are "[L", "F"
|
||||
val parameterTypes = methodDef.parameterTypes
|
||||
val firstParameter = parameterTypes.firstOrNull()
|
||||
|
||||
if (firstParameter == null || !firstParameter.startsWith("[L")) {
|
||||
return@custom false
|
||||
}
|
||||
|
||||
parameterTypes.size == 1 || (parameterTypes.size == 2 && parameterTypes[1] == "F")
|
||||
}
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user