Skip to content

Commit 3da2c96

Browse files
fix: failed to play YT videos if logged in under certain conditions (YouTube)
1 parent ab4ce4f commit 3da2c96

2 files changed

Lines changed: 100 additions & 103 deletions

File tree

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeApiDecoder.java

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import java.io.IOException;
1515
import java.net.URLEncoder;
1616
import java.nio.charset.StandardCharsets;
17-
import java.util.ArrayList;
17+
import java.util.Collections;
1818
import java.util.HashMap;
1919
import java.util.List;
2020
import java.util.Map;
@@ -32,7 +32,6 @@ public final class YoutubeApiDecoder {
3232
private static final String API_BASE_URL = "https://api.pipepipe.dev/decoder/decode";
3333
private static final String USER_AGENT = "PipePipe/4.9.0";
3434

35-
// Cache for decoded parameters to avoid redundant API calls
3635
@Nonnull
3736
private static final Map<String, String> DECODE_CACHE = new HashMap<>();
3837

@@ -81,35 +80,27 @@ static String decodeThrottlingParameter(@Nonnull final String playerId,
8180
private static String decode(@Nonnull final String playerId,
8281
@Nonnull final String paramType,
8382
@Nonnull final String value) throws ParsingException {
84-
// Check cache first
8583
final String cacheKey = playerId + ":" + paramType + ":" + value;
8684
final String cachedResult = DECODE_CACHE.get(cacheKey);
8785
if (cachedResult != null) {
8886
return cachedResult;
8987
}
9088

9189
try {
92-
// Build API URL
9390
final String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
9491
final String url = API_BASE_URL + "?player=" + playerId + "&" + paramType + "=" + encodedValue;
9592

96-
// Set headers
9793
final Map<String, java.util.List<String>> headers = new HashMap<>();
98-
headers.put("User-Agent", java.util.Collections.singletonList(USER_AGENT));
94+
headers.put("User-Agent", Collections.singletonList(USER_AGENT));
9995

100-
// Make API call
10196
final Response response = NewPipe.getDownloader().get(url, headers, Localization.DEFAULT);
102-
103-
// Parse response
10497
final String responseBody = response.responseBody();
10598
final JsonObject jsonResponse = JsonParser.object().from(responseBody);
10699

107-
// Validate response structure
108100
if (!"result".equals(jsonResponse.getString("type"))) {
109101
throw new ParsingException("API returned unexpected type: " + jsonResponse.getString("type"));
110102
}
111103

112-
// Extract decoded value
113104
final JsonObject firstResponse = jsonResponse.getArray("responses").getObject(0);
114105
if (!"result".equals(firstResponse.getString("type"))) {
115106
throw new ParsingException("API response item has unexpected type: " + firstResponse.getString("type"));
@@ -122,9 +113,7 @@ private static String decode(@Nonnull final String playerId,
122113
throw new ParsingException("API returned empty decoded value for: " + value);
123114
}
124115

125-
// Cache the result
126116
DECODE_CACHE.put(cacheKey, decodedValue);
127-
128117
return decodedValue;
129118
} catch (final IOException e) {
130119
throw new ParsingException("Failed to call decode API", e);
@@ -135,18 +124,10 @@ private static String decode(@Nonnull final String playerId,
135124
}
136125
}
137126

138-
/**
139-
* Clear the decode cache.
140-
*/
141127
static void clearCache() {
142128
DECODE_CACHE.clear();
143129
}
144130

145-
/**
146-
* Get the current cache size.
147-
*
148-
* @return the number of cached decode results
149-
*/
150131
static int getCacheSize() {
151132
return DECODE_CACHE.size();
152133
}
@@ -173,16 +154,14 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
173154
return new BatchDecodeResult(new HashMap<>(), new HashMap<>());
174155
}
175156

176-
// Check cache first and collect uncached values
177157
final Map<String, String> sigResults = new HashMap<>();
178158
final Map<String, String> nResults = new HashMap<>();
179-
final List<String> uncachedSigs = new ArrayList<>();
180-
final List<String> uncachedNs = new ArrayList<>();
159+
final List<String> uncachedSigs = new java.util.ArrayList<>();
160+
final List<String> uncachedNs = new java.util.ArrayList<>();
181161

182162
if (hasSigs) {
183163
for (final String sig : signatureParams) {
184-
final String cacheKey = playerId + ":sig:" + sig;
185-
final String cachedResult = DECODE_CACHE.get(cacheKey);
164+
final String cachedResult = DECODE_CACHE.get(playerId + ":sig:" + sig);
186165
if (cachedResult != null) {
187166
sigResults.put(sig, cachedResult);
188167
} else {
@@ -193,8 +172,7 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
193172

194173
if (hasNs) {
195174
for (final String n : nParams) {
196-
final String cacheKey = playerId + ":n:" + n;
197-
final String cachedResult = DECODE_CACHE.get(cacheKey);
175+
final String cachedResult = DECODE_CACHE.get(playerId + ":n:" + n);
198176
if (cachedResult != null) {
199177
nResults.put(n, cachedResult);
200178
} else {
@@ -203,13 +181,11 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
203181
}
204182
}
205183

206-
// If all values are cached, return immediately
207184
if (uncachedSigs.isEmpty() && uncachedNs.isEmpty()) {
208185
return new BatchDecodeResult(sigResults, nResults);
209186
}
210187

211188
try {
212-
// Build API URL with batch parameters
213189
final StringBuilder urlBuilder = new StringBuilder(API_BASE_URL);
214190
urlBuilder.append("?player=").append(playerId);
215191

@@ -233,25 +209,19 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
233209
}
234210
}
235211

236-
// Set headers
237212
final Map<String, java.util.List<String>> headers = new HashMap<>();
238-
headers.put("User-Agent", java.util.Collections.singletonList(USER_AGENT));
213+
headers.put("User-Agent", Collections.singletonList(USER_AGENT));
239214

240-
// Make API call
241215
final Response response = NewPipe.getDownloader().get(urlBuilder.toString(), headers, Localization.DEFAULT);
242-
243-
// Parse response
244216
final String responseBody = response.responseBody();
245217
final JsonObject jsonResponse = JsonParser.object().from(responseBody);
246218

247-
// Validate response structure
248219
if (!"result".equals(jsonResponse.getString("type"))) {
249220
throw new ParsingException("API returned unexpected type: " + jsonResponse.getString("type"));
250221
}
251222

252223
final JsonArray responses = jsonResponse.getArray("responses");
253224

254-
// Process n parameters first (if present)
255225
int responseIndex = 0;
256226
if (!uncachedNs.isEmpty()) {
257227
final JsonObject nResponse = responses.getObject(responseIndex++);
@@ -266,12 +236,10 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
266236
throw new ParsingException("API returned empty decoded value for n parameter: " + nParam);
267237
}
268238
nResults.put(nParam, decodedValue);
269-
// Cache the result
270239
DECODE_CACHE.put(playerId + ":n:" + nParam, decodedValue);
271240
}
272241
}
273242

274-
// Process signature parameters (if present)
275243
if (!uncachedSigs.isEmpty()) {
276244
final JsonObject sigResponse = responses.getObject(responseIndex);
277245
if (!"result".equals(sigResponse.getString("type"))) {
@@ -285,7 +253,6 @@ static BatchDecodeResult decodeBatch(@Nonnull final String playerId,
285253
throw new ParsingException("API returned empty decoded value for signature: " + sig);
286254
}
287255
sigResults.put(sig, decodedValue);
288-
// Cache the result
289256
DECODE_CACHE.put(playerId + ":sig:" + sig, decodedValue);
290257
}
291258
}

0 commit comments

Comments
 (0)