From c57fbdb6448cecd0ba570b91627a1d5e2ee5aa88 Mon Sep 17 00:00:00 2001 From: rhunk <101876869+rhunk@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:27:09 +0200 Subject: [PATCH] feat(common): bolt resolver api Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com> --- .../common/util/snap/RemoteMediaResolver.kt | 36 ++++++++----------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt b/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt index c1942878..b59b4f9f 100644 --- a/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt +++ b/common/src/main/kotlin/me/rhunk/snapenhance/common/util/snap/RemoteMediaResolver.kt @@ -2,6 +2,7 @@ package me.rhunk.snapenhance.common.util.snap import me.rhunk.snapenhance.common.Constants import me.rhunk.snapenhance.common.util.ktx.await +import me.rhunk.snapenhance.common.util.protobuf.ProtoReader import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request @@ -9,37 +10,28 @@ import java.io.InputStream import java.util.Base64 object RemoteMediaResolver { - private const val BOLT_HTTP_RESOLVER_URL = "https://web.snapchat.com/bolt-http" const val CF_ST_CDN_D = "https://cf-st.sc-cdn.net/d/" - private val urlCache = mutableMapOf() - val okHttpClient = OkHttpClient.Builder() .followRedirects(true) .retryOnConnectionFailure(true) .readTimeout(20, java.util.concurrent.TimeUnit.SECONDS) - .addInterceptor { chain -> - val request = chain.request() - val requestUrl = request.url.toString() + .build() - if (urlCache.containsKey(requestUrl)) { - val cachedUrl = urlCache[requestUrl]!! - return@addInterceptor chain.proceed(request.newBuilder().url(cachedUrl).build()) - } - - chain.proceed(request).apply { - val responseUrl = this.request.url.toString() - if (responseUrl.startsWith("https://cf-st.sc-cdn.net")) { - urlCache[requestUrl] = responseUrl - } - } + fun newResolveRequest(protoKey: ByteArray): Request { + val protoReader = ProtoReader(protoKey) + val url = if (!protoReader.containsPath(2, 3)) { + "https://bolt-gcdn.sc-cdn.net/br/" + protoReader.getString(2, 2) + } + else { + "https://gcp.api.snapchat.com/bolt-http/resolve?co=" + Base64.getUrlEncoder().encodeToString(protoKey) } - .build() - fun newResolveRequest(protoKey: ByteArray) = Request.Builder() - .url(BOLT_HTTP_RESOLVER_URL + "/resolve?co=" + Base64.getUrlEncoder().encodeToString(protoKey)) - .addHeader("User-Agent", Constants.USER_AGENT) - .build() + return Request.Builder() + .url(url) + .addHeader("User-Agent", Constants.USER_AGENT) + .build() + } suspend inline fun downloadMedia(url: String, decryptionCallback: (InputStream) -> InputStream = { it }, result: (InputStream, Long) -> Unit) { okHttpClient.newCall(Request.Builder().url(url).build()).await().use { response ->