Skip to content

Commit 17b53bf

Browse files
committed
fix: app no name youtube src main
1 parent 57333db commit 17b53bf

File tree

868 files changed

+47874
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

868 files changed

+47874
-0
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package app.revanced.extensions
2+
3+
import app.revanced.patcher.data.BytecodeContext
4+
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
5+
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
6+
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
7+
import app.revanced.patcher.patch.PatchException
8+
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
9+
import app.revanced.patcher.util.proxy.mutableTypes.MutableField
10+
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
11+
import app.revanced.patcher.util.smali.toInstruction
12+
import app.revanced.util.integrations.Constants.PATCHES_PATH
13+
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
14+
import com.android.tools.smali.dexlib2.iface.Method
15+
import com.android.tools.smali.dexlib2.util.MethodUtil
16+
import org.w3c.dom.Node
17+
18+
internal fun MutableMethodImplementation.injectHideCall(
19+
index: Int,
20+
register: Int,
21+
patches: String,
22+
method: String
23+
) {
24+
this.addInstruction(
25+
index,
26+
"invoke-static { v$register }, $PATCHES_PATH/$patches;->$method(Landroid/view/View;)V".toInstruction()
27+
)
28+
}
29+
30+
/**
31+
* Return [PatchException] from a [MethodFingerprint].
32+
*
33+
* @return The [PatchException] for the [MethodFingerprint].
34+
*/
35+
val MethodFingerprint.exception
36+
get() = PatchException("Failed to resolve $name")
37+
38+
/**
39+
* Find the [MutableMethod] from a given [Method] in a [MutableClass].
40+
*
41+
* @param method The [Method] to find.
42+
* @return The [MutableMethod].
43+
*/
44+
fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first {
45+
MethodUtil.methodSignaturesMatch(it, method)
46+
}
47+
48+
/**
49+
* apply a transform to all methods of the class
50+
*
51+
* @param transform the transformation function. original method goes in, transformed method goes out
52+
*/
53+
fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) {
54+
val transformedMethods = methods.map { it.transform() }
55+
methods.clear()
56+
methods.addAll(transformedMethods)
57+
}
58+
59+
/**
60+
* apply a transform to all fields of the class
61+
*
62+
* @param transform the transformation function. original field goes in, transformed field goes out
63+
*/
64+
fun MutableClass.transformFields(transform: MutableField.() -> MutableField) {
65+
val transformedFields = fields.map { it.transform() }
66+
fields.clear()
67+
fields.addAll(transformedFields)
68+
}
69+
70+
internal fun Node.doRecursively(action: (Node) -> Unit) {
71+
action(this)
72+
for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action)
73+
}
74+
75+
internal fun String.startsWithAny(vararg prefixes: String): Boolean {
76+
for (prefix in prefixes)
77+
if (this.startsWith(prefix))
78+
return true
79+
80+
return false
81+
}
82+
83+
/**
84+
* traverse the class hierarchy starting from the given root class
85+
*
86+
* @param targetClass the class to start traversing the class hierarchy from
87+
* @param callback function that is called for every class in the hierarchy
88+
*/
89+
fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) {
90+
callback(targetClass)
91+
this.findClass(targetClass.superclass ?: return)?.mutableClass?.let {
92+
traverseClassHierarchy(it, callback)
93+
}
94+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package app.revanced.meta
2+
3+
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
4+
import app.revanced.patcher.extensions.PatchExtensions.dependencies
5+
import app.revanced.patcher.extensions.PatchExtensions.description
6+
import app.revanced.patcher.extensions.PatchExtensions.include
7+
import app.revanced.patcher.extensions.PatchExtensions.options
8+
import app.revanced.patcher.extensions.PatchExtensions.patchName
9+
import app.revanced.patcher.patch.PatchOption
10+
import com.google.gson.GsonBuilder
11+
import java.io.File
12+
13+
internal class JsonGenerator : PatchesFileGenerator {
14+
override fun generate(bundle: PatchBundlePatches) {
15+
val patches = bundle.map {
16+
JsonPatch(
17+
it.patchName,
18+
it.description ?: "This patch has no description.",
19+
!it.include,
20+
it.options?.map { option ->
21+
JsonPatch.Option(
22+
option.key,
23+
option.title,
24+
option.description,
25+
option.required,
26+
option.let { listOption ->
27+
if (listOption is PatchOption.ListOption<*>) {
28+
listOption.options.toMutableList().toTypedArray()
29+
} else null
30+
}
31+
)
32+
}?.toTypedArray() ?: emptyArray(),
33+
it.dependencies?.map { dep ->
34+
dep.java.patchName
35+
}?.toTypedArray() ?: emptyArray(),
36+
it.compatiblePackages?.map { pkg ->
37+
JsonPatch.CompatiblePackage(pkg.name, pkg.versions)
38+
}?.toTypedArray() ?: emptyArray()
39+
)
40+
}
41+
42+
val json = File("patches.json")
43+
json.writeText(GsonBuilder().serializeNulls().create().toJson(patches))
44+
}
45+
46+
private class JsonPatch(
47+
val name: String,
48+
val description: String,
49+
val excluded: Boolean,
50+
val options: Array<Option>,
51+
val dependencies: Array<String>,
52+
val compatiblePackages: Array<CompatiblePackage>,
53+
) {
54+
class CompatiblePackage(
55+
val name: String,
56+
val versions: Array<String>,
57+
)
58+
59+
class Option(
60+
val key: String,
61+
val title: String,
62+
val description: String,
63+
val required: Boolean,
64+
val choices: Array<*>?,
65+
)
66+
}
67+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package app.revanced.meta
2+
3+
import app.revanced.patcher.PatchBundleLoader
4+
import app.revanced.patcher.patch.PatchClass
5+
import java.io.File
6+
7+
internal typealias PatchBundlePatches = List<PatchClass>
8+
9+
internal interface PatchesFileGenerator {
10+
fun generate(bundle: PatchBundlePatches)
11+
12+
private companion object {
13+
@JvmStatic
14+
fun main(args: Array<String>) = PatchBundleLoader.Jar(
15+
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first()
16+
).also { loader ->
17+
if (loader.isEmpty()) throw IllegalStateException("No patches found")
18+
}.let { bundle ->
19+
arrayOf(JsonGenerator(), ReadmeGenerator()).forEach { generator ->
20+
generator.generate(
21+
bundle
22+
)
23+
}
24+
}
25+
}
26+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package app.revanced.meta
2+
3+
import app.revanced.patcher.data.Context
4+
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
5+
import app.revanced.patcher.extensions.PatchExtensions.description
6+
import app.revanced.patcher.extensions.PatchExtensions.patchName
7+
import app.revanced.patcher.patch.Patch
8+
import com.unascribed.flexver.FlexVerComparator
9+
import java.io.File
10+
11+
internal class ReadmeGenerator : PatchesFileGenerator {
12+
private companion object {
13+
private const val TABLE_HEADER =
14+
"| \uD83D\uDC8A Patch | \uD83D\uDCDC Description | \uD83C\uDFF9 Target Version |\n" +
15+
"|:--------:|:--------------:|:-----------------:|"
16+
}
17+
18+
override fun generate(bundle: PatchBundlePatches) {
19+
val output = StringBuilder()
20+
21+
mutableMapOf<String, MutableList<Class<out Patch<Context<*>>>>>()
22+
.apply {
23+
for (patch in bundle) {
24+
patch.compatiblePackages?.forEach { pkg ->
25+
if (!contains(pkg.name)) put(pkg.name, mutableListOf())
26+
this[pkg.name]!!.add(patch)
27+
}
28+
}
29+
}
30+
.entries
31+
.sortedByDescending { it.value.size }
32+
.forEach { (`package`, patches) ->
33+
val supportVersions = buildMap {
34+
patches.forEach { patch ->
35+
patch.compatiblePackages?.single { compatiblePackage -> compatiblePackage.name == `package` }?.versions?.let {
36+
it.forEach { version -> merge(version, 1, Integer::sum) }
37+
}
38+
}
39+
}
40+
41+
val minVersion = supportVersions.let { commonMap ->
42+
commonMap.maxByOrNull { it.value }?.value?.let {
43+
commonMap.entries.filter { supported -> supported.value == it }
44+
.minOfWith(FlexVerComparator::compare, Map.Entry<String, Int>::key)
45+
} ?: "all"
46+
}
47+
val maxVersion = supportVersions.let { commonMap ->
48+
commonMap.maxByOrNull { it.value }?.value?.let {
49+
commonMap.entries.filter { supported -> supported.value == it }
50+
.maxOfWith(FlexVerComparator::compare, Map.Entry<String, Int>::key)
51+
} ?: "all"
52+
}
53+
54+
output.apply {
55+
appendLine("### [\uD83D\uDCE6 `${`package`}`](https://play.google.com/store/apps/details?id=${`package`})")
56+
appendLine("<details>\n")
57+
appendLine(TABLE_HEADER)
58+
patches.forEach { patch ->
59+
val supportedVersion =
60+
if (
61+
patch.compatiblePackages?.single { it.name == `package` }?.versions?.isNotEmpty() == true
62+
) {
63+
if (minVersion == maxVersion)
64+
maxVersion
65+
else
66+
"$minVersion ~ $maxVersion"
67+
} else
68+
"all"
69+
70+
appendLine(
71+
"| `${patch.patchName.lowercase().replace(" ", "-")}` " +
72+
"| ${patch.description} " +
73+
"| $supportedVersion |"
74+
)
75+
}
76+
appendLine("</details>\n")
77+
}
78+
}
79+
80+
StringBuilder(File("README-template.md").readText())
81+
.replace(Regex("\\{\\{\\s?table\\s?}}"), output.toString())
82+
.let(File("README.md")::writeText)
83+
}
84+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package app.revanced.patches.music.ads.music.patch
2+
3+
import app.revanced.patcher.annotation.Description
4+
import app.revanced.patcher.annotation.Name
5+
6+
import app.revanced.patcher.data.BytecodeContext
7+
8+
import app.revanced.patcher.patch.annotations.DependsOn
9+
import app.revanced.patcher.patch.annotations.Patch
10+
import app.revanced.patches.music.utils.annotations.MusicCompatibility
11+
import app.revanced.patches.music.utils.litho.patch.LithoFilterPatch
12+
import app.revanced.patches.music.utils.settings.resource.patch.SettingsPatch
13+
import app.revanced.patches.shared.patch.ads.AbstractAdsPatch
14+
import app.revanced.util.enum.CategoryType
15+
import app.revanced.util.integrations.Constants.MUSIC_ADS_PATH
16+
17+
@Patch
18+
@Name("Hide music ads")
19+
@Description("Hides ads before playing a music.")
20+
@DependsOn(
21+
[
22+
LithoFilterPatch::class,
23+
SettingsPatch::class
24+
]
25+
)
26+
@MusicCompatibility
27+
28+
class MusicAdsPatch : AbstractAdsPatch(
29+
"$MUSIC_ADS_PATH/HideMusicAdsPatch;->hideMusicAds()Z"
30+
) {
31+
override fun execute(context: BytecodeContext) {
32+
super.execute(context)
33+
34+
SettingsPatch.addMusicPreference(CategoryType.ADS, "revanced_hide_music_ads", "true")
35+
36+
LithoFilterPatch.addFilter(FILTER_CLASS_DESCRIPTOR)
37+
}
38+
39+
private companion object {
40+
private const val FILTER_CLASS_DESCRIPTOR =
41+
"$MUSIC_ADS_PATH/AdsFilter;"
42+
}
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package app.revanced.patches.music.buttoncontainer.downloadbuttonhook.patch
2+
3+
import app.revanced.patcher.annotation.Description
4+
import app.revanced.patcher.annotation.Name
5+
import app.revanced.patcher.data.BytecodeContext
6+
import app.revanced.patcher.patch.BytecodePatch
7+
import app.revanced.patcher.patch.annotations.DependsOn
8+
import app.revanced.patcher.patch.annotations.Patch
9+
import app.revanced.patches.music.utils.annotations.MusicCompatibility
10+
import app.revanced.patches.music.utils.buttoncontainerhook.patch.ButtonContainerHookPatch
11+
import app.revanced.patches.music.utils.intenthook.patch.IntentHookPatch
12+
import app.revanced.patches.music.utils.settings.resource.patch.SettingsPatch
13+
import app.revanced.patches.music.utils.videoid.patch.VideoIdPatch
14+
import app.revanced.util.enum.CategoryType
15+
16+
@Patch
17+
@Name("Hook download button")
18+
@Description("Replaces the offline download button in the button container with an external download button.")
19+
@DependsOn(
20+
[
21+
ButtonContainerHookPatch::class,
22+
IntentHookPatch::class,
23+
SettingsPatch::class,
24+
VideoIdPatch::class
25+
]
26+
)
27+
@MusicCompatibility
28+
class DownloadButtonHookPatch : BytecodePatch() {
29+
override fun execute(context: BytecodeContext) {
30+
31+
SettingsPatch.addMusicPreference(
32+
CategoryType.BUTTON_CONTAINER,
33+
"revanced_hook_button_container_download",
34+
"false"
35+
)
36+
SettingsPatch.addMusicPreferenceWithIntent(
37+
CategoryType.BUTTON_CONTAINER,
38+
"revanced_external_downloader_package_name",
39+
"revanced_hook_button_container_download"
40+
)
41+
42+
}
43+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package app.revanced.patches.music.buttoncontainer.label.fingerprints
2+
3+
import app.revanced.patcher.extensions.or
4+
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
5+
import com.android.tools.smali.dexlib2.AccessFlags
6+
import com.android.tools.smali.dexlib2.Opcode
7+
8+
object ButtonContainerLabelFingerprint : MethodFingerprint(
9+
returnType = "V",
10+
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
11+
parameters = listOf("L", "L"),
12+
opcodes = listOf(
13+
Opcode.INVOKE_INTERFACE,
14+
Opcode.MOVE_RESULT_OBJECT,
15+
Opcode.CHECK_CAST,
16+
Opcode.INVOKE_VIRTUAL,
17+
Opcode.MOVE_RESULT,
18+
Opcode.IF_EQZ,
19+
)
20+
)

0 commit comments

Comments
 (0)