mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-28 16:00:31 +05:30
Merge pull request #7111 from Bnyro/master
fix: no shorts in locally generated subscriptions feed
This commit is contained in:
commit
470c3bb714
@ -10,6 +10,7 @@ import com.github.libretube.api.obj.PreviewFrames
|
|||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.api.obj.Streams
|
import com.github.libretube.api.obj.Streams
|
||||||
import com.github.libretube.api.obj.Subtitle
|
import com.github.libretube.api.obj.Subtitle
|
||||||
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
import com.github.libretube.ui.dialogs.ShareDialog.Companion.YOUTUBE_FRONTEND_URL
|
import com.github.libretube.ui.dialogs.ShareDialog.Companion.YOUTUBE_FRONTEND_URL
|
||||||
import kotlinx.datetime.toKotlinInstant
|
import kotlinx.datetime.toKotlinInstant
|
||||||
@ -40,13 +41,13 @@ fun StreamInfoItem.toStreamItem(
|
|||||||
uploaderAvatarUrl: String? = null
|
uploaderAvatarUrl: String? = null
|
||||||
): StreamItem = StreamItem(
|
): StreamItem = StreamItem(
|
||||||
type = StreamItem.TYPE_STREAM,
|
type = StreamItem.TYPE_STREAM,
|
||||||
url = url.replace(YOUTUBE_FRONTEND_URL, ""),
|
url = url.toID(),
|
||||||
title = name,
|
title = name,
|
||||||
uploaded = uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: 0,
|
uploaded = uploadDate?.offsetDateTime()?.toEpochSecond()?.times(1000) ?: -1,
|
||||||
uploadedDate = textualUploadDate ?: uploadDate?.offsetDateTime()?.toLocalDateTime()?.toLocalDate()
|
uploadedDate = textualUploadDate ?: uploadDate?.offsetDateTime()?.toLocalDateTime()?.toLocalDate()
|
||||||
?.toString(),
|
?.toString(),
|
||||||
uploaderName = uploaderName,
|
uploaderName = uploaderName,
|
||||||
uploaderUrl = uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""),
|
uploaderUrl = uploaderUrl.toID(),
|
||||||
uploaderAvatar = uploaderAvatarUrl ?: uploaderAvatars.maxByOrNull { it.height }?.url,
|
uploaderAvatar = uploaderAvatarUrl ?: uploaderAvatars.maxByOrNull { it.height }?.url,
|
||||||
thumbnail = thumbnails.maxByOrNull { it.height }?.url,
|
thumbnail = thumbnails.maxByOrNull { it.height }?.url,
|
||||||
duration = duration,
|
duration = duration,
|
||||||
@ -68,7 +69,7 @@ object StreamsExtractor {
|
|||||||
description = resp.description.content,
|
description = resp.description.content,
|
||||||
uploader = resp.uploaderName,
|
uploader = resp.uploaderName,
|
||||||
uploaderAvatar = resp.uploaderAvatars.maxBy { it.height }.url,
|
uploaderAvatar = resp.uploaderAvatars.maxBy { it.height }.url,
|
||||||
uploaderUrl = resp.uploaderUrl.replace(YOUTUBE_FRONTEND_URL, ""),
|
uploaderUrl = resp.uploaderUrl.toID(),
|
||||||
uploaderVerified = resp.isUploaderVerified,
|
uploaderVerified = resp.isUploaderVerified,
|
||||||
uploaderSubscriberCount = resp.uploaderSubscriberCount,
|
uploaderSubscriberCount = resp.uploaderSubscriberCount,
|
||||||
category = resp.category,
|
category = resp.category,
|
||||||
|
@ -28,7 +28,7 @@ data class StreamItem(
|
|||||||
val shortDescription: String? = null,
|
val shortDescription: String? = null,
|
||||||
val isShort: Boolean = false
|
val isShort: Boolean = false
|
||||||
) : Parcelable {
|
) : Parcelable {
|
||||||
val isLive get() = (duration == null) || (duration <= 0L)
|
val isLive get() = !isShort && ((duration == null) || (duration <= 0L))
|
||||||
val isUpcoming get() = uploaded > System.currentTimeMillis()
|
val isUpcoming get() = uploaded > System.currentTimeMillis()
|
||||||
|
|
||||||
fun toLocalPlaylistItem(playlistId: String): LocalPlaylistItem {
|
fun toLocalPlaylistItem(playlistId: String): LocalPlaylistItem {
|
||||||
|
@ -17,7 +17,7 @@ interface SubscriptionsFeedDao {
|
|||||||
@Query("SELECT EXISTS (SELECT * FROM feedItem WHERE videoId = :videoId)")
|
@Query("SELECT EXISTS (SELECT * FROM feedItem WHERE videoId = :videoId)")
|
||||||
suspend fun contains(videoId: String): Boolean
|
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)
|
suspend fun cleanUpOlderThan(olderThan: Long)
|
||||||
|
|
||||||
@Query("DELETE FROM feedItem WHERE uploaderUrl NOT IN (:channelUrls)")
|
@Query("DELETE FROM feedItem WHERE uploaderUrl NOT IN (:channelUrls)")
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
package com.github.libretube.extensions
|
package com.github.libretube.extensions
|
||||||
|
|
||||||
|
import com.github.libretube.ui.dialogs.ShareDialog.Companion.YOUTUBE_FRONTEND_URL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* format a Piped route to an ID
|
* format a Piped route to an ID
|
||||||
*/
|
*/
|
||||||
fun String.toID(): String {
|
fun String.toID(): String {
|
||||||
return this
|
return this
|
||||||
|
.replace(YOUTUBE_FRONTEND_URL, "")
|
||||||
.replace("/watch?v=", "") // videos
|
.replace("/watch?v=", "") // videos
|
||||||
.replace("/channel/", "") // channels
|
.replace("/channel/", "") // channels
|
||||||
.replace("/playlist?list=", "") // playlists
|
.replace("/playlist?list=", "") // playlists
|
||||||
|
// channel urls for different categories than the main one
|
||||||
|
.removeSuffix("/shorts")
|
||||||
|
.removeSuffix("/streams")
|
||||||
|
.removeSuffix("/videos")
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,10 @@ class LocalFeedRepository : FeedRepository {
|
|||||||
|
|
||||||
val channelIds = SubscriptionHelper.getSubscriptionChannelIds()
|
val channelIds = SubscriptionHelper.getSubscriptionChannelIds()
|
||||||
// remove videos from channels that are no longer subscribed
|
// 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) {
|
if (!forceRefresh) {
|
||||||
val feed = DatabaseHolder.Database.feedDao().getAll()
|
val feed = DatabaseHolder.Database.feedDao().getAll()
|
||||||
@ -104,7 +107,7 @@ class LocalFeedRepository : FeedRepository {
|
|||||||
mostRecentChannelVideo.uploadDate?.offsetDateTime()?.toInstant()?.toEpochMilli() ?: 0
|
mostRecentChannelVideo.uploadDate?.offsetDateTime()?.toInstant()?.toEpochMilli() ?: 0
|
||||||
val hasNewerUploads =
|
val hasNewerUploads =
|
||||||
mostRecentUploadTime > minimumDateMillis && !DatabaseHolder.Database.feedDao()
|
mostRecentUploadTime > minimumDateMillis && !DatabaseHolder.Database.feedDao()
|
||||||
.contains(mostRecentChannelVideo.url.replace(YOUTUBE_FRONTEND_URL, "").toID())
|
.contains(mostRecentChannelVideo.url.toID())
|
||||||
if (!hasNewerUploads) return emptyList()
|
if (!hasNewerUploads) return emptyList()
|
||||||
|
|
||||||
val channelInfo = ChannelInfo.getInfo(channelUrl)
|
val channelInfo = ChannelInfo.getInfo(channelUrl)
|
||||||
@ -122,7 +125,10 @@ class LocalFeedRepository : FeedRepository {
|
|||||||
return related.map { item ->
|
return related.map { item ->
|
||||||
// avatar is not always included in these info items, thus must be taken from channel info response
|
// 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)
|
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 {
|
companion object {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user