Piped-Backend/src/main/java/me/kavin/piped/utils/CollectionUtils.java
2023-10-10 22:57:34 +01:00

142 lines
7.5 KiB
Java

package me.kavin.piped.utils;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import me.kavin.piped.utils.obj.*;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.ReadyChannelTabListLinkHandler;
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.stream.StreamType;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import static me.kavin.piped.utils.URLUtils.*;
public class CollectionUtils {
public static Streams collectStreamInfo(StreamInfo info) {
final List<Subtitle> subtitles = new ObjectArrayList<>();
final List<ChapterSegment> chapters = new ObjectArrayList<>();
info.getStreamSegments().forEach(segment -> chapters.add(new ChapterSegment(segment.getTitle(), rewriteURL(segment.getPreviewUrl()),
segment.getStartTimeSeconds())));
final List<PreviewFrames> previewFrames = new ObjectArrayList<>();
info.getPreviewFrames().forEach(frame -> previewFrames.add(new PreviewFrames(frame.getUrls().stream().map(URLUtils::rewriteURL).toList(), frame.getFrameWidth(),
frame.getFrameHeight(), frame.getTotalCount(), frame.getDurationPerFrame(), frame.getFramesPerPageX(),
frame.getFramesPerPageY())));
info.getSubtitles()
.forEach(subtitle -> subtitles.add(new Subtitle(rewriteURL(subtitle.getContent()),
subtitle.getFormat().getMimeType(), subtitle.getDisplayLanguageName(),
subtitle.getLanguageTag(), subtitle.isAutoGenerated())));
final List<PipedStream> videoStreams = new ObjectArrayList<>();
final List<PipedStream> audioStreams = new ObjectArrayList<>();
boolean livestream = info.getStreamType() == StreamType.LIVE_STREAM;
if (!livestream) {
info.getVideoOnlyStreams().forEach(stream -> videoStreams.add(new PipedStream(stream.getItag(), rewriteVideoURL(stream.getContent()),
String.valueOf(stream.getFormat()), stream.getResolution(), stream.getFormat().getMimeType(), true,
stream.getBitrate(), stream.getInitStart(), stream.getInitEnd(), stream.getIndexStart(),
stream.getIndexEnd(), stream.getCodec(), stream.getWidth(), stream.getHeight(), stream.getFps(), stream.getItagItem().getContentLength())));
info.getVideoStreams()
.forEach(stream -> videoStreams
.add(new PipedStream(stream.getItag(), rewriteVideoURL(stream.getContent()), String.valueOf(stream.getFormat()),
stream.getResolution(), stream.getFormat().getMimeType(), false, stream.getItagItem().getContentLength())));
info.getAudioStreams()
.forEach(stream -> audioStreams.add(new PipedStream(stream.getItag(), rewriteVideoURL(stream.getContent()),
String.valueOf(stream.getFormat()), stream.getAverageBitrate() + " kbps",
stream.getFormat().getMimeType(), false, stream.getBitrate(), stream.getInitStart(),
stream.getInitEnd(), stream.getIndexStart(), stream.getIndexEnd(), stream.getItagItem().getContentLength(), stream.getCodec(), stream.getAudioTrackId(),
stream.getAudioTrackName(), Optional.ofNullable(stream.getAudioTrackType()).map(Enum::name).orElse(null),
Optional.ofNullable(stream.getAudioLocale()).map(Locale::toLanguageTag).orElse(null)
)));
}
final List<ContentItem> relatedStreams = collectRelatedItems(info.getRelatedItems());
final List<MetaInfo> metaInfo = new ObjectArrayList<>();
info.getMetaInfo().forEach(metaInfoItem -> metaInfo.add(new MetaInfo(metaInfoItem.getTitle(), metaInfoItem.getContent().getContent(),
metaInfoItem.getUrls(), metaInfoItem.getUrlTexts()
)));
return new Streams(info.getName(), info.getDescription().getContent(),
info.getTextualUploadDate(), info.getUploaderName(), substringYouTube(info.getUploaderUrl()),
getLastThumbnail(info.getUploaderAvatars()), getLastThumbnail(info.getThumbnails()), info.getDuration(),
info.getViewCount(), info.getLikeCount(), info.getDislikeCount(), info.getUploaderSubscriberCount(), info.isUploaderVerified(),
audioStreams, videoStreams, relatedStreams, subtitles, livestream, rewriteVideoURL(info.getHlsUrl()),
rewriteVideoURL(info.getDashMpdUrl()), null, info.getCategory(), info.getLicence(),
info.getPrivacy().name().toLowerCase(), info.getTags(), metaInfo, chapters, previewFrames);
}
public static List<ContentItem> collectRelatedItems(List<? extends InfoItem> items) {
return items
.stream()
.parallel()
.map(item -> {
if (item instanceof StreamInfoItem) {
return collectRelatedStream(item);
} else if (item instanceof PlaylistInfoItem) {
return collectRelatedPlaylist(item);
} else if (item instanceof ChannelInfoItem) {
return collectRelatedChannel(item);
} else {
throw new RuntimeException(
"Unknown item type: " + item.getClass().getName());
}
}).toList();
}
private static StreamItem collectRelatedStream(Object o) {
StreamInfoItem item = (StreamInfoItem) o;
return new StreamItem(substringYouTube(item.getUrl()), item.getName(),
getLastThumbnail(item.getThumbnails()),
item.getUploaderName(), substringYouTube(item.getUploaderUrl()),
getLastThumbnail(item.getUploaderAvatars()), item.getTextualUploadDate(),
item.getShortDescription(), item.getDuration(),
item.getViewCount(), item.getUploadDate() != null ?
item.getUploadDate().offsetDateTime().toInstant().toEpochMilli() : -1,
item.isUploaderVerified(), item.isShortFormContent());
}
private static PlaylistItem collectRelatedPlaylist(Object o) {
PlaylistInfoItem item = (PlaylistInfoItem) o;
return new PlaylistItem(substringYouTube(item.getUrl()), item.getName(),
getLastThumbnail(item.getThumbnails()),
item.getUploaderName(), substringYouTube(item.getUploaderUrl()),
item.isUploaderVerified(),
item.getPlaylistType().name(), item.getStreamCount());
}
private static ChannelItem collectRelatedChannel(Object o) {
ChannelInfoItem item = (ChannelInfoItem) o;
return new ChannelItem(substringYouTube(item.getUrl()), item.getName(),
getLastThumbnail(item.getThumbnails()),
item.getDescription(), item.getSubscriberCount(), item.getStreamCount(),
item.isVerified());
}
public static List<ReadyChannelTabListLinkHandler> collectPreloadedTabs(List<ListLinkHandler> tabs) {
return tabs
.stream()
.filter(ReadyChannelTabListLinkHandler.class::isInstance)
.map(ReadyChannelTabListLinkHandler.class::cast)
.toList();
}
}