From 9e415bbe23e2e6a393846e301bfe70c5aef2856b Mon Sep 17 00:00:00 2001 From: Bnyro Date: Wed, 6 Dec 2023 14:39:50 +0100 Subject: [PATCH] fix: improve download speeds and anonymity --- .../github/libretube/api/obj/PipedStream.kt | 3 +-- .../github/libretube/helpers/ProxyHelper.kt | 6 ++++-- .../libretube/services/DownloadService.kt | 20 +++++++++++++------ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/github/libretube/api/obj/PipedStream.kt b/app/src/main/java/com/github/libretube/api/obj/PipedStream.kt index ab81a6c63..e4e1fa65d 100644 --- a/app/src/main/java/com/github/libretube/api/obj/PipedStream.kt +++ b/app/src/main/java/com/github/libretube/api/obj/PipedStream.kt @@ -2,7 +2,6 @@ package com.github.libretube.api.obj import com.github.libretube.db.obj.DownloadItem import com.github.libretube.enums.FileType -import com.github.libretube.helpers.ProxyHelper import kotlin.io.path.Path import kotlinx.serialization.Serializable @@ -38,7 +37,7 @@ data class PipedStream( videoId = videoId, fileName = getQualityString(fileName), path = Path(""), - url = url?.let { ProxyHelper.unwrapUrl(it) }, + url = url, format = format, quality = quality, language = audioTrackLocale, diff --git a/app/src/main/java/com/github/libretube/helpers/ProxyHelper.kt b/app/src/main/java/com/github/libretube/helpers/ProxyHelper.kt index 8cd31ed95..b8df40b0c 100644 --- a/app/src/main/java/com/github/libretube/helpers/ProxyHelper.kt +++ b/app/src/main/java/com/github/libretube/helpers/ProxyHelper.kt @@ -60,15 +60,17 @@ object ProxyHelper { * Convert a proxied Piped url to a YouTube url that's not proxied */ fun unwrapUrl(url: String, unwrap: Boolean = true) = url.toHttpUrlOrNull() - ?.takeIf { unwrap }?.let { + ?.takeIf { unwrap } + ?.let { val host = it.queryParameter("host") // if there's no host parameter specified, there's no way to unwrap the URL // and the proxied one must be used. That's the case if using LBRY. if (host.isNullOrEmpty()) return@let url + it.newBuilder() .host(host) .removeAllQueryParameters("host") - .removeAllQueryParameters("ump") + // .removeAllQueryParameters("ump") .removeAllQueryParameters("qhash") .build() .toString() diff --git a/app/src/main/java/com/github/libretube/services/DownloadService.kt b/app/src/main/java/com/github/libretube/services/DownloadService.kt index 65ed8f31c..2d7bc05c2 100644 --- a/app/src/main/java/com/github/libretube/services/DownloadService.kt +++ b/app/src/main/java/com/github/libretube/services/DownloadService.kt @@ -32,6 +32,7 @@ import com.github.libretube.extensions.toastFromMainThread import com.github.libretube.helpers.DownloadHelper import com.github.libretube.helpers.DownloadHelper.getNotificationId import com.github.libretube.helpers.ImageHelper +import com.github.libretube.helpers.ProxyHelper import com.github.libretube.obj.DownloadStatus import com.github.libretube.parcelable.DownloadData import com.github.libretube.receivers.NotificationReceiver @@ -162,9 +163,9 @@ class DownloadService : LifecycleService() { downloadQueue[item.id] = true val notificationBuilder = getNotificationBuilder(item) setResumeNotification(notificationBuilder, item) - val path = item.path - var totalRead = path.fileSize() - val url = URL(item.url ?: return) + + var totalRead = item.path.fileSize() + val url = URL(ProxyHelper.unwrapStreamUrl(item.url ?: return)) // only fetch the content length if it's not been returned by the API if (item.downloadSize <= 0L) { @@ -179,7 +180,7 @@ class DownloadService : LifecycleService() { val con = startConnection(item, url, totalRead, item.downloadSize) ?: return @Suppress("NewApi") // The StandardOpenOption enum is desugared. - val sink = path.sink(StandardOpenOption.APPEND).buffer() + val sink = item.path.sink(StandardOpenOption.APPEND).buffer() val sourceByte = con.inputStream.source() var lastTime = System.currentTimeMillis() / 1000 @@ -269,7 +270,9 @@ class DownloadService : LifecycleService() { val limit = if (readLimit == null) { "" } else { - min(readLimit, alreadyRead + BYTES_PER_REQUEST) + // generate a random byte distance to make it more difficult to fingerprint + val nextBytesToReadSize = (BYTES_PER_REQUEST_MIN..BYTES_PER_REQUEST_MAX).random() + min(readLimit, alreadyRead + nextBytesToReadSize) } con.setRequestProperty("Range", "bytes=$alreadyRead-$limit") con.connectTimeout = DownloadHelper.DEFAULT_TIMEOUT @@ -536,7 +539,12 @@ class DownloadService : LifecycleService() { "com.github.libretube.services.DownloadService.ACTION_SERVICE_STARTED" const val ACTION_SERVICE_STOPPED = "com.github.libretube.services.DownloadService.ACTION_SERVICE_STOPPED" + + // any values that are not in that range are strictly rate limited by YT or are very slow due + // to the amount of requests that's being made + private const val BYTES_PER_REQUEST_MIN = 500_000L + private const val BYTES_PER_REQUEST_MAX = 3_000_000L + var IS_DOWNLOAD_RUNNING = false - private const val BYTES_PER_REQUEST = 10000000L } }