mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-03-12 14:38:15 +00:00
Recreate poToken generator if current is broken
This will be tried only once, and afterwards an error will be thrown
This commit is contained in:
parent
0066b322e1
commit
f856bd9306
@ -1,5 +1,7 @@
|
||||
package org.schabi.newpipe.util.potoken
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import org.schabi.newpipe.App
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
@ -22,33 +24,68 @@ object PoTokenProviderImpl : PoTokenProvider {
|
||||
return null
|
||||
}
|
||||
|
||||
val (poTokenGenerator, visitorData, streamingPot) = synchronized(WebPoTokenGenLock) {
|
||||
if (webPoTokenGenerator == null || webPoTokenGenerator!!.isExpired()) {
|
||||
webPoTokenGenerator = PoTokenWebView.newPoTokenGenerator(App.getApp()).blockingGet()
|
||||
return getWebClientPoToken(videoId = videoId, forceRecreate = false)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forceRecreate whether to force the recreation of [webPoTokenGenerator], to be used in
|
||||
* case the current [webPoTokenGenerator] threw an error last time
|
||||
* [PoTokenGenerator.generatePoToken] was called
|
||||
*/
|
||||
private fun getWebClientPoToken(videoId: String, forceRecreate: Boolean): PoTokenResult {
|
||||
// just a helper class since Kotlin does not have builtin support for 4-tuples
|
||||
data class Quadruple<T1, T2, T3, T4>(val t1: T1, val t2: T2, val t3: T3, val t4: T4)
|
||||
|
||||
val (poTokenGenerator, visitorData, streamingPot, hasBeenRecreated) =
|
||||
synchronized(WebPoTokenGenLock) {
|
||||
val shouldRecreate = webPoTokenGenerator == null || forceRecreate ||
|
||||
webPoTokenGenerator!!.isExpired()
|
||||
|
||||
if (shouldRecreate) {
|
||||
// close the current webPoTokenGenerator on the main thread
|
||||
webPoTokenGenerator?.let { Handler(Looper.getMainLooper()).post { it.close() } }
|
||||
|
||||
// create a new webPoTokenGenerator
|
||||
webPoTokenGenerator = PoTokenWebView
|
||||
.newPoTokenGenerator(App.getApp()).blockingGet()
|
||||
webPoTokenVisitorData = YoutubeParsingHelper
|
||||
.randomVisitorData(NewPipe.getPreferredContentCountry())
|
||||
|
||||
// The streaming poToken needs to be generated exactly once before generating any
|
||||
// other (player) tokens.
|
||||
// The streaming poToken needs to be generated exactly once before generating
|
||||
// any other (player) tokens.
|
||||
webPoTokenStreamingPot = webPoTokenGenerator!!
|
||||
.generatePoToken(webPoTokenVisitorData!!).blockingGet()
|
||||
}
|
||||
return@synchronized Triple(
|
||||
webPoTokenGenerator!!, webPoTokenVisitorData!!, webPoTokenStreamingPot!!
|
||||
|
||||
return@synchronized Quadruple(
|
||||
webPoTokenGenerator!!,
|
||||
webPoTokenVisitorData!!,
|
||||
webPoTokenStreamingPot!!,
|
||||
shouldRecreate
|
||||
)
|
||||
}
|
||||
|
||||
// Not using synchronized here, since poTokenGenerator would be able to generate multiple
|
||||
// poTokens in parallel if needed. The only important thing is for exactly one
|
||||
val playerPot = try {
|
||||
// Not using synchronized here, since poTokenGenerator would be able to generate
|
||||
// multiple poTokens in parallel if needed. The only important thing is for exactly one
|
||||
// visitorData/streaming poToken to be generated before anything else.
|
||||
val playerPot = poTokenGenerator.generatePoToken(videoId).blockingGet()
|
||||
Log.e(TAG, "success($videoId) $playerPot,web.gvs+$streamingPot;visitor_data=$visitorData")
|
||||
poTokenGenerator.generatePoToken(videoId).blockingGet()
|
||||
} catch (throwable: Throwable) {
|
||||
if (hasBeenRecreated) {
|
||||
// the poTokenGenerator has just been recreated (and possibly this is already the
|
||||
// second time we try), so there is likely nothing we can do
|
||||
throw throwable
|
||||
} else {
|
||||
// retry, this time recreating the [webPoTokenGenerator] from scratch;
|
||||
// this might happen for example if NewPipe goes in the background and the WebView
|
||||
// content is lost
|
||||
Log.e(TAG, "Failed to obtain poToken, retrying", throwable)
|
||||
return getWebClientPoToken(videoId = videoId, forceRecreate = true)
|
||||
}
|
||||
}
|
||||
|
||||
return PoTokenResult(
|
||||
webPoTokenVisitorData!!,
|
||||
playerPot,
|
||||
webPoTokenStreamingPot!!,
|
||||
)
|
||||
Log.e(TAG, "success($videoId) $playerPot,web.gvs+$streamingPot;visitor_data=$visitorData")
|
||||
return PoTokenResult(visitorData, playerPot, streamingPot)
|
||||
}
|
||||
|
||||
override fun getWebEmbedClientPoToken(videoId: String): PoTokenResult? = null
|
||||
|
@ -7,6 +7,7 @@ import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.WebView
|
||||
import androidx.annotation.MainThread
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.core.SingleEmitter
|
||||
@ -275,6 +276,7 @@ class PoTokenWebView private constructor(
|
||||
/**
|
||||
* Releases all [webView] and [disposables] resources.
|
||||
*/
|
||||
@MainThread
|
||||
override fun close() {
|
||||
disposables.dispose()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user