Rest API to add downloads (#331)

* feat: rest api to add silent downloads
This commit is contained in:
Talha Ahmed 2025-01-05 11:33:39 +05:00 committed by GitHub
parent b23cfcc672
commit 3f7824dab8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 185 additions and 3 deletions

View File

@ -125,6 +125,7 @@ follow these steps.
1. Clone the project
2. Install the [JBR](https://github.com/JetBrains/JetBrainsRuntime/releases)
1. If you extract it to your home directory and don't want to modify global `JAVA_HOME` environment variable you can set `JAVA_HOME` to the extracted directory e.g. `export JAVA_HOME=~/jbrsdk_jcef-21.0.4-linux-x64-b620.4` for linux or `$env:JAVA_HOME="C:\path\to\jbr"` on Windows
3. cd into the project, open your terminal and execute the following commands
4. select which way you want to compile the app
<details>

100
REST-API.yml Normal file
View File

@ -0,0 +1,100 @@
openapi: 3.0.0
info:
title: Download Service API
version: 1.0.0
description: API for managing download tasks and queues.
servers:
- url: http://localhost:15151
description: Default server running on port 15151
paths:
/add:
post:
summary: Add a new download source
requestBody:
description: Data for adding a download source
content:
application/json:
schema:
type: object
properties:
link:
type: string
description: The link to the download source
headers:
type: object
additionalProperties:
type: string
description: Optional headers for the request
downloadPage:
type: string
description: Optional download page URL
responses:
"200":
description: Successfully added the download
content:
plain/text:
schema:
type: string
description: OK on success
/queues:
get:
summary: Get list of download queues
responses:
"200":
description: List of download queues
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: integer
description: The unique ID of the queue
name:
type: string
description: The name of the queue
/start-headless-download:
post:
summary: Add a new download task
requestBody:
description: Data for adding a download task
content:
application/json:
schema:
type: object
properties:
downloadSource:
type: object
properties:
link:
type: string
description: The link to the download source
headers:
type: object
additionalProperties:
type: string
description: Optional headers for the request
downloadPage:
type: string
description: Optional download page URL
folder:
type: string
description: Optional folder to save the download (Unix style path)
name:
type: string
description: Optional name for the download task
queueId:
type: integer
description: Optional queue ID to associate the task with
responses:
"200":
description: Successfully added the download task
content:
plain/text:
schema:
type: string
description: OK on success

View File

@ -1,14 +1,24 @@
package com.abdownloadmanager.desktop.integration
import com.abdownloadmanager.integration.IntegrationHandler
import com.abdownloadmanager.desktop.AppComponent
import ir.amirab.downloader.downloaditem.DownloadCredentials
import com.abdownloadmanager.desktop.repository.AppRepository
import com.abdownloadmanager.utils.DownloadSystem
import com.abdownloadmanager.integration.IntegrationHandler
import com.abdownloadmanager.integration.NewDownloadInfoFromIntegration
import com.abdownloadmanager.integration.NewDownloadTask
import com.abdownloadmanager.integration.ApiQueueModel
import ir.amirab.downloader.downloaditem.DownloadCredentials
import ir.amirab.downloader.downloaditem.DownloadItem
import ir.amirab.downloader.queue.QueueManager
import ir.amirab.downloader.utils.OnDuplicateStrategy
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class IntegrationHandlerImp: IntegrationHandler,KoinComponent{
val appComponent by inject<AppComponent>()
val downloadSystem by inject<DownloadSystem>()
val queueManager by inject<QueueManager>()
val appSettings by inject<AppRepository>()
override suspend fun addDownload(list: List<NewDownloadInfoFromIntegration>) {
appComponent.externalCredentialComingIntoApp(list.map {
DownloadCredentials(
@ -18,4 +28,34 @@ class IntegrationHandlerImp: IntegrationHandler,KoinComponent{
)
})
}
}
override fun listQueues(): List<ApiQueueModel> {
return queueManager.getAll().map { downloadQueue ->
val queueModel = downloadQueue.getQueueModel()
ApiQueueModel(id = queueModel.id, name = queueModel.name)
}
}
override suspend fun addDownloadTask(task: NewDownloadTask) {
val downloadItem =
DownloadItem(
link = task.downloadSource.link,
headers = task.downloadSource.headers,
downloadPage = task.downloadSource.downloadPage,
folder = task.folder ?: appSettings.saveLocation.value,
id = -1,
name = task.name ?: task.downloadSource.link.substringAfterLast("/"),
)
val id =
downloadSystem.addDownload(
downloadItem = downloadItem,
onDuplicateStrategy = OnDuplicateStrategy.default(),
queueId = task.queueId,
categoryId = null
)
if (task.queueId != null) {
val queue = queueManager.getQueue(task.queueId!!)
queue.start()
} else {
downloadSystem.manualResume(id)
}
}
}

View File

@ -0,0 +1,9 @@
package com.abdownloadmanager.integration
import kotlinx.serialization.Serializable
@Serializable
data class ApiQueueModel(
val id: Long,
val name: String,
)

View File

@ -4,6 +4,7 @@ import com.abdownloadmanager.integration.http4k.MyHttp4KServer
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.builtins.ListSerializer
//val scope = CoroutineScope(SupervisorJob())
@ -114,6 +115,24 @@ class Integration(
}
MyResponse.Text("OK")
}
get("/queues") {
runBlocking {
val queues = integrationHandler.listQueues()
val jsonResponse = customJson.encodeToString(ListSerializer(ApiQueueModel.serializer()), queues)
MyResponse.Text(jsonResponse)
}
}
post("/start-headless-download") {
runBlocking {
val itemsToAdd = kotlin.runCatching {
val message = it.getBody().orEmpty()
customJson.decodeFromString<NewDownloadTask>(message)
}
itemsToAdd.onFailure { it.printStackTrace() }
integrationHandler.addDownloadTask(itemsToAdd.getOrThrow())
}
MyResponse.Text("OK")
}
post("/ping") {
MyResponse.Text("pong")
}

View File

@ -4,4 +4,6 @@ interface IntegrationHandler{
suspend fun addDownload(
list: List<NewDownloadInfoFromIntegration>
)
fun listQueues(): List<ApiQueueModel>
suspend fun addDownloadTask(task: NewDownloadTask)
}

View File

@ -0,0 +1,11 @@
package com.abdownloadmanager.integration
import kotlinx.serialization.Serializable
@Serializable
data class NewDownloadTask(
val downloadSource: NewDownloadInfoFromIntegration,
var folder: String? = null,
var name: String? = null,
var queueId: Long? = null,
)