Skip to content

Commit

Permalink
test
Browse files Browse the repository at this point in the history
  • Loading branch information
reocat committed Nov 8, 2024
1 parent 94ecbf8 commit 7bc66cf
Showing 1 changed file with 94 additions and 28 deletions.
122 changes: 94 additions & 28 deletions innertube/src/main/java/com/zionhuang/innertube/InnerTube.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import io.ktor.client.plugins.*
import io.ktor.client.plugins.compression.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.HttpRequestRetry
import kotlinx.coroutines.delay
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.util.encodeBase64
Expand Down Expand Up @@ -61,22 +64,78 @@ class InnerTube {
})
}

install(HttpTimeout) {
requestTimeoutMillis = 30000
connectTimeoutMillis = 15000
socketTimeoutMillis = 15000
}

install(HttpRequestRetry) {
retryOnServerErrors(maxRetries = 3)
retryOnException(maxRetries = 3, retryOnTimeout = true)
exponentialDelay()
}

engine {
config {
retryOnConnectionFailure(true)
connectionPool(maxIdleConnections = 5, keepAliveDuration = 5L, timeUnit = TimeUnit.MINUTES)
protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
}
}

install(ContentEncoding) {
brotli(1.0F)
gzip(0.9F)
deflate(0.8F)
}

if (proxy != null) {
engine {
engine {
if (proxy != null) {
proxy = this@InnerTube.proxy
}
}
}

defaultRequest {
url("https://music.youtube.com/youtubei/v1/")
}
}

private suspend inline fun <T> safeApiCall(crossinline apiCall: suspend () -> T): Result<T> {
return try {
Result.success(apiCall())
} catch (e: SocketException) {
Result.failure(e)
} catch (e: IOException) {
Result.failure(e)
} catch (e: Exception) {
Result.failure(e)
}
}

private class ConnectionManager {
private var failureCount = 0
private val maxFailures = 3
private val backoffDelays = listOf(1000L, 2000L, 4000L)

suspend fun <T> executeWithRetry(block: suspend () -> T): T {
while (true) {
try {
return block().also { failureCount = 0 }
} catch (e: SocketException) {
failureCount++
if (failureCount >= maxFailures) throw e
delay(backoffDelays[failureCount - 1])
} catch (e: IOException) {
failureCount++
if (failureCount >= maxFailures) throw e
delay(backoffDelays[failureCount - 1])
}
}
}
}

private val connectionManager = ConnectionManager()

private fun HttpRequestBuilder.ytClient(client: YouTubeClient, setLogin: Boolean = false) {
contentType(ContentType.Application.Json)
Expand All @@ -85,6 +144,9 @@ class InnerTube {
append("X-YouTube-Client-Name", client.clientName)
append("X-YouTube-Client-Version", client.clientVersion)
append("x-origin", "https://music.youtube.com")
append("Connection", "keep-alive")
append("Accept-Encoding", "gzip, deflate, br")

if (client.referer != null) {
append("Referer", client.referer)
}
Expand All @@ -108,40 +170,44 @@ class InnerTube {
query: String? = null,
params: String? = null,
continuation: String? = null,
) = httpClient.post("search") {
ytClient(client, setLogin = useLoginForBrowse)
setBody(
SearchBody(
context = client.toContext(locale, visitorData),
query = query,
params = params
) = safeApiCall {
httpClient.post("search") {
ytClient(client, setLogin = useLoginForBrowse)
setBody(
SearchBody(
context = client.toContext(locale, visitorData),
query = query,
params = params
)
)
)
parameter("continuation", continuation)
parameter("ctoken", continuation)
parameter("continuation", continuation)
parameter("ctoken", continuation)
}
}

suspend fun player(
client: YouTubeClient,
videoId: String,
playlistId: String?,
) = httpClient.post("player") {
ytClient(client, setLogin = true)
setBody(
PlayerBody(
context = client.toContext(locale, visitorData).let {
if (client == YouTubeClient.TVHTML5) {
it.copy(
thirdParty = Context.ThirdParty(
embedUrl = "https://www.youtube.com/watch?v=${videoId}"
) = connectionManager.executeWithRetry {
httpClient.post("player") {
ytClient(client, setLogin = true)
setBody(
PlayerBody(
context = client.toContext(locale, visitorData).let {
if (client == YouTubeClient.TVHTML5) {
it.copy(
thirdParty = Context.ThirdParty(
embedUrl = "https://www.youtube.com/watch?v=${videoId}"
)
)
)
} else it
},
videoId = videoId,
playlistId = playlistId
} else it
},
videoId = videoId,
playlistId = playlistId
)
)
)
}
}

suspend fun registerPlayback(url: String, cpn: String, playlistId: String?)
Expand Down

0 comments on commit 7bc66cf

Please sign in to comment.