mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-02 23:54:33 +02:00
perf: Use KMP to search Shorts video id (#109)
* ci: workflow to ping Discord users when patches are released (#72) * init: Workflow to notify discord users of releases * Rename workflow * chore (Background playback): Shorten description * Revert "chore (Background playback): Shorten description" This reverts commit 10661b870f0c9c670c5d522f9b2ca7cc82d32772. * Change message contents * perf: Use KMP to search Shorts videoId * Beautify * Incorrect key-value * Incorrect key-value * Rename variable * Comment * Comment * Comment * Comment * Beauty * fix: video id is not updated in some case * fix build error * chore: Simplify --------- Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com> Co-authored-by: inotia00 <108592928+inotia00@users.noreply.github.com>
This commit is contained in:
parent
6bb067f6ec
commit
a6f8596a0d
@ -5,7 +5,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import app.revanced.extension.shared.patches.components.ByteArrayFilterGroup;
|
import app.revanced.extension.shared.patches.components.ByteArrayFilterGroup;
|
||||||
@ -36,11 +35,12 @@ import app.revanced.extension.youtube.shared.VideoInformation;
|
|||||||
public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last unique video id's loaded. Value is ignored and Map is treated as a Set.
|
* Last unique video id's loaded.
|
||||||
* Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry().
|
* Key is a String represeting the video id.
|
||||||
|
* Value is a ByteArrayFilterGroup used for performing KMP pattern searching.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("itself")
|
@GuardedBy("itself")
|
||||||
private static final Map<String, Boolean> lastVideoIds = new LinkedHashMap<>() {
|
private static final Map<String, ByteArrayFilterGroup> lastVideoIds = new LinkedHashMap<>() {
|
||||||
/**
|
/**
|
||||||
* Number of video id's to keep track of for searching thru the buffer.
|
* 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.
|
* A minimum value of 3 should be sufficient, but check a few more just in case.
|
||||||
@ -101,8 +101,11 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (lastVideoIds) {
|
synchronized (lastVideoIds) {
|
||||||
if (lastVideoIds.put(videoId, Boolean.TRUE) == null) {
|
if (!lastVideoIds.containsKey(videoId)) {
|
||||||
Logger.printDebug(() -> "New Short video id: " + videoId);
|
Logger.printDebug(() -> "New Shorts video id: " + videoId);
|
||||||
|
// Put a placeholder first
|
||||||
|
lastVideoIds.put(videoId, null);
|
||||||
|
lastVideoIds.put(videoId, new ByteArrayFilterGroup(null, videoId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
@ -114,7 +117,12 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
|||||||
* This could use {@link TrieSearch}, but since the patterns are constantly changing
|
* This could use {@link TrieSearch}, but since the patterns are constantly changing
|
||||||
* the overhead of updating the Trie might negate the search performance gain.
|
* the overhead of updating the Trie might negate the search performance gain.
|
||||||
*/
|
*/
|
||||||
private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text) {
|
private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text,
|
||||||
|
@Nullable ByteArrayFilterGroup videoIdFilter) {
|
||||||
|
// If a video filter is available, check it first.
|
||||||
|
if (videoIdFilter != null) {
|
||||||
|
return videoIdFilter.check(array).isFiltered();
|
||||||
|
}
|
||||||
for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) {
|
for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) {
|
||||||
boolean found = true;
|
boolean found = true;
|
||||||
for (int j = 0, textLength = text.length(); j < textLength; j++) {
|
for (int j = 0, textLength = text.length(); j < textLength; j++) {
|
||||||
@ -154,12 +162,14 @@ public final class ReturnYouTubeDislikeFilterPatch extends Filter {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private String findVideoId(byte[] protobufBufferArray) {
|
private String findVideoId(byte[] protobufBufferArray) {
|
||||||
synchronized (lastVideoIds) {
|
synchronized (lastVideoIds) {
|
||||||
for (String videoId : lastVideoIds.keySet()) {
|
for (Map.Entry<String, ByteArrayFilterGroup> entry : lastVideoIds.entrySet()) {
|
||||||
if (byteArrayContainsString(protobufBufferArray, videoId)) {
|
final String videoId = entry.getKey();
|
||||||
|
final ByteArrayFilterGroup videoIdFilter = entry.getValue();
|
||||||
|
if (byteArrayContainsString(protobufBufferArray, videoId, videoIdFilter)) {
|
||||||
return videoId;
|
return videoId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import app.revanced.extension.shared.patches.components.ByteArrayFilterGroup;
|
import app.revanced.extension.shared.patches.components.ByteArrayFilterGroup;
|
||||||
@ -30,11 +29,12 @@ public final class ShortsCustomActionsFilter extends Filter {
|
|||||||
SHORTS_CUSTOM_ACTIONS_FLYOUT_MENU_ENABLED || SHORTS_CUSTOM_ACTIONS_TOOLBAR_ENABLED;
|
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.
|
* Last unique video id's loaded.
|
||||||
* Cannot use {@link LinkedHashSet} because it's missing #removeEldestEntry().
|
* Key is a String represeting the video id.
|
||||||
|
* Value is a ByteArrayFilterGroup used for performing KMP pattern searching.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("itself")
|
@GuardedBy("itself")
|
||||||
private static final Map<String, Boolean> lastVideoIds = new LinkedHashMap<>() {
|
private static final Map<String, ByteArrayFilterGroup> lastVideoIds = new LinkedHashMap<>() {
|
||||||
/**
|
/**
|
||||||
* Number of video id's to keep track of for searching thru the buffer.
|
* 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.
|
* A minimum value of 3 should be sufficient, but check a few more just in case.
|
||||||
@ -117,7 +117,11 @@ public final class ShortsCustomActionsFilter extends Filter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (lastVideoIds) {
|
synchronized (lastVideoIds) {
|
||||||
lastVideoIds.putIfAbsent(videoId, Boolean.TRUE);
|
if (!lastVideoIds.containsKey(videoId)) {
|
||||||
|
// Put a placeholder first
|
||||||
|
lastVideoIds.put(videoId, null);
|
||||||
|
lastVideoIds.put(videoId, new ByteArrayFilterGroup(null, videoId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.printException(() -> "newPlayerResponseVideoId failure", ex);
|
Logger.printException(() -> "newPlayerResponseVideoId failure", ex);
|
||||||
@ -129,7 +133,12 @@ public final class ShortsCustomActionsFilter extends Filter {
|
|||||||
* This could use {@link TrieSearch}, but since the patterns are constantly changing
|
* This could use {@link TrieSearch}, but since the patterns are constantly changing
|
||||||
* the overhead of updating the Trie might negate the search performance gain.
|
* the overhead of updating the Trie might negate the search performance gain.
|
||||||
*/
|
*/
|
||||||
private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text) {
|
private static boolean byteArrayContainsString(@NonNull byte[] array, @NonNull String text,
|
||||||
|
@Nullable ByteArrayFilterGroup videoIdFilter) {
|
||||||
|
// If a video filter is available, check it first.
|
||||||
|
if (videoIdFilter != null) {
|
||||||
|
return videoIdFilter.check(array).isFiltered();
|
||||||
|
}
|
||||||
for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) {
|
for (int i = 0, lastArrayStartIndex = array.length - text.length(); i <= lastArrayStartIndex; i++) {
|
||||||
boolean found = true;
|
boolean found = true;
|
||||||
for (int j = 0, textLength = text.length(); j < textLength; j++) {
|
for (int j = 0, textLength = text.length(); j < textLength; j++) {
|
||||||
@ -164,9 +173,12 @@ public final class ShortsCustomActionsFilter extends Filter {
|
|||||||
|
|
||||||
private void findVideoId(byte[] protobufBufferArray) {
|
private void findVideoId(byte[] protobufBufferArray) {
|
||||||
synchronized (lastVideoIds) {
|
synchronized (lastVideoIds) {
|
||||||
for (String videoId : lastVideoIds.keySet()) {
|
for (Map.Entry<String, ByteArrayFilterGroup> entry : lastVideoIds.entrySet()) {
|
||||||
if (byteArrayContainsString(protobufBufferArray, videoId)) {
|
final String videoId = entry.getKey();
|
||||||
|
final ByteArrayFilterGroup videoIdFilter = entry.getValue();
|
||||||
|
if (byteArrayContainsString(protobufBufferArray, videoId, videoIdFilter)) {
|
||||||
setShortsVideoId(videoId, false);
|
setShortsVideoId(videoId, false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user