feat(MediaService/Local): implement SponsorBlock support

Allows users to use SponsorBlock when using full local mode.

Closes: https://github.com/libre-tube/LibreTube/issues/7193
This commit is contained in:
FineFindus 2025-03-13 15:55:54 +01:00
parent 2497fa8702
commit 31613c8f84
No known key found for this signature in database
GPG Key ID: 64873EE210FF8E6B
2 changed files with 26 additions and 3 deletions

View File

@ -3,12 +3,14 @@ package com.github.libretube.api
import com.github.libretube.api.obj.DeArrowBody
import com.github.libretube.api.obj.PipedConfig
import com.github.libretube.api.obj.PipedInstance
import com.github.libretube.api.obj.SegmentData
import com.github.libretube.api.obj.SubmitSegmentResponse
import com.github.libretube.api.obj.VoteInfo
import com.github.libretube.obj.update.UpdateInfo
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
import retrofit2.http.Url
@ -43,6 +45,13 @@ interface ExternalApi {
@Query("description") description: String = ""
): List<SubmitSegmentResponse>
@GET("$SB_API_URL/api/skipSegments/{videoId}")
suspend fun getSegments(
@Path("videoId") videoId: String,
@Query("category") category: List<String>,
@Query("actionType") actionType: List<String>? = null
): List<SegmentData>
@POST("$SB_API_URL/api/branding")
suspend fun submitDeArrow(@Body body: DeArrowBody)

View File

@ -48,6 +48,7 @@ import org.schabi.newpipe.extractor.stream.AudioStream
import org.schabi.newpipe.extractor.stream.StreamInfo
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.extractor.stream.VideoStream
import java.security.MessageDigest
private fun VideoStream.toPipedStream() = PipedStream(
@ -319,11 +320,24 @@ class NewPipeMediaServiceRepository : MediaServiceRepository {
)
}
@OptIn(ExperimentalStdlibApi::class)
override suspend fun getSegments(
videoId: String,
category: String,
actionType: String?
): SegmentData = SegmentData()
category: List<String>,
actionType: List<String>?
): SegmentData {
// use hashed video id for privacy
// https://wiki.sponsor.ajay.app/w/API_Docs#GET_/api/skipSegments/:sha256HashPrefix
val hashedId = MessageDigest.getInstance("SHA-256")
.digest(videoId.toByteArray())
.toHexString()
return RetrofitInstance.externalApi.getSegments(
hashedId.substring(0..4),
category,
actionType
).first { it.videoID == videoId }
}
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
emptyMap()