fix tiktok download restrictions

This commit is contained in:
lbux 2026-02-19 14:57:44 -08:00
parent c17c4e9050
commit e4cfa15efc
6 changed files with 73 additions and 5 deletions

View file

@ -1,9 +1,10 @@
package app.revanced.extension.tiktok.download;
import app.revanced.extension.tiktok.settings.Settings;
import com.ss.android.ugc.aweme.feed.model.Video;
@SuppressWarnings("unused")
public class DownloadsPatch {
public static String getDownloadPath() {
return "Pictures/Tiktok";
//return Settings.DOWNLOAD_PATH.get();
@ -13,4 +14,30 @@ public class DownloadsPatch {
return true;
//return Settings.DOWNLOAD_WATERMARK.get();
}
}
public static void patchVideoObject(Video video) {
if (video == null) return;
try {
boolean isMissingCleanUrl = false;
// non-watermark url is removed by tiktok for some videos (licensing/user restrictions)
if (video.downloadNoWatermarkAddr == null) {
isMissingCleanUrl = true;
} else if (video.downloadNoWatermarkAddr.getUrlList() == null || video.downloadNoWatermarkAddr.getUrlList().isEmpty()) {
isMissingCleanUrl = true;
}
// overwrite field with the play address if empty
if (isMissingCleanUrl) {
if (video.h264PlayAddr != null && video.h264PlayAddr.getUrlList() != null && !video.h264PlayAddr.getUrlList().isEmpty()) {
video.downloadNoWatermarkAddr = video.h264PlayAddr;
} else if (video.playAddr != null) {
// fallback
video.downloadNoWatermarkAddr = video.playAddr;
}
}
} catch (Throwable t) {
}
}
}

View file

@ -0,0 +1,7 @@
package com.ss.android.ugc.aweme.base.model;
import java.util.List;
public class UrlModel {
public List<String> getUrlList() { throw new UnsupportedOperationException("Stub"); }
public String getUri() { throw new UnsupportedOperationException("Stub"); }
}

View file

@ -0,0 +1,8 @@
package com.ss.android.ugc.aweme.feed.model;
import com.ss.android.ugc.aweme.base.model.UrlModel;
public class Video {
public VideoUrlModel playAddr;
public VideoUrlModel h264PlayAddr;
public UrlModel downloadNoWatermarkAddr;
}

View file

@ -0,0 +1,5 @@
package com.ss.android.ugc.aweme.feed.model;
import com.ss.android.ugc.aweme.base.model.UrlModel;
public class VideoUrlModel extends UrlModel {
}

View file

@ -11,6 +11,7 @@ import app.revanced.patches.tiktok.misc.settings.settingsStatusLoadFingerprint
import app.revanced.util.findInstructionIndicesReversedOrThrow
import app.revanced.util.getReference
import app.revanced.util.returnEarly
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@ -35,7 +36,6 @@ val downloadsPatch = bytecodePatch(
aclCommonShareFingerprint.method.returnEarly(0)
aclCommonShare2Fingerprint.method.returnEarly(2)
// Download videos without watermark.
aclCommonShare3Fingerprint.method.addInstructionsWithLabels(
0,
"""
@ -49,7 +49,18 @@ val downloadsPatch = bytecodePatch(
""",
)
// Change the download path patch.
awemeGetVideoFingerprint.method.apply {
val returnIndex = findInstructionIndicesReversedOrThrow { opcode == Opcode.RETURN_OBJECT }.first()
val register = getInstruction<OneRegisterInstruction>(returnIndex).registerA
addInstructions(
returnIndex,
"""
invoke-static {v$register}, $EXTENSION_CLASS_DESCRIPTOR->patchVideoObject(Lcom/ss/android/ugc/aweme/feed/model/Video;)V
"""
)
}
downloadUriFingerprint.method.apply {
findInstructionIndicesReversedOrThrow {
getReference<FieldReference>().let {
@ -78,4 +89,4 @@ val downloadsPatch = bytecodePatch(
"invoke-static {}, Lapp/revanced/extension/tiktok/settings/SettingsStatus;->enableDownload()V",
)
}
}
}

View file

@ -44,3 +44,13 @@ internal val downloadUriFingerprint = fingerprint {
"video/mp4"
)
}
internal val awemeGetVideoFingerprint = fingerprint {
accessFlags(AccessFlags.PUBLIC)
returns("Lcom/ss/android/ugc/aweme/feed/model/Video;")
custom { method, classDef ->
classDef.endsWith("/Aweme;") &&
method.name == "getVideo" &&
method.parameterTypes.isEmpty()
}
}