From 77b6c08c540f13395d375b190e4edb1aaf8ebcf4 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 17 Feb 2025 22:31:06 +0100 Subject: [PATCH] fix: no shorts in locally generated subscriptions feed --- .../com/github/libretube/api/StreamsExtractor.kt | 9 +++++---- .../java/com/github/libretube/api/obj/StreamItem.kt | 2 +- .../github/libretube/db/dao/SubscriptionsFeedDao.kt | 2 +- .../java/com/github/libretube/extensions/ToID.kt | 7 +++++++ .../com/github/libretube/repo/LocalFeedRepository.kt | 12 +++++++++--- 5 files changed, 23 insertions(+), 9 deletions(-) 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 97ae44183..5320de268 100644 --- a/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt +++ b/app/src/main/java/com/github/libretube/api/StreamsExtractor.kt @@ -10,6 +10,7 @@ import com.github.libretube.api.obj.PreviewFrames import com.github.libretube.api.obj.StreamItem import com.github.libretube.api.obj.Streams import com.github.libretube.api.obj.Subtitle +import com.github.libretube.extensions.toID import com.github.libretube.helpers.PlayerHelper import com.github.libretube.ui.dialogs.ShareDialog.Companion.YOUTUBE_FRONTEND_URL import kotlinx.datetime.toKotlinInstant @@ -40,13 +41,13 @@ fun StreamInfoItem.toStreamItem( uploaderAvatarUrl: String? = null ): StreamItem = StreamItem( type = StreamItem.TYPE_STREAM, - url = url.replace(YOUTUBE_FRONTEND_URL, ""), + url = url.toID(), title = name, - uploaded = uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: 0, + uploaded = uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: -1, uploadedDate = textualUploadDate ?: uploadDate?.offsetDateTime()?.toLocalDateTime()?.toLocalDate() ?.toString(), uploaderName = uploaderName, - uploaderUrl = uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""), + uploaderUrl = uploaderUrl.toID(), uploaderAvatar = uploaderAvatarUrl ?: uploaderAvatars.maxByOrNull { it.height }?.url, thumbnail = thumbnails.maxByOrNull { it.height }?.url, duration = duration, @@ -68,7 +69,7 @@ object StreamsExtractor { description = resp.description.content, uploader = resp.uploaderName, uploaderAvatar = resp.uploaderAvatars.maxBy { it.height }.url, - uploaderUrl = resp.uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""), + uploaderUrl = resp.uploaderUrl.toID(), uploaderVerified = resp.isUploaderVerified, uploaderSubscriberCount = resp.uploaderSubscriberCount, category = resp.category, diff --git a/app/src/main/java/com/github/libretube/api/obj/StreamItem.kt b/app/src/main/java/com/github/libretube/api/obj/StreamItem.kt index a2a12ccde..ef663ff27 100644 --- a/app/src/main/java/com/github/libretube/api/obj/StreamItem.kt +++ b/app/src/main/java/com/github/libretube/api/obj/StreamItem.kt @@ -28,7 +28,7 @@ data class StreamItem( val shortDescription: String? = null, val isShort: Boolean = false ) : Parcelable { - val isLive get() = (duration == null) || (duration <= 0L) + val isLive get() = !isShort && ((duration == null) || (duration <= 0L)) val isUpcoming get() = uploaded > System.currentTimeMillis() fun toLocalPlaylistItem(playlistId: String): LocalPlaylistItem { diff --git a/app/src/main/java/com/github/libretube/db/dao/SubscriptionsFeedDao.kt b/app/src/main/java/com/github/libretube/db/dao/SubscriptionsFeedDao.kt index 80443b421..57be8f49e 100644 --- a/app/src/main/java/com/github/libretube/db/dao/SubscriptionsFeedDao.kt +++ b/app/src/main/java/com/github/libretube/db/dao/SubscriptionsFeedDao.kt @@ -17,7 +17,7 @@ interface SubscriptionsFeedDao { @Query("SELECT EXISTS (SELECT * FROM feedItem WHERE videoId = :videoId)") suspend fun contains(videoId: String): Boolean - @Query("DELETE FROM feedItem WHERE uploaded < :olderThan") + @Query("DELETE FROM feedItem WHERE (uploaded < :olderThan AND uploaded != -1)") suspend fun cleanUpOlderThan(olderThan: Long) @Query("DELETE FROM feedItem WHERE uploaderUrl NOT IN (:channelUrls)") diff --git a/app/src/main/java/com/github/libretube/extensions/ToID.kt b/app/src/main/java/com/github/libretube/extensions/ToID.kt index b3439cb72..286e3ba42 100644 --- a/app/src/main/java/com/github/libretube/extensions/ToID.kt +++ b/app/src/main/java/com/github/libretube/extensions/ToID.kt @@ -1,11 +1,18 @@ package com.github.libretube.extensions +import com.github.libretube.ui.dialogs.ShareDialog.Companion.YOUTUBE_FRONTEND_URL + /** * format a Piped route to an ID */ fun String.toID(): String { return this + .replace(YOUTUBE_FRONTEND_URL, "") .replace("/watch?v=", "") // videos .replace("/channel/", "") // channels .replace("/playlist?list=", "") // playlists + // channel urls for different categories than the main one + .removeSuffix("/shorts") + .removeSuffix("/streams") + .removeSuffix("/videos") } 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 426a62359..5bf8679f8 100644 --- a/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt +++ b/app/src/main/java/com/github/libretube/repo/LocalFeedRepository.kt @@ -39,7 +39,10 @@ class LocalFeedRepository : FeedRepository { val channelIds = SubscriptionHelper.getSubscriptionChannelIds() // remove videos from channels that are no longer subscribed - DatabaseHolder.Database.feedDao().deleteAllExcept(channelIds.map { id -> "/channel/${id}" }) + DatabaseHolder.Database.feedDao().deleteAllExcept( + // TODO: the /channel/ prefix is allowed for compatibility reasons and will be removed in the future + channelIds + channelIds.map { id -> "/channel/${id}" } + ) if (!forceRefresh) { val feed = DatabaseHolder.Database.feedDao().getAll() @@ -104,7 +107,7 @@ class LocalFeedRepository : FeedRepository { mostRecentChannelVideo.uploadDate?.offsetDateTime()?.toInstant()?.toEpochMilli() ?: 0 val hasNewerUploads = mostRecentUploadTime > minimumDateMillis && !DatabaseHolder.Database.feedDao() - .contains(mostRecentChannelVideo.url.replace(YOUTUBE_FRONTEND_URL, "").toID()) + .contains(mostRecentChannelVideo.url.toID()) if (!hasNewerUploads) return emptyList() val channelInfo = ChannelInfo.getInfo(channelUrl) @@ -122,7 +125,10 @@ class LocalFeedRepository : FeedRepository { return related.map { item -> // 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 } + }.filter { + // shorts don't have upload dates apparently + it.isShort || it.uploaded > minimumDateMillis + } } companion object {