diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/ReturnYouTubeUsernamePatch.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/ReturnYouTubeUsernamePatch.java index 45a79db40..a0b009040 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/ReturnYouTubeUsernamePatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/ReturnYouTubeUsernamePatch.java @@ -14,12 +14,14 @@ import app.revanced.extension.shared.utils.Logger; @SuppressWarnings("unused") public class ReturnYouTubeUsernamePatch { - private static final boolean RETURN_YOUTUBE_USERNAME_ENABLED = BaseSettings.RETURN_YOUTUBE_USERNAME_ENABLED.get(); - private static final Boolean RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = BaseSettings.RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.get().userNameFirst; - private static final String YOUTUBE_API_KEY = BaseSettings.RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.get(); + private static final String YOUTUBE_API_KEY = + BaseSettings.RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.get(); + private static final boolean RETURN_YOUTUBE_USERNAME_ENABLED = + BaseSettings.RETURN_YOUTUBE_USERNAME_ENABLED.get() && !YOUTUBE_API_KEY.isEmpty(); + private static final Boolean RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = + BaseSettings.RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.get().userNameFirst; private static final String AUTHOR_BADGE_PATH = "|author_badge.eml|"; - private static volatile String lastFetchedHandle = ""; /** * Injection point. @@ -51,18 +53,12 @@ public class ReturnYouTubeUsernamePatch { if (!RETURN_YOUTUBE_USERNAME_ENABLED) { return original; } - if (YOUTUBE_API_KEY.isEmpty()) { - Logger.printDebug(() -> "API key is empty"); - return original; - } // In comments, the path to YouTube Handle(@youtube) always includes [AUTHOR_BADGE_PATH]. if (!conversionContext.toString().contains(AUTHOR_BADGE_PATH)) { return original; } String handle = original.toString(); - if (fetchNeeded && !handle.equals(lastFetchedHandle)) { - lastFetchedHandle = handle; - // Get the original username using YouTube Data API v3. + if (fetchNeeded) { ChannelRequest.fetchRequestIfNeeded(handle, YOUTUBE_API_KEY, RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT); return original; } @@ -77,9 +73,7 @@ public class ReturnYouTubeUsernamePatch { Logger.printDebug(() -> "ChannelRequest Stream is null, handle:" + handle); return original; } - final CharSequence copiedSpannableString = copySpannableString(original, userName); - Logger.printDebug(() -> "Replaced: '" + original + "' with: '" + copiedSpannableString + "'"); - return copiedSpannableString; + return copySpannableString(original, userName); } catch (Exception ex) { Logger.printException(() -> "onLithoTextLoaded failure", ex); } diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/BlockRequestPatch.java b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/BlockRequestPatch.java index c0728522d..7e90cfce9 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/BlockRequestPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/patches/spoof/BlockRequestPatch.java @@ -89,22 +89,21 @@ public class BlockRequestPatch { *

* Blocks /initplayback requests. */ - public static String blockInitPlaybackRequest(String originalUrlString) { + public static Uri blockInitPlaybackRequest(Uri initPlaybackRequestUri) { if (BLOCK_REQUEST) { try { - var originalUri = Uri.parse(originalUrlString); - String path = originalUri.getPath(); + String path = initPlaybackRequestUri.getPath(); if (path != null && path.contains("initplayback")) { Logger.printDebug(() -> "Blocking 'initplayback' by clearing query"); - return originalUri.buildUpon().clearQuery().build().toString(); + return initPlaybackRequestUri.buildUpon().clearQuery().build(); } } catch (Exception ex) { Logger.printException(() -> "blockInitPlaybackRequest failure", ex); } } - return originalUrlString; + return initPlaybackRequestUri; } } diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRequest.java b/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRequest.java index 84e02755b..492a7598e 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRequest.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRequest.java @@ -50,14 +50,18 @@ public class ChannelRequest { }); public static void fetchRequestIfNeeded(@NonNull String handle, @NonNull String apiKey, Boolean userNameFirst) { - if (!cache.containsKey(handle)) { - cache.put(handle, new ChannelRequest(handle, apiKey, userNameFirst)); + synchronized (cache) { + if (cache.get(handle) == null) { + cache.put(handle, new ChannelRequest(handle, apiKey, userNameFirst)); + } } } @Nullable public static ChannelRequest getRequestForHandle(@NonNull String handle) { - return cache.get(handle); + synchronized (cache) { + return cache.get(handle); + } } private static void handleConnectionError(String toastMessage, @Nullable Exception ex) { @@ -108,7 +112,8 @@ public class ChannelRequest { final String userName = channelJsonObject .getJSONArray("items") .getJSONObject(0) - .getJSONObject("snippet") + .getJSONObject("brandingSettings") + .getJSONObject("channel") .getString("title"); return authorBadgeBuilder(handle, userName, userNameFirst); } catch (JSONException e) { diff --git a/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRoutes.java b/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRoutes.java index 14da59603..414dc7fbd 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRoutes.java +++ b/extensions/shared/src/main/java/app/revanced/extension/shared/returnyoutubeusername/requests/ChannelRoutes.java @@ -11,7 +11,7 @@ import app.revanced.extension.shared.requests.Route; public class ChannelRoutes { public static final String YOUTUBEI_V3_GAPIS_URL = "https://www.googleapis.com/youtube/v3/"; - public static final Route GET_CHANNEL_DETAILS = new Route(GET, "channels?part=snippet&forHandle={handle}&key={api_key}"); + public static final Route GET_CHANNEL_DETAILS = new Route(GET, "channels?part=brandingSettings&maxResults=1&prettyPrint=false&forHandle={handle}&key={api_key}"); public ChannelRoutes() { } diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/BlockRequestPatch.kt b/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/BlockRequestPatch.kt index 1063044ad..dbb60c9af 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/BlockRequestPatch.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/BlockRequestPatch.kt @@ -4,7 +4,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.patch.bytecodePatch import app.revanced.patches.shared.extension.Constants.SPOOF_PATH -import app.revanced.util.fingerprint.matchOrThrow import app.revanced.util.fingerprint.methodOrThrow import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction @@ -18,20 +17,18 @@ val blockRequestPatch = bytecodePatch( execute { // region Block /initplayback requests to fall back to /get_watch requests. - buildInitPlaybackRequestFingerprint.matchOrThrow().let { - it.method.apply { - val moveUriStringIndex = it.patternMatch!!.startIndex - val targetRegister = - getInstruction(moveUriStringIndex).registerA + buildInitPlaybackRequestFingerprint.methodOrThrow().apply { + val uriIndex = indexOfUriToStringInstruction(this) + val uriRegister = + getInstruction(uriIndex).registerC - addInstructions( - moveUriStringIndex + 1, - """ - invoke-static { v$targetRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$targetRegister - """, - ) - } + addInstructions( + uriIndex, + """ + invoke-static { v$uriRegister }, $EXTENSION_CLASS_DESCRIPTOR->blockInitPlaybackRequest(Landroid/net/Uri;)Landroid/net/Uri; + move-result-object v$uriRegister + """, + ) } // endregion @@ -39,7 +36,7 @@ val blockRequestPatch = bytecodePatch( // region Block /get_watch requests to fall back to /player requests. buildPlayerRequestURIFingerprint.methodOrThrow().apply { - val invokeToStringIndex = indexOfToStringInstruction(this) + val invokeToStringIndex = indexOfUriToStringInstruction(this) val uriRegister = getInstruction(invokeToStringIndex).registerC diff --git a/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/Fingerprints.kt index 13797f4de..2fc03222d 100644 --- a/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/Fingerprints.kt +++ b/patches/src/main/kotlin/app/revanced/patches/shared/spoof/blockrequest/Fingerprints.kt @@ -18,6 +18,9 @@ internal val buildInitPlaybackRequestFingerprint = legacyFingerprint( "Content-Type", "Range", ), + customFingerprint = { method, _ -> + indexOfUriToStringInstruction(method) >= 0 + }, ) internal val buildPlayerRequestURIFingerprint = legacyFingerprint( @@ -28,11 +31,11 @@ internal val buildPlayerRequestURIFingerprint = legacyFingerprint( "asig", ), customFingerprint = { method, _ -> - indexOfToStringInstruction(method) >= 0 + indexOfUriToStringInstruction(method) >= 0 }, ) -internal fun indexOfToStringInstruction(method: Method) = +internal fun indexOfUriToStringInstruction(method: Method) = method.indexOfFirstInstruction { opcode == Opcode.INVOKE_VIRTUAL && getReference().toString() == "Landroid/net/Uri;->toString()Ljava/lang/String;"