Skip to content

Commit a484d0a

Browse files
fix initial continuation token extraction for web based clients (lavalink-devs#156)
* fix initial continuation token extraction for web based clients * requested changes
1 parent 641e49b commit a484d0a

File tree

1 file changed

+66
-56
lines changed
  • common/src/main/java/dev/lavalink/youtube/clients

1 file changed

+66
-56
lines changed

common/src/main/java/dev/lavalink/youtube/clients/Web.java

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.sedmelluq.discord.lavaplayer.tools.ExceptionTools;
44
import com.sedmelluq.discord.lavaplayer.tools.JsonBrowser;
5+
import com.sedmelluq.discord.lavaplayer.tools.DataFormatTools;
56
import com.sedmelluq.discord.lavaplayer.tools.io.HttpClientTools;
67
import com.sedmelluq.discord.lavaplayer.tools.io.HttpInterface;
78
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
@@ -32,9 +33,9 @@ public class Web extends StreamingNonMusicClient {
3233
protected static Pattern CONFIG_REGEX = Pattern.compile("ytcfg\\.set\\((\\{.+})\\);");
3334

3435
public static ClientConfig BASE_CONFIG = new ClientConfig()
35-
.withClientName("WEB")
36-
.withClientField("clientVersion", "2.20250403.01.00")
37-
.withUserField("lockedSafetyMode", false);
36+
.withClientName("WEB")
37+
.withClientField("clientVersion", "2.20250403.01.00")
38+
.withUserField("lockedSafetyMode", false);
3839

3940
public static String poToken;
4041

@@ -88,20 +89,20 @@ protected void fetchClientConfig(@NotNull HttpInterface httpInterface) {
8889
if (!client.isNull()) {
8990
/*
9091
* "client": {
91-
* "hl": "en-GB",
92-
* "gl": "GB",
93-
* "remoteHost": "<ip>",
94-
* "deviceMake": "",
95-
* "deviceModel": "",
96-
* "visitorData": "<base64>",
97-
* "userAgent": "...",
98-
* "clientName": "WEB",
99-
* "clientVersion": "2.20240401.05.00",
100-
* "osVersion": "",
101-
* "originalUrl": "https://www.youtube.com/",
102-
* "platform": "DESKTOP",
103-
* "clientFormFactor": "UNKNOWN_FORM_FACTOR",
104-
* ...
92+
* "hl": "en-GB",
93+
* "gl": "GB",
94+
* "remoteHost": "<ip>",
95+
* "deviceMake": "",
96+
* "deviceModel": "",
97+
* "visitorData": "<base64>",
98+
* "userAgent": "...",
99+
* "clientName": "WEB",
100+
* "clientVersion": "2.20240401.05.00",
101+
* "osVersion": "",
102+
* "originalUrl": "https://www.youtube.com/",
103+
* "platform": "DESKTOP",
104+
* "clientFormFactor": "UNKNOWN_FORM_FACTOR",
105+
* ...
105106
*/
106107
String clientVersion = client.get("clientVersion").text();
107108

@@ -110,11 +111,11 @@ protected void fetchClientConfig(@NotNull HttpInterface httpInterface) {
110111
BASE_CONFIG.withClientField("clientVersion", clientVersion);
111112
}
112113

113-
// String visitorData = client.get("visitorData").text();
114-
//
115-
// if (visitorData != null && !visitorData.isEmpty()) {
116-
// BASE_CONFIG.withVisitorData(visitorData);
117-
// }
114+
// String visitorData = client.get("visitorData").text();
115+
//
116+
// if (visitorData != null && !visitorData.isEmpty()) {
117+
// BASE_CONFIG.withVisitorData(visitorData);
118+
// }
118119
}
119120
} catch (IOException e) {
120121
throw ExceptionTools.toRuntimeException(e);
@@ -157,27 +158,27 @@ public URI transformPlaybackUri(@NotNull URI originalUri, @NotNull URI resolvedP
157158
@Override
158159
@NotNull
159160
protected List<AudioTrack> extractSearchResults(@NotNull YoutubeAudioSourceManager source,
160-
@NotNull JsonBrowser json) {
161+
@NotNull JsonBrowser json) {
161162
return json.get("contents")
162-
.get("twoColumnSearchResultsRenderer")
163-
.get("primaryContents")
164-
.get("sectionListRenderer")
165-
.get("contents")
166-
.values() // .index(0)
167-
.stream()
168-
.flatMap(item -> item.get("itemSectionRenderer").get("contents").values().stream()) // actual results
169-
.map(item -> extractAudioTrack(item.get("videoRenderer"), source))
170-
.filter(Objects::nonNull)
171-
.collect(Collectors.toList());
163+
.get("twoColumnSearchResultsRenderer")
164+
.get("primaryContents")
165+
.get("sectionListRenderer")
166+
.get("contents")
167+
.values() // .index(0)
168+
.stream()
169+
.flatMap(item -> item.get("itemSectionRenderer").get("contents").values().stream()) // actual results
170+
.map(item -> extractAudioTrack(item.get("videoRenderer"), source))
171+
.filter(Objects::nonNull)
172+
.collect(Collectors.toList());
172173
}
173174

174175
@Override
175176
@NotNull
176177
protected JsonBrowser extractMixPlaylistData(@NotNull JsonBrowser json) {
177178
return json.get("contents")
178-
.get("twoColumnWatchNextResults")
179-
.get("playlist") // this doesn't exist if mix is not found
180-
.get("playlist");
179+
.get("twoColumnWatchNextResults")
180+
.get("playlist") // this doesn't exist if mix is not found
181+
.get("playlist");
181182
}
182183

183184
@Override
@@ -188,18 +189,18 @@ protected String extractPlaylistName(@NotNull JsonBrowser json) {
188189
@NotNull
189190
protected JsonBrowser extractPlaylistVideoList(@NotNull JsonBrowser json) {
190191
return json.get("contents")
191-
.get("twoColumnBrowseResultsRenderer")
192-
.get("tabs")
193-
.index(0)
194-
.get("tabRenderer")
195-
.get("content")
196-
.get("sectionListRenderer")
197-
.get("contents")
198-
.index(0)
199-
.get("itemSectionRenderer")
200-
.get("contents")
201-
.index(0)
202-
.get("playlistVideoListRenderer");
192+
.get("twoColumnBrowseResultsRenderer")
193+
.get("tabs")
194+
.index(0)
195+
.get("tabRenderer")
196+
.get("content")
197+
.get("sectionListRenderer")
198+
.get("contents")
199+
.index(0)
200+
.get("itemSectionRenderer")
201+
.get("contents")
202+
.index(0)
203+
.get("playlistVideoListRenderer");
203204
}
204205

205206
@Override
@@ -213,20 +214,29 @@ protected String extractPlaylistContinuationToken(@NotNull JsonBrowser videoList
213214
}
214215

215216
return videoList.values()
216-
.stream()
217-
.filter(item -> !item.get("continuationItemRenderer").isNull())
218-
.findFirst()
219-
.map(item -> item.get("continuationItemRenderer").get("continuationEndpoint").get("continuationCommand").get("token").text())
220-
.orElse(null);
217+
.stream()
218+
.filter(item -> !item.get("continuationItemRenderer").isNull())
219+
.findFirst()
220+
.map(item -> {
221+
JsonBrowser continuationEndpoint = item.get("continuationItemRenderer").get("continuationEndpoint");
222+
String token = continuationEndpoint.get("continuationCommand").get("token").text();
223+
if (!DataFormatTools.isNullOrEmpty(token)) {
224+
return token;
225+
}
226+
227+
return continuationEndpoint.get("commandExecutorCommand").get("commands").index(1)
228+
.get("continuationCommand").get("token").text();
229+
})
230+
.orElse(null);
221231
}
222232

223233
@Override
224234
@NotNull
225235
protected JsonBrowser extractPlaylistContinuationVideos(@NotNull JsonBrowser continuationJson) {
226236
return continuationJson.get("onResponseReceivedActions")
227-
.index(0)
228-
.get("appendContinuationItemsAction")
229-
.get("continuationItems");
237+
.index(0)
238+
.get("appendContinuationItemsAction")
239+
.get("continuationItems");
230240
}
231241

232242
@Override

0 commit comments

Comments
 (0)