-
-
Notifications
You must be signed in to change notification settings - Fork 448
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: move local stream extraction to sub-package
- Loading branch information
1 parent
817521a
commit 5b9b297
Showing
12 changed files
with
138 additions
and
132 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...om/github/libretube/api/JavaScriptUtil.kt → ...hub/libretube/api/local/JavaScriptUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
app/src/main/java/com/github/libretube/api/local/PoTokenGenerator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package com.github.libretube.api.local | ||
|
||
import android.os.Handler | ||
import android.os.Looper | ||
import android.util.Log | ||
import android.webkit.CookieManager | ||
import com.github.libretube.BuildConfig | ||
import com.github.libretube.LibreTubeApp | ||
import kotlinx.coroutines.runBlocking | ||
import org.schabi.newpipe.extractor.NewPipe | ||
import org.schabi.newpipe.extractor.services.youtube.InnertubeClientRequestInfo | ||
import org.schabi.newpipe.extractor.services.youtube.PoTokenProvider | ||
import org.schabi.newpipe.extractor.services.youtube.PoTokenResult | ||
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper | ||
|
||
class PoTokenGenerator : PoTokenProvider { | ||
val TAG = PoTokenGenerator::class.simpleName | ||
private val supportsWebView by lazy { runCatching { CookieManager.getInstance() }.isSuccess } | ||
|
||
private object WebPoTokenGenLock | ||
private var webPoTokenVisitorData: String? = null | ||
private var webPoTokenStreamingPot: String? = null | ||
private var webPoTokenGenerator: PoTokenWebView? = null | ||
|
||
|
||
override fun getWebClientPoToken(videoId: String): PoTokenResult? { | ||
if (!supportsWebView) { | ||
return null | ||
} | ||
|
||
return getWebClientPoToken(videoId, 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) { | ||
val innertubeClientRequestInfo = InnertubeClientRequestInfo.ofWebClient() | ||
innertubeClientRequestInfo.clientInfo.clientVersion = | ||
YoutubeParsingHelper.getClientVersion() | ||
|
||
webPoTokenVisitorData = YoutubeParsingHelper.getVisitorDataFromInnertube( | ||
innertubeClientRequestInfo, | ||
NewPipe.getPreferredLocalization(), | ||
NewPipe.getPreferredContentCountry(), | ||
YoutubeParsingHelper.getYouTubeHeaders(), | ||
YoutubeParsingHelper.YOUTUBEI_V1_URL, | ||
null, | ||
false | ||
) | ||
|
||
runBlocking { | ||
// close the current webPoTokenGenerator on the main thread | ||
webPoTokenGenerator?.let { Handler(Looper.getMainLooper()).post { it.close() } } | ||
|
||
// create a new webPoTokenGenerator | ||
webPoTokenGenerator = PoTokenWebView | ||
.newPoTokenGenerator(LibreTubeApp.instance) | ||
|
||
// The streaming poToken needs to be generated exactly once before generating | ||
// any other (player) tokens. | ||
webPoTokenStreamingPot = webPoTokenGenerator!!.generatePoToken(webPoTokenVisitorData!!) | ||
} | ||
} | ||
|
||
return@synchronized Quadruple( | ||
webPoTokenGenerator!!, | ||
webPoTokenVisitorData!!, | ||
webPoTokenStreamingPot!!, | ||
shouldRecreate | ||
) | ||
} | ||
|
||
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. | ||
runBlocking { | ||
poTokenGenerator.generatePoToken(videoId) | ||
} | ||
} 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) | ||
} | ||
} | ||
|
||
|
||
if (BuildConfig.DEBUG) { | ||
Log.d( | ||
TAG, | ||
"poToken for $videoId: playerPot=$playerPot, " + | ||
"streamingPot=$streamingPot, visitor_data=$visitorData" | ||
) | ||
} | ||
|
||
return PoTokenResult(visitorData, playerPot, streamingPot) | ||
} | ||
|
||
override fun getWebEmbedClientPoToken(videoId: String?): PoTokenResult? = null | ||
|
||
override fun getAndroidClientPoToken(videoId: String?): PoTokenResult? = null | ||
|
||
override fun getIosClientPoToken(videoId: String?): PoTokenResult? = null | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters