Skip to content

Commit 63ed06a

Browse files
committed
[YouTube] Differentiate genre mixes from normal mixes
Note: genre mixes already worked, now they are just considered as such in various video id extraction and in related items Note 2: now extracting a mix id from a *normal* youtube mix id will fail if the video id wouldn't be exactly 11 characters long
1 parent f19660e commit 63ed06a

2 files changed

Lines changed: 43 additions & 8 deletions

File tree

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

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.schabi.newpipe.extractor.exceptions.*;
1414
import org.schabi.newpipe.extractor.localization.ContentCountry;
1515
import org.schabi.newpipe.extractor.localization.Localization;
16+
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
1617
import org.schabi.newpipe.extractor.stream.Description;
1718
import org.schabi.newpipe.extractor.utils.JsonUtils;
1819
import org.schabi.newpipe.extractor.utils.Parser;
@@ -246,7 +247,8 @@ public static OffsetDateTime parseDateFrom(final String textualUploadDate)
246247
* @return Whether given id belongs to a YouTube Mix
247248
*/
248249
public static boolean isYoutubeMixId(@Nonnull final String playlistId) {
249-
return playlistId.startsWith("RD") && !isYoutubeMusicMixId(playlistId);
250+
return playlistId.startsWith("RD")
251+
&& !isYoutubeMusicMixId(playlistId);
250252
}
251253

252254
/**
@@ -282,28 +284,57 @@ public static boolean isYoutubeChannelMixId(@Nonnull final String playlistId) {
282284
}
283285

284286
/**
285-
* @return the video id extracted from the playlist id for Mixes
286-
* @throws ParsingException If the playlistId is a Channel Mix or not a mix.
287+
* Checks if the given playlist id is a YouTube Genre Mix (auto-generated playlist)
288+
* Ids from a YouTube Genre Mix start with "RDGMEM"
289+
*
290+
* @return Whether given id belongs to a YouTube Genre Mix
291+
*/
292+
public static boolean isYoutubeGenreMixId(@Nonnull final String playlistId) {
293+
return playlistId.startsWith("RDGMEM");
294+
}
295+
296+
/**
297+
* @param playlistId the playlist id to parse
298+
* @return the {@link PlaylistInfo.PlaylistType} extracted from the playlistId (mix playlist
299+
* types included)
300+
* @throws ParsingException if the playlistId is null or empty, if the playlistId is not a mix,
301+
* if it is a mix but it's not based on a specific stream (this is the
302+
* case for channel or genre mixes)
287303
*/
288304
@Nonnull
289-
public static String extractVideoIdFromMixId(@Nonnull final String playlistId)
305+
public static String extractVideoIdFromMixId(final String playlistId)
290306
throws ParsingException {
291-
if (isYoutubeMyMixId(playlistId)) {
307+
if (isNullOrEmpty(playlistId)) {
308+
throw new ParsingException("Video id could not be determined from empty playlist id");
309+
310+
} else if (isYoutubeMyMixId(playlistId)) {
292311
return playlistId.substring(4);
293312

294313
} else if (isYoutubeMusicMixId(playlistId)) {
295314
return playlistId.substring(6);
296315

297316
} else if (isYoutubeChannelMixId(playlistId)) {
298-
// Channel mix are build with RMCM{channelId}, so videoId can't be determined
299-
throw new ParsingException("Video id could not be determined from mix id: "
317+
// Channel mixes are of the form RMCM{channelId}, so videoId can't be determined
318+
throw new ParsingException("Video id could not be determined from channel mix id: "
319+
+ playlistId);
320+
321+
} else if (isYoutubeGenreMixId(playlistId)) {
322+
// Genre mixes are of the form RDGMEM{garbage}, so videoId can't be determined
323+
throw new ParsingException("Video id could not be determined from genre mix id: "
300324
+ playlistId);
301325

302326
} else if (isYoutubeMixId(playlistId)) { // normal mix
327+
if (playlistId.length() != 13) {
328+
// Stream YouTube mixes are of the form RD{videoId}, but if videoId is not exactly
329+
// 11 characters then it can't be a video id, hence we are dealing with a different
330+
// type of mix (e.g. genre mixes handled above, of the form RDGMEM{garbage})
331+
throw new ParsingException("Video id could not be determined from mix id: "
332+
+ playlistId);
333+
}
303334
return playlistId.substring(2);
304335

305336
} else { // not a mix
306-
throw new ParsingException("Video id could not be determined from mix id: "
337+
throw new ParsingException("Video id could not be determined from playlist id: "
307338
+ playlistId);
308339
}
309340
}

extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/extractors/YoutubeMixPlaylistInfoItemExtractor.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
44
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getThumbnailUrlFromInfoItem;
55
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isYoutubeChannelMixId;
6+
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isYoutubeGenreMixId;
67
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.isYoutubeMusicMixId;
78
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
89

@@ -74,8 +75,11 @@ public PlaylistInfo.PlaylistType getPlaylistType() throws ParsingException {
7475
return PlaylistInfo.PlaylistType.MIX_MUSIC;
7576
} else if (isYoutubeChannelMixId(mixPlaylistId)) {
7677
return PlaylistInfo.PlaylistType.MIX_CHANNEL;
78+
} else if (isYoutubeGenreMixId(mixPlaylistId)) {
79+
return PlaylistInfo.PlaylistType.MIX_GENRE;
7780
} else {
7881
// either a normal mix based on a stream, or a "my mix" (still based on a stream)
82+
// note: if YouTube introduces even more types of mixes, they will default to this
7983
return PlaylistInfo.PlaylistType.MIX_STREAM;
8084
}
8185
} catch (final MalformedURLException e) {

0 commit comments

Comments
 (0)