diff --git a/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt b/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt index c9fdecde8b..97ae441837 100644 --- a/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt +++ b/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt @@ -36,6 +36,26 @@ fun VideoStream.toPipedStream(): PipedStream = PipedStream( contentLength = itagItem?.contentLength ?: 0L ) +fun StreamInfoItem.toStreamItem( + uploaderAvatarUrl: String? = null +): StreamItem = StreamItem( + type = StreamItem.TYPE_STREAM, + url = url.replace(YOUTUBE_FRONTEND_URL, ""), + title = name, + uploaded = uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: 0, + uploadedDate = textualUploadDate ?: uploadDate?.offsetDateTime()?.toLocalDateTime()?.toLocalDate() + ?.toString(), + uploaderName = uploaderName, + uploaderUrl = uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""), + uploaderAvatar = uploaderAvatarUrl ?: uploaderAvatars.maxByOrNull { it.height }?.url, + thumbnail = thumbnails.maxByOrNull { it.height }?.url, + duration = duration, + views = viewCount, + uploaderVerified = isUploaderVerified, + shortDescription = shortDescription, + isShort = isShortFormContent +) + object StreamsExtractor { suspend fun extractStreams(videoId: String): Streams { if (!PlayerHelper.disablePipedProxy || !PlayerHelper.localStreamExtraction) { @@ -74,24 +94,7 @@ object StreamsExtractor { uploadTimestamp = resp.uploadDate.offsetDateTime().toInstant().toKotlinInstant(), uploaded = resp.uploadDate.offsetDateTime().toEpochSecond() * 1000, thumbnailUrl = resp.thumbnails.maxBy { it.height }.url, - relatedStreams = resp.relatedItems.filterIsInstance().map { - StreamItem( - it.url.replace(YOUTUBE_FRONTEND_URL, ""), - StreamItem.TYPE_STREAM, - it.name, - it.thumbnails.maxBy { image -> image.height }.url, - it.uploaderName, - it.uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""), - it.uploaderAvatars.maxBy { image -> image.height }.url, - it.textualUploadDate, - it.duration, - it.viewCount, - it.isUploaderVerified, - it.uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: 0L, - it.shortDescription, - it.isShortFormContent, - ) - }, + relatedStreams = resp.relatedItems.filterIsInstance().map(StreamInfoItem::toStreamItem), chapters = resp.streamSegments.map { ChapterSegment( title = it.title, diff --git a/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt b/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt index 17117c01f0..81cc9da0ed 100644 --- a/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt +++ b/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt @@ -3,6 +3,7 @@ package com.github.libretube.repo import android.util.Log import com.github.libretube.api.SubscriptionHelper import com.github.libretube.api.obj.StreamItem +import com.github.libretube.api.toStreamItem import com.github.libretube.constants.PreferenceKeys import com.github.libretube.db.DatabaseHolder import com.github.libretube.db.obj.SubscriptionsFeedItem @@ -72,7 +73,10 @@ class LocalFeedRepository : FeedRepository { } } - private suspend fun getRelatedStreams(channelId: String, minimumDateMillis: Long): List { + private suspend fun getRelatedStreams( + channelId: String, + minimumDateMillis: Long + ): List { val channelUrl = "$YOUTUBE_FRONTEND_URL/channel/${channelId}" val feedInfo = FeedInfo.getInfo(channelUrl) @@ -95,23 +99,8 @@ class LocalFeedRepository : FeedRepository { }.flatten().filterIsInstance() return related.map { item -> - StreamItem( - type = StreamItem.TYPE_STREAM, - url = item.url.replace(YOUTUBE_FRONTEND_URL, ""), - title = item.name, - uploaded = item.uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: 0, - uploadedDate = item.uploadDate?.offsetDateTime()?.toLocalDateTime()?.toLocalDate() - ?.toString(), - uploaderName = item.uploaderName, - uploaderUrl = item.uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""), - uploaderAvatar = channelInfo.avatars.maxByOrNull { it.height }?.url, - thumbnail = item.thumbnails.maxByOrNull { it.height }?.url, - duration = item.duration, - views = item.viewCount, - uploaderVerified = item.isUploaderVerified, - shortDescription = item.shortDescription, - isShort = item.isShortFormContent - ) + // avatar is not always included in these info items, thus must be taken from channel info response + item.toStreamItem(channelInfo.avatars.maxByOrNull { it.height }?.url) }.filter { it.uploaded > minimumDateMillis } }