mirror of
https://github.com/TeamNewPipe/NewPipeExtractor
synced 2025-08-22 01:48:58 +00:00
[YouTube Music] Fix uploader and stream count for album/playlist info items
- handles autogenerated albums instead of returning an error for invalid uploader url - extracts uploader url of playlists too using another method - getStreamCount() now returns ITEM_COUNT_UNKNOWN because no info is included in the JSON
This commit is contained in:
parent
260ba4749a
commit
03a65516b0
@ -5,32 +5,34 @@ import com.grack.nanojson.JsonObject;
|
||||
import org.schabi.newpipe.extractor.Image;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItemExtractor;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import static org.schabi.newpipe.extractor.ListExtractor.ITEM_COUNT_MORE_THAN_100;
|
||||
import static org.schabi.newpipe.extractor.ListExtractor.ITEM_COUNT_UNKNOWN;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getTextFromObject;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getImagesFromThumbnailsArray;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper.getUrlFromNavigationEndpoint;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_ALBUMS;
|
||||
import static org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeSearchQueryHandlerFactory.MUSIC_PLAYLISTS;
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
public class YoutubeMusicAlbumOrPlaylistInfoItemExtractor implements PlaylistInfoItemExtractor {
|
||||
private final JsonObject albumOrPlaylistInfoItem;
|
||||
private final JsonArray descriptionElements;
|
||||
private final String searchType;
|
||||
private final JsonObject descriptionElementUploader;
|
||||
|
||||
public YoutubeMusicAlbumOrPlaylistInfoItemExtractor(final JsonObject albumOrPlaylistInfoItem,
|
||||
final JsonArray descriptionElements,
|
||||
final String searchType) {
|
||||
this.albumOrPlaylistInfoItem = albumOrPlaylistInfoItem;
|
||||
this.descriptionElements = descriptionElements;
|
||||
this.searchType = searchType;
|
||||
|
||||
if (searchType.equals(MUSIC_ALBUMS)) {
|
||||
// "Album", " • ", uploader, " • ", year
|
||||
this.descriptionElementUploader = descriptionElements.getObject(2);
|
||||
} else {
|
||||
// uploader, " • ", view count
|
||||
this.descriptionElementUploader = descriptionElements.getObject(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -92,12 +94,7 @@ public class YoutubeMusicAlbumOrPlaylistInfoItemExtractor implements PlaylistInf
|
||||
|
||||
@Override
|
||||
public String getUploaderName() throws ParsingException {
|
||||
final String name;
|
||||
if (searchType.equals(MUSIC_ALBUMS)) {
|
||||
name = descriptionElements.getObject(2).getString("text");
|
||||
} else {
|
||||
name = descriptionElements.getObject(0).getString("text");
|
||||
}
|
||||
final String name = descriptionElementUploader.getString("text");
|
||||
|
||||
if (!isNullOrEmpty(name)) {
|
||||
return name;
|
||||
@ -109,10 +106,7 @@ public class YoutubeMusicAlbumOrPlaylistInfoItemExtractor implements PlaylistInf
|
||||
@Nullable
|
||||
@Override
|
||||
public String getUploaderUrl() throws ParsingException {
|
||||
if (searchType.equals(MUSIC_PLAYLISTS)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// first try obtaining the uploader from the menu (will not work for MUSIC_PLAYLISTS though)
|
||||
final JsonArray items = albumOrPlaylistInfoItem.getObject("menu")
|
||||
.getObject("menuRenderer")
|
||||
.getArray("items");
|
||||
@ -127,7 +121,15 @@ public class YoutubeMusicAlbumOrPlaylistInfoItemExtractor implements PlaylistInf
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParsingException("Could not get uploader URL");
|
||||
// then try obtaining it from the uploader description element
|
||||
if (descriptionElementUploader.has("navigationEndpoint")) {
|
||||
return getUrlFromNavigationEndpoint(
|
||||
descriptionElementUploader.getObject("navigationEndpoint"));
|
||||
} else {
|
||||
// if there is no navigationEndpoint for the uploader
|
||||
// then this playlist/album is likely autogenerated
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -137,21 +139,7 @@ public class YoutubeMusicAlbumOrPlaylistInfoItemExtractor implements PlaylistInf
|
||||
|
||||
@Override
|
||||
public long getStreamCount() throws ParsingException {
|
||||
if (searchType.equals(MUSIC_ALBUMS)) {
|
||||
return ITEM_COUNT_UNKNOWN;
|
||||
}
|
||||
|
||||
final String count = descriptionElements.getObject(2)
|
||||
.getString("text");
|
||||
|
||||
if (!isNullOrEmpty(count)) {
|
||||
if (count.contains("100+")) {
|
||||
return ITEM_COUNT_MORE_THAN_100;
|
||||
} else {
|
||||
return Long.parseLong(Utils.removeNonDigitCharacters(count));
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParsingException("Could not get stream count");
|
||||
// YouTube Music album and playlist info items don't expose the stream count anywhere...
|
||||
return ITEM_COUNT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,9 @@ public class YoutubeMusicSearchExtractorTest {
|
||||
}
|
||||
|
||||
public static class MusicAlbums extends DefaultSearchExtractorTest implements InitYoutubeTest {
|
||||
private static final String QUERY = "johnny sellah";
|
||||
// searching for "scenography" on 28/07/2025 returns some autogenerated albums,
|
||||
// and we want to test the extraction of those, too
|
||||
private static final String QUERY = "scenography";
|
||||
|
||||
@Override
|
||||
protected SearchExtractor createExtractor() throws Exception {
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user