2019-04-28 20:43:52 +00:00
|
|
|
package org.schabi.newpipe.database.feed.dao
|
|
|
|
|
2020-11-04 17:07:40 +00:00
|
|
|
import androidx.room.Dao
|
|
|
|
import androidx.room.Insert
|
|
|
|
import androidx.room.OnConflictStrategy
|
|
|
|
import androidx.room.Query
|
|
|
|
import androidx.room.Transaction
|
|
|
|
import androidx.room.Update
|
2020-10-31 20:55:45 +00:00
|
|
|
import io.reactivex.rxjava3.core.Flowable
|
2021-09-03 19:35:23 +00:00
|
|
|
import io.reactivex.rxjava3.core.Maybe
|
2019-04-28 20:43:52 +00:00
|
|
|
import org.schabi.newpipe.database.feed.model.FeedEntity
|
2022-07-13 09:37:46 +00:00
|
|
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
2019-12-16 07:36:04 +00:00
|
|
|
import org.schabi.newpipe.database.feed.model.FeedLastUpdatedEntity
|
2020-04-05 14:11:03 +00:00
|
|
|
import org.schabi.newpipe.database.stream.StreamWithState
|
2021-03-26 10:27:25 +00:00
|
|
|
import org.schabi.newpipe.database.stream.model.StreamStateEntity
|
2021-11-21 21:53:10 +00:00
|
|
|
import org.schabi.newpipe.database.subscription.NotificationMode
|
2019-12-16 07:36:04 +00:00
|
|
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity
|
2020-10-31 20:55:45 +00:00
|
|
|
import java.time.OffsetDateTime
|
2019-04-28 20:43:52 +00:00
|
|
|
|
|
|
|
@Dao
|
|
|
|
abstract class FeedDAO {
|
|
|
|
@Query("DELETE FROM feed")
|
|
|
|
abstract fun deleteAll(): Int
|
|
|
|
|
2021-06-07 07:43:08 +00:00
|
|
|
/**
|
2022-07-13 09:37:46 +00:00
|
|
|
* @param groupId the group id to get feed streams of; use
|
|
|
|
* [FeedGroupEntity.GROUP_ALL_ID] to not filter by group
|
|
|
|
* @param includePlayed if false, only return all of the live, never-played or non-finished
|
|
|
|
* feed streams (see `@see` items); if true no filter is applied
|
|
|
|
* @param uploadDateBefore get only streams uploaded before this date (useful to filter out
|
|
|
|
* future streams); use null to not filter by upload date
|
|
|
|
* @return the feed streams filtered according to the conditions provided in the parameters
|
2021-06-07 07:43:08 +00:00
|
|
|
* @see StreamStateEntity.isFinished()
|
|
|
|
* @see StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS
|
2023-01-30 21:37:24 +00:00
|
|
|
* @see StreamStateEntity.PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS
|
2021-06-07 07:43:08 +00:00
|
|
|
*/
|
2020-04-05 14:11:03 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2021-03-26 10:35:54 +00:00
|
|
|
SELECT s.*, sst.progress_time
|
2020-04-05 14:11:03 +00:00
|
|
|
FROM streams s
|
|
|
|
|
|
|
|
LEFT JOIN stream_state sst
|
|
|
|
ON s.uid = sst.stream_id
|
|
|
|
|
|
|
|
LEFT JOIN stream_history sh
|
|
|
|
ON s.uid = sh.stream_id
|
|
|
|
|
|
|
|
INNER JOIN feed f
|
|
|
|
ON s.uid = f.stream_id
|
|
|
|
|
2022-07-13 09:37:46 +00:00
|
|
|
LEFT JOIN feed_group_subscription_join fgs
|
2022-10-27 21:43:27 +00:00
|
|
|
ON (
|
|
|
|
:groupId <> ${FeedGroupEntity.GROUP_ALL_ID}
|
|
|
|
AND fgs.subscription_id = f.subscription_id
|
|
|
|
)
|
2019-04-28 20:43:52 +00:00
|
|
|
|
2022-07-13 09:37:46 +00:00
|
|
|
WHERE (
|
|
|
|
:groupId = ${FeedGroupEntity.GROUP_ALL_ID}
|
|
|
|
OR fgs.group_id = :groupId
|
|
|
|
)
|
2020-04-05 14:11:03 +00:00
|
|
|
AND (
|
2022-07-13 09:37:46 +00:00
|
|
|
:includePlayed
|
|
|
|
OR sh.stream_id IS NULL
|
2021-06-07 07:43:08 +00:00
|
|
|
OR sst.stream_id IS NULL
|
|
|
|
OR sst.progress_time < s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
|
|
|
|
OR sst.progress_time < s.duration * 1000 * 3 / 4
|
2020-04-05 14:11:03 +00:00
|
|
|
OR s.stream_type = 'LIVE_STREAM'
|
|
|
|
OR s.stream_type = 'AUDIO_LIVE_STREAM'
|
|
|
|
)
|
2023-01-30 21:37:24 +00:00
|
|
|
AND (
|
|
|
|
:includePartiallyPlayed
|
|
|
|
OR sh.stream_id IS NULL
|
|
|
|
OR sst.stream_id IS NULL
|
2023-02-01 22:10:31 +00:00
|
|
|
OR (sst.progress_time <= ${StreamStateEntity.PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS}
|
|
|
|
AND sst.progress_time <= s.duration * 1000 / 4)
|
2023-02-04 17:48:27 +00:00
|
|
|
OR (sst.progress_time >= s.duration * 1000 - ${StreamStateEntity.PLAYBACK_FINISHED_END_MILLISECONDS}
|
2023-02-09 20:18:21 +00:00
|
|
|
AND sst.progress_time >= s.duration * 1000 * 3 / 4)
|
2023-01-30 21:37:24 +00:00
|
|
|
)
|
2022-07-13 09:37:46 +00:00
|
|
|
AND (
|
|
|
|
:uploadDateBefore IS NULL
|
|
|
|
OR s.upload_date IS NULL
|
|
|
|
OR s.upload_date < :uploadDateBefore
|
|
|
|
)
|
2019-04-28 20:43:54 +00:00
|
|
|
|
|
|
|
ORDER BY s.upload_date IS NULL DESC, s.upload_date DESC, s.uploader ASC
|
|
|
|
LIMIT 500
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2022-07-13 09:37:46 +00:00
|
|
|
abstract fun getStreams(
|
|
|
|
groupId: Long,
|
|
|
|
includePlayed: Boolean,
|
2023-01-30 21:37:24 +00:00
|
|
|
includePartiallyPlayed: Boolean,
|
2022-07-13 09:37:46 +00:00
|
|
|
uploadDateBefore: OffsetDateTime?
|
|
|
|
): Maybe<List<StreamWithState>>
|
2019-04-28 20:43:52 +00:00
|
|
|
|
2023-10-14 16:31:33 +00:00
|
|
|
/**
|
|
|
|
* Remove links to streams that are older than the given date
|
|
|
|
* **but keep at least one stream per uploader**.
|
|
|
|
*
|
|
|
|
* One stream per uploader is kept because it is needed as reference
|
|
|
|
* when fetching new streams to check if they are new or not.
|
|
|
|
* @param offsetDateTime the newest date to keep, older streams are removed
|
|
|
|
*/
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2023-10-14 16:31:33 +00:00
|
|
|
DELETE FROM feed
|
|
|
|
WHERE feed.stream_id IN (SELECT uid from (
|
|
|
|
SELECT s.uid,
|
|
|
|
(SELECT MAX(upload_date)
|
2023-11-23 16:12:16 +00:00
|
|
|
FROM streams s1
|
|
|
|
INNER JOIN feed f1
|
|
|
|
ON s1.uid = f1.stream_id
|
|
|
|
WHERE f1.subscription_id = f.subscription_id) max_upload_date
|
2023-10-14 16:31:33 +00:00
|
|
|
FROM streams s
|
|
|
|
INNER JOIN feed f
|
|
|
|
ON s.uid = f.stream_id
|
|
|
|
|
|
|
|
WHERE s.upload_date < :offsetDateTime
|
|
|
|
AND s.upload_date <> max_upload_date))
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2020-10-18 06:16:55 +00:00
|
|
|
abstract fun unlinkStreamsOlderThan(offsetDateTime: OffsetDateTime)
|
2019-04-28 20:43:54 +00:00
|
|
|
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2019-04-28 20:43:54 +00:00
|
|
|
DELETE FROM feed
|
|
|
|
|
|
|
|
WHERE feed.subscription_id = :subscriptionId
|
|
|
|
|
|
|
|
AND feed.stream_id IN (
|
|
|
|
SELECT s.uid FROM streams s
|
|
|
|
|
|
|
|
INNER JOIN feed f
|
|
|
|
ON s.uid = f.stream_id
|
|
|
|
|
|
|
|
WHERE s.stream_type = "LIVE_STREAM" OR s.stream_type = "AUDIO_LIVE_STREAM"
|
|
|
|
)
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2019-04-28 20:43:54 +00:00
|
|
|
abstract fun unlinkOldLivestreams(subscriptionId: Long)
|
|
|
|
|
|
|
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
2019-04-28 20:43:52 +00:00
|
|
|
abstract fun insert(feedEntity: FeedEntity)
|
|
|
|
|
2019-04-28 20:43:54 +00:00
|
|
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
2019-04-28 20:43:52 +00:00
|
|
|
abstract fun insertAll(entities: List<FeedEntity>): List<Long>
|
2019-12-16 07:36:04 +00:00
|
|
|
|
|
|
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
|
|
|
internal abstract fun insertLastUpdated(lastUpdatedEntity: FeedLastUpdatedEntity): Long
|
|
|
|
|
|
|
|
@Update(onConflict = OnConflictStrategy.IGNORE)
|
|
|
|
internal abstract fun updateLastUpdated(lastUpdatedEntity: FeedLastUpdatedEntity)
|
|
|
|
|
|
|
|
@Transaction
|
|
|
|
open fun setLastUpdatedForSubscription(lastUpdatedEntity: FeedLastUpdatedEntity) {
|
|
|
|
val id = insertLastUpdated(lastUpdatedEntity)
|
|
|
|
|
|
|
|
if (id == -1L) {
|
|
|
|
updateLastUpdated(lastUpdatedEntity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2019-12-16 07:36:04 +00:00
|
|
|
SELECT MIN(lu.last_updated) FROM feed_last_updated lu
|
|
|
|
|
|
|
|
INNER JOIN feed_group_subscription_join fgs
|
|
|
|
ON fgs.subscription_id = lu.subscription_id AND fgs.group_id = :groupId
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2020-10-18 06:16:55 +00:00
|
|
|
abstract fun oldestSubscriptionUpdate(groupId: Long): Flowable<List<OffsetDateTime>>
|
2019-12-16 07:36:04 +00:00
|
|
|
|
|
|
|
@Query("SELECT MIN(last_updated) FROM feed_last_updated")
|
2020-10-18 06:16:55 +00:00
|
|
|
abstract fun oldestSubscriptionUpdateFromAll(): Flowable<List<OffsetDateTime>>
|
2019-12-16 07:36:04 +00:00
|
|
|
|
|
|
|
@Query("SELECT COUNT(*) FROM feed_last_updated WHERE last_updated IS NULL")
|
|
|
|
abstract fun notLoadedCount(): Flowable<Long>
|
|
|
|
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2019-12-16 07:36:04 +00:00
|
|
|
SELECT COUNT(*) FROM subscriptions s
|
|
|
|
|
|
|
|
INNER JOIN feed_group_subscription_join fgs
|
|
|
|
ON s.uid = fgs.subscription_id AND fgs.group_id = :groupId
|
|
|
|
|
|
|
|
LEFT JOIN feed_last_updated lu
|
|
|
|
ON s.uid = lu.subscription_id
|
|
|
|
|
|
|
|
WHERE lu.last_updated IS NULL
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2019-12-16 07:36:04 +00:00
|
|
|
abstract fun notLoadedCountForGroup(groupId: Long): Flowable<Long>
|
|
|
|
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2019-12-16 07:36:04 +00:00
|
|
|
SELECT s.* FROM subscriptions s
|
|
|
|
|
|
|
|
LEFT JOIN feed_last_updated lu
|
|
|
|
ON s.uid = lu.subscription_id
|
|
|
|
|
|
|
|
WHERE lu.last_updated IS NULL OR lu.last_updated < :outdatedThreshold
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2020-10-18 06:16:55 +00:00
|
|
|
abstract fun getAllOutdated(outdatedThreshold: OffsetDateTime): Flowable<List<SubscriptionEntity>>
|
2019-12-16 07:36:04 +00:00
|
|
|
|
2020-10-31 20:55:45 +00:00
|
|
|
@Query(
|
|
|
|
"""
|
2019-12-16 07:36:04 +00:00
|
|
|
SELECT s.* FROM subscriptions s
|
|
|
|
|
|
|
|
INNER JOIN feed_group_subscription_join fgs
|
|
|
|
ON s.uid = fgs.subscription_id AND fgs.group_id = :groupId
|
|
|
|
|
|
|
|
LEFT JOIN feed_last_updated lu
|
|
|
|
ON s.uid = lu.subscription_id
|
|
|
|
|
|
|
|
WHERE lu.last_updated IS NULL OR lu.last_updated < :outdatedThreshold
|
2020-10-31 20:55:45 +00:00
|
|
|
"""
|
|
|
|
)
|
2020-10-18 06:16:55 +00:00
|
|
|
abstract fun getAllOutdatedForGroup(groupId: Long, outdatedThreshold: OffsetDateTime): Flowable<List<SubscriptionEntity>>
|
2021-11-21 21:53:10 +00:00
|
|
|
|
|
|
|
@Query(
|
|
|
|
"""
|
|
|
|
SELECT s.* FROM subscriptions s
|
|
|
|
|
|
|
|
LEFT JOIN feed_last_updated lu
|
|
|
|
ON s.uid = lu.subscription_id
|
|
|
|
|
|
|
|
WHERE
|
|
|
|
(lu.last_updated IS NULL OR lu.last_updated < :outdatedThreshold)
|
|
|
|
AND s.notification_mode = :notificationMode
|
|
|
|
"""
|
|
|
|
)
|
|
|
|
abstract fun getOutdatedWithNotificationMode(
|
|
|
|
outdatedThreshold: OffsetDateTime,
|
|
|
|
@NotificationMode notificationMode: Int
|
|
|
|
): Flowable<List<SubscriptionEntity>>
|
2019-04-28 20:43:52 +00:00
|
|
|
}
|