Skip to content

Commit ce48dd6

Browse files
authored
Add optional filter for Soundcloud preview tracks (#181)
* Add optional filter for Soundcloud preview tracks * Ignore preview filter from already loaded track
1 parent 66ae62f commit ce48dd6

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

main/src/main/java/com/sedmelluq/discord/lavaplayer/source/soundcloud/SoundCloudAudioSourceManager.java

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.apache.http.client.utils.URIBuilder;
1919
import org.apache.http.impl.client.HttpClientBuilder;
2020
import org.apache.http.util.EntityUtils;
21+
import org.jetbrains.annotations.Nullable;
2122

2223
import java.io.DataInput;
2324
import java.io.DataOutput;
@@ -27,6 +28,7 @@
2728
import java.nio.charset.StandardCharsets;
2829
import java.util.ArrayList;
2930
import java.util.List;
31+
import java.util.Objects;
3032
import java.util.function.Consumer;
3133
import java.util.function.Function;
3234
import java.util.regex.Matcher;
@@ -51,6 +53,7 @@ public class SoundCloudAudioSourceManager implements AudioSourceManager, HttpCon
5153
private static final String SEARCH_PREFIX = "scsearch";
5254
private static final String SEARCH_PREFIX_DEFAULT = "scsearch:";
5355
private static final String SEARCH_REGEX = SEARCH_PREFIX + "\\[([0-9]{1,9}),([0-9]{1,9})\\]:\\s*(.*)\\s*";
56+
private static final String FULL_TRACK_UNAVAILABLE_MARKER = "SUB_HIGH_TIER";
5457

5558
private static final Pattern mobileUrlPattern = Pattern.compile(MOBILE_URL_REGEX);
5659
private static final Pattern trackUrlPattern = Pattern.compile(TRACK_URL_REGEX);
@@ -67,14 +70,20 @@ public class SoundCloudAudioSourceManager implements AudioSourceManager, HttpCon
6770
private final HttpInterfaceManager httpInterfaceManager;
6871
private final SoundCloudClientIdTracker clientIdTracker;
6972
private final boolean allowSearch;
73+
private final boolean filterOutPreviewTracks;
7074

7175
public static SoundCloudAudioSourceManager createDefault() {
7276
SoundCloudDataReader dataReader = new DefaultSoundCloudDataReader();
7377
SoundCloudDataLoader dataLoader = new DefaultSoundCloudDataLoader();
7478
SoundCloudFormatHandler formatHandler = new DefaultSoundCloudFormatHandler();
7579

76-
return new SoundCloudAudioSourceManager(true, dataReader, dataLoader, formatHandler,
77-
new DefaultSoundCloudPlaylistLoader(dataLoader, dataReader, formatHandler));
80+
return new SoundCloudAudioSourceManager(true,
81+
dataReader,
82+
dataLoader,
83+
formatHandler,
84+
new DefaultSoundCloudPlaylistLoader(dataLoader, dataReader, formatHandler),
85+
false
86+
);
7887
}
7988

8089
public static Builder builder() {
@@ -91,13 +100,15 @@ public SoundCloudAudioSourceManager(
91100
SoundCloudDataReader dataReader,
92101
SoundCloudDataLoader dataLoader,
93102
SoundCloudFormatHandler formatHandler,
94-
SoundCloudPlaylistLoader playlistLoader
103+
SoundCloudPlaylistLoader playlistLoader,
104+
boolean filterOutPreviewTracks
95105
) {
96106
this.allowSearch = allowSearch;
97107
this.dataReader = dataReader;
98108
this.dataLoader = dataLoader;
99109
this.formatHandler = formatHandler;
100110
this.playlistLoader = playlistLoader;
111+
this.filterOutPreviewTracks = filterOutPreviewTracks;
101112

102113
httpInterfaceManager = HttpClientTools.createDefaultThreadLocalManager();
103114
clientIdTracker = new SoundCloudClientIdTracker(httpInterfaceManager);
@@ -209,7 +220,13 @@ private AudioItem processAsLikedTracks(AudioReference reference) {
209220
}
210221
}
211222

223+
@Nullable
212224
public AudioTrack loadTrack(String trackWebUrl) {
225+
return loadTrack(trackWebUrl, true);
226+
}
227+
228+
@Nullable
229+
public AudioTrack loadTrack(String trackWebUrl, boolean honorPreviewFilter) {
213230
try (HttpInterface httpInterface = getHttpInterface()) {
214231
JsonBrowser rootData = dataLoader.load(httpInterface, trackWebUrl);
215232
JsonBrowser trackData = dataReader.findTrackData(rootData);
@@ -218,6 +235,10 @@ public AudioTrack loadTrack(String trackWebUrl) {
218235
throw new FriendlyException("This track is not available", COMMON, null);
219236
}
220237

238+
if (honorPreviewFilter && filterOutPreviewTracks && Objects.equals(trackData.get("monetization_model").text(), FULL_TRACK_UNAVAILABLE_MARKER)) {
239+
return null;
240+
}
241+
221242
return loadFromTrackData(trackData);
222243
} catch (IOException e) {
223244
throw new FriendlyException("Loading track from SoundCloud failed.", SUSPICIOUS, e);
@@ -363,6 +384,7 @@ public static class Builder {
363384
private SoundCloudFormatHandler formatHandler;
364385
private SoundCloudPlaylistLoader playlistLoader;
365386
private PlaylistLoaderFactory playlistLoaderFactory;
387+
private boolean filterOutPreviewTracks = false;
366388

367389
public Builder withAllowSearch(boolean allowSearch) {
368390
this.allowSearch = allowSearch;
@@ -394,6 +416,16 @@ public Builder withPlaylistLoaderFactory(PlaylistLoaderFactory playlistLoaderFac
394416
return this;
395417
}
396418

419+
/**
420+
* Whether to filter out short preview tracks that are only fully available with a Soundcloud subscription.
421+
* Lavaplayer does not support getting the full track. Only affects new AudioTracks being loaded by this source,
422+
* with no effect on deserialized tracks.
423+
*/
424+
public Builder withFilterOutPreviewTracks(boolean filterOutPreviewTracks) {
425+
this.filterOutPreviewTracks = filterOutPreviewTracks;
426+
return this;
427+
}
428+
397429
public SoundCloudAudioSourceManager build() {
398430
SoundCloudDataReader usedDataReader = dataReader;
399431

@@ -432,7 +464,8 @@ public SoundCloudAudioSourceManager build() {
432464
usedDataReader,
433465
usedDataLoader,
434466
usedFormatHandler,
435-
usedPlaylistLoader
467+
usedPlaylistLoader,
468+
filterOutPreviewTracks
436469
);
437470
}
438471

main/src/main/java/com/sedmelluq/discord/lavaplayer/source/soundcloud/SoundCloudAudioTrack.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ private void playFromIdentifier(
6363

6464
if (!recursion) {
6565
// Old "track ID" entry? Let's "load" it to get url.
66-
AudioTrack track = sourceManager.loadTrack(trackInfo.uri);
66+
AudioTrack track = sourceManager.loadTrack(trackInfo.uri, false);
67+
//noinspection DataFlowIssue
6768
playFromIdentifier(httpInterface, track.getIdentifier(), true, localExecutor);
6869
}
6970
}

0 commit comments

Comments
 (0)