Add category-aware save_path and completed-by-category endpoint
- save_path in torrent info now includes the query category, matching what Radarr/Sonarr each request for their own category, so imports resolve to per-app subfolders via Remote Path Mapping. - New /internal/completed-by-category plain-text endpoint exposing the real stored hash->category mapping (not the request filter echo), for the amule incoming-folder mover to sort completed downloads by category without needing a JSON parser.
This commit is contained in:
@@ -73,6 +73,13 @@ fun Application.torrentApi(amuleClient: AmuleClient, categoryStore: CategoryStor
|
|||||||
val response = listOf(service.getFile(hash))
|
val response = listOf(service.getFile(hash))
|
||||||
call.respond(response)
|
call.respond(response)
|
||||||
}
|
}
|
||||||
|
get("/internal/completed-by-category") {
|
||||||
|
// Plain "category\tfileName" lines (no JSON) so the incoming-folder mover,
|
||||||
|
// running in a separate container with no JSON tooling, can parse it with
|
||||||
|
// plain shell text processing.
|
||||||
|
val lines = service.getCompletedByCategory().joinToString("\n") { (category, name) -> "$category\t$name" }
|
||||||
|
call.respondText(lines)
|
||||||
|
}
|
||||||
get("/api/v2/torrents/properties") {
|
get("/api/v2/torrents/properties") {
|
||||||
val hash = call.request.queryParameters["hash"]!!
|
val hash = call.request.queryParameters["hash"]!!
|
||||||
call.application.log.debug("Received get properties request with hash: {}", hash)
|
call.application.log.debug("Received get properties request with hash: {}", hash)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class TorrentService(
|
|||||||
name = dl.fileName!!,
|
name = dl.fileName!!,
|
||||||
size = dl.sizeFull!!,
|
size = dl.sizeFull!!,
|
||||||
total_size = dl.sizeFull!!,
|
total_size = dl.sizeFull!!,
|
||||||
save_path = finishedPath,
|
save_path = if (category != null) "$finishedPath/$category" else finishedPath,
|
||||||
downloaded = dl.sizeDone!!,
|
downloaded = dl.sizeDone!!,
|
||||||
progress = dl.sizeDone!!.toDouble() / dl.sizeFull!!.toDouble(),
|
progress = dl.sizeDone!!.toDouble() / dl.sizeFull!!.toDouble(),
|
||||||
priority = dl.downPrio.toInt(),
|
priority = dl.downPrio.toInt(),
|
||||||
@@ -66,7 +66,7 @@ class TorrentService(
|
|||||||
name = dl.fileName!!,
|
name = dl.fileName!!,
|
||||||
size = dl.sizeFull!!,
|
size = dl.sizeFull!!,
|
||||||
total_size = dl.sizeFull!!,
|
total_size = dl.sizeFull!!,
|
||||||
save_path = finishedPath,
|
save_path = if (category != null) "$finishedPath/$category" else finishedPath,
|
||||||
dlspeed = 0,
|
dlspeed = 0,
|
||||||
downloaded = dl.sizeFull!!,
|
downloaded = dl.sizeFull!!,
|
||||||
progress = 1.0,
|
progress = 1.0,
|
||||||
@@ -79,6 +79,27 @@ class TorrentService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns (category, fileName) pairs for fully-downloaded files that were added
|
||||||
|
* with a category. Used by the incoming-folder mover to know where to file
|
||||||
|
* each completed download, since [getTorrentInfo]'s reported category is just
|
||||||
|
* an echo of the caller's filter, not the file's real stored category.
|
||||||
|
*/
|
||||||
|
fun getCompletedByCategory(): List<Pair<String, String>> {
|
||||||
|
val downloadingFiles = amuleClient.getDownloadQueue().getOrThrow()
|
||||||
|
val sharedFiles = amuleClient.getSharedFiles().getOrThrow()
|
||||||
|
val downloadingFilesHashSet = downloadingFiles.map { it.fileHashHexString }.toHashSet()
|
||||||
|
|
||||||
|
val allFiles = sharedFiles.filterNot { downloadingFilesHashSet.contains(it.fileHashHexString) }
|
||||||
|
|
||||||
|
return allFiles.mapNotNull { dl ->
|
||||||
|
val hash = dl.fileHashHexString ?: return@mapNotNull null
|
||||||
|
val name = dl.fileName ?: return@mapNotNull null
|
||||||
|
val category = categoryStore.getCategory(hash) ?: return@mapNotNull null
|
||||||
|
category to name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun computeEta(speed: Long, sizeFull: Long, sizeDone: Long): Int {
|
private fun computeEta(speed: Long, sizeFull: Long, sizeDone: Long): Int {
|
||||||
val remainingBytes = sizeFull - sizeDone
|
val remainingBytes = sizeFull - sizeDone
|
||||||
return if (speed == 0L) 8640000 else Math.min((remainingBytes / speed).toInt(), 8640000)
|
return if (speed == 0L) 8640000 else Math.min((remainingBytes / speed).toInt(), 8640000)
|
||||||
|
|||||||
Reference in New Issue
Block a user