mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-09-20 19:29:47 +00:00
150 lines
5.4 KiB
Kotlin
150 lines
5.4 KiB
Kotlin
package org.schabi.newpipe.database.stream.dao
|
|
|
|
import androidx.room.ColumnInfo
|
|
import androidx.room.Dao
|
|
import androidx.room.Insert
|
|
import androidx.room.OnConflictStrategy
|
|
import androidx.room.Query
|
|
import androidx.room.Transaction
|
|
import io.reactivex.rxjava3.core.Completable
|
|
import io.reactivex.rxjava3.core.Flowable
|
|
import org.schabi.newpipe.database.BasicDAO
|
|
import org.schabi.newpipe.database.stream.model.StreamEntity
|
|
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID
|
|
import org.schabi.newpipe.extractor.stream.StreamType
|
|
import org.schabi.newpipe.util.StreamTypeUtil
|
|
import java.time.OffsetDateTime
|
|
|
|
@Dao
|
|
abstract class StreamDAO : BasicDAO<StreamEntity> {
|
|
@Query("SELECT * FROM streams")
|
|
abstract override fun getAll(): Flowable<List<StreamEntity>>
|
|
|
|
@Query("DELETE FROM streams")
|
|
abstract override fun deleteAll(): Int
|
|
|
|
@Query("SELECT * FROM streams WHERE service_id = :serviceId")
|
|
abstract override fun listByService(serviceId: Int): Flowable<List<StreamEntity>>
|
|
|
|
@Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId")
|
|
abstract fun getStream(serviceId: Long, url: String): Flowable<List<StreamEntity>>
|
|
|
|
@Query("UPDATE streams SET uploader_url = :uploaderUrl WHERE url = :url AND service_id = :serviceId")
|
|
abstract fun setUploaderUrl(serviceId: Long, url: String, uploaderUrl: String): Completable
|
|
|
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
|
internal abstract fun silentInsertInternal(stream: StreamEntity): Long
|
|
|
|
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
|
internal abstract fun silentInsertAllInternal(streams: List<StreamEntity>): List<Long>
|
|
|
|
@Query("SELECT COUNT(*) != 0 FROM streams WHERE url = :url AND service_id = :serviceId")
|
|
internal abstract fun exists(serviceId: Int, url: String): Boolean
|
|
|
|
@Query(
|
|
"""
|
|
SELECT uid, stream_type, textual_upload_date, upload_date, is_upload_date_approximation, duration
|
|
FROM streams WHERE url = :url AND service_id = :serviceId
|
|
"""
|
|
)
|
|
internal abstract fun getMinimalStreamForCompare(serviceId: Int, url: String): StreamCompareFeed?
|
|
|
|
@Transaction
|
|
open fun upsert(newerStream: StreamEntity): Long {
|
|
val uid = silentInsertInternal(newerStream)
|
|
|
|
if (uid != -1L) {
|
|
newerStream.uid = uid
|
|
return uid
|
|
}
|
|
|
|
compareAndUpdateStream(newerStream)
|
|
|
|
update(newerStream)
|
|
return newerStream.uid
|
|
}
|
|
|
|
@Transaction
|
|
open fun upsertAll(streams: List<StreamEntity>): List<Long> {
|
|
val insertUidList = silentInsertAllInternal(streams)
|
|
|
|
val streamIds = ArrayList<Long>(streams.size)
|
|
for ((index, uid) in insertUidList.withIndex()) {
|
|
val newerStream = streams[index]
|
|
if (uid != -1L) {
|
|
streamIds.add(uid)
|
|
newerStream.uid = uid
|
|
continue
|
|
}
|
|
|
|
compareAndUpdateStream(newerStream)
|
|
streamIds.add(newerStream.uid)
|
|
}
|
|
|
|
update(streams)
|
|
return streamIds
|
|
}
|
|
|
|
private fun compareAndUpdateStream(newerStream: StreamEntity) {
|
|
val existentMinimalStream = getMinimalStreamForCompare(newerStream.serviceId, newerStream.url)
|
|
?: throw IllegalStateException("Stream cannot be null just after insertion.")
|
|
newerStream.uid = existentMinimalStream.uid
|
|
|
|
if (!StreamTypeUtil.isLiveStream(newerStream.streamType)) {
|
|
|
|
// Use the existent upload date if the newer stream does not have a better precision
|
|
// (i.e. is an approximation). This is done to prevent unnecessary changes.
|
|
val hasBetterPrecision =
|
|
newerStream.uploadDate != null && newerStream.isUploadDateApproximation != true
|
|
if (existentMinimalStream.uploadDate != null && !hasBetterPrecision) {
|
|
newerStream.uploadDate = existentMinimalStream.uploadDate
|
|
newerStream.textualUploadDate = existentMinimalStream.textualUploadDate
|
|
newerStream.isUploadDateApproximation = existentMinimalStream.isUploadDateApproximation
|
|
}
|
|
|
|
if (existentMinimalStream.duration > 0 && newerStream.duration < 0) {
|
|
newerStream.duration = existentMinimalStream.duration
|
|
}
|
|
}
|
|
}
|
|
|
|
@Query(
|
|
"""
|
|
DELETE FROM streams WHERE
|
|
|
|
NOT EXISTS (SELECT 1 FROM stream_history sh
|
|
WHERE sh.stream_id = streams.uid)
|
|
|
|
AND NOT EXISTS (SELECT 1 FROM playlist_stream_join ps
|
|
WHERE ps.stream_id = streams.uid)
|
|
|
|
AND NOT EXISTS (SELECT 1 FROM feed f
|
|
WHERE f.stream_id = streams.uid)
|
|
"""
|
|
)
|
|
abstract fun deleteOrphans(): Int
|
|
|
|
/**
|
|
* Minimal entry class used when comparing/updating an existent stream.
|
|
*/
|
|
internal data class StreamCompareFeed(
|
|
@ColumnInfo(name = STREAM_ID)
|
|
var uid: Long = 0,
|
|
|
|
@ColumnInfo(name = StreamEntity.STREAM_TYPE)
|
|
var streamType: StreamType,
|
|
|
|
@ColumnInfo(name = StreamEntity.STREAM_TEXTUAL_UPLOAD_DATE)
|
|
var textualUploadDate: String? = null,
|
|
|
|
@ColumnInfo(name = StreamEntity.STREAM_UPLOAD_DATE)
|
|
var uploadDate: OffsetDateTime? = null,
|
|
|
|
@ColumnInfo(name = StreamEntity.STREAM_IS_UPLOAD_DATE_APPROXIMATION)
|
|
var isUploadDateApproximation: Boolean? = null,
|
|
|
|
@ColumnInfo(name = StreamEntity.STREAM_DURATION)
|
|
var duration: Long
|
|
)
|
|
}
|