Skip to content

Commit cbe576b

Browse files
fix(YouTube - Spoof video streams): Do not use Android Creator for livestreams
1 parent 3a29f2a commit cbe576b

File tree

14 files changed

+57
-44
lines changed

14 files changed

+57
-44
lines changed

extensions/youtube/src/main/java/app/revanced/extension/youtube/ByteTrieSearch.java renamed to extensions/shared/library/src/main/java/app/revanced/extension/shared/ByteTrieSearch.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
package app.revanced.extension.youtube;
2-
3-
import androidx.annotation.NonNull;
1+
package app.revanced.extension.shared;
42

53
import java.nio.charset.StandardCharsets;
64

@@ -39,7 +37,7 @@ public static byte[][] convertStringsToBytes(String... strings) {
3937
return replacement;
4038
}
4139

42-
public ByteTrieSearch(@NonNull byte[]... patterns) {
40+
public ByteTrieSearch(byte[]... patterns) {
4341
super(new ByteTrieNode(), patterns);
4442
}
4543
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/StringTrieSearch.java renamed to extensions/shared/library/src/main/java/app/revanced/extension/shared/StringTrieSearch.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
package app.revanced.extension.youtube;
2-
3-
import androidx.annotation.NonNull;
1+
package app.revanced.extension.shared;
42

53
/**
64
* Text pattern searching using a prefix tree (trie).
@@ -28,7 +26,7 @@ int getTextLength(String text) {
2826
}
2927
}
3028

31-
public StringTrieSearch(@NonNull String... patterns) {
29+
public StringTrieSearch(String... patterns) {
3230
super(new StringTrieNode(), patterns);
3331
}
3432
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/TrieSearch.java renamed to extensions/shared/library/src/main/java/app/revanced/extension/shared/TrieSearch.java

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
package app.revanced.extension.youtube;
1+
package app.revanced.extension.shared;
22

3-
import androidx.annotation.NonNull;
43
import androidx.annotation.Nullable;
54

65
import java.util.ArrayList;
76
import java.util.Collections;
87
import java.util.List;
98
import java.util.Objects;
109

11-
/**
12-
* Searches for a group of different patterns using a trie (prefix tree).
10+
/**Searches for a group of different patterns using a trie (prefix tree).
1311
* Can significantly speed up searching for multiple patterns.
1412
*/
1513
public abstract class TrieSearch<T> {
@@ -136,7 +134,7 @@ static abstract class TrieNode<T> {
136134
* @param patternLength Length of the pattern.
137135
* @param callback Callback, where a value of NULL indicates to always accept a pattern match.
138136
*/
139-
private void addPattern(@NonNull T pattern, int patternIndex, int patternLength,
137+
private void addPattern(T pattern, int patternIndex, int patternLength,
140138
@Nullable TriePatternMatchedCallback<T> callback) {
141139
if (patternIndex == patternLength) { // Reached the end of the pattern.
142140
if (endOfPatternCallback == null) {
@@ -308,13 +306,13 @@ private int estimatedNumberOfPointersUsed() {
308306
private final List<T> patterns = new ArrayList<>();
309307

310308
@SafeVarargs
311-
TrieSearch(@NonNull TrieNode<T> root, @NonNull T... patterns) {
309+
TrieSearch(TrieNode<T> root, T... patterns) {
312310
this.root = Objects.requireNonNull(root);
313311
addPatterns(patterns);
314312
}
315313

316314
@SafeVarargs
317-
public final void addPatterns(@NonNull T... patterns) {
315+
public final void addPatterns(T... patterns) {
318316
for (T pattern : patterns) {
319317
addPattern(pattern);
320318
}
@@ -325,39 +323,39 @@ public final void addPatterns(@NonNull T... patterns) {
325323
*
326324
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
327325
*/
328-
public void addPattern(@NonNull T pattern) {
326+
public void addPattern(T pattern) {
329327
addPattern(pattern, root.getTextLength(pattern), null);
330328
}
331329

332330
/**
333331
* @param pattern Pattern to add. Calling this with a zero length pattern does nothing.
334332
* @param callback Callback to determine if searching should halt when a match is found.
335333
*/
336-
public void addPattern(@NonNull T pattern, @NonNull TriePatternMatchedCallback<T> callback) {
334+
public void addPattern(T pattern, TriePatternMatchedCallback<T> callback) {
337335
addPattern(pattern, root.getTextLength(pattern), Objects.requireNonNull(callback));
338336
}
339337

340-
void addPattern(@NonNull T pattern, int patternLength, @Nullable TriePatternMatchedCallback<T> callback) {
338+
void addPattern(T pattern, int patternLength, @Nullable TriePatternMatchedCallback<T> callback) {
341339
if (patternLength == 0) return; // Nothing to match
342340

343341
patterns.add(pattern);
344342
root.addPattern(pattern, 0, patternLength, callback);
345343
}
346344

347-
public final boolean matches(@NonNull T textToSearch) {
345+
public final boolean matches(T textToSearch) {
348346
return matches(textToSearch, 0);
349347
}
350348

351-
public boolean matches(@NonNull T textToSearch, @NonNull Object callbackParameter) {
349+
public boolean matches(T textToSearch, Object callbackParameter) {
352350
return matches(textToSearch, 0, root.getTextLength(textToSearch),
353351
Objects.requireNonNull(callbackParameter));
354352
}
355353

356-
public boolean matches(@NonNull T textToSearch, int startIndex) {
354+
public boolean matches(T textToSearch, int startIndex) {
357355
return matches(textToSearch, startIndex, root.getTextLength(textToSearch));
358356
}
359357

360-
public final boolean matches(@NonNull T textToSearch, int startIndex, int endIndex) {
358+
public final boolean matches(T textToSearch, int startIndex, int endIndex) {
361359
return matches(textToSearch, startIndex, endIndex, null);
362360
}
363361

@@ -370,11 +368,11 @@ public final boolean matches(@NonNull T textToSearch, int startIndex, int endInd
370368
* @param callbackParameter Optional parameter passed to the callbacks.
371369
* @return If any pattern matched, and it's callback halted searching.
372370
*/
373-
public boolean matches(@NonNull T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
371+
public boolean matches(T textToSearch, int startIndex, int endIndex, @Nullable Object callbackParameter) {
374372
return matches(textToSearch, root.getTextLength(textToSearch), startIndex, endIndex, callbackParameter);
375373
}
376374

377-
private boolean matches(@NonNull T textToSearch, int textToSearchLength, int startIndex, int endIndex,
375+
private boolean matches(T textToSearch, int textToSearchLength, int startIndex, int endIndex,
378376
@Nullable Object callbackParameter) {
379377
if (endIndex > textToSearchLength) {
380378
throw new IllegalArgumentException("endIndex: " + endIndex

extensions/shared/library/src/main/java/app/revanced/extension/shared/spoof/requests/StreamingDataRequest.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package app.revanced.extension.shared.spoof.requests;
22

3+
import static app.revanced.extension.shared.ByteTrieSearch.convertStringsToBytes;
34
import static app.revanced.extension.shared.spoof.requests.PlayerRoutes.GET_STREAMING_DATA;
45

56
import androidx.annotation.NonNull;
@@ -13,12 +14,18 @@
1314
import java.net.SocketTimeoutException;
1415
import java.nio.ByteBuffer;
1516
import java.nio.charset.StandardCharsets;
16-
import java.util.*;
17+
import java.util.Arrays;
18+
import java.util.Collections;
19+
import java.util.LinkedHashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Objects;
1723
import java.util.concurrent.ExecutionException;
1824
import java.util.concurrent.Future;
1925
import java.util.concurrent.TimeUnit;
2026
import java.util.concurrent.TimeoutException;
2127

28+
import app.revanced.extension.shared.ByteTrieSearch;
2229
import app.revanced.extension.shared.Logger;
2330
import app.revanced.extension.shared.Utils;
2431
import app.revanced.extension.shared.settings.BaseSettings;
@@ -93,6 +100,16 @@ protected boolean removeEldestEntry(Entry eldest) {
93100
}
94101
});
95102

103+
/**
104+
* Strings found in the response if the video is a livestream.
105+
*/
106+
private static final ByteTrieSearch liveStreamBufferSearch = new ByteTrieSearch(
107+
convertStringsToBytes(
108+
"yt_live_broadcast",
109+
"yt_premiere_broadcast"
110+
)
111+
);
112+
96113
private static volatile ClientType lastSpoofedClientType;
97114

98115
public static String getLastSpoofedClientName() {
@@ -221,9 +238,13 @@ private static ByteBuffer fetch(String videoId, Map<String, String> playerHeader
221238
while ((bytesRead = inputStream.read(buffer)) >= 0) {
222239
baos.write(buffer, 0, bytesRead);
223240
}
224-
lastSpoofedClientType = clientType;
241+
if (clientType == ClientType.ANDROID_CREATOR && liveStreamBufferSearch.matches(buffer)) {
242+
Logger.printDebug(() -> "Skipping Android Studio as video is a livestream: " + videoId);
243+
} else {
244+
lastSpoofedClientType = clientType;
225245

226-
return ByteBuffer.wrap(baos.toByteArray());
246+
return ByteBuffer.wrap(baos.toByteArray());
247+
}
227248
}
228249
}
229250
} catch (IOException ex) {

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/AdsFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import app.revanced.extension.shared.Logger;
1212
import app.revanced.extension.shared.Utils;
13-
import app.revanced.extension.youtube.StringTrieSearch;
13+
import app.revanced.extension.shared.StringTrieSearch;
1414
import app.revanced.extension.youtube.settings.Settings;
1515

1616
@SuppressWarnings("unused")

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/CustomFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import app.revanced.extension.shared.Logger;
1616
import app.revanced.extension.shared.Utils;
17-
import app.revanced.extension.youtube.ByteTrieSearch;
17+
import app.revanced.extension.shared.ByteTrieSearch;
1818
import app.revanced.extension.youtube.settings.Settings;
1919

2020
/**

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/DescriptionComponentsFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package app.revanced.extension.youtube.patches.components;
22

3-
import app.revanced.extension.youtube.StringTrieSearch;
3+
import app.revanced.extension.shared.StringTrieSearch;
44
import app.revanced.extension.youtube.settings.Settings;
55
import app.revanced.extension.youtube.shared.PlayerType;
66

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/FilterGroup.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import app.revanced.extension.shared.Logger;
66
import app.revanced.extension.shared.settings.BooleanSetting;
7-
import app.revanced.extension.youtube.ByteTrieSearch;
7+
import app.revanced.extension.shared.ByteTrieSearch;
88

99
abstract class FilterGroup<T> {
1010
final static class FilterGroupResult {

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/FilterGroupList.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import java.util.*;
66
import java.util.function.Consumer;
77

8-
import app.revanced.extension.youtube.ByteTrieSearch;
9-
import app.revanced.extension.youtube.StringTrieSearch;
10-
import app.revanced.extension.youtube.TrieSearch;
8+
import app.revanced.extension.shared.ByteTrieSearch;
9+
import app.revanced.extension.shared.StringTrieSearch;
10+
import app.revanced.extension.shared.TrieSearch;
1111

1212
abstract class FilterGroupList<V, T extends FilterGroup<V>> implements Iterable<T> {
1313

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/components/KeywordContentFilter.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414

1515
import app.revanced.extension.shared.Logger;
1616
import app.revanced.extension.shared.Utils;
17-
import app.revanced.extension.youtube.ByteTrieSearch;
18-
import app.revanced.extension.youtube.StringTrieSearch;
19-
import app.revanced.extension.youtube.TrieSearch;
17+
import app.revanced.extension.shared.ByteTrieSearch;
18+
import app.revanced.extension.shared.StringTrieSearch;
19+
import app.revanced.extension.shared.TrieSearch;
2020
import app.revanced.extension.youtube.settings.Settings;
2121
import app.revanced.extension.youtube.shared.NavigationBar;
2222
import app.revanced.extension.youtube.shared.PlayerType;

0 commit comments

Comments
 (0)