mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-07 09:53:55 +01:00
Compare commits
604 Commits
v2.42.0
...
v2.157.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06a981a317 | ||
|
|
dd3a9a4f38 | ||
|
|
5228700317 | ||
|
|
e68a65c950 | ||
|
|
817ad0b9f2 | ||
|
|
57e13cf8a8 | ||
|
|
e4fa523b15 | ||
|
|
440278be33 | ||
|
|
3bf8d1d3cb | ||
|
|
246a6ce927 | ||
|
|
225726feeb | ||
|
|
f0b384bbfe | ||
|
|
160191b5cb | ||
|
|
bc06b4dfda | ||
|
|
c6e0e79cd5 | ||
|
|
53ab837489 | ||
|
|
1a94209bfb | ||
|
|
c30bf18745 | ||
|
|
068f18cd5b | ||
|
|
06105f4c87 | ||
|
|
5359965a0b | ||
|
|
3881fda3f4 | ||
|
|
cc43f356b5 | ||
|
|
939c084e31 | ||
|
|
b888eafce1 | ||
|
|
df3316b804 | ||
|
|
68f941deda | ||
|
|
0b18ed8f7f | ||
|
|
1f1519ca33 | ||
|
|
6bc5025e1f | ||
|
|
94f7897a34 | ||
|
|
9c3a8aad83 | ||
|
|
44451c9b95 | ||
|
|
474cc4d5e6 | ||
|
|
d492ff23af | ||
|
|
34c1b4a871 | ||
|
|
e6360285eb | ||
|
|
7814ce9a5d | ||
|
|
9013eea406 | ||
|
|
5240e749e1 | ||
|
|
0310fa434c | ||
|
|
1e728b4ecf | ||
|
|
b285183554 | ||
|
|
772d3ae073 | ||
|
|
b7390de6bf | ||
|
|
8ac6ab6a9c | ||
|
|
67bf5a0d16 | ||
|
|
4ce31eedd7 | ||
|
|
270916bb43 | ||
|
|
3944521a01 | ||
|
|
b57eee8582 | ||
|
|
e4cc17e6ef | ||
|
|
3789a205cb | ||
|
|
efe814f2e1 | ||
|
|
e13db6934f | ||
|
|
7e8c544d42 | ||
|
|
8a3c0e1bcb | ||
|
|
ce0158db3a | ||
|
|
2c8550c7e7 | ||
|
|
6b35ffc5b8 | ||
|
|
f0b0017ff1 | ||
|
|
a3e7ee6454 | ||
|
|
b885bf82cd | ||
|
|
09ea24938c | ||
|
|
58994b14f8 | ||
|
|
370067266c | ||
|
|
62a8ac4f9b | ||
|
|
4d74458023 | ||
|
|
37cfb6900c | ||
|
|
c0bc6fe658 | ||
|
|
ec64b8d1ff | ||
|
|
a52a692062 | ||
|
|
c372d7823c | ||
|
|
47dce0d01e | ||
|
|
b777d2e230 | ||
|
|
c98baf93fc | ||
|
|
4e4b0ecb0d | ||
|
|
e8391b3e93 | ||
|
|
1db7eebeaa | ||
|
|
50e210d94f | ||
|
|
ad6fab930d | ||
|
|
7966be827f | ||
|
|
6a6f05e2cb | ||
|
|
752b12b66d | ||
|
|
623a9bce98 | ||
|
|
6441b031e3 | ||
|
|
4227ffa40f | ||
|
|
9158fd5054 | ||
|
|
7f529d1038 | ||
|
|
bb38c02b51 | ||
|
|
b927e8b93f | ||
|
|
ba4676d500 | ||
|
|
1af1bf8342 | ||
|
|
2374af6f82 | ||
|
|
4da3e4f369 | ||
|
|
f89027609f | ||
|
|
7e3184b5f7 | ||
|
|
49cca5a258 | ||
|
|
63f5af5c3b | ||
|
|
82df77460f | ||
|
|
3227d66dc2 | ||
|
|
62102c9543 | ||
|
|
adc2f738c0 | ||
|
|
a3b3b613e2 | ||
|
|
e60173addf | ||
|
|
be80837218 | ||
|
|
528cbfc171 | ||
|
|
dc055a0b20 | ||
|
|
7f1f317c08 | ||
|
|
b18256a2a2 | ||
|
|
a3ece1e154 | ||
|
|
5ead461caf | ||
|
|
66c582795e | ||
|
|
c3641d90dd | ||
|
|
da108ca9bb | ||
|
|
96d88ae0fb | ||
|
|
6e0830929c | ||
|
|
e67f18b9c2 | ||
|
|
b2b1108c47 | ||
|
|
89215d6513 | ||
|
|
ce4d144910 | ||
|
|
dbd2f5b7da | ||
|
|
ed7b86072c | ||
|
|
c90069f9c5 | ||
|
|
df2a051724 | ||
|
|
6831b3ce25 | ||
|
|
c201f6dc2c | ||
|
|
9849df5814 | ||
|
|
677fd639b7 | ||
|
|
63b63a394d | ||
|
|
936780038b | ||
|
|
6c4c834587 | ||
|
|
2ef3625cac | ||
|
|
10107919bd | ||
|
|
76b6c1561a | ||
|
|
73023cd45e | ||
|
|
456c6ce2bf | ||
|
|
d32782962f | ||
|
|
0fe7cacb31 | ||
|
|
e6e5864450 | ||
|
|
a767f77b72 | ||
|
|
3dc88e2578 | ||
|
|
2df07cad36 | ||
|
|
943221173e | ||
|
|
6ff3f3c974 | ||
|
|
e4c2bb9d39 | ||
|
|
67e2e00cdc | ||
|
|
170c5daa33 | ||
|
|
ce1099cd9c | ||
|
|
9af1fef0b7 | ||
|
|
a421da53f3 | ||
|
|
6a49b617fd | ||
|
|
d5bff774ed | ||
|
|
72dacd7c9d | ||
|
|
2afdb1a70d | ||
|
|
127ab85d5e | ||
|
|
817a6a9f87 | ||
|
|
18b39a448e | ||
|
|
13e74c9946 | ||
|
|
d77c9fec15 | ||
|
|
27c66f7d12 | ||
|
|
ad3041635f | ||
|
|
8ff56f557c | ||
|
|
6369b24f64 | ||
|
|
f1960310b6 | ||
|
|
0aaa2a40ec | ||
|
|
9d6c99930b | ||
|
|
d50a58900c | ||
|
|
139f9a88eb | ||
|
|
f057ba8eab | ||
|
|
7bd544e171 | ||
|
|
796d4dc407 | ||
|
|
99f6363606 | ||
|
|
f63cfb52b0 | ||
|
|
583ec5d8e3 | ||
|
|
b675adef30 | ||
|
|
a08fe535b1 | ||
|
|
7e5c963e36 | ||
|
|
05ea840b8f | ||
|
|
da4b80c5dd | ||
|
|
4ca19b7fd2 | ||
|
|
260b395426 | ||
|
|
b4d8dbcc3d | ||
|
|
7180914df1 | ||
|
|
748b14d547 | ||
|
|
d9d4d1f38c | ||
|
|
0f73a9dd5e | ||
|
|
fafcd751b2 | ||
|
|
ea7b3f5529 | ||
|
|
4935c00aa5 | ||
|
|
06098713bb | ||
|
|
eb505d802a | ||
|
|
e8b7cdfa35 | ||
|
|
986951dc8a | ||
|
|
b88fda959c | ||
|
|
96c36dca74 | ||
|
|
4ce3fd4ff7 | ||
|
|
81c5c3870c | ||
|
|
30aeaf70d8 | ||
|
|
712423789e | ||
|
|
1ad2db1ca4 | ||
|
|
16b4e78d79 | ||
|
|
f57c555395 | ||
|
|
53f1f6fc96 | ||
|
|
b4b8f62c7b | ||
|
|
8b2703273a | ||
|
|
9e2a6eead1 | ||
|
|
5afd49a111 | ||
|
|
e79ad750d4 | ||
|
|
97ea238520 | ||
|
|
700ca5b543 | ||
|
|
b792be5b78 | ||
|
|
025b480175 | ||
|
|
e1b53b214f | ||
|
|
30939e5efe | ||
|
|
4d9c41488d | ||
|
|
2fffcde357 | ||
|
|
7af08e0ba7 | ||
|
|
228834fda8 | ||
|
|
7466aecc5b | ||
|
|
8ee36541b4 | ||
|
|
a4fd6603fe | ||
|
|
510cb8f590 | ||
|
|
c02ebd752c | ||
|
|
b4d7eca5fa | ||
|
|
c6125c071b | ||
|
|
478de297f9 | ||
|
|
ebc4a12cd7 | ||
|
|
b3c0291e70 | ||
|
|
c43588ee40 | ||
|
|
c74b5d4e47 | ||
|
|
91ae954210 | ||
|
|
65172cad4f | ||
|
|
c2122494bc | ||
|
|
6ed94935ca | ||
|
|
a934821fa7 | ||
|
|
f3785c4e47 | ||
|
|
67e0db5ac9 | ||
|
|
aaa820430b | ||
|
|
cf5ed1baea | ||
|
|
206341cec4 | ||
|
|
e8f4890edd | ||
|
|
9463f11dbf | ||
|
|
2b3e153b60 | ||
|
|
4b6bf69366 | ||
|
|
38e8e7898b | ||
|
|
3175e864af | ||
|
|
d320dd4e58 | ||
|
|
f5ae96defb | ||
|
|
bfe3876cea | ||
|
|
3ad2c42a53 | ||
|
|
0d22fc2d2f | ||
|
|
6e6dbd0c1a | ||
|
|
4272fade4f | ||
|
|
2095e34db8 | ||
|
|
1483a9d8bb | ||
|
|
ea113f01a3 | ||
|
|
d4658c7056 | ||
|
|
a615717580 | ||
|
|
04db353154 | ||
|
|
7cb0312a9d | ||
|
|
5357ff2e48 | ||
|
|
62083ead98 | ||
|
|
6f04169117 | ||
|
|
cc1b283cb7 | ||
|
|
4597a74e32 | ||
|
|
3734545ca6 | ||
|
|
60ef90c745 | ||
|
|
ece4ac1a9e | ||
|
|
d6e17f948d | ||
|
|
9ab3bd0313 | ||
|
|
0f10888aa3 | ||
|
|
63c0e5dc84 | ||
|
|
41bc0222b9 | ||
|
|
71e4cc964b | ||
|
|
afc9886ebd | ||
|
|
de06d96ea0 | ||
|
|
1139f77cb9 | ||
|
|
5a801b1562 | ||
|
|
7f301090b9 | ||
|
|
28a687c605 | ||
|
|
9b74a08ae1 | ||
|
|
1177c41373 | ||
|
|
be4de62c8f | ||
|
|
528156aec9 | ||
|
|
e377ecf208 | ||
|
|
fa147bd6cc | ||
|
|
88211e28ca | ||
|
|
a4e3a97937 | ||
|
|
02bd807a27 | ||
|
|
a06e81ae39 | ||
|
|
a87d0bc440 | ||
|
|
a2b64f63e0 | ||
|
|
80ab1592c3 | ||
|
|
e17f476c46 | ||
|
|
bfa9abe4cf | ||
|
|
0e0118eaa6 | ||
|
|
7b6439b200 | ||
|
|
65e3b21d64 | ||
|
|
d90bcc3135 | ||
|
|
eee47ee37c | ||
|
|
d340dd0e0d | ||
|
|
2193a0307e | ||
|
|
58dcd172f9 | ||
|
|
f818396243 | ||
|
|
3d124af58c | ||
|
|
df18d4a15a | ||
|
|
f08a2b6a90 | ||
|
|
fce8df8284 | ||
|
|
6ec99045d7 | ||
|
|
757784b038 | ||
|
|
7e06f23e29 | ||
|
|
26a43b1753 | ||
|
|
c8023f0b66 | ||
|
|
25f65c7c02 | ||
|
|
07d39f2b81 | ||
|
|
01e226d0c9 | ||
|
|
c98e10adf7 | ||
|
|
858b8a6fa8 | ||
|
|
53a66f64ab | ||
|
|
e2b9baed25 | ||
|
|
6bc24755d5 | ||
|
|
e871d655d2 | ||
|
|
1fa0d5da0e | ||
|
|
461e4bef09 | ||
|
|
9b1df03087 | ||
|
|
541a1a0e0a | ||
|
|
ce2f7042da | ||
|
|
ca3438b640 | ||
|
|
5121c3d45b | ||
|
|
666b241a53 | ||
|
|
b961bdf9d3 | ||
|
|
8aa1d58b76 | ||
|
|
570723bb59 | ||
|
|
7027929e30 | ||
|
|
f11f269c2f | ||
|
|
b0cd520b1a | ||
|
|
5c0fd8a6da | ||
|
|
e34d67f01e | ||
|
|
72703d6a56 | ||
|
|
b8c473796a | ||
|
|
25e86c5545 | ||
|
|
f1bf2c589b | ||
|
|
8b54559953 | ||
|
|
3761dbd7b2 | ||
|
|
8cf0343f29 | ||
|
|
f3753a22da | ||
|
|
c90312a925 | ||
|
|
c1d6aa3e49 | ||
|
|
c097370960 | ||
|
|
8ffa3b4746 | ||
|
|
1e6d0f7f62 | ||
|
|
e73c5dfebd | ||
|
|
32309ac007 | ||
|
|
079800aa1a | ||
|
|
06f0d05d19 | ||
|
|
c618a18851 | ||
|
|
1aac521af3 | ||
|
|
68fe1cc792 | ||
|
|
ba519d4b10 | ||
|
|
0351c8a50d | ||
|
|
d0c4ac5d8a | ||
|
|
daa55c59e2 | ||
|
|
4ad057b748 | ||
|
|
3eaefc7979 | ||
|
|
d81ce614a8 | ||
|
|
dcd711b341 | ||
|
|
96d500bc70 | ||
|
|
031b517245 | ||
|
|
79a0ea78cf | ||
|
|
2a54e624a0 | ||
|
|
e8cc0de11c | ||
|
|
d2209569e0 | ||
|
|
492cce9452 | ||
|
|
a17232da24 | ||
|
|
3ae7858adf | ||
|
|
1a6bb30789 | ||
|
|
2b10b834c7 | ||
|
|
35c86c6ff5 | ||
|
|
f4897e41a9 | ||
|
|
1eadafb098 | ||
|
|
7eb2a0b1bc | ||
|
|
a13e294978 | ||
|
|
a3548ed524 | ||
|
|
37cbbccec5 | ||
|
|
4e83400de4 | ||
|
|
e9e5f7b018 | ||
|
|
01be9fd79e | ||
|
|
e8faa5d944 | ||
|
|
9ac84ae720 | ||
|
|
52424bd6ab | ||
|
|
4c2d6466cc | ||
|
|
6bcae6ddeb | ||
|
|
65cee57493 | ||
|
|
5058fd3c43 | ||
|
|
b2affc5493 | ||
|
|
01a4349a3f | ||
|
|
3a25dc4fa2 | ||
|
|
7f1a918649 | ||
|
|
c26de68a27 | ||
|
|
9381508678 | ||
|
|
6d9c743618 | ||
|
|
6c9986290b | ||
|
|
adc7f670d1 | ||
|
|
fdc34023fc | ||
|
|
1e54bc457f | ||
|
|
9552100878 | ||
|
|
9166024b01 | ||
|
|
acc0f5018c | ||
|
|
05c043ada3 | ||
|
|
e30967bedd | ||
|
|
40d56f6e59 | ||
|
|
8bdfe8b74f | ||
|
|
c7c9440a60 | ||
|
|
4dcd487275 | ||
|
|
68eff6fd76 | ||
|
|
9b58c642f3 | ||
|
|
f9c16396d6 | ||
|
|
7c528856e1 | ||
|
|
29c18ad537 | ||
|
|
1654d4121b | ||
|
|
05c6c9e683 | ||
|
|
facb808e37 | ||
|
|
fe1427b88a | ||
|
|
634c6c3344 | ||
|
|
d438d9b866 | ||
|
|
e4139a112e | ||
|
|
559d7ad50c | ||
|
|
e1bbe59b40 | ||
|
|
2f932d697b | ||
|
|
237129d327 | ||
|
|
e4d7dc0aa9 | ||
|
|
fed9e4aafa | ||
|
|
85aa45d3f2 | ||
|
|
16df8d5ebc | ||
|
|
e89c3dad39 | ||
|
|
0f78f621c7 | ||
|
|
fe30cea22d | ||
|
|
5a30d8564c | ||
|
|
34222d9f2c | ||
|
|
f765af0929 | ||
|
|
298c33deb6 | ||
|
|
111db2a499 | ||
|
|
fa536957cc | ||
|
|
980deec6af | ||
|
|
658638bfad | ||
|
|
d5ee3b006d | ||
|
|
36ab007924 | ||
|
|
c46705f21a | ||
|
|
31ae362d18 | ||
|
|
b64f7bb400 | ||
|
|
64244ec476 | ||
|
|
f005314358 | ||
|
|
ae1aeffc62 | ||
|
|
56768caa4c | ||
|
|
19484ca2bc | ||
|
|
a8a98646e7 | ||
|
|
4927bc7451 | ||
|
|
66a5ca3fa8 | ||
|
|
6c0b9213fe | ||
|
|
70e21500cc | ||
|
|
784e97591a | ||
|
|
26ff3b338e | ||
|
|
28c864ae95 | ||
|
|
deb829c791 | ||
|
|
3c0f3ac968 | ||
|
|
2f6da4ed27 | ||
|
|
1b653c77c4 | ||
|
|
82ea2d3498 | ||
|
|
07dee5b87a | ||
|
|
7713516ed8 | ||
|
|
22fa09dc27 | ||
|
|
24d03387de | ||
|
|
04310901b7 | ||
|
|
3011c1fa45 | ||
|
|
6b83fe572a | ||
|
|
32d303f4b7 | ||
|
|
837c381e19 | ||
|
|
09ae60bb28 | ||
|
|
f9d180aad4 | ||
|
|
c40181140d | ||
|
|
c5e190a4d5 | ||
|
|
24e3f8b24e | ||
|
|
53b0485642 | ||
|
|
b362b560b6 | ||
|
|
b285bf96bd | ||
|
|
bfb47eb1c4 | ||
|
|
4e2d30228a | ||
|
|
dce28760f5 | ||
|
|
68ec6d2258 | ||
|
|
83498fd29c | ||
|
|
1ab35a1cfa | ||
|
|
e0b45237bb | ||
|
|
161a1b0af1 | ||
|
|
7618376388 | ||
|
|
2bdb857a9f | ||
|
|
be02acecfc | ||
|
|
9e873329c6 | ||
|
|
8a2b79ec16 | ||
|
|
9842f7ca0d | ||
|
|
8a913c6a2a | ||
|
|
84676ef33d | ||
|
|
eb985942f0 | ||
|
|
886018d6fb | ||
|
|
e7a17ccbc6 | ||
|
|
c707dc8769 | ||
|
|
1bb93e3598 | ||
|
|
e8848171ac | ||
|
|
249288c8a5 | ||
|
|
1791525b54 | ||
|
|
47fbe3cb25 | ||
|
|
89235ca7fa | ||
|
|
f63abb8eb3 | ||
|
|
b701f86fa1 | ||
|
|
3117ee7ba4 | ||
|
|
b8e084b9e1 | ||
|
|
bafeff84c2 | ||
|
|
8d193786cb | ||
|
|
d78d271967 | ||
|
|
59ea2bc636 | ||
|
|
e8b550f5aa | ||
|
|
e73c0e0a00 | ||
|
|
8c132be096 | ||
|
|
cb10ea1797 | ||
|
|
6d6a0375c8 | ||
|
|
8541ee0066 | ||
|
|
f7e0b46bc7 | ||
|
|
59af825d0a | ||
|
|
04ffffbdf2 | ||
|
|
ecc131fa4f | ||
|
|
a4f1d3558e | ||
|
|
4cbd58721d | ||
|
|
7cfe43e666 | ||
|
|
c93d7bc212 | ||
|
|
c28fd5cf20 | ||
|
|
069f754d51 | ||
|
|
cba04cf5a6 | ||
|
|
5e358c7319 | ||
|
|
ce69471684 | ||
|
|
a0981dda9d | ||
|
|
6073181ee1 | ||
|
|
522587321c | ||
|
|
b16748794e | ||
|
|
01e9a396d6 | ||
|
|
86fcd4d475 | ||
|
|
8bbc744114 | ||
|
|
d7a4ad76ea | ||
|
|
7e6ee73908 | ||
|
|
87954a1aaf | ||
|
|
e5a2ed0f70 | ||
|
|
2295aaebf4 | ||
|
|
a72bf150c2 | ||
|
|
0290cd3d36 | ||
|
|
e8d61e0c0e | ||
|
|
19769d80eb | ||
|
|
12c16d4644 | ||
|
|
75f4653c16 | ||
|
|
3286d26996 | ||
|
|
edbc36e90f | ||
|
|
7ad2be7f27 | ||
|
|
1702322671 | ||
|
|
9c9bfbd593 | ||
|
|
3df662a39c | ||
|
|
572c110a6e | ||
|
|
0be9f00915 | ||
|
|
0b6f643ff3 | ||
|
|
1989d53938 | ||
|
|
ac1acf10e6 | ||
|
|
0ad686da21 | ||
|
|
e734b2231a | ||
|
|
efe06d1cdc | ||
|
|
a0f9013fab | ||
|
|
93dcd542d5 | ||
|
|
3bac23f577 | ||
|
|
febcf60efb | ||
|
|
0d74a2dfa6 | ||
|
|
5b04fbb748 | ||
|
|
fbfa0ea3be | ||
|
|
4a30afe1e2 | ||
|
|
dd1df32036 | ||
|
|
a52d674cde | ||
|
|
67f6041bab | ||
|
|
6b3f8e46fd | ||
|
|
b95058f20a | ||
|
|
5b80ac1216 | ||
|
|
6fe1bfb856 | ||
|
|
589a7c01d1 | ||
|
|
4cd6d4459a | ||
|
|
89a92b2057 | ||
|
|
9f265a46cf | ||
|
|
a740690a08 | ||
|
|
d722a64d3c | ||
|
|
abe2674290 | ||
|
|
e5ec40f6fa | ||
|
|
96c43fc6f5 | ||
|
|
4e36d72c5c | ||
|
|
6197246e8e | ||
|
|
15a044cae1 | ||
|
|
ede60b994c | ||
|
|
c15cc431d6 | ||
|
|
fb006f87ab | ||
|
|
28206fd804 | ||
|
|
e425e75152 | ||
|
|
69d6c55942 |
14
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
14
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
@@ -36,7 +36,7 @@ body:
|
|||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Relevant log output
|
label: Relevant log output
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. Capture crash logs by running `logcat | grep AndroidRuntime`.
|
||||||
render: shell
|
render: shell
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -59,3 +59,15 @@ body:
|
|||||||
description: Add additional context here.
|
description: Add additional context here.
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
id: acknowledgements
|
||||||
|
attributes:
|
||||||
|
label: Acknowledgements
|
||||||
|
description: Your issue will be closed if you haven't done these steps.
|
||||||
|
options:
|
||||||
|
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||||
|
required: true
|
||||||
|
- label: I have written a short but informative title.
|
||||||
|
required: true
|
||||||
|
- label: I filled out all of the requested information in this issue properly.
|
||||||
|
required: true
|
||||||
|
|||||||
46
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
46
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
@@ -1,46 +0,0 @@
|
|||||||
name: ⭐ Feature request
|
|
||||||
description: Create a detailed feature request.
|
|
||||||
title: 'feat: <title>'
|
|
||||||
labels: [feature-request]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
# ReVanced feature request
|
|
||||||
|
|
||||||
Do not submit requests for patches here. Please submit them [here](https://github.com/orgs/revanced/discussions/categories/patches) instead.
|
|
||||||
Important to note that your feature request may have already been made before. Please check for existing feature requests [here](https://github.com/revanced/revanced-patches/labels/feature-request).
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
attributes:
|
|
||||||
label: Type
|
|
||||||
options:
|
|
||||||
- Functionality
|
|
||||||
- Cosmetic
|
|
||||||
- Other
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Issue
|
|
||||||
description: What is the current problem. Why does it require a feature request?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Feature
|
|
||||||
description: Describe your feature in detail. How does it solve the issue?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Motivation
|
|
||||||
description: Why should your feature should be considered?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Additional context
|
|
||||||
description: Add additional context here.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
41
.github/ISSUE_TEMPLATE/patch-request.yml
vendored
Normal file
41
.github/ISSUE_TEMPLATE/patch-request.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
name: ⭐ Patch Request
|
||||||
|
description: Create a detailed patch request.
|
||||||
|
title: 'feat(patch): '
|
||||||
|
labels: [patch-request]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Application
|
||||||
|
description: Which application is this patch for?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Issue
|
||||||
|
description: What is the issue this patch should solve?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Patch
|
||||||
|
description: "Describe the patch you'd like to see in detail."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Motivation
|
||||||
|
description: Why should your patch request should be considered? What makes it valuable to the community?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: acknowledgements
|
||||||
|
attributes:
|
||||||
|
label: Acknowledgements
|
||||||
|
description: Your issue will be closed if you haven't done these steps.
|
||||||
|
options:
|
||||||
|
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||||
|
required: true
|
||||||
|
- label: I have written a short but informative title.
|
||||||
|
required: true
|
||||||
|
- label: I filled out all of the requested information in this issue properly.
|
||||||
|
required: true
|
||||||
25
.github/workflows/pull_request.yml
vendored
Normal file
25
.github/workflows/pull_request.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: PR to main
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pull-request:
|
||||||
|
name: Open pull request
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Open pull request
|
||||||
|
uses: repo-sync/pull-request@v2
|
||||||
|
with:
|
||||||
|
destination_branch: 'main'
|
||||||
|
pr_title: 'chore: ${{ env.MESSAGE }}'
|
||||||
|
pr_body: 'This pull request will ${{ env.MESSAGE }}.'
|
||||||
|
pr_draft: true
|
||||||
32
.github/workflows/release.yml
vendored
32
.github/workflows/release.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
name: Release
|
name: Release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
@@ -9,36 +10,43 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
# Make sure the release step uses its own credentials:
|
||||||
|
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||||
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup JDK
|
- name: Setup JDK
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '17'
|
||||||
distribution: 'adopt'
|
distribution: 'zulu'
|
||||||
cache: gradle
|
cache: gradle
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: 'latest'
|
||||||
|
cache: 'npm'
|
||||||
- name: Setup Android SDK
|
- name: Setup Android SDK
|
||||||
uses: android-actions/setup-android@v2
|
uses: amyu/setup-android@v2
|
||||||
|
with:
|
||||||
|
cache-disabled: false
|
||||||
|
sdk-version: '33'
|
||||||
|
build-tools-version: '33.0.1'
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: ./gradlew build clean generateReadme
|
run: ./gradlew generateMeta clean --no-daemon
|
||||||
- name: Install Android build-tools
|
|
||||||
run: sdkmanager "build-tools;32.0.0"
|
|
||||||
- name: Setup semantic-release
|
- name: Setup semantic-release
|
||||||
run: npm install -g semantic-release @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
|
run: npm install semantic-release@19.0.5 @saithodev/semantic-release-backmerge @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin@1.7.4 -D
|
||||||
- name: Release
|
- name: Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||||
run: npx semantic-release
|
run: npx semantic-release
|
||||||
|
|||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -114,4 +114,10 @@ gradle-app.setting
|
|||||||
# gradle/wrapper/gradle-wrapper.properties
|
# gradle/wrapper/gradle-wrapper.properties
|
||||||
|
|
||||||
# Potentially copyrighted test APK
|
# Potentially copyrighted test APK
|
||||||
*.apk
|
*.apk
|
||||||
|
|
||||||
|
# Ignore vscode config
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
1
.idea/.gitignore
generated
vendored
1
.idea/.gitignore
generated
vendored
@@ -6,3 +6,4 @@
|
|||||||
/dataSources.local.xml
|
/dataSources.local.xml
|
||||||
# Editor-based HTTP Client requests
|
# Editor-based HTTP Client requests
|
||||||
/httpRequests/
|
/httpRequests/
|
||||||
|
/kotlinc.xml
|
||||||
|
|||||||
22
.releaserc
22
.releaserc
@@ -7,11 +7,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["@semantic-release/commit-analyzer", {
|
"@semantic-release/commit-analyzer",
|
||||||
"releaseRules": [
|
|
||||||
{"type": "build", "release": "patch"}
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
"gradle-semantic-release-plugin",
|
"gradle-semantic-release-plugin",
|
||||||
@@ -21,7 +17,8 @@
|
|||||||
"assets": [
|
"assets": [
|
||||||
"README.md",
|
"README.md",
|
||||||
"CHANGELOG.md",
|
"CHANGELOG.md",
|
||||||
"gradle.properties"
|
"gradle.properties",
|
||||||
|
"patches.json"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -31,8 +28,19 @@
|
|||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"path": "build/libs/*.jar"
|
"path": "build/libs/*.jar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "patches.json"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
successComment: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@saithodev/semantic-release-backmerge",
|
||||||
|
{
|
||||||
|
branches: [{from: "main", to: "dev"}],
|
||||||
|
clearWorkspace: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
1759
CHANGELOG.md
1759
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,122 @@
|
|||||||
# 🧩 ReVanced Patches
|
## 🧩 Patches
|
||||||
|
|
||||||
Official patches by ReVanced
|
The official Patch bundle provided by ReVanced and the community.
|
||||||
|
|
||||||
## 📜 List of available patches
|
> Looking for the JSON variant of this? [Click here](patches.json).
|
||||||
|
|
||||||
{{ table }}
|
{{ table }}
|
||||||
|
|
||||||
|
## 📝 JSON Format
|
||||||
|
|
||||||
|
This section explains the JSON format for the [patches.json](patches.json) file.
|
||||||
|
|
||||||
|
The file contains an array of objects, each object representing a patch. The object contains the following properties:
|
||||||
|
|
||||||
|
| key | description |
|
||||||
|
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `name` | The name of the patch. |
|
||||||
|
| `description` | The description of the patch. |
|
||||||
|
| `version` | The version of the patch. |
|
||||||
|
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
|
||||||
|
| `options` | An array of options for this patch. |
|
||||||
|
| `options.key` | The key of the option. |
|
||||||
|
| `options.title` | The title of the option. |
|
||||||
|
| `options.description` | The description of the option. |
|
||||||
|
| `options.required` | Whether the option is required. |
|
||||||
|
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
|
||||||
|
| `dependencies` | An array of dependencies, which are patch names. |
|
||||||
|
| `compatiblePackages` | An array of packages compatible with this patch. |
|
||||||
|
| `compatiblePackages.name` | The name of the package. |
|
||||||
|
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "remember-video-quality",
|
||||||
|
"description": "Adds the ability to remember the video quality you chose in the video quality flyout.",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"options": [],
|
||||||
|
"dependencies": [
|
||||||
|
"integrations",
|
||||||
|
"video-id-hook"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": [
|
||||||
|
"17.22.36",
|
||||||
|
"17.24.35",
|
||||||
|
"17.26.35",
|
||||||
|
"17.27.39",
|
||||||
|
"17.28.34",
|
||||||
|
"17.29.34",
|
||||||
|
"17.32.35",
|
||||||
|
"17.33.42"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme",
|
||||||
|
"description": "Enables a custom theme.",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"key": "theme",
|
||||||
|
"title": "Theme",
|
||||||
|
"description": "Select a theme.",
|
||||||
|
"required": true,
|
||||||
|
"choices": [
|
||||||
|
"Amoled"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"locale-config-fix"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "custom-branding",
|
||||||
|
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"key": "appName",
|
||||||
|
"title": "Application Name",
|
||||||
|
"description": "The name of the application it will show on your home screen.",
|
||||||
|
"required": true,
|
||||||
|
"choices": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "appIconPath",
|
||||||
|
"title": "Application Icon Path",
|
||||||
|
"description": "A path to the icon of the application.",
|
||||||
|
"required": false,
|
||||||
|
"choices": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"locale-config-fix"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
408
README.md
408
README.md
@@ -1,51 +1,218 @@
|
|||||||
# 🧩 ReVanced Patches
|
## 🧩 Patches
|
||||||
|
|
||||||
Official patches by ReVanced
|
The official Patch bundle provided by ReVanced and the community.
|
||||||
|
|
||||||
## 📜 List of available patches
|
> Looking for the JSON variant of this? [Click here](patches.json).
|
||||||
|
|
||||||
### 📦 `com.twitter.android`
|
### [📦 `com.google.android.youtube`](https://play.google.com/store/apps/details?id=com.google.android.youtube)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `timeline-ads` | Removes ads from the Twitter timeline. | all |
|
| `always-autorepeat` | Always repeats the playing video again. | 18.03.36 |
|
||||||
|
| `client-spoof` | Spoofs the YouTube or Vanced client to prevent playback issues. | all |
|
||||||
|
| `comments` | Hides components related to comments. | 18.03.36 |
|
||||||
|
| `copy-video-url` | Adds buttons in player to copy video links. | 18.03.36 |
|
||||||
|
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
||||||
|
| `custom-video-buffer` | Lets you change the buffers of videos. | 18.03.36 |
|
||||||
|
| `custom-video-speed` | Adds more video speed options. | 18.03.36 |
|
||||||
|
| `debugging` | Adds debugging options. | all |
|
||||||
|
| `disable-auto-captions` | Disable forced captions from being automatically enabled. | 18.03.36 |
|
||||||
|
| `disable-auto-player-popup-panels` | Disable automatic popup panels (playlist or live chat) on video player. | 18.03.36 |
|
||||||
|
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 18.03.36 |
|
||||||
|
| `disable-startup-shorts-player` | Disables playing YouTube Shorts when launching YouTube. | 18.03.36 |
|
||||||
|
| `disable-zoom-haptics` | Disables haptics when zooming. | all |
|
||||||
|
| `downloads` | Enables downloading music and videos from YouTube. | 18.03.36 |
|
||||||
|
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 18.03.36 |
|
||||||
|
| `general-ads` | Removes general ads. | 18.03.36 |
|
||||||
|
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 18.03.36 |
|
||||||
|
| `hide-album-cards` | Hides the album cards below the artist description. | 18.03.36 |
|
||||||
|
| `hide-artist-card` | Hides the artist card below the searchbar. | 18.03.36 |
|
||||||
|
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 18.03.36 |
|
||||||
|
| `hide-breaking-news-shelf` | Hides the breaking news shelf on the homepage tab. | 18.03.36 |
|
||||||
|
| `hide-captions-button` | Hides the captions button on video player. | 18.03.36 |
|
||||||
|
| `hide-cast-button` | Hides the cast button in the video player. | all |
|
||||||
|
| `hide-create-button` | Hides the create button in the navigation bar. | 18.03.36 |
|
||||||
|
| `hide-crowdfunding-box` | Hides the crowdfunding box between the player and video description. | 18.03.36 |
|
||||||
|
| `hide-email-address` | Hides the email address in the account switcher. | 18.03.36 |
|
||||||
|
| `hide-endscreen-cards` | Hides the suggested video cards at the end of a video in fullscreen. | 18.03.36 |
|
||||||
|
| `hide-info-cards` | Hides info-cards in videos. | 18.03.36 |
|
||||||
|
| `hide-my-mix` | Hides mix playlists. | 18.03.36 |
|
||||||
|
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | 18.03.36 |
|
||||||
|
| `hide-time-and-seekbar` | Hides progress bar and time counter on videos. | 18.03.36 |
|
||||||
|
| `hide-video-buttons` | Adds options to hide action buttons under a video. | 18.03.36 |
|
||||||
|
| `hide-watch-in-vr` | Hides the Watch in VR option in the player settings flyout panel. | 18.03.36 |
|
||||||
|
| `hide-watermark` | Hides creator's watermarks on videos. | 18.03.36 |
|
||||||
|
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG. | 18.03.36 |
|
||||||
|
| `minimized-playback` | Enables minimized and background playback. | 18.03.36 |
|
||||||
|
| `old-quality-layout` | Enables the original video quality flyout in the video player settings | 18.03.36 |
|
||||||
|
| `open-links-directly` | Bypasses https://youtube.com/redirect URLs. | 18.03.36 |
|
||||||
|
| `open-links-externally` | Open links outside of the app directly in your browser. | 18.03.36 |
|
||||||
|
| `premium-heading` | Shows premium branding on the home screen. | all |
|
||||||
|
| `remember-playback-rate` | Adds the ability to remember the playback rate you chose in the video playback rate flyout. | 18.03.36 |
|
||||||
|
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 18.03.36 |
|
||||||
|
| `remove-player-button-background` | Removes the background from the video player buttons. | 18.03.36 |
|
||||||
|
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 18.03.36 |
|
||||||
|
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 18.03.36 |
|
||||||
|
| `sponsorblock` | Integrate SponsorBlock. | 18.03.36 |
|
||||||
|
| `spoof-app-version` | Tricks YouTube into thinking, you are running an older version of the app. One of the side effects also includes restoring the old UI. | 18.03.36 |
|
||||||
|
| `swipe-controls` | Adds volume and brightness swipe controls. | 18.03.36 |
|
||||||
|
| `tablet-mini-player` | Enables the tablet mini player layout. | 18.03.36 |
|
||||||
|
| `theme` | Applies a custom theme. | all |
|
||||||
|
| `video-ads` | Removes ads in the video player. | 18.03.36 |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `com.reddit.frontpage`
|
### [📦 `com.google.android.apps.youtube.music`](https://play.google.com/store/apps/details?id=com.google.android.apps.youtube.music)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | all |
|
| `background-play` | Enables playing music in the background. | 5.39.52 |
|
||||||
|
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | 5.39.52 |
|
||||||
|
| `compact-header` | Hides the music category bar at the top of the homepage. | 5.39.52 |
|
||||||
|
| `exclusive-audio-playback` | Enables the option to play music without video. | 5.39.52 |
|
||||||
|
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.39.52 |
|
||||||
|
| `minimized-playback-music` | Enables minimized playback on Kids music. | 5.39.52 |
|
||||||
|
| `music-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | 5.39.52 |
|
||||||
|
| `music-video-ads` | Removes ads in the music player. | 5.39.52 |
|
||||||
|
| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | 5.39.52 |
|
||||||
|
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | 5.39.52 |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `com.garzotto.pflotsh.ecmwf_a`
|
### [📦 `com.ss.android.ugc.trill`](https://play.google.com/store/apps/details?id=com.ss.android.ugc.trill)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `pflotsh-ecmwf-subscription-unlock` | Unlocks all subscription features. | 3.5.4 |
|
| `disable-login-requirement` | Do not force login. | all |
|
||||||
|
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
|
||||||
|
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
|
||||||
|
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||||
|
| `hide-ads` | Removes ads from TikTok. | all |
|
||||||
|
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||||
|
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
|
||||||
|
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||||
|
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `com.google.android.apps.youtube.music`
|
### [📦 `com.zhiliaoapp.musically`](https://play.google.com/store/apps/details?id=com.zhiliaoapp.musically)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `minimized-playback-music` | Enables minimized playback on Kids music. | 5.17.51 |
|
| `disable-login-requirement` | Do not force login. | all |
|
||||||
| `tasteBuilder-remover` | Removes the "Tell us which artists you like" card from the home screen. | 5.16.51 |
|
| `downloads` | Removes download restrictions and changes the default path to download to. | 27.8.3 |
|
||||||
| `hide-get-premium` | Removes all "Get Premium" evidences from the avatar menu. | 5.17.51 |
|
| `feed-filter` | Filters tiktok videos: removing ads, removing livestreams. | 27.8.3 |
|
||||||
| `compact-header` | Hides the music category bar at the top of the homepage. | 5.16.51 |
|
| `fix-google-login` | Allows logging in with a Google account. | all |
|
||||||
| `upgrade-button-remover` | Removes the upgrade tab from the pivot bar. | 5.17.51 |
|
| `hide-ads` | Removes ads from TikTok. | all |
|
||||||
| `background-play` | Enables playing music in the background. | 5.17.51 |
|
| `playback-speed` | Enables the playback speed option for all videos. | all |
|
||||||
| `music-microg-support` | Allows YouTube Music ReVanced to run without root and under a different package name. | 5.17.51 |
|
| `settings` | Adds ReVanced settings to TikTok. | 27.8.3 |
|
||||||
| `music-video-ads` | Removes ads in the music player. | 5.17.51 |
|
| `show-seekbar` | Shows progress bar for all video. | all |
|
||||||
| `codecs-unlock` | Adds more audio codec options. The new audio codecs usually result in better audio quality. | 5.17.51 |
|
| `sim-spoof` | Spoofs the information which is retrieved from the sim-card. | 27.8.3 |
|
||||||
| `exclusive-audio-playback` | Enables the option to play music without video. | 5.17.51 |
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `de.dwd.warnapp`
|
### [📦 `tv.twitch.android.app`](https://play.google.com/store/apps/details?id=tv.twitch.android.app)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `block-audio-ads` | Blocks audio ads in streams and VODs. | all |
|
||||||
|
| `block-embedded-ads` | Blocks embedded steam ads using services like TTV.lol or PurpleAdBlocker. | all |
|
||||||
|
| `block-video-ads` | Blocks video ads in streams and VODs. | all |
|
||||||
|
| `debug-mode` | Enables Twitch's internal debugging mode. | all |
|
||||||
|
| `settings` | Adds settings menu to Twitch. | all |
|
||||||
|
| `show-deleted-messages` | Shows deleted chat messages behind a clickable spoiler. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.twitter.android`](https://play.google.com/store/apps/details?id=com.twitter.android)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `dynamic-color` | Replaces the default Twitter Blue with the users Material You palette. | all |
|
||||||
|
| `hide-views-stats` | Hides the view stats under tweets. | 9.69.1-release.0 |
|
||||||
|
| `monochrome-icon` | Adds a monochrome icon. | all |
|
||||||
|
| `timeline-ads` | Removes ads from the Twitter timeline. Might require clearing app data to remove already cached ads. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.spotify.music`](https://play.google.com/store/apps/details?id=com.spotify.music)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `disable-capture-restriction` | Allows capturing Spotify's audio output while screen sharing or screen recording. | all |
|
||||||
|
| `hide-premium-navbar` | Removes the premium tab from the navbar. | all |
|
||||||
|
| `spotify-theme` | Applies a custom theme. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.reddit.frontpage`](https://play.google.com/store/apps/details?id=com.reddit.frontpage)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `general-reddit-ads` | Removes general ads from the Reddit frontpage and subreddits. | 2022.43.0 |
|
||||||
|
| `premium-icon-reddit` | Unlocks premium Reddit app icons. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `at.gv.bmf.bmf2go`](https://play.google.com/store/apps/details?id=at.gv.bmf.bmf2go)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `remove-bootloader-detection` | Removes the check for an unlocked bootloader. | 2.2.0 |
|
||||||
|
| `remove-root-detection` | Removes the check for root permissions | 2.2.0 |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `at.gv.oe.app`](https://play.google.com/store/apps/details?id=at.gv.oe.app)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `remove-root-detection` | Removes the check for root permissions and unlocked bootloader. | 2.5.2 |
|
||||||
|
| `spoof-signature` | Spoofs the signature of the app. | 2.5.2 |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.vanced.android.youtube`](https://play.google.com/store/apps/details?id=com.vanced.android.youtube)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `client-spoof` | Spoofs the YouTube or Vanced client to prevent playback issues. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.myprog.hexedit`](https://play.google.com/store/apps/details?id=com.myprog.hexedit)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `disable-ads` | Disables ads in HexEditor. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `org.citra.citra_emu`](https://play.google.com/store/apps/details?id=org.citra.citra_emu)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `premium-unlock` | Unlocks premium functions. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `org.citra.citra_emu.canary`](https://play.google.com/store/apps/details?id=org.citra.citra_emu.canary)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `premium-unlock` | Unlocks premium functions. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.backdrops.wallpapers`](https://play.google.com/store/apps/details?id=com.backdrops.wallpapers)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `pro-unlock` | Unlocks pro-only functions. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `de.dwd.warnapp`](https://play.google.com/store/apps/details?id=de.dwd.warnapp)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
@@ -53,48 +220,183 @@ Official patches by ReVanced
|
|||||||
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
|
| `promo-code-unlock` | Disables the validation of promo code. Any code will work to unlock all features. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `com.ss.android.ugc.trill`
|
### [📦 `com.teslacoilsw.launcher`](https://play.google.com/store/apps/details?id=com.teslacoilsw.launcher)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `tiktok-ads` | Removes ads from TikTok. | all |
|
| `unlock-prime` | Unlocks Nova Prime and all functions of the app. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### 📦 `com.google.android.youtube`
|
### [📦 `co.windyapp.android`](https://play.google.com/store/apps/details?id=co.windyapp.android)
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|:--------:|:--------------:|:-----------------:|
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `swipe-controls` | Adds volume and brightness swipe controls. | 17.32.35 |
|
| `unlock-pro` | Unlocks all pro features. | all |
|
||||||
| `downloads` | Enables downloading music and videos from YouTube. | 17.32.35 |
|
</details>
|
||||||
| `seekbar-tapping` | Enables tap-to-seek on the seekbar of the video player. | 17.32.35 |
|
|
||||||
| `amoled` | Enables pure black theme. | 17.32.35 |
|
### [📦 `com.awedea.nyx`](https://play.google.com/store/apps/details?id=com.awedea.nyx)
|
||||||
| `disable-create-button` | Hides the create button in the navigation bar. | 17.32.35 |
|
<details>
|
||||||
| `hide-cast-button` | Hides the cast button in the video player. | all |
|
|
||||||
| `return-youtube-dislike` | Shows the dislike count of videos using the Return YouTube Dislike API. | 17.32.35 |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
| `hide-autoplay-button` | Hides the autoplay button in the video player. | 17.32.35 |
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `premium-heading` | Shows premium branding on the home screen. | all |
|
| `unlock-pro` | Unlocks all pro features. | all |
|
||||||
| `custom-branding` | Changes the YouTube launcher icon and name to your choice (defaults to ReVanced). | all |
|
</details>
|
||||||
| `disable-fullscreen-panels` | Disables video description and comments panel in fullscreen view. | 17.32.35 |
|
|
||||||
| `old-quality-layout` | Enables the original quality flyout menu. | 17.32.35 |
|
### [📦 `ginlemon.iconpackstudio`](https://play.google.com/store/apps/details?id=ginlemon.iconpackstudio)
|
||||||
| `hide-shorts-button` | Hides the shorts button on the navigation bar. | 17.32.35 |
|
<details>
|
||||||
| `hide-watermark` | Hides creator's watermarks on videos. | 17.32.35 |
|
|
||||||
| `sponsorblock` | Integrate SponsorBlock. | 17.32.35 |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
| `enable-wide-searchbar` | Replaces the search icon with a wide search bar. This will hide the YouTube logo when active. | 17.32.35 |
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `tablet-mini-player` | Enables the tablet mini player layout. | 17.32.35 |
|
| `unlock-pro` | Unlocks all pro features. | all |
|
||||||
| `minimized-playback` | Enables minimized and background playback. | 17.32.35 |
|
</details>
|
||||||
| `custom-video-buffer` | Lets you change the buffers of videos. | 17.32.35 |
|
|
||||||
| `always-autorepeat` | Always repeats the playing video again. | 17.32.35 |
|
### [📦 `org.totschnig.myexpenses`](https://play.google.com/store/apps/details?id=org.totschnig.myexpenses)
|
||||||
| `microg-support` | Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG | 17.32.35 |
|
<details>
|
||||||
| `settings` | Adds settings for ReVanced to YouTube. | all |
|
|
||||||
| `enable-debugging` | Enables app debugging by patching the manifest file. | all |
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
| `custom-playback-speed` | Adds more video playback speed options. | 17.32.35 |
|
|:--------:|:--------------:|:-----------------:|
|
||||||
| `hdr-auto-brightness` | Makes the brightness of HDR videos follow the system default. | 17.32.35 |
|
| `unlock-pro` | Unlocks all professional features. | all |
|
||||||
| `remember-video-quality` | Adds the ability to remember the video quality you chose in the video quality flyout. | 17.32.35 |
|
</details>
|
||||||
| `video-ads` | Removes ads in the video player. | 17.32.35 |
|
|
||||||
| `general-ads` | Removes general ads. | 17.32.35 |
|
### [📦 `com.ithebk.expensemanager`](https://play.google.com/store/apps/details?id=com.ithebk.expensemanager)
|
||||||
| `hide-infocard-suggestions` | Hides infocards in videos. | 17.32.35 |
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `unlock-pro` | Unlocks pro features. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `com.ticktick.task`](https://play.google.com/store/apps/details?id=com.ticktick.task)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `unlock-themes` | Unlocks all themes. | all |
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### [📦 `net.dinglisch.android.taskerm`](https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm)
|
||||||
|
<details>
|
||||||
|
|
||||||
|
| 💊 Patch | 📜 Description | 🏹 Target Version |
|
||||||
|
|:--------:|:--------------:|:-----------------:|
|
||||||
|
| `unlock-trial` | Unlocks the trial version. | all |
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 📝 JSON Format
|
||||||
|
|
||||||
|
This section explains the JSON format for the [patches.json](patches.json) file.
|
||||||
|
|
||||||
|
The file contains an array of objects, each object representing a patch. The object contains the following properties:
|
||||||
|
|
||||||
|
| key | description |
|
||||||
|
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| `name` | The name of the patch. |
|
||||||
|
| `description` | The description of the patch. |
|
||||||
|
| `version` | The version of the patch. |
|
||||||
|
| `excluded` | Whether the patch is excluded by default. If `true`, the patch must never be included by default. |
|
||||||
|
| `options` | An array of options for this patch. |
|
||||||
|
| `options.key` | The key of the option. |
|
||||||
|
| `options.title` | The title of the option. |
|
||||||
|
| `options.description` | The description of the option. |
|
||||||
|
| `options.required` | Whether the option is required. |
|
||||||
|
| `options.choices?` | An array of choices of the option. This may be `null` if this option has no choices. The element type of this array may be any type. It can be a `String`, `Int` or something else. |
|
||||||
|
| `dependencies` | An array of dependencies, which are patch names. |
|
||||||
|
| `compatiblePackages` | An array of packages compatible with this patch. |
|
||||||
|
| `compatiblePackages.name` | The name of the package. |
|
||||||
|
| `compatiblePackages.versions` | An array of versions of the package compatible with this patch. If empty, all versions are seemingly compatible. |
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "remember-video-quality",
|
||||||
|
"description": "Adds the ability to remember the video quality you chose in the video quality flyout.",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"options": [],
|
||||||
|
"dependencies": [
|
||||||
|
"integrations",
|
||||||
|
"video-id-hook"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": [
|
||||||
|
"17.22.36",
|
||||||
|
"17.24.35",
|
||||||
|
"17.26.35",
|
||||||
|
"17.27.39",
|
||||||
|
"17.28.34",
|
||||||
|
"17.29.34",
|
||||||
|
"17.32.35",
|
||||||
|
"17.33.42"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme",
|
||||||
|
"description": "Enables a custom theme.",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"key": "theme",
|
||||||
|
"title": "Theme",
|
||||||
|
"description": "Select a theme.",
|
||||||
|
"required": true,
|
||||||
|
"choices": [
|
||||||
|
"Amoled"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"locale-config-fix"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "custom-branding",
|
||||||
|
"description": "Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"excluded": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"key": "appName",
|
||||||
|
"title": "Application Name",
|
||||||
|
"description": "The name of the application it will show on your home screen.",
|
||||||
|
"required": true,
|
||||||
|
"choices": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "appIconPath",
|
||||||
|
"title": "Application Icon Path",
|
||||||
|
"description": "A path to the icon of the application.",
|
||||||
|
"required": false,
|
||||||
|
"choices": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"locale-config-fix"
|
||||||
|
],
|
||||||
|
"compatiblePackages": [
|
||||||
|
{
|
||||||
|
"name": "com.google.android.youtube",
|
||||||
|
"versions": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
@@ -20,10 +20,10 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("stdlib"))
|
implementation("app.revanced:revanced-patcher:6.4.2")
|
||||||
|
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
|
||||||
implementation("app.revanced:revanced-patcher:3.3.3")
|
// Required for meta
|
||||||
implementation("app.revanced:multidexlib2:2.5.2.r2")
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
@@ -33,7 +33,7 @@ tasks {
|
|||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
val androidHome = System.getenv("ANDROID_HOME") ?: throw GradleException("ANDROID_HOME not found")
|
val androidHome = System.getenv("ANDROID_HOME") ?: throw GradleException("ANDROID_HOME not found")
|
||||||
val d8 = "${androidHome}/build-tools/32.0.0/d8"
|
val d8 = "${androidHome}/build-tools/33.0.1/d8"
|
||||||
val input = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
val input = configurations.archives.get().allArtifacts.files.files.first().absolutePath
|
||||||
val work = File("${buildDir}/libs")
|
val work = File("${buildDir}/libs")
|
||||||
|
|
||||||
@@ -48,12 +48,12 @@ tasks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
register<JavaExec>("generateReadme") {
|
register<JavaExec>("generateMeta") {
|
||||||
description = "Generate README.md"
|
description = "Generate metadata for this bundle"
|
||||||
dependsOn(build)
|
dependsOn(build)
|
||||||
|
|
||||||
classpath = sourceSets["main"].runtimeClasspath
|
classpath = sourceSets["main"].runtimeClasspath
|
||||||
mainClass.set("app.revanced.meta.readme.Generator")
|
mainClass.set("app.revanced.meta.PatchesFileGenerator")
|
||||||
}
|
}
|
||||||
// Dummy task to fix the Gradle semantic-release plugin.
|
// Dummy task to fix the Gradle semantic-release plugin.
|
||||||
// Remove this if you forked it to support building only.
|
// Remove this if you forked it to support building only.
|
||||||
@@ -61,6 +61,6 @@ tasks {
|
|||||||
register<DefaultTask>("publish") {
|
register<DefaultTask>("publish") {
|
||||||
group = "publish"
|
group = "publish"
|
||||||
description = "Dummy task"
|
description = "Dummy task"
|
||||||
dependsOn(named("generateBundle"), named("generateReadme"))
|
dependsOn(named("generateBundle"), named("generateMeta"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 2.42.0
|
version = 2.157.0-dev.4
|
||||||
|
|||||||
6107
package-lock.json
generated
Normal file
6107
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
package.json
Normal file
8
package.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@semantic-release/changelog": "^6.0.2",
|
||||||
|
"@semantic-release/git": "^10.0.1",
|
||||||
|
"gradle-semantic-release-plugin": "^1.7.4",
|
||||||
|
"semantic-release": "^19.0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
patches.json
Normal file
1
patches.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,45 +1,30 @@
|
|||||||
package app.revanced.extensions
|
package app.revanced.extensions
|
||||||
|
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
||||||
import app.revanced.patcher.data.impl.ResourceData
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
|
||||||
import app.revanced.patcher.patch.PatchResultError
|
import app.revanced.patcher.patch.PatchResultError
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
import app.revanced.patcher.util.smali.toInstruction
|
import org.jf.dexlib2.iface.Method
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.util.MethodUtil
|
||||||
import org.jf.dexlib2.Opcode
|
|
||||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11n
|
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
|
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
|
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
|
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
// TODO: this method does not make sense here
|
// TODO: populate this to all patches
|
||||||
internal fun MutableMethodImplementation.injectHideCall(
|
/**
|
||||||
index: Int,
|
* Convert a [MethodFingerprint] to a [PatchResultError].
|
||||||
register: Int
|
*
|
||||||
) {
|
* @return A [PatchResultError] for the [MethodFingerprint].
|
||||||
this.addInstruction(
|
*/
|
||||||
index,
|
fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name")
|
||||||
"invoke-static { v$register }, Lapp/revanced/integrations/patches/HideHomeAdsPatch;->HideHomeAds(Landroid/view/View;)V".toInstruction()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* traverse the class hierarchy starting from the given root class
|
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
|
||||||
*
|
*
|
||||||
* @param targetClass the class to start traversing the class hierarchy from
|
* @param method The [Method] to find.
|
||||||
* @param callback function that is called for every class in the hierarchy
|
* @return The [MutableMethod].
|
||||||
*/
|
*/
|
||||||
fun BytecodeData.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) {
|
fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
|
||||||
callback(targetClass)
|
MethodUtil.methodSignaturesMatch(it, method)
|
||||||
this.findClass(targetClass.superclass ?: return)?.resolve()?.let {
|
|
||||||
traverseClassHierarchy(it, callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,160 +38,7 @@ fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod)
|
|||||||
methods.addAll(transformedMethods)
|
methods.addAll(transformedMethods)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert an event hook at the top of the method. If the hook returns true, the event is consumed and the method will return with true
|
|
||||||
*
|
|
||||||
* the hook method MUST return a boolean and MUST take two parameters, like so:
|
|
||||||
* fun hook(thisRef: Object, eventData: Object): Boolean {}
|
|
||||||
*
|
|
||||||
* The final injected code will resemble the following logic:
|
|
||||||
* if( YouHook(this, event) ) { return true; }
|
|
||||||
* ...
|
|
||||||
*
|
|
||||||
* @param hookRef reference to the hook method
|
|
||||||
*/
|
|
||||||
internal fun MutableMethod.injectConsumableEventHook(hookRef: ImmutableMethodReference) {
|
|
||||||
val isStaticMethod = AccessFlags.STATIC.isSet(this.accessFlags)
|
|
||||||
this.implementation?.let { impl ->
|
|
||||||
// create label to index 0 to continue to the normal program flow
|
|
||||||
val lblContinueNormalFlow = impl.newLabelForIndex(0)
|
|
||||||
|
|
||||||
// define registers
|
|
||||||
/** V0 */
|
|
||||||
val regV0 = 0
|
|
||||||
|
|
||||||
/** this */
|
|
||||||
val regP0 = impl.registerCount - this.parameters.size - (if (isStaticMethod) 0 else 1)
|
|
||||||
|
|
||||||
/** motionEvent */
|
|
||||||
val regP1 = regP0 + 1
|
|
||||||
|
|
||||||
// insert instructions at the start of the method:
|
|
||||||
// if( Hook(this, event) ) { return true; }
|
|
||||||
impl.addInstructions(
|
|
||||||
0, listOf(
|
|
||||||
// invoke-static { p0, p1 } <hook>
|
|
||||||
BuilderInstruction35c(
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
2,
|
|
||||||
regP0,
|
|
||||||
regP1,
|
|
||||||
0, 0, 0,
|
|
||||||
hookRef
|
|
||||||
),
|
|
||||||
|
|
||||||
// move-result v0
|
|
||||||
BuilderInstruction11x(
|
|
||||||
Opcode.MOVE_RESULT,
|
|
||||||
regV0
|
|
||||||
),
|
|
||||||
|
|
||||||
// if-eqz v0, :continue_normal_flow
|
|
||||||
BuilderInstruction21t(
|
|
||||||
Opcode.IF_EQZ,
|
|
||||||
regV0,
|
|
||||||
lblContinueNormalFlow
|
|
||||||
),
|
|
||||||
|
|
||||||
// const/4 v0, 0x1
|
|
||||||
BuilderInstruction11n(
|
|
||||||
Opcode.CONST_4,
|
|
||||||
regV0,
|
|
||||||
0x1
|
|
||||||
),
|
|
||||||
|
|
||||||
// return v0
|
|
||||||
BuilderInstruction11x(
|
|
||||||
Opcode.RETURN,
|
|
||||||
regV0
|
|
||||||
)
|
|
||||||
|
|
||||||
// :continue_normal_flow
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* inject resources into the patched app
|
|
||||||
*
|
|
||||||
* @param classLoader classloader to use for loading the resources
|
|
||||||
* @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder
|
|
||||||
* @param resourceType the resource type, for example 'drawable'. this has to match both the source and the target
|
|
||||||
* @param resourceFileNames names of all resources of this type to inject
|
|
||||||
*/
|
|
||||||
fun ResourceData.injectResources(
|
|
||||||
classLoader: ClassLoader,
|
|
||||||
patchDirectoryPath: String,
|
|
||||||
resourceType: String,
|
|
||||||
resourceFileNames: List<String>
|
|
||||||
) {
|
|
||||||
resourceFileNames.forEach { name ->
|
|
||||||
val relativePath = "$resourceType/$name"
|
|
||||||
val sourceRes = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath")
|
|
||||||
?: throw PatchResultError("could not open resource '$patchDirectoryPath/$relativePath'")
|
|
||||||
|
|
||||||
Files.copy(
|
|
||||||
sourceRes,
|
|
||||||
this["res"].resolve(relativePath).toPath()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* inject strings into the patched app
|
|
||||||
*
|
|
||||||
* @param classLoader classloader to use for loading the resources
|
|
||||||
* @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder
|
|
||||||
* @param languageIdentifier ISO 639-2 two- letter language code identifier (aka the one android uses for values directory)
|
|
||||||
*/
|
|
||||||
fun ResourceData.injectStrings(
|
|
||||||
classLoader: ClassLoader,
|
|
||||||
patchDirectoryPath: String,
|
|
||||||
languageIdentifier: String? = null,
|
|
||||||
) {
|
|
||||||
val relativePath =
|
|
||||||
if (languageIdentifier.isNullOrBlank()) "values/strings.xml" else "values/strings-$languageIdentifier.xml"
|
|
||||||
|
|
||||||
// open source strings.xml
|
|
||||||
val sourceInputStream = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath")
|
|
||||||
?: throw PatchResultError("failed to open '$patchDirectoryPath/$relativePath'")
|
|
||||||
xmlEditor[sourceInputStream].use { sourceStringsXml ->
|
|
||||||
val strings = sourceStringsXml.file.getElementsByTagName("resources").item(0).childNodes
|
|
||||||
|
|
||||||
// open target strings.xml
|
|
||||||
xmlEditor["res/$relativePath"].use { targetStringsXml ->
|
|
||||||
val targetFile = targetStringsXml.file
|
|
||||||
val targetRootNode = targetFile.getElementsByTagName("resources").item(0)
|
|
||||||
|
|
||||||
// process all children strings in the source
|
|
||||||
for (i in 0 until strings.length) {
|
|
||||||
// clone the node from source to target
|
|
||||||
val node = strings.item(i).cloneNode(true)
|
|
||||||
targetFile.adoptNode(node)
|
|
||||||
targetRootNode.appendChild(node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun Node.doRecursively(action: (Node) -> Unit) {
|
internal fun Node.doRecursively(action: (Node) -> Unit) {
|
||||||
action(this)
|
action(this)
|
||||||
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
|
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun String.startsWithAny(vararg prefixes: String): Boolean {
|
|
||||||
for (prefix in prefixes)
|
|
||||||
if (this.startsWith(prefix))
|
|
||||||
return true
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun String.equalsAny(vararg other: String): Boolean {
|
|
||||||
for (_other in other)
|
|
||||||
if (this == _other)
|
|
||||||
return true
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
70
src/main/kotlin/app/revanced/meta/JsonGenerator.kt
Normal file
70
src/main/kotlin/app/revanced/meta/JsonGenerator.kt
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package app.revanced.meta
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.dependencies
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.include
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.options
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.version
|
||||||
|
import app.revanced.patcher.patch.PatchOption
|
||||||
|
import com.google.gson.GsonBuilder
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class JsonGenerator : PatchesFileGenerator {
|
||||||
|
override fun generate(bundle: PatchBundlePatches) {
|
||||||
|
val patches = bundle.map {
|
||||||
|
JsonPatch(
|
||||||
|
it.patchName,
|
||||||
|
it.description ?: "This patch has no description.",
|
||||||
|
it.version ?: "0.0.0",
|
||||||
|
!it.include,
|
||||||
|
it.options?.map { option ->
|
||||||
|
JsonPatch.Option(
|
||||||
|
option.key,
|
||||||
|
option.title,
|
||||||
|
option.description,
|
||||||
|
option.required,
|
||||||
|
option.let { listOption ->
|
||||||
|
if (listOption is PatchOption.ListOption<*>) {
|
||||||
|
listOption.options.toMutableList().toTypedArray()
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}?.toTypedArray() ?: emptyArray(),
|
||||||
|
it.dependencies?.map { dep ->
|
||||||
|
dep.java.patchName
|
||||||
|
}?.toTypedArray() ?: emptyArray(),
|
||||||
|
it.compatiblePackages?.map { pkg ->
|
||||||
|
JsonPatch.CompatiblePackage(pkg.name, pkg.versions)
|
||||||
|
}?.toTypedArray() ?: emptyArray()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val json = File("patches.json")
|
||||||
|
json.writeText(GsonBuilder().serializeNulls().create().toJson(patches))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsonPatch(
|
||||||
|
val name: String,
|
||||||
|
val description: String,
|
||||||
|
val version: String,
|
||||||
|
val excluded: Boolean,
|
||||||
|
val options: Array<Option>,
|
||||||
|
val dependencies: Array<String>,
|
||||||
|
val compatiblePackages: Array<CompatiblePackage>,
|
||||||
|
) {
|
||||||
|
class CompatiblePackage(
|
||||||
|
val name: String,
|
||||||
|
val versions: Array<String>,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Option(
|
||||||
|
val key: String,
|
||||||
|
val title: String,
|
||||||
|
val description: String,
|
||||||
|
val required: Boolean,
|
||||||
|
val choices: Array<*>?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt
Normal file
25
src/main/kotlin/app/revanced/meta/PatchesFileGenerator.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package app.revanced.meta
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.Context
|
||||||
|
import app.revanced.patcher.patch.Patch
|
||||||
|
import app.revanced.patcher.util.patch.PatchBundle
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
typealias PatchBundlePatches = List<Class<out Patch<Context>>>
|
||||||
|
|
||||||
|
internal interface PatchesFileGenerator {
|
||||||
|
fun generate(bundle: PatchBundlePatches)
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) = PatchBundle.Jar(
|
||||||
|
File("build/libs/").listFiles()!!.first {
|
||||||
|
it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar")
|
||||||
|
}.absolutePath
|
||||||
|
).loadPatches().also {
|
||||||
|
if (it.isEmpty()) throw IllegalStateException("No patches found")
|
||||||
|
}.let { bundle ->
|
||||||
|
arrayOf(JsonGenerator(), ReadmeGenerator()).forEach { it.generate(bundle) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
Normal file
69
src/main/kotlin/app/revanced/meta/ReadmeGenerator.kt
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package app.revanced.meta
|
||||||
|
|
||||||
|
import app.revanced.patcher.data.Context
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||||
|
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||||
|
import app.revanced.patcher.patch.Patch
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class ReadmeGenerator : PatchesFileGenerator {
|
||||||
|
private companion object {
|
||||||
|
private const val TABLE_HEADER =
|
||||||
|
"| \uD83D\uDC8A Patch | \uD83D\uDCDC Description | \uD83C\uDFF9 Target Version |\n" +
|
||||||
|
"|:--------:|:--------------:|:-----------------:|"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun generate(bundle: PatchBundlePatches) {
|
||||||
|
val output = StringBuilder()
|
||||||
|
|
||||||
|
mutableMapOf<String, MutableList<Class<out Patch<Context>>>>()
|
||||||
|
.apply {
|
||||||
|
for (patch in bundle) {
|
||||||
|
patch.compatiblePackages?.forEach { pkg ->
|
||||||
|
if (!contains(pkg.name)) put(pkg.name, mutableListOf())
|
||||||
|
this[pkg.name]!!.add(patch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.entries
|
||||||
|
.sortedByDescending { it.value.size }
|
||||||
|
.forEach { (`package`, patches) ->
|
||||||
|
val mostCommonVersion = buildMap {
|
||||||
|
patches.forEach { patch ->
|
||||||
|
patch.compatiblePackages?.single { compatiblePackage -> compatiblePackage.name == `package` }?.versions?.let {
|
||||||
|
it.forEach { version -> merge(version, 1, Integer::sum) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.let { commonMap ->
|
||||||
|
commonMap.maxByOrNull { it.value }?.value?.let {
|
||||||
|
// This is not foolproof, because for example v1.0.0-dev.0 will be returned instead of v1.0.0-release.
|
||||||
|
// Unfortunately this can not be solved easily because versioning can be complex.
|
||||||
|
commonMap.entries.filter { mostCommon -> mostCommon.value == it }.maxBy { it.key }.key
|
||||||
|
} ?: "all"
|
||||||
|
}
|
||||||
|
|
||||||
|
output.apply {
|
||||||
|
appendLine("### [\uD83D\uDCE6 `${`package`}`](https://play.google.com/store/apps/details?id=${`package`})")
|
||||||
|
appendLine("<details>\n")
|
||||||
|
appendLine(TABLE_HEADER)
|
||||||
|
patches.forEach { patch ->
|
||||||
|
val recommendedPatchVersion = if (
|
||||||
|
patch.compatiblePackages?.single { it.name == `package` }?.versions?.isNotEmpty() == true
|
||||||
|
) mostCommonVersion else "all"
|
||||||
|
|
||||||
|
appendLine(
|
||||||
|
"| `${patch.patchName}` " +
|
||||||
|
"| ${patch.description} " +
|
||||||
|
"| $recommendedPatchVersion |"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
appendLine("</details>\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder(File("README-template.md").readText())
|
||||||
|
.replace(Regex("\\{\\{\\s?table\\s?}}"), output.toString())
|
||||||
|
.let(File("README.md")::writeText)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package app.revanced.meta.readme
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.Data
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
|
|
||||||
internal fun Class<out Patch<Data>>.getLatestVersion(): SemanticVersion? =
|
|
||||||
this.compatiblePackages?.first()?.versions?.map { SemanticVersion.fromString(it) }
|
|
||||||
?.maxWithOrNull(
|
|
||||||
SemanticVersionComparator
|
|
||||||
)
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package app.revanced.meta.readme
|
|
||||||
|
|
||||||
import app.revanced.patcher.data.Data
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.description
|
|
||||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
|
||||||
import app.revanced.patcher.patch.Patch
|
|
||||||
import app.revanced.patcher.util.patch.impl.JarPatchBundle
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
object Generator {
|
|
||||||
private const val TABLE_HEADER =
|
|
||||||
"| \uD83D\uDC8A Patch | \uD83D\uDCDC Description | \uD83C\uDFF9 Target Version |\n" +
|
|
||||||
"|:--------:|:--------------:|:-----------------:|"
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
val buildDir = File("build/libs/")
|
|
||||||
val buildJar =
|
|
||||||
buildDir.listFiles()?.first { it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar") }!!
|
|
||||||
|
|
||||||
val bundle = JarPatchBundle(buildJar.absolutePath).loadPatches()
|
|
||||||
|
|
||||||
val output = StringBuilder()
|
|
||||||
|
|
||||||
val packages = mutableMapOf<String, MutableList<Class<out Patch<Data>>>>()
|
|
||||||
|
|
||||||
bundle.map {
|
|
||||||
val packageName = it.compatiblePackages?.first()?.name!!
|
|
||||||
if (!packages.contains(packageName)) {
|
|
||||||
packages[packageName] = mutableListOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
packages[packageName]?.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (pkg in packages) {
|
|
||||||
output.appendLine("### \uD83D\uDCE6 `${pkg.key}`")
|
|
||||||
output.appendLine("<details>\n")
|
|
||||||
|
|
||||||
output.appendLine(TABLE_HEADER)
|
|
||||||
pkg.value.forEach { output.appendLine("| `${it.patchName}` | ${it.description} | ${it.getLatestVersion() ?: "all"} |") }
|
|
||||||
|
|
||||||
output.appendLine("</details>\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
val readMeTemplateFile = File("README-template.md")
|
|
||||||
val readmeTemplate = Template(readMeTemplateFile.readText())
|
|
||||||
|
|
||||||
readmeTemplate.replaceVariable("table", output.toString())
|
|
||||||
|
|
||||||
val readme = File("README.md")
|
|
||||||
readme.writeText(readmeTemplate.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package app.revanced.meta.readme
|
|
||||||
|
|
||||||
data class SemanticVersion(val major: Int, val minor: Int, val patch: Int) {
|
|
||||||
companion object {
|
|
||||||
fun fromString(version: String): SemanticVersion {
|
|
||||||
var parts = version.split(".")
|
|
||||||
|
|
||||||
if (parts.count() != 3) throw IllegalArgumentException("Invalid semantic version")
|
|
||||||
|
|
||||||
val versionNumbers = parts.map { it.toInt() }
|
|
||||||
return SemanticVersion(versionNumbers[0], versionNumbers[1], versionNumbers[2])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = "$major.$minor.$patch"
|
|
||||||
}
|
|
||||||
|
|
||||||
object SemanticVersionComparator : Comparator<SemanticVersion> {
|
|
||||||
override fun compare(a: SemanticVersion, b: SemanticVersion): Int = when {
|
|
||||||
a.major != b.major -> a.major - b.major
|
|
||||||
a.minor != b.minor -> a.minor - b.minor
|
|
||||||
else -> a.patch - b.patch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package app.revanced.meta.readme
|
|
||||||
|
|
||||||
class Template(template: String) {
|
|
||||||
val result: StringBuilder = StringBuilder(template)
|
|
||||||
|
|
||||||
fun replaceVariable(name: String, value: String) {
|
|
||||||
val regex = Regex("\\{\\{\\s?$name\\s?}}")
|
|
||||||
val range = regex.find(result)!!.range
|
|
||||||
|
|
||||||
result.replace(range.first, range.last + 1, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = result.toString()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package app.revanced.patches.all.interaction.gestures.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.ResourceContext
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
|
||||||
|
@Patch(false)
|
||||||
|
@Name("predictive-back-gesture")
|
||||||
|
@Description("Enables the predictive back gesture introduced on Android 13.")
|
||||||
|
@Version("0.0.1")
|
||||||
|
class PredictiveBackGesturePatch : ResourcePatch {
|
||||||
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
|
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
|
val document = editor.file
|
||||||
|
|
||||||
|
with(document.getElementsByTagName("application").item(0)) {
|
||||||
|
if (attributes.getNamedItem(FLAG) != null) return@with
|
||||||
|
|
||||||
|
document.createAttribute(FLAG)
|
||||||
|
.apply { value = "true" }
|
||||||
|
.let(attributes::setNamedItem)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val FLAG = "android:enableOnBackInvokedCallback"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package app.revanced.patches.all.screenshot.removerestriction.patch
|
||||||
|
|
||||||
|
import app.revanced.extensions.findMutableMethodOf
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
|
||||||
|
import org.jf.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
|
@Patch(false)
|
||||||
|
@Name("remove-screenshot-restriction")
|
||||||
|
@Description("Removes the restriction of making screenshots.")
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RemoveScreenshotRestrictionPatch : BytecodePatch() {
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/all/screenshot/removerestriction/RemoveScreenshotRestrictionPatch;"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Information about method calls we want to replace
|
||||||
|
private enum class MethodCall(
|
||||||
|
val definedClassName: String,
|
||||||
|
val methodName: String,
|
||||||
|
val replacementMethodDefinition: String
|
||||||
|
) {
|
||||||
|
SetFlags(
|
||||||
|
"Landroid/view/Window;",
|
||||||
|
"setFlags",
|
||||||
|
"setFlags(Landroid/view/Window;II)V",
|
||||||
|
);
|
||||||
|
|
||||||
|
fun replaceInstruction(method: MutableMethod, instruction: Instruction35c, instructionIndex: Int) {
|
||||||
|
when (this) {
|
||||||
|
SetFlags -> {
|
||||||
|
method.replaceInstruction(
|
||||||
|
instructionIndex,
|
||||||
|
"invoke-static { v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE} }, ${INTEGRATIONS_CLASS_DESCRIPTOR}->${replacementMethodDefinition}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromMethodReference(methodReference: MethodReference) = values().firstOrNull { search ->
|
||||||
|
search.definedClassName == methodReference.definingClass && search.methodName == methodReference.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
// Find all instructions where one of the methods is called
|
||||||
|
buildMap {
|
||||||
|
context.classes.forEach { classDef ->
|
||||||
|
if (classDef.type == INTEGRATIONS_CLASS_DESCRIPTOR) {
|
||||||
|
// avoid infinite recursion
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
classDef.methods.let { methods ->
|
||||||
|
buildMap methodList@{
|
||||||
|
methods.forEach methods@{ method ->
|
||||||
|
with(method.implementation?.instructions ?: return@methods) {
|
||||||
|
ArrayDeque<Triple<MethodCall, Instruction35c, Int>>().also { patchIndices ->
|
||||||
|
this.forEachIndexed { index, instruction ->
|
||||||
|
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@forEachIndexed
|
||||||
|
|
||||||
|
val invokeInstruction = instruction as Instruction35c
|
||||||
|
val methodRef = invokeInstruction.reference as MethodReference
|
||||||
|
val methodCall = MethodCall.fromMethodReference(methodRef) ?: return@forEachIndexed
|
||||||
|
|
||||||
|
patchIndices.add(Triple(methodCall, invokeInstruction, index))
|
||||||
|
}
|
||||||
|
}.also { if (it.isEmpty()) return@methods }.let { patches ->
|
||||||
|
put(method, patches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.also { if (it.isEmpty()) return@forEach }.let { methodPatches ->
|
||||||
|
put(classDef, methodPatches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.forEach { (classDef, methods) ->
|
||||||
|
// And finally replace the instructions...
|
||||||
|
with(context.proxy(classDef).mutableClass) {
|
||||||
|
methods.forEach { (method, patches) ->
|
||||||
|
val mutableMethod = findMutableMethodOf(method)
|
||||||
|
while (!patches.isEmpty()) {
|
||||||
|
val (methodType, instruction, instructionIndex) = patches.removeLast()
|
||||||
|
methodType.replaceInstruction(mutableMethod, instruction, instructionIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package app.revanced.patches.backdrops.misc.pro.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.backdrops.wallpapers")])
|
||||||
|
internal annotation class ProUnlockCompatibility
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package app.revanced.patches.backdrops.misc.pro.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object ProUnlockFingerprint : MethodFingerprint(
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.INVOKE_VIRTUAL,
|
||||||
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT,
|
||||||
|
Opcode.IF_EQZ
|
||||||
|
),
|
||||||
|
customFingerprint = { it.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;" && it.name == "lambda\$existPurchase\$0" }
|
||||||
|
)
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package app.revanced.patches.backdrops.misc.pro.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.instruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.backdrops.misc.pro.annotations.ProUnlockCompatibility
|
||||||
|
import app.revanced.patches.backdrops.misc.pro.fingerprints.ProUnlockFingerprint
|
||||||
|
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("pro-unlock")
|
||||||
|
@Description("Unlocks pro-only functions.")
|
||||||
|
@ProUnlockCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class ProUnlockPatch : BytecodePatch(
|
||||||
|
listOf(ProUnlockFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
val result = ProUnlockFingerprint.result ?: return PatchResultError("${ProUnlockFingerprint.name} not found")
|
||||||
|
|
||||||
|
val moveRegisterInstruction = result.mutableMethod.instruction(result.scanResult.patternScanResult!!.endIndex - 1)
|
||||||
|
val register = (moveRegisterInstruction as OneRegisterInstruction).registerA
|
||||||
|
|
||||||
|
result.mutableMethod.addInstructions(
|
||||||
|
result.scanResult.patternScanResult!!.endIndex,
|
||||||
|
"""
|
||||||
|
const/4 v$register, 0x1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package app.revanced.patches.citra.misc.premium.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("org.citra.citra_emu"), Package("org.citra.citra_emu.canary")])
|
||||||
|
internal annotation class PremiumUnlockCompatbility
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package app.revanced.patches.citra.misc.premium.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object PremiumUnlockFingerprint : MethodFingerprint(
|
||||||
|
customFingerprint = { it.definingClass == "Lorg/citra/citra_emu/ui/main/MainActivity;" && it.name == "isPremiumActive" }
|
||||||
|
)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package app.revanced.patches.citra.misc.premium.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultError
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patches.citra.misc.premium.annotations.PremiumUnlockCompatbility
|
||||||
|
import app.revanced.patches.citra.misc.premium.fingerprints.PremiumUnlockFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("premium-unlock")
|
||||||
|
@Description("Unlocks premium functions.")
|
||||||
|
@PremiumUnlockCompatbility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class PremiumUnlockPatch : BytecodePatch(
|
||||||
|
listOf(PremiumUnlockFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
val result = PremiumUnlockFingerprint.result ?: return PatchResultError("${PremiumUnlockFingerprint.name} not found")
|
||||||
|
|
||||||
|
result.mutableMethod.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.bootloader.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object BootStateFingerprint : MethodFingerprint(
|
||||||
|
"Z",
|
||||||
|
access = AccessFlags.PUBLIC.value,
|
||||||
|
strings = listOf("Boot state of device: %s"),
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("/AttestationHelper;")
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.bootloader.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object BootloaderDetectionFingerprint : MethodFingerprint(
|
||||||
|
"Z",
|
||||||
|
access = AccessFlags.PUBLIC.value,
|
||||||
|
strings = listOf("Creation of attestation key succeeded", "Creation of attestation key failed"),
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("/AttestationHelper;")
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.bootloader.patch
|
||||||
|
|
||||||
|
import app.revanced.extensions.toErrorResult
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootStateFingerprint
|
||||||
|
import app.revanced.patches.finanzonline.detection.bootloader.fingerprints.BootloaderDetectionFingerprint
|
||||||
|
import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
|
||||||
|
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("remove-bootloader-detection")
|
||||||
|
@Description("Removes the check for an unlocked bootloader.")
|
||||||
|
@DetectionCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class BootloaderDetectionPatch : BytecodePatch(
|
||||||
|
listOf(BootloaderDetectionFingerprint, BootStateFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
arrayOf(BootloaderDetectionFingerprint, BootStateFingerprint).forEach { fingerprint ->
|
||||||
|
fingerprint.result?.mutableMethod?.addInstruction(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
) ?: return fingerprint.toErrorResult()
|
||||||
|
}
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.root.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object RootDetectionFingerprint : MethodFingerprint(
|
||||||
|
"L",
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass == "Lat/gv/bmf/bmf2go/tools/utils/z;"
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.root.patch
|
||||||
|
|
||||||
|
import app.revanced.extensions.toErrorResult
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.finanzonline.detection.root.fingerprints.RootDetectionFingerprint
|
||||||
|
import app.revanced.patches.finanzonline.detection.shared.annotations.DetectionCompatibility
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("remove-root-detection")
|
||||||
|
@Description("Removes the check for root permissions")
|
||||||
|
@DetectionCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RootDetectionPatch : BytecodePatch(
|
||||||
|
listOf(RootDetectionFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
RootDetectionFingerprint.result?.mutableMethod?.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
) ?: return RootDetectionFingerprint.toErrorResult()
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.finanzonline.detection.shared.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("at.gv.bmf.bmf2go", arrayOf("2.2.0"))])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class DetectionCompatibility
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.hexeditor.ad.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[
|
||||||
|
Package("com.myprog.hexedit")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class HexEditorAdsCompatibility
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.hexeditor.ad.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object PrimaryAdsFingerprint : MethodFingerprint(
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled"
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package app.revanced.patches.hexeditor.ad.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.removeInstruction
|
||||||
|
import app.revanced.patcher.extensions.replaceInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility
|
||||||
|
import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("disable-ads")
|
||||||
|
@Description("Disables ads in HexEditor.")
|
||||||
|
@HexEditorAdsCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class HexEditorAdsPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
PrimaryAdsFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
val method = PrimaryAdsFingerprint.result!!.mutableMethod
|
||||||
|
|
||||||
|
method.replaceInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.iconpackstudio.misc.pro.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("ginlemon.iconpackstudio")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UnlockProCompatibility
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package app.revanced.patches.iconpackstudio.misc.pro.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object CheckProFingerprint : MethodFingerprint(
|
||||||
|
"Z",
|
||||||
|
customFingerprint = { it.definingClass.endsWith("IPSPurchaseRepository;")}
|
||||||
|
)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package app.revanced.patches.iconpackstudio.misc.pro.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.removeInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility
|
||||||
|
import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("unlock-pro")
|
||||||
|
@Description("Unlocks all pro features.")
|
||||||
|
@UnlockProCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class UnlockProPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
CheckProFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
val method = CheckProFingerprint.result!!.mutableMethod
|
||||||
|
method.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.root.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object RootDetectionFingerprint : MethodFingerprint(
|
||||||
|
"V",
|
||||||
|
access = AccessFlags.PUBLIC.value,
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.root.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.*
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.idaustria.detection.root.fingerprints.RootDetectionFingerprint
|
||||||
|
import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("remove-root-detection")
|
||||||
|
@Description("Removes the check for root permissions and unlocked bootloader.")
|
||||||
|
@DetectionCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class RootDetectionPatch : BytecodePatch(
|
||||||
|
listOf(RootDetectionFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
RootDetectionFingerprint.result!!.mutableMethod.addInstructions(0, "return-void")
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.shared.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("at.gv.oe.app", arrayOf("2.5.2"))])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class DetectionCompatibility
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.signature.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
|
object SpoofSignatureFingerprint : MethodFingerprint(
|
||||||
|
"L",
|
||||||
|
parameters = listOf("L"),
|
||||||
|
access = AccessFlags.PRIVATE.value,
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey"
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package app.revanced.patches.idaustria.detection.signature.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.*
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.idaustria.detection.shared.annotations.DetectionCompatibility
|
||||||
|
import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSignatureFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("spoof-signature")
|
||||||
|
@Description("Spoofs the signature of the app.")
|
||||||
|
@DetectionCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class SpoofSignaturePatch : BytecodePatch(
|
||||||
|
listOf(SpoofSignatureFingerprint)
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val EXPECTED_SIGNATURE = "OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
|
||||||
|
"067c149768320026e10b24799a1339e414605e448e3f264444a327b9ae292be2b62ad567dd1800dbed4a88f718a33dc6db6b" +
|
||||||
|
"f5178aa41aa0efff8a3409f5ca95dbfccd92c7b4298966df806ea7a0204a00f0e745f6d9f13bdf24f3df715d7b62c1600906" +
|
||||||
|
"15de1c8a956b9286764985a3b3c060963c435fb9481a5543aaf0671fc2dba6c5c2b17d1ef1d85137f14dc9bbdf3490288087" +
|
||||||
|
"324cd48341cce64fabf6a9b55d1a7bf23b2fcdff451fd85bf0c7feb0a5e884d7c5c078e413149566a12a686e6efa70ae5161" +
|
||||||
|
"a0201307692834cda336c55157fef125e67c01c1359886f94742105596b42a790404bbcda5dad6a65f115aaff5e45ef3c28b" +
|
||||||
|
"2316ff6cef07aa49a45aa58c07bf258051b13ef449ccb37a3679afd5cfb9132f70bb9d931a937897544f90c3bcc80ed012e9" +
|
||||||
|
"f6ba020b8cdc23f8c29ac092b88f0e370ff9434e4f0f359e614ae0868dc526fa41e4b7596533e8d10279b66e923ecd9f0b20" +
|
||||||
|
"0def55be2c1f6f9c72c92fb45d7e0a9ac571cb38f0a9a37bb33ea06f223fde8c7a92e8c47769e386f9799776e8f110c21df2" +
|
||||||
|
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
|
||||||
|
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
SpoofSignatureFingerprint.result!!.mutableMethod.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const-string v0, "$EXPECTED_SIGNATURE"
|
||||||
|
return-object v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.moneymanager.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.ithebk.expensemanager")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UnlockProCompatibility
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package app.revanced.patches.moneymanager.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.extensions.or
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object UnlockProFingerprint : MethodFingerprint(
|
||||||
|
"Z",
|
||||||
|
AccessFlags.STATIC or AccessFlags.SYNTHETIC,
|
||||||
|
parameters = listOf("L"),
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IGET_BOOLEAN,
|
||||||
|
Opcode.RETURN
|
||||||
|
),
|
||||||
|
customFingerprint = { methodDef ->
|
||||||
|
methodDef.definingClass.endsWith("MainActivity;")
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package app.revanced.patches.moneymanager.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.moneymanager.annotations.UnlockProCompatibility
|
||||||
|
import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("unlock-pro")
|
||||||
|
@Description("Unlocks pro features.")
|
||||||
|
@UnlockProCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class UnlockProPatch : BytecodePatch(
|
||||||
|
listOf(UnlockProFingerprint)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
UnlockProFingerprint.result!!.mutableMethod.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,23 +1,11 @@
|
|||||||
package app.revanced.patches.music.ad.video.fingerprints
|
package app.revanced.patches.music.ad.video.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("show-video-ads-constructor-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Laghd;",
|
|
||||||
"<init>",
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@MusicVideoAdsCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
|
object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_DIRECT,
|
||||||
|
|||||||
@@ -1,22 +1,10 @@
|
|||||||
package app.revanced.patches.music.ad.video.fingerprints
|
package app.revanced.patches.music.ad.video.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("show-video-ads-method-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Laghd;", "d"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
|
||||||
@MusicVideoAdsCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ShowMusicVideoAdsFingerprint : MethodFingerprint(
|
object ShowMusicVideoAdsFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf(
|
||||||
Opcode.IPUT_BOOLEAN,
|
Opcode.IPUT_BOOLEAN,
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package app.revanced.patches.music.ad.video.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
|
import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility
|
||||||
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
|
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint
|
||||||
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
|
import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint
|
||||||
@@ -24,13 +24,13 @@ class MusicVideoAdsPatch : BytecodePatch(
|
|||||||
ShowMusicVideoAdsConstructorFingerprint
|
ShowMusicVideoAdsConstructorFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
ShowMusicVideoAdsFingerprint.resolve(data, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
|
ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef)
|
||||||
|
|
||||||
val result = ShowMusicVideoAdsFingerprint.result!!
|
val result = ShowMusicVideoAdsFingerprint.result!!
|
||||||
|
|
||||||
result.mutableMethod.addInstructions(
|
result.mutableMethod.addInstructions(
|
||||||
result.patternScanResult!!.startIndex, """
|
result.scanResult.patternScanResult!!.startIndex, """
|
||||||
const/4 p1, 0x0
|
const/4 p1, 0x0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
package app.revanced.patches.music.audio.codecs.fingerprints
|
package app.revanced.patches.music.audio.codecs.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher. fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("all-codecs-reference-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Laari;",
|
|
||||||
"b",
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@CodecsUnlockCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object AllCodecsReferenceFingerprint : MethodFingerprint(
|
object AllCodecsReferenceFingerprint : MethodFingerprint(
|
||||||
"J", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
"J", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf(
|
||||||
Opcode.INVOKE_STATIC,
|
Opcode.INVOKE_STATIC,
|
||||||
|
|||||||
@@ -1,25 +1,15 @@
|
|||||||
package app.revanced.patches.music.audio.codecs.fingerprints
|
package app.revanced.patches.music.audio.codecs.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("codec-lock-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lacfr;",
|
|
||||||
"a",
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@CodecsUnlockCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object CodecsLockFingerprint : MethodFingerprint(
|
object CodecsLockFingerprint : MethodFingerprint(
|
||||||
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, null, listOf(
|
"L", AccessFlags.PUBLIC or AccessFlags.STATIC, opcodes = listOf(
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_DIRECT,
|
||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_VIRTUAL,
|
||||||
Opcode.MOVE_RESULT,
|
Opcode.MOVE_RESULT,
|
||||||
@@ -32,8 +22,8 @@ object CodecsLockFingerprint : MethodFingerprint(
|
|||||||
Opcode.INVOKE_STATIC,
|
Opcode.INVOKE_STATIC,
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
Opcode.INVOKE_INTERFACE,
|
Opcode.INVOKE_INTERFACE,
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_VIRTUAL,
|
||||||
Opcode.RETURN_OBJECT
|
Opcode.RETURN_OBJECT
|
||||||
),
|
),
|
||||||
listOf("eac3_supported")
|
strings = listOf("eac3_supported")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package app.revanced.patches.music.audio.codecs.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.data.impl.toMethodWalker
|
import app.revanced.patcher.data.toMethodWalker
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.util.smali.toInstruction
|
import app.revanced.patcher.util.smali.toInstruction
|
||||||
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility
|
||||||
import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint
|
import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint
|
||||||
@@ -25,12 +25,12 @@ class CodecsUnlockPatch : BytecodePatch(
|
|||||||
CodecsLockFingerprint, AllCodecsReferenceFingerprint
|
CodecsLockFingerprint, AllCodecsReferenceFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val codecsLockResult = CodecsLockFingerprint.result!!
|
val codecsLockResult = CodecsLockFingerprint.result!!
|
||||||
|
|
||||||
val implementation = codecsLockResult.mutableMethod.implementation!!
|
val implementation = codecsLockResult.mutableMethod.implementation!!
|
||||||
|
|
||||||
val scanResultStartIndex = codecsLockResult.patternScanResult!!.startIndex
|
val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex
|
||||||
val instructionIndex = scanResultStartIndex +
|
val instructionIndex = scanResultStartIndex +
|
||||||
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
|
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
|
||||||
// for 5.16.xx and lower
|
// for 5.16.xx and lower
|
||||||
@@ -42,8 +42,8 @@ class CodecsUnlockPatch : BytecodePatch(
|
|||||||
|
|
||||||
val allCodecsResult = AllCodecsReferenceFingerprint.result!!
|
val allCodecsResult = AllCodecsReferenceFingerprint.result!!
|
||||||
val allCodecsMethod =
|
val allCodecsMethod =
|
||||||
data.toMethodWalker(allCodecsResult.method)
|
context.toMethodWalker(allCodecsResult.method)
|
||||||
.nextMethod(allCodecsResult.patternScanResult!!.startIndex)
|
.nextMethod(allCodecsResult.scanResult.patternScanResult!!.startIndex)
|
||||||
.getMethod()
|
.getMethod()
|
||||||
|
|
||||||
implementation.replaceInstruction(
|
implementation.replaceInstruction(
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,25 +1,10 @@
|
|||||||
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("audio-only-enabler-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lgmd;",
|
|
||||||
"d"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@ExclusiveAudioCompatibility
|
|
||||||
@Version(
|
|
||||||
"0.0.1"
|
|
||||||
)
|
|
||||||
object AudioOnlyEnablerFingerprint: MethodFingerprint(
|
object AudioOnlyEnablerFingerprint: MethodFingerprint(
|
||||||
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
"Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||||
Opcode.IGET_OBJECT,
|
Opcode.IGET_OBJECT,
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
package app.revanced.patches.music.audio.exclusiveaudio.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("exclusive-audio-fingerprints")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lgmd;", "c"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@ExclusiveAudioCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ExclusiveAudioFingerprint : MethodFingerprint(
|
object ExclusiveAudioFingerprint : MethodFingerprint(
|
||||||
"V",
|
"V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
|||||||
@@ -3,17 +3,15 @@ package app.revanced.patches.music.audio.exclusiveaudio.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstruction
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility
|
||||||
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AudioOnlyEnablerFingerprint
|
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AudioOnlyEnablerFingerprint
|
||||||
import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.ExclusiveAudioFingerprint
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("exclusive-audio-playback")
|
@Name("exclusive-audio-playback")
|
||||||
@@ -25,7 +23,7 @@ class ExclusiveAudioPatch : BytecodePatch(
|
|||||||
AudioOnlyEnablerFingerprint
|
AudioOnlyEnablerFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val method = AudioOnlyEnablerFingerprint.result!!.mutableMethod
|
val method = AudioOnlyEnablerFingerprint.result!!.mutableMethod
|
||||||
method.replaceInstruction(method.implementation!!.instructions.count() - 1, "const/4 v0, 0x1")
|
method.replaceInstruction(method.implementation!!.instructions.count() - 1, "const/4 v0, 0x1")
|
||||||
method.addInstruction("return v0")
|
method.addInstruction("return v0")
|
||||||
|
|||||||
@@ -5,7 +5,26 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
package app.revanced.patches.music.layout.compactheader.fingerprints
|
package app.revanced.patches.music.layout.compactheader.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("compact-header-constructor-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Llcz;", "<init>"
|
|
||||||
)
|
|
||||||
@CompactHeaderCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object CompactHeaderConstructorFingerprint : MethodFingerprint(
|
object CompactHeaderConstructorFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf(
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_DIRECT,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package app.revanced.patches.music.layout.compactheader.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility
|
import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility
|
||||||
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
|
import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
||||||
@@ -23,16 +23,16 @@ class CompactHeaderPatch : BytecodePatch(
|
|||||||
CompactHeaderConstructorFingerprint
|
CompactHeaderConstructorFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val result = CompactHeaderConstructorFingerprint.result!!
|
val result = CompactHeaderConstructorFingerprint.result!!
|
||||||
val method = result.mutableMethod
|
val method = result.mutableMethod
|
||||||
|
|
||||||
val insertIndex = result.patternScanResult!!.endIndex
|
val insertIndex = result.scanResult.patternScanResult!!.endIndex
|
||||||
val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
|
val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
|
||||||
method.addInstructions(
|
method.addInstructions(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
const/16 v0, 0x8
|
const/16 v2, 0x8
|
||||||
invoke-virtual {v${register}, v0}, Landroid/view/View;->setVisibility(I)V
|
invoke-virtual {v${register}, v2}, Landroid/view/View;->setVisibility(I)V
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
|
package app.revanced.patches.music.layout.minimizedplayback.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("minimized-playback-manager-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Llxw;", "c"
|
|
||||||
)
|
|
||||||
@MinimizedPlaybackCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
|
object MinimizedPlaybackManagerFingerprint : MethodFingerprint(
|
||||||
"V",
|
"V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||||
|
|||||||
@@ -3,18 +3,14 @@ package app.revanced.patches.music.layout.minimizedplayback.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.data.impl.toMethodWalker
|
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
|
||||||
import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility
|
||||||
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint
|
||||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
|
||||||
import org.jf.dexlib2.iface.reference.MethodReference
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@Name("minimized-playback-music")
|
@Name("minimized-playback-music")
|
||||||
@@ -26,7 +22,7 @@ class MinimizedPlaybackPatch : BytecodePatch(
|
|||||||
MinimizedPlaybackManagerFingerprint
|
MinimizedPlaybackManagerFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions(
|
MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions(
|
||||||
0, """
|
0, """
|
||||||
return-void
|
return-void
|
||||||
|
|||||||
@@ -5,7 +5,26 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
package app.revanced.patches.music.layout.premium.fingerprints
|
package app.revanced.patches.music.layout.premium.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("hide-get-premium-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lktn;", "k"
|
|
||||||
)
|
|
||||||
@HideGetPremiumCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object HideGetPremiumFingerprint : MethodFingerprint(
|
object HideGetPremiumFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||||
Opcode.IF_NEZ,
|
Opcode.IF_NEZ,
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
package app.revanced.patches.music.layout.premium.fingerprints
|
package app.revanced.patches.music.layout.premium.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("hide-get-premium-parent-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lktn;", "k"
|
|
||||||
)
|
|
||||||
@HideGetPremiumCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object HideGetPremiumParentFingerprint : MethodFingerprint(
|
object HideGetPremiumParentFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf(
|
||||||
Opcode.IGET_BOOLEAN,
|
Opcode.IGET_BOOLEAN,
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package app.revanced.patches.music.layout.premium.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
import app.revanced.patcher.fingerprint.method.utils.MethodFingerprintUtils.resolve
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
|
import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility
|
||||||
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
|
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint
|
||||||
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
|
import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint
|
||||||
@@ -25,13 +25,15 @@ class HideGetPremiumPatch : BytecodePatch(
|
|||||||
HideGetPremiumParentFingerprint
|
HideGetPremiumParentFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val parentResult = HideGetPremiumParentFingerprint.result!!
|
val parentResult = HideGetPremiumParentFingerprint.result!!
|
||||||
HideGetPremiumFingerprint.resolve(data, parentResult.classDef)
|
HideGetPremiumFingerprint.resolve(context, parentResult.classDef)
|
||||||
|
|
||||||
|
val startIndex = parentResult.scanResult.patternScanResult!!.startIndex
|
||||||
|
|
||||||
val parentMethod = parentResult.mutableMethod
|
val parentMethod = parentResult.mutableMethod
|
||||||
parentMethod.replaceInstruction(
|
parentMethod.replaceInstruction(
|
||||||
parentResult.patternScanResult!!.startIndex, """
|
startIndex, """
|
||||||
const/4 v1, 0x0
|
const/4 v1, 0x0
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
@@ -39,7 +41,7 @@ class HideGetPremiumPatch : BytecodePatch(
|
|||||||
val result = HideGetPremiumFingerprint.result!!
|
val result = HideGetPremiumFingerprint.result!!
|
||||||
val method = result.mutableMethod
|
val method = result.mutableMethod
|
||||||
method.addInstructions(
|
method.addInstructions(
|
||||||
result.patternScanResult!!.startIndex, """
|
startIndex, """
|
||||||
const/16 v0, 0x8
|
const/16 v0, 0x8
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,7 +10,24 @@ import app.revanced.patcher.annotation.Package
|
|||||||
*/
|
*/
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,24 +1,15 @@
|
|||||||
package app.revanced.patches.music.layout.tastebuilder.fingerprints
|
package app.revanced.patches.music.layout.tastebuilder.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("taste-builder-constructor-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lkyu;", "<init>"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@RemoveTasteBuilderCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object TasteBuilderConstructorFingerprint : MethodFingerprint(
|
object TasteBuilderConstructorFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L"), listOf(
|
"V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf(
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_DIRECT,
|
||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_VIRTUAL,
|
||||||
Opcode.NEW_INSTANCE,
|
Opcode.NEW_INSTANCE,
|
||||||
@@ -35,9 +26,9 @@ object TasteBuilderConstructorFingerprint : MethodFingerprint(
|
|||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_VIRTUAL,
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
Opcode.MOVE_RESULT_OBJECT,
|
||||||
Opcode.CHECK_CAST,
|
Opcode.CHECK_CAST,
|
||||||
Opcode.IPUT_OBJECT,
|
|
||||||
Opcode.NEW_INSTANCE,
|
Opcode.NEW_INSTANCE,
|
||||||
Opcode.INVOKE_DIRECT,
|
Opcode.INVOKE_DIRECT,
|
||||||
Opcode.IPUT_OBJECT
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -3,12 +3,12 @@ package app.revanced.patches.music.layout.tastebuilder.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
|
import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility
|
||||||
import app.revanced.patches.music.layout.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint
|
import app.revanced.patches.music.layout.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
|
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
|
||||||
@@ -23,11 +23,11 @@ class RemoveTasteBuilderPatch : BytecodePatch(
|
|||||||
TasteBuilderConstructorFingerprint
|
TasteBuilderConstructorFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val result = TasteBuilderConstructorFingerprint.result!!
|
val result = TasteBuilderConstructorFingerprint.result!!
|
||||||
val method = result.mutableMethod
|
val method = result.mutableMethod
|
||||||
|
|
||||||
val insertIndex = result.patternScanResult!!.endIndex - 8
|
val insertIndex = result.scanResult.patternScanResult!!.endIndex - 8
|
||||||
val register = (method.implementation!!.instructions[insertIndex] as Instruction22c).registerA
|
val register = (method.implementation!!.instructions[insertIndex] as Instruction22c).registerA
|
||||||
method.addInstructions(
|
method.addInstructions(
|
||||||
insertIndex, """
|
insertIndex, """
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
package app.revanced.patches.music.layout.upgradebutton.fingerprints
|
package app.revanced.patches.music.layout.upgradebutton.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("pivot-bar-constructor-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lhfu;", "<init2>"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@RemoveUpgradeButtonCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object PivotBarConstructorFingerprint : MethodFingerprint(
|
object PivotBarConstructorFingerprint : MethodFingerprint(
|
||||||
"V",
|
"V",
|
||||||
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package app.revanced.patches.music.layout.upgradebutton.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.util.smali.toInstructions
|
import app.revanced.patcher.util.smali.toInstructions
|
||||||
import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
|
import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility
|
||||||
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
|
import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint
|
||||||
@@ -28,12 +28,12 @@ class RemoveUpgradeButtonPatch : BytecodePatch(
|
|||||||
PivotBarConstructorFingerprint
|
PivotBarConstructorFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
val result = PivotBarConstructorFingerprint.result!!
|
val result = PivotBarConstructorFingerprint.result!!
|
||||||
val implementation = result.mutableMethod.implementation!!
|
val implementation = result.mutableMethod.implementation!!
|
||||||
|
|
||||||
val pivotBarElementFieldRef =
|
val pivotBarElementFieldRef =
|
||||||
(implementation.instructions[result.patternScanResult!!.endIndex - 1] as Instruction22c).reference
|
(implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference
|
||||||
|
|
||||||
val register = (implementation.instructions.first() as Instruction35c).registerC
|
val register = (implementation.instructions.first() as Instruction35c).registerC
|
||||||
// first compile all the needed instructions
|
// first compile all the needed instructions
|
||||||
@@ -46,16 +46,18 @@ class RemoveUpgradeButtonPatch : BytecodePatch(
|
|||||||
""".toInstructions().toMutableList()
|
""".toInstructions().toMutableList()
|
||||||
|
|
||||||
|
|
||||||
|
val endIndex = result.scanResult.patternScanResult!!.endIndex
|
||||||
|
|
||||||
// replace the instruction to retain the label at given index
|
// replace the instruction to retain the label at given index
|
||||||
implementation.replaceInstruction(
|
implementation.replaceInstruction(
|
||||||
result.patternScanResult!!.endIndex - 1, instructionList[0] // invoke-interface
|
endIndex - 1, instructionList[0] // invoke-interface
|
||||||
)
|
)
|
||||||
// do not forget to remove this instruction since we added it already
|
// do not forget to remove this instruction since we added it already
|
||||||
instructionList.removeFirst()
|
instructionList.removeFirst()
|
||||||
|
|
||||||
val exitInstruction = instructionList.last() // iput-object
|
val exitInstruction = instructionList.last() // iput-object
|
||||||
implementation.addInstruction(
|
implementation.addInstruction(
|
||||||
result.patternScanResult!!.endIndex, exitInstruction
|
endIndex, exitInstruction
|
||||||
)
|
)
|
||||||
// do not forget to remove this instruction since we added it already
|
// do not forget to remove this instruction since we added it already
|
||||||
instructionList.removeLast()
|
instructionList.removeLast()
|
||||||
@@ -64,12 +66,12 @@ class RemoveUpgradeButtonPatch : BytecodePatch(
|
|||||||
instructionList.add(
|
instructionList.add(
|
||||||
2, // if-le
|
2, // if-le
|
||||||
BuilderInstruction22t(
|
BuilderInstruction22t(
|
||||||
Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(result.patternScanResult!!.endIndex)
|
Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(endIndex)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
implementation.addInstructions(
|
implementation.addInstructions(
|
||||||
result.patternScanResult!!.endIndex, instructionList
|
endIndex, instructionList
|
||||||
)
|
)
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,20 +1,8 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
|
||||||
|
|
||||||
@Name("cast-context-fetch-fingerprint")
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
@MatchingMethod(
|
|
||||||
"Lvvz;", "a"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@MicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object CastContextFetchFingerprint : MethodFingerprint(
|
object CastContextFetchFingerprint : MethodFingerprint(
|
||||||
null, null, null, null,
|
strings = listOf("Error fetching CastContext.")
|
||||||
listOf("Error fetching CastContext.")
|
|
||||||
)
|
)
|
||||||
@@ -1,20 +1,8 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
|
||||||
|
|
||||||
@Name("cast-module-fingerprint")
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
@MatchingMethod(
|
|
||||||
"Llqh;", "c"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@MicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object CastDynamiteModuleFingerprint : MethodFingerprint(
|
object CastDynamiteModuleFingerprint : MethodFingerprint(
|
||||||
null, null, null, null,
|
strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
|
||||||
listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
|
|
||||||
)
|
)
|
||||||
@@ -1,20 +1,8 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility
|
|
||||||
|
|
||||||
@Name("cast-context-fetch-fingerprint")
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
@MatchingMethod(
|
|
||||||
"Lmcf;", "c"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@MicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object CastDynamiteModuleV2Fingerprint : MethodFingerprint(
|
object CastDynamiteModuleV2Fingerprint : MethodFingerprint(
|
||||||
null, null, null, null,
|
strings = listOf("Failed to load module via V2: ")
|
||||||
listOf("Failed to load module via V2: ")
|
|
||||||
)
|
)
|
||||||
@@ -1,21 +1,18 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
@Name("google-play-utility-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lnuv;", "b"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@MusicMicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object GooglePlayUtilityFingerprint : MethodFingerprint(
|
object GooglePlayUtilityFingerprint : MethodFingerprint(
|
||||||
"I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), null, listOf("This should never happen.", "MetadataValueReader", "GooglePlayServicesUtil", "com.android.vending", "android.hardware.type.embedded")
|
"I",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
listOf("L", "I"),
|
||||||
|
strings = listOf(
|
||||||
|
"This should never happen.",
|
||||||
|
"MetadataValueReader",
|
||||||
|
"GooglePlayServicesUtil",
|
||||||
|
"com.android.vending",
|
||||||
|
"android.hardware.type.embedded"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
@@ -1,19 +1,8 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.DirectPatternScanMethod
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
|
||||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
|
||||||
|
|
||||||
@Name("google-play-prime-fingerprint")
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
@MatchingMethod(
|
|
||||||
"Lrwi;", "a"
|
|
||||||
)
|
|
||||||
@DirectPatternScanMethod
|
|
||||||
@MusicMicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object PrimeFingerprint : MethodFingerprint(
|
object PrimeFingerprint : MethodFingerprint(
|
||||||
null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending")
|
strings = listOf("com.google.android.GoogleCamera", "com.android.vending")
|
||||||
)
|
)
|
||||||
@@ -1,21 +1,15 @@
|
|||||||
package app.revanced.patches.music.misc.microg.fingerprints
|
package app.revanced.patches.music.misc.microg.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
|
|
||||||
@Name("google-play-service-checker-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lnuv;", "d"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@MusicMicroGPatchCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object ServiceCheckFingerprint : MethodFingerprint(
|
object ServiceCheckFingerprint : MethodFingerprint(
|
||||||
"V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), null, listOf("Google Play Services not available")
|
"V",
|
||||||
|
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||||
|
listOf("L", "I"),
|
||||||
|
strings = listOf("Google Play Services not available")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,37 +1,27 @@
|
|||||||
package app.revanced.patches.music.misc.microg.patch.bytecode
|
package app.revanced.patches.music.misc.microg.patch.bytecode
|
||||||
|
|
||||||
import app.revanced.extensions.equalsAny
|
|
||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.annotations.DependsOn
|
import app.revanced.patcher.patch.annotations.DependsOn
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
|
||||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
|
|
||||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||||
import app.revanced.patches.music.misc.microg.patch.resource.MusicMicroGResourcePatch
|
|
||||||
import app.revanced.patches.youtube.misc.microg.patch.resource.enum.StringReplaceMode
|
|
||||||
import app.revanced.patches.music.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
|
||||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
|
||||||
import app.revanced.patches.music.misc.microg.fingerprints.*
|
import app.revanced.patches.music.misc.microg.fingerprints.*
|
||||||
import org.jf.dexlib2.Opcode
|
import app.revanced.patches.music.misc.microg.patch.resource.MusicMicroGResourcePatch
|
||||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME
|
||||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
|
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||||
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
|
import app.revanced.patches.youtube.misc.microg.shared.Constants
|
||||||
import org.jf.dexlib2.iface.reference.StringReference
|
import app.revanced.util.microg.MicroGBytecodeHelper
|
||||||
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
|
|
||||||
|
|
||||||
@Patch
|
@Patch
|
||||||
@DependsOn([MusicMicroGResourcePatch::class])
|
@DependsOn([MusicMicroGResourcePatch::class])
|
||||||
@Name("music-microg-support")
|
@Name("music-microg-support")
|
||||||
@Description("Allows YouTube Music ReVanced to run without root and under a different package name.")
|
@Description("Allows YouTube Music ReVanced to run without root and under a different package name.")
|
||||||
@MusicMicroGPatchCompatibility
|
@MusicMicroGPatchCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.2")
|
||||||
class MusicMicroGBytecodePatch : BytecodePatch(
|
class MusicMicroGBytecodePatch : BytecodePatch(
|
||||||
listOf(
|
listOf(
|
||||||
ServiceCheckFingerprint,
|
ServiceCheckFingerprint,
|
||||||
@@ -42,130 +32,34 @@ class MusicMicroGBytecodePatch : BytecodePatch(
|
|||||||
PrimeFingerprint,
|
PrimeFingerprint,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
// NOTE: the previous patch also replaced the following strings, but it seems like they are not needed:
|
||||||
disablePlayServiceChecks()
|
// - "com.google.android.gms.chimera.GmsIntentOperationService",
|
||||||
data.classes.forEach { classDef ->
|
// - "com.google.android.gms.phenotype.internal.IPhenotypeCallbacks",
|
||||||
var proxiedClass: MutableClass? = null
|
// - "com.google.android.gms.phenotype.internal.IPhenotypeService",
|
||||||
|
// - "com.google.android.gms.phenotype.PACKAGE_NAME",
|
||||||
classDef.methods.forEach methodLoop@{ method ->
|
// - "com.google.android.gms.phenotype.UPDATE",
|
||||||
val implementation = method.implementation ?: return@methodLoop
|
// - "com.google.android.gms.phenotype",
|
||||||
|
override fun execute(context: BytecodeContext) =
|
||||||
var proxiedImplementation: MutableMethodImplementation? = null
|
// apply common microG patch
|
||||||
|
MicroGBytecodeHelper.patchBytecode(
|
||||||
implementation.instructions.forEachIndexed { i, instruction ->
|
context,
|
||||||
if (instruction.opcode != Opcode.CONST_STRING) return@forEachIndexed
|
arrayOf(
|
||||||
|
MicroGBytecodeHelper.packageNameTransform(
|
||||||
val stringValue = ((instruction as Instruction21c).reference as StringReference).string
|
Constants.PACKAGE_NAME,
|
||||||
|
Constants.REVANCED_PACKAGE_NAME
|
||||||
val replaceMode = if (stringValue.equalsAny(
|
)
|
||||||
"com.google.android.gms",
|
),
|
||||||
"com.google.android.gms.chimera",
|
MicroGBytecodeHelper.PrimeMethodTransformationData(
|
||||||
"com.google.android.c2dm.intent.REGISTER",
|
PrimeFingerprint,
|
||||||
"com.google.android.c2dm.permission.SEND",
|
MUSIC_PACKAGE_NAME,
|
||||||
"com.google.iid.TOKEN_REQUEST",
|
REVANCED_MUSIC_PACKAGE_NAME
|
||||||
"com.google",
|
),
|
||||||
"com.google.android.gms.chimera.GmsIntentOperationService",
|
listOf(
|
||||||
"com.google.android.gms.phenotype.internal.IPhenotypeCallbacks",
|
ServiceCheckFingerprint,
|
||||||
"com.google.android.gms.phenotype.internal.IPhenotypeService",
|
GooglePlayUtilityFingerprint,
|
||||||
"com.google.android.gms.phenotype.service.START",
|
CastDynamiteModuleFingerprint,
|
||||||
"com.google.android.gms.phenotype.PACKAGE_NAME",
|
CastDynamiteModuleV2Fingerprint,
|
||||||
"com.google.android.gms.phenotype.UPDATE",
|
CastContextFetchFingerprint
|
||||||
"com.google.android.gms.phenotype",
|
|
||||||
"com.google.android.gms.auth.accounts",
|
|
||||||
"com.google.android.c2dm.intent.REGISTRATION",
|
|
||||||
"com.google.android.gsf.action.GET_GLS",
|
|
||||||
"com.google.android.gsf.login",
|
|
||||||
"content://com.google.settings/partner",
|
|
||||||
"content://com.google.android.gms.phenotype/",
|
|
||||||
"content://com.google.android.gsf.gservices",
|
|
||||||
"content://com.google.android.gsf.gservices/prefix",
|
|
||||||
"com.google.android.c2dm.intent.RECEIVE"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
StringReplaceMode.REPLACE_WITH_MICROG
|
|
||||||
} else if (stringValue.equalsAny(
|
|
||||||
"com.google.android.apps.youtube.music.SuggestionsProvider", "com.google.android.apps.youtube.music.fileprovider"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
StringReplaceMode.REPLACE_WITH_REVANCED
|
|
||||||
} else {
|
|
||||||
StringReplaceMode.DO_NOT_REPLACE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) {
|
|
||||||
if (proxiedClass == null) {
|
|
||||||
proxiedClass = data.proxy(classDef).resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proxiedImplementation == null) {
|
|
||||||
proxiedImplementation = proxiedClass!!.methods.first {
|
|
||||||
it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes)
|
|
||||||
}.implementation!!
|
|
||||||
}
|
|
||||||
|
|
||||||
val newString = if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace(
|
|
||||||
"com.google.android.apps.youtube.music", REVANCED_MUSIC_PACKAGE_NAME
|
|
||||||
)
|
|
||||||
else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME)
|
|
||||||
|
|
||||||
proxiedImplementation!!.replaceInstruction(
|
|
||||||
i, BuilderInstruction21c(
|
|
||||||
Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun disablePlayServiceChecks() {
|
|
||||||
listOf(
|
|
||||||
ServiceCheckFingerprint,
|
|
||||||
GooglePlayUtilityFingerprint,
|
|
||||||
CastDynamiteModuleFingerprint,
|
|
||||||
CastDynamiteModuleV2Fingerprint,
|
|
||||||
CastContextFetchFingerprint,
|
|
||||||
).forEach { fingerprint ->
|
|
||||||
val result = fingerprint.result!!
|
|
||||||
val stringInstructions = when (result.method.returnType.first()) {
|
|
||||||
'L' -> """
|
|
||||||
const/4 v0, 0x0
|
|
||||||
return-object v0
|
|
||||||
"""
|
|
||||||
|
|
||||||
'V' -> "return-void"
|
|
||||||
'I' -> """
|
|
||||||
const/4 v0, 0x0
|
|
||||||
return v0
|
|
||||||
"""
|
|
||||||
|
|
||||||
else -> throw Exception("This case should never happen.")
|
|
||||||
}
|
|
||||||
result.mutableMethod.addInstructions(
|
|
||||||
0, stringInstructions
|
|
||||||
)
|
)
|
||||||
}
|
).let { PatchResultSuccess() }
|
||||||
|
|
||||||
val primeMethod = PrimeFingerprint.result!!.mutableMethod
|
|
||||||
val implementation = primeMethod.implementation!!
|
|
||||||
|
|
||||||
var register = 2
|
|
||||||
val index = implementation.instructions.indexOfFirst {
|
|
||||||
if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false
|
|
||||||
|
|
||||||
val instructionString = ((it as Instruction21c).reference as StringReference).string
|
|
||||||
if (instructionString != "com.google.android.apps.youtube.music") return@indexOfFirst false
|
|
||||||
|
|
||||||
register = it.registerA
|
|
||||||
return@indexOfFirst true
|
|
||||||
}
|
|
||||||
|
|
||||||
primeMethod.replaceInstruction(
|
|
||||||
index, "const-string v$register, \"$REVANCED_MUSIC_PACKAGE_NAME\""
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,41 @@
|
|||||||
package app.revanced.patches.music.misc.microg.patch.resource
|
package app.revanced.patches.music.misc.microg.patch.resource
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.ResourceData
|
import app.revanced.patcher.data.ResourceContext
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
import app.revanced.patcher.patch.impl.ResourcePatch
|
import app.revanced.patcher.patch.ResourcePatch
|
||||||
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility
|
||||||
import app.revanced.patches.music.misc.microg.shared.Constants.BASE_MICROG_PACKAGE_NAME
|
import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME
|
||||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME
|
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME
|
||||||
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME
|
||||||
|
import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME
|
||||||
@Name("music-microg-resource-patch")
|
import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE
|
||||||
@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
|
import app.revanced.util.microg.MicroGManifestHelper
|
||||||
@MusicMicroGPatchCompatibility
|
import app.revanced.util.microg.MicroGResourceHelper
|
||||||
@Version("0.0.1")
|
|
||||||
class MusicMicroGResourcePatch : ResourcePatch() {
|
@Name("music-microg-resource-patch")
|
||||||
override fun execute(data: ResourceData): PatchResult {
|
@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.")
|
||||||
|
@MusicMicroGPatchCompatibility
|
||||||
val manifest = data["AndroidManifest.xml"].readText()
|
@Version("0.0.2")
|
||||||
|
class MusicMicroGResourcePatch : ResourcePatch {
|
||||||
data["AndroidManifest.xml"].writeText(
|
override fun execute(context: ResourceContext): PatchResult {
|
||||||
manifest.replace(
|
// update manifest
|
||||||
"package=\"com.google.android.apps.youtube.music", "package=\"$REVANCED_MUSIC_PACKAGE_NAME"
|
MicroGResourceHelper.patchManifest(
|
||||||
).replace(
|
context,
|
||||||
"android:label=\"@string/app_name", "android:label=\"$REVANCED_MUSIC_APP_NAME"
|
MUSIC_PACKAGE_NAME,
|
||||||
).replace(
|
REVANCED_MUSIC_PACKAGE_NAME,
|
||||||
"android:label=\"@string/app_launcher_name", "android:label=\"$REVANCED_MUSIC_APP_NAME"
|
REVANCED_MUSIC_APP_NAME
|
||||||
).replace(
|
)
|
||||||
"android:authorities=\"com.google.android.apps.youtube.music", "android:authorities=\"$REVANCED_MUSIC_PACKAGE_NAME"
|
|
||||||
).replace(
|
// add metadata to the manifest
|
||||||
"com.google.android.apps.youtube.music.permission.C2D_MESSAGE", "$REVANCED_MUSIC_PACKAGE_NAME.permission.C2D_MESSAGE"
|
MicroGManifestHelper.addSpoofingMetadata(
|
||||||
).replace(
|
context,
|
||||||
"com.google.android.c2dm", "$BASE_MICROG_PACKAGE_NAME.android.c2dm"
|
SPOOFED_PACKAGE_NAME,
|
||||||
).replace(
|
SPOOFED_PACKAGE_SIGNATURE
|
||||||
"</queries>", "<package android:name=\"$BASE_MICROG_PACKAGE_NAME.android.gms\"/></queries>"
|
)
|
||||||
)
|
return PatchResultSuccess()
|
||||||
)
|
}
|
||||||
|
|
||||||
return PatchResultSuccess()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package app.revanced.patches.music.misc.microg.shared
|
package app.revanced.patches.music.misc.microg.shared
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
internal const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle"
|
internal const val REVANCED_MUSIC_APP_NAME = "YT Music ReVanced"
|
||||||
internal const val REVANCED_MUSIC_APP_NAME = "YouTube Music ReVanced"
|
|
||||||
internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music"
|
internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music"
|
||||||
}
|
internal const val MUSIC_PACKAGE_NAME = "com.google.android.apps.youtube.music"
|
||||||
|
internal const val SPOOFED_PACKAGE_NAME = MUSIC_PACKAGE_NAME
|
||||||
|
internal const val SPOOFED_PACKAGE_SIGNATURE = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875"
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,27 @@ import app.revanced.patcher.annotation.Package
|
|||||||
|
|
||||||
@Compatibility(
|
@Compatibility(
|
||||||
[Package(
|
[Package(
|
||||||
"com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51")
|
"com.google.android.apps.youtube.music",
|
||||||
|
arrayOf(
|
||||||
|
"5.14.53",
|
||||||
|
"5.16.51",
|
||||||
|
"5.17.51",
|
||||||
|
"5.21.52",
|
||||||
|
"5.22.54",
|
||||||
|
"5.23.50",
|
||||||
|
"5.25.51",
|
||||||
|
"5.25.52",
|
||||||
|
"5.26.52",
|
||||||
|
"5.27.51",
|
||||||
|
"5.28.52",
|
||||||
|
"5.29.52",
|
||||||
|
"5.31.50",
|
||||||
|
"5.34.51",
|
||||||
|
"5.36.51",
|
||||||
|
"5.38.53",
|
||||||
|
"5.39.52",
|
||||||
|
"5.40.51"
|
||||||
|
)
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
|||||||
@@ -1,22 +1,13 @@
|
|||||||
package app.revanced.patches.music.premium.backgroundplay.fingerprints
|
package app.revanced.patches.music.premium.backgroundplay.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.annotation.Name
|
|
||||||
import app.revanced.patcher.annotation.Version
|
|
||||||
import app.revanced.patcher.extensions.or
|
import app.revanced.patcher.extensions.or
|
||||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
|
||||||
import app.revanced.patcher.fingerprint.method.annotation.MatchingMethod
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
|
|
||||||
import org.jf.dexlib2.AccessFlags
|
import org.jf.dexlib2.AccessFlags
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
@Name("background-playback-disabler-fingerprint")
|
|
||||||
@MatchingMethod(
|
|
||||||
"Lafgf;", "e"
|
|
||||||
)
|
|
||||||
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
|
||||||
@BackgroundPlayCompatibility
|
|
||||||
@Version("0.0.1")
|
|
||||||
object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
|
object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
|
||||||
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf(
|
"Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf(
|
||||||
Opcode.CONST_4,
|
Opcode.CONST_4,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package app.revanced.patches.music.premium.backgroundplay.patch
|
|||||||
import app.revanced.patcher.annotation.Description
|
import app.revanced.patcher.annotation.Description
|
||||||
import app.revanced.patcher.annotation.Name
|
import app.revanced.patcher.annotation.Name
|
||||||
import app.revanced.patcher.annotation.Version
|
import app.revanced.patcher.annotation.Version
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.patch.annotations.Patch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.impl.BytecodePatch
|
|
||||||
import app.revanced.patcher.patch.PatchResult
|
import app.revanced.patcher.patch.PatchResult
|
||||||
import app.revanced.patcher.patch.PatchResultSuccess
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
|
import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility
|
||||||
import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
|
import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ class BackgroundPlayPatch : BytecodePatch(
|
|||||||
BackgroundPlaybackDisableFingerprint
|
BackgroundPlaybackDisableFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
BackgroundPlaybackDisableFingerprint.result!!.mutableMethod.addInstructions(
|
BackgroundPlaybackDisableFingerprint.result!!.mutableMethod.addInstructions(
|
||||||
0,
|
0,
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.myexpenses.misc.pro.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("org.totschnig.myexpenses")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UnlockProCompatibility
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package app.revanced.patches.myexpenses.misc.pro.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
|
||||||
|
object IsEnabledFingerprint : MethodFingerprint(
|
||||||
|
"Z",
|
||||||
|
strings = listOf("feature", "feature.licenceStatus")
|
||||||
|
)
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package app.revanced.patches.myexpenses.misc.pro.patch
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.removeInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.myexpenses.misc.pro.annotations.UnlockProCompatibility
|
||||||
|
import app.revanced.patches.myexpenses.misc.pro.fingerprints.IsEnabledFingerprint
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("unlock-pro")
|
||||||
|
@Description("Unlocks all professional features.")
|
||||||
|
@UnlockProCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class UnlockProPatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
IsEnabledFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
val method = IsEnabledFingerprint.result!!.mutableMethod
|
||||||
|
method.addInstructions(
|
||||||
|
0,
|
||||||
|
"""
|
||||||
|
const/4 v0, 0x1
|
||||||
|
return v0
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package app.revanced.patches.nova.prime.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility(
|
||||||
|
[
|
||||||
|
Package("com.teslacoilsw.launcher")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UnlockPrimeCompatibility
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package app.revanced.patches.nova.prime.fingerprints
|
||||||
|
|
||||||
|
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||||
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
object UnlockPrimeFingerprint : MethodFingerprint(
|
||||||
|
"V",
|
||||||
|
opcodes = listOf(
|
||||||
|
Opcode.IPUT_OBJECT,
|
||||||
|
Opcode.CONST_STRING,
|
||||||
|
Opcode.CONST_4,
|
||||||
|
Opcode.INVOKE_INTERFACE,
|
||||||
|
Opcode.MOVE_RESULT
|
||||||
|
),
|
||||||
|
strings = listOf("1")
|
||||||
|
)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package app.revanced.patches.nova.prime.patch
|
||||||
|
|
||||||
|
import app.revanced.extensions.toErrorResult
|
||||||
|
import app.revanced.patcher.annotation.Description
|
||||||
|
import app.revanced.patcher.annotation.Name
|
||||||
|
import app.revanced.patcher.annotation.Version
|
||||||
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
|
import app.revanced.patcher.patch.PatchResult
|
||||||
|
import app.revanced.patcher.patch.PatchResultSuccess
|
||||||
|
import app.revanced.patcher.patch.annotations.Patch
|
||||||
|
import app.revanced.patches.nova.prime.annotations.UnlockPrimeCompatibility
|
||||||
|
import app.revanced.patches.nova.prime.fingerprints.UnlockPrimeFingerprint
|
||||||
|
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
||||||
|
|
||||||
|
@Patch
|
||||||
|
@Name("unlock-prime")
|
||||||
|
@Description("Unlocks Nova Prime and all functions of the app.")
|
||||||
|
@UnlockPrimeCompatibility
|
||||||
|
@Version("0.0.1")
|
||||||
|
class UnlockPrimePatch : BytecodePatch(
|
||||||
|
listOf(
|
||||||
|
UnlockPrimeFingerprint
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
private companion object {
|
||||||
|
// Any value except 0 unlocks prime, but 512 is needed for a protection mechanism
|
||||||
|
// which would reset the preferences if the value on disk had changed after a restart.
|
||||||
|
const val PRIME_STATUS: Int = 512
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun execute(context: BytecodeContext): PatchResult {
|
||||||
|
UnlockPrimeFingerprint.result?.apply {
|
||||||
|
val insertIndex = scanResult.patternScanResult!!.endIndex + 1
|
||||||
|
|
||||||
|
val primeStatusRegister =
|
||||||
|
(mutableMethod.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
|
||||||
|
|
||||||
|
mutableMethod.addInstruction(
|
||||||
|
insertIndex,
|
||||||
|
"""
|
||||||
|
const/16 v$primeStatusRegister, $PRIME_STATUS
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
} ?: UnlockPrimeFingerprint.toErrorResult()
|
||||||
|
|
||||||
|
return PatchResultSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package app.revanced.patches.nyx.misc.pro.annotations
|
||||||
|
|
||||||
|
import app.revanced.patcher.annotation.Compatibility
|
||||||
|
import app.revanced.patcher.annotation.Package
|
||||||
|
|
||||||
|
@Compatibility([Package("com.awedea.nyx")])
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
internal annotation class UnlockProCompatibility
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user