Skip to content

Commit 1eb98b7

Browse files
committed
add all clients failed error
1 parent aaaeed2 commit 1eb98b7

File tree

4 files changed

+56
-54
lines changed

4 files changed

+56
-54
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package dev.lavalink.youtube;
2+
3+
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Thrown when all clients failed to load a track.
9+
*/
10+
public class AllClientsFailedException extends FriendlyException {
11+
/**
12+
* @param suppressed The exceptions that were caused client failures.
13+
*/
14+
public AllClientsFailedException(List<Throwable> suppressed) {
15+
super("All clients failed to load the item. See suppressed exceptions for details.", Severity.SUSPICIOUS, null);
16+
suppressed.forEach(this::addSuppressed);
17+
}
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package dev.lavalink.youtube;
2+
3+
import dev.lavalink.youtube.clients.skeleton.Client;
4+
import org.jetbrains.annotations.NotNull;
5+
6+
/**
7+
* Wraps an exception with client context
8+
*/
9+
public class ClientException extends Exception {
10+
public ClientException(@NotNull String message, @NotNull Client client, @NotNull Throwable cause) {
11+
super(String.format("Client [%s] failed: %s", client.getIdentifier(), message), cause);
12+
addSuppressed(ClientInformation.create(client));
13+
}
14+
}

common/src/main/java/dev/lavalink/youtube/YoutubeAudioSourceManager.java

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.io.DataOutput;
3535
import java.io.IOException;
3636
import java.net.URI;
37+
import java.util.ArrayList;
3738
import java.util.Arrays;
3839
import java.util.List;
3940
import java.util.regex.Matcher;
@@ -213,7 +214,8 @@ public AudioItem loadItem(@NotNull AudioPlayerManager manager, @NotNull AudioRef
213214

214215
@Nullable
215216
protected AudioItem loadItemOnce(@NotNull AudioReference reference) {
216-
Throwable lastException = null;
217+
AudioItem item = null;
218+
List<Throwable> exceptions = new ArrayList<>();
217219

218220
try (HttpInterface httpInterface = httpInterfaceManager.getInterface()) {
219221
Router router = getRouter(httpInterface, reference.identifier);
@@ -243,28 +245,27 @@ protected AudioItem loadItemOnce(@NotNull AudioReference reference) {
243245
httpInterface.getContext().setAttribute(Client.OAUTH_CLIENT_ATTRIBUTE, client.supportsOAuth());
244246

245247
try {
246-
AudioItem item = router.route(client);
247-
248-
if (item != null) {
249-
return item;
250-
}
248+
item = router.route(client);
251249
} catch (CannotBeLoaded cbl) {
252250
throw ExceptionTools.wrapUnfriendlyExceptions("This video cannot be loaded.", Severity.SUSPICIOUS, cbl.getCause());
253251
} catch (Throwable t) {
254252
log.debug("Client \"{}\" threw a non-fatal exception, storing and proceeding...", client.getIdentifier(), t);
255-
t.addSuppressed(ClientInformation.create(client));
256-
lastException = t;
253+
exceptions.add(new ClientException(t.getMessage(), client, t));
254+
}
255+
256+
if (item != null) {
257+
break;
257258
}
258259
}
259260
} catch (IOException e) {
260261
throw ExceptionTools.toRuntimeException(e);
261262
}
262263

263-
if (lastException != null) {
264-
throw ExceptionTools.wrapUnfriendlyExceptions("This video cannot be loaded.", SUSPICIOUS, lastException);
264+
if (item == null && !exceptions.isEmpty()) {
265+
throw new AllClientsFailedException(exceptions);
265266
}
266267

267-
return null;
268+
return item;
268269
}
269270

270271
@Nullable

common/src/main/java/dev/lavalink/youtube/track/YoutubeAudioTrack.java

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
import com.sedmelluq.discord.lavaplayer.track.DelegatedAudioTrack;
1414
import com.sedmelluq.discord.lavaplayer.track.playback.LocalAudioTrackExecutor;
1515
import dev.lavalink.youtube.CannotBeLoaded;
16+
import dev.lavalink.youtube.AllClientsFailedException;
1617
import dev.lavalink.youtube.ClientInformation;
17-
import dev.lavalink.youtube.UrlTools;
18+
import dev.lavalink.youtube.*;
1819
import dev.lavalink.youtube.UrlTools.UrlInfo;
19-
import dev.lavalink.youtube.YoutubeAudioSourceManager;
2020
import dev.lavalink.youtube.cipher.ScriptExtractionException;
2121
import dev.lavalink.youtube.clients.skeleton.Client;
2222
import dev.lavalink.youtube.track.format.StreamFormat;
@@ -29,7 +29,9 @@
2929
import java.io.IOException;
3030
import java.net.URI;
3131
import java.net.URISyntaxException;
32+
import java.util.ArrayList;
3233
import java.util.Arrays;
34+
import java.util.List;
3335
import java.util.Map;
3436

3537
import static com.sedmelluq.discord.lavaplayer.container.Formats.MIME_AUDIO_WEBM;
@@ -84,7 +86,7 @@ public void process(LocalAudioTrackExecutor localExecutor) throws Exception {
8486
log.debug("Failed to parse token from userData", e);
8587
}
8688

87-
Exception lastException = null;
89+
List<Throwable> exceptions = new ArrayList<>();
8890

8991
for (Client client : clients) {
9092
if (!client.supportsFormatLoading()) {
@@ -95,49 +97,16 @@ public void process(LocalAudioTrackExecutor localExecutor) throws Exception {
9597

9698
try {
9799
processWithClient(localExecutor, httpInterface, client, 0);
98-
return; // stream played through successfully, short-circuit.
99-
} catch (RuntimeException e) {
100-
// store exception so it can be thrown if we run out of clients to
101-
// load formats with.
102-
e.addSuppressed(ClientInformation.create(client));
103-
lastException = e;
104-
105-
if (e instanceof FriendlyException) {
106-
// usually thrown by getPlayabilityStatus when loading formats.
107-
// these aren't considered fatal, so we just store them and continue.
108-
continue;
109-
}
110-
111-
if (e instanceof ScriptExtractionException) {
112-
// If we're still early in playback, we can try another client
113-
if (localExecutor.getPosition() <= BAD_STREAM_POSITION_THRESHOLD_MS) {
114-
continue;
115-
}
116-
} else if ("Not success status code: 403".equals(e.getMessage()) ||
117-
"Invalid status code for player api response: 400".equals(e.getMessage())) {
118-
// As long as the executor position has not surpassed the threshold for which
119-
// a stream is considered unrecoverable, we can try to renew the playback URL with
120-
// another client.
121-
if (localExecutor.getPosition() <= BAD_STREAM_POSITION_THRESHOLD_MS) {
122-
continue;
123-
}
124-
}
125-
126-
throw e; // Unhandled exception, just rethrow.
100+
return;
101+
} catch (CannotBeLoaded e) {
102+
throw e;
103+
} catch (Exception e) {
104+
exceptions.add(new ClientException(e.getMessage(), client, e));
127105
}
128106
}
129107

130-
if (lastException != null) {
131-
if (lastException instanceof FriendlyException) {
132-
if (!"YouTube WebM streams are currently not supported.".equals(lastException.getMessage())) {
133-
// Rethrow certain FriendlyExceptions as suspicious to ensure LavaPlayer logs them.
134-
throw new FriendlyException(lastException.getMessage(), Severity.SUSPICIOUS, lastException.getCause());
135-
}
136-
137-
throw lastException;
138-
}
139-
140-
throw ExceptionTools.toRuntimeException(lastException);
108+
if (!exceptions.isEmpty()) {
109+
throw ExceptionTools.wrapUnfriendlyExceptions("All clients failed to load the track.", Severity.SUSPICIOUS, new AllClientsFailedException(exceptions));
141110
}
142111
} catch (CannotBeLoaded e) {
143112
throw ExceptionTools.wrapUnfriendlyExceptions("This video is unavailable", Severity.SUSPICIOUS, e.getCause());

0 commit comments

Comments
 (0)