commit c57fbdb6448cecd0ba570b91627a1d5e2ee5aa88
parent 0a395627efc5740e9d99c1c09d230419d0dfafff
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date: Tue, 1 Jul 2025 11:27:09 +0200
feat(common): bolt resolver api
Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>
Diffstat:
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
@@ -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<String, String>()
-
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()
-
- if (urlCache.containsKey(requestUrl)) {
- val cachedUrl = urlCache[requestUrl]!!
- return@addInterceptor chain.proceed(request.newBuilder().url(cachedUrl).build())
- }
+ .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 ->