diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java index cc668821e9..cd87cfc760 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ReturnYouTubeDislikeFilterPatch.java @@ -36,11 +36,12 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter { /** - * Last unique video id's loaded. Value is ignored and Map is treated as a Set. - * Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry(). + * Last unique video id's loaded. + * Key is a String represeting the video id. + * Value is a ByteArrayFilterGroup used for performing KMP pattern searching. */ @GuardedBy("itself") - private static final Map lastVideoIds = new LinkedHashMap<>() { + private static final Map lastVideoIds = new LinkedHashMap<>() { /** * Number of video id's to keep track of for searching thru the buffer. * A minimum value of 3 should be sufficient, but check a few more just in case. @@ -101,36 +102,17 @@ public static void newPlayerResponseVideoId(String videoId, boolean isShortAndOp return; } synchronized (lastVideoIds) { - if (lastVideoIds.put(videoId, Boolean.TRUE) == null) { - Logger.printDebug(() -> "New Short video id: " + videoId); - } + if (lastVideoIds.containsKey(videoId)) return; + Logger.printDebug(() -> "New Shorts video id: " + videoId); + + final ByteArrayFilterGroup videoIdFilter = new ByteArrayFilterGroup(null, videoId); + lastVideoIds.put(videoId, videoIdFilter); } } catch (Exception ex) { Logger.printException(() -> "newPlayerResponseVideoId failure", ex); } } - /** - * This could use {@link TrieSearch}, but since the patterns are constantly changing - * the overhead of updating the Trie might negate the search performance gain. - */ - private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text) { - for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) { - boolean found = true; - for (int j = 0, textLength = text.length(); j < textLength; j++) { - if (array[i + j] != (byte) text.charAt(j)) { - found = false; - break; - } - } - if (found) { - return true; - } - } - - return false; - } - @Override public boolean isFiltered(String path, @Nullable String identifier, String allValue, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { @@ -154,13 +136,15 @@ public boolean isFiltered(String path, @Nullable String identifier, String allVa @Nullable private String findVideoId(byte[] protobufBufferArray) { synchronized (lastVideoIds) { - for (String videoId : lastVideoIds.keySet()) { - if (byteArrayContainsString(protobufBufferArray, videoId)) { - return videoId; + for (Map.Entry entry : lastVideoIds.entrySet()) { + final ByteArrayFilterGroup videoIdFilter = entry.getValue(); + + if (videoIdFilter.check(protobufBufferArray).isFiltered()) { + return entry.getKey(); // Return videoId } } return null; } } -} \ No newline at end of file +} diff --git a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ShortsCustomActionsFilter.java b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ShortsCustomActionsFilter.java index bbd5151673..c22d3bba4d 100644 --- a/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ShortsCustomActionsFilter.java +++ b/extensions/shared/src/main/java/app/revanced/extension/youtube/patches/components/ShortsCustomActionsFilter.java @@ -30,11 +30,12 @@ public final class ShortsCustomActionsFilter extends Filter { SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU_ENABLED || SHORTS_CUSTOM_ACTIONS_TOOLBAR_ENABLED; /** - * Last unique video id's loaded. Value is ignored and Map is treated as a Set. - * Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry(). + * Last unique video id's loaded. + * Key is a String represeting the video id. + * Value is a ByteArrayFilterGroup used for performing KMP pattern searching. */ @GuardedBy("itself") - private static final Map lastVideoIds = new LinkedHashMap<>() { + private static final Map lastVideoIds = new LinkedHashMap<>() { /** * Number of video id's to keep track of for searching thru the buffer. * A minimum value of 3 should be sufficient, but check a few more just in case. @@ -117,35 +118,16 @@ public static void newPlayerResponseVideoId(String videoId, boolean isShortAndOp return; } synchronized (lastVideoIds) { - lastVideoIds.putIfAbsent(videoId, Boolean.TRUE); + if (lastVideoIds.containsKey(videoId)) return; + + final ByteArrayFilterGroup videoIdFilter = new ByteArrayFilterGroup(null, videoId); + lastVideoIds.put(videoId, videoIdFilter); } } catch (Exception ex) { Logger.printException(() -> "newPlayerResponseVideoId failure", ex); } } - - /** - * This could use {@link TrieSearch}, but since the patterns are constantly changing - * the overhead of updating the Trie might negate the search performance gain. - */ - private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text) { - for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) { - boolean found = true; - for (int j = 0, textLength = text.length(); j < textLength; j++) { - if (array[i + j] != (byte) text.charAt(j)) { - found = false; - break; - } - } - if (found) { - return true; - } - } - - return false; - } - @Override public boolean isFiltered(String path, @Nullable String identifier, String allValue, byte[] protobufBufferArray, StringFilterGroup matchedGroup, FilterContentType contentType, int contentIndex) { @@ -164,9 +146,13 @@ public boolean isFiltered(String path, @Nullable String identifier, String allVa private void findVideoId(byte[] protobufBufferArray) { synchronized (lastVideoIds) { - for (String videoId : lastVideoIds.keySet()) { - if (byteArrayContainsString(protobufBufferArray, videoId)) { + for (Map.Entry entry : lastVideoIds.entrySet()) { + final ByteArrayFilterGroup videoIdFilter = entry.getValue(); + + if (videoIdFilter.check(protobufBufferArray).isFiltered()) { + final String videoId = entry.getKey(); setShortsVideoId(videoId, false); + return; } } }