mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
Merge pull request #7195 from FineFindus/feat/local-sb
feat(local): implement support for SponsorBlock and DeArrow
This commit is contained in:
commit
69c4ab871f
@ -1,14 +1,17 @@
|
|||||||
package com.github.libretube.api
|
package com.github.libretube.api
|
||||||
|
|
||||||
import com.github.libretube.api.obj.DeArrowBody
|
import com.github.libretube.api.obj.DeArrowBody
|
||||||
|
import com.github.libretube.api.obj.DeArrowContent
|
||||||
import com.github.libretube.api.obj.PipedConfig
|
import com.github.libretube.api.obj.PipedConfig
|
||||||
import com.github.libretube.api.obj.PipedInstance
|
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.SubmitSegmentResponse
|
||||||
import com.github.libretube.api.obj.VoteInfo
|
import com.github.libretube.api.obj.VoteInfo
|
||||||
import com.github.libretube.obj.update.UpdateInfo
|
import com.github.libretube.obj.update.UpdateInfo
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
import retrofit2.http.Url
|
import retrofit2.http.Url
|
||||||
|
|
||||||
@ -43,6 +46,13 @@ interface ExternalApi {
|
|||||||
@Query("description") description: String = ""
|
@Query("description") description: String = ""
|
||||||
): List<SubmitSegmentResponse>
|
): 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")
|
@POST("$SB_API_URL/api/branding")
|
||||||
suspend fun submitDeArrow(@Body body: DeArrowBody)
|
suspend fun submitDeArrow(@Body body: DeArrowBody)
|
||||||
|
|
||||||
@ -55,4 +65,7 @@ interface ExternalApi {
|
|||||||
@Query("userID") userID: String,
|
@Query("userID") userID: String,
|
||||||
@Query("type") score: Int
|
@Query("type") score: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@GET("$SB_API_URL/api/branding/{videoId}")
|
||||||
|
suspend fun getDeArrowContent(@Path("videoId") videoId: String): Map<String, DeArrowContent>
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ interface MediaServiceRepository {
|
|||||||
suspend fun getComments(videoId: String): CommentsPage
|
suspend fun getComments(videoId: String): CommentsPage
|
||||||
suspend fun getSegments(
|
suspend fun getSegments(
|
||||||
videoId: String,
|
videoId: String,
|
||||||
category: String,
|
category: List<String>,
|
||||||
actionType: String? = null
|
actionType: List<String>? = null
|
||||||
): SegmentData
|
): SegmentData
|
||||||
|
|
||||||
suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent>
|
suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent>
|
||||||
|
@ -20,6 +20,8 @@ import com.github.libretube.api.obj.StreamItem.Companion.TYPE_PLAYLIST
|
|||||||
import com.github.libretube.api.obj.StreamItem.Companion.TYPE_STREAM
|
import com.github.libretube.api.obj.StreamItem.Companion.TYPE_STREAM
|
||||||
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.parallelMap
|
||||||
|
import com.github.libretube.extensions.sha256Sum
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.helpers.NewPipeExtractorInstance
|
import com.github.libretube.helpers.NewPipeExtractorInstance
|
||||||
import com.github.libretube.helpers.PlayerHelper
|
import com.github.libretube.helpers.PlayerHelper
|
||||||
@ -321,13 +323,32 @@ class NewPipeMediaServiceRepository : MediaServiceRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getSegments(
|
override suspend fun getSegments(
|
||||||
videoId: String,
|
videoId: String, category: List<String>, actionType: List<String>?
|
||||||
category: String,
|
): SegmentData = RetrofitInstance.externalApi.getSegments(
|
||||||
actionType: String?
|
// use hashed video id for privacy
|
||||||
): SegmentData = SegmentData()
|
// https://wiki.sponsor.ajay.app/w/API_Docs#GET_/api/skipSegments/:sha256HashPrefix
|
||||||
|
videoId.sha256Sum().substring(0, 4), category, actionType
|
||||||
|
).first { it.videoID == videoId }
|
||||||
|
|
||||||
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
|
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
|
||||||
emptyMap()
|
videoIds.split(',').chunked(25).flatMap {
|
||||||
|
it.parallelMap { videoId ->
|
||||||
|
runCatching {
|
||||||
|
RetrofitInstance.externalApi.getDeArrowContent(
|
||||||
|
// use hashed video id for privacy
|
||||||
|
// https://wiki.sponsor.ajay.app/w/API_Docs/DeArrow#GET_/api/branding/:sha256HashPrefix
|
||||||
|
videoId.sha256Sum().substring(0, 4)
|
||||||
|
)
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
}.filterNotNull().reduce { acc, map -> acc + map }.mapValues { (videoId, value) ->
|
||||||
|
value.copy(
|
||||||
|
thumbnails = value.thumbnails.map { thumbnail ->
|
||||||
|
thumbnail.takeIf { it.original } ?: thumbnail.copy(
|
||||||
|
thumbnail = "${DEARROW_THUMBNAIL_URL}?videoID=$videoId&time=${thumbnail.timestamp}"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getSearchResults(searchQuery: String, filter: String): SearchResult {
|
override suspend fun getSearchResults(searchQuery: String, filter: String): SearchResult {
|
||||||
val queryHandler = NewPipeExtractorInstance.extractor.searchQHFactory.fromQuery(
|
val queryHandler = NewPipeExtractorInstance.extractor.searchQHFactory.fromQuery(
|
||||||
@ -481,4 +502,8 @@ class NewPipeMediaServiceRepository : MediaServiceRepository {
|
|||||||
comments = commentsInfo.items.map { it.toComment() }
|
comments = commentsInfo.items.map { it.toComment() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DEARROW_THUMBNAIL_URL = "https://dearrow-thumb.ajay.app/api/v1/getThumbnail"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ 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.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
import com.github.libretube.helpers.PreferenceHelper
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
|
|
||||||
open class PipedMediaServiceRepository : MediaServiceRepository {
|
open class PipedMediaServiceRepository : MediaServiceRepository {
|
||||||
@ -36,9 +37,13 @@ open class PipedMediaServiceRepository : MediaServiceRepository {
|
|||||||
|
|
||||||
override suspend fun getSegments(
|
override suspend fun getSegments(
|
||||||
videoId: String,
|
videoId: String,
|
||||||
category: String,
|
category: List<String>,
|
||||||
actionType: String?
|
actionType: List<String>?
|
||||||
): SegmentData = api.getSegments(videoId, category, actionType)
|
): SegmentData = api.getSegments(
|
||||||
|
videoId,
|
||||||
|
JsonHelper.json.encodeToString(category),
|
||||||
|
JsonHelper.json.encodeToString(actionType)
|
||||||
|
)
|
||||||
|
|
||||||
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
|
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
|
||||||
api.getDeArrowContent(videoIds)
|
api.getDeArrowContent(videoIds)
|
||||||
|
11
app/src/main/java/com/github/libretube/extensions/ShaSum.kt
Normal file
11
app/src/main/java/com/github/libretube/extensions/ShaSum.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.github.libretube.extensions
|
||||||
|
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the SHA-256 hash of the String and returns the result in hexadecimal.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
fun String.sha256Sum(): String = MessageDigest.getInstance("SHA-256")
|
||||||
|
.digest(this.toByteArray())
|
||||||
|
.toHexString()
|
@ -209,8 +209,8 @@ open class OnlinePlayerService : AbstractPlayerService() {
|
|||||||
if (sponsorBlockConfig.isEmpty()) return@runCatching
|
if (sponsorBlockConfig.isEmpty()) return@runCatching
|
||||||
sponsorBlockSegments = MediaServiceRepository.instance.getSegments(
|
sponsorBlockSegments = MediaServiceRepository.instance.getSegments(
|
||||||
videoId,
|
videoId,
|
||||||
JsonHelper.json.encodeToString(sponsorBlockConfig.keys),
|
sponsorBlockConfig.keys.toList(),
|
||||||
"""["skip","mute","full","poi","chapter"]"""
|
listOf("skip","mute","full","poi","chapter")
|
||||||
).segments
|
).segments
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
|
@ -147,7 +147,7 @@ class SubmitSegmentDialog : DialogFragment() {
|
|||||||
private suspend fun fetchSegments() {
|
private suspend fun fetchSegments() {
|
||||||
val categories = resources.getStringArray(R.array.sponsorBlockSegments).toList()
|
val categories = resources.getStringArray(R.array.sponsorBlockSegments).toList()
|
||||||
segments = try {
|
segments = try {
|
||||||
MediaServiceRepository.instance.getSegments(videoId, JsonHelper.json.encodeToString(categories)).segments
|
MediaServiceRepository.instance.getSegments(videoId, categories).segments
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG(), e.toString())
|
Log.e(TAG(), e.toString())
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user