Skip to content

Commit 680adee

Browse files
committed
feat: add get_download RPC method and OutsideProvider registration
- Add register_provider and get_download JSON-RPC server methods - Add DownloadItemData, RpcRegisterProviderRequest, RpcDownloadInfoRequest structs - Implement get_download on OutsideProvider (HTTP JSON-RPC callback to Kotlin) - Add GetDownload variant to FunctionType enum with default impl on BaseProvider - Add get_download routing in provider.rs and api.rs - Make data module public for cross-module imports
1 parent 1225359 commit 680adee

11 files changed

Lines changed: 163 additions & 2 deletions

File tree

src/rpc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
pub mod client;
2-
mod data;
2+
pub mod data;
33
pub mod server;

src/rpc/client.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,20 @@ impl Client {
5858
};
5959
self.client.request("get_releases", data).await
6060
}
61+
62+
pub async fn get_download(
63+
&self,
64+
hub_uuid: &str,
65+
app_data: BTreeMap<&str, &str>,
66+
hub_data: BTreeMap<&str, &str>,
67+
asset_index: &[i32],
68+
) -> Result<Vec<DownloadItemData>, Error> {
69+
let data = RpcDownloadInfoRequest {
70+
hub_uuid,
71+
app_data,
72+
hub_data,
73+
asset_index: asset_index.to_vec(),
74+
};
75+
self.client.request("get_download", data).await
76+
}
6177
}

src/rpc/data.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::downloader::{DownloadState, TaskInfo};
22
use jsonrpsee::core::traits::ToRpcParams;
33
use serde::{Deserialize, Serialize};
44
use serde_json::value::to_raw_value;
5-
use std::collections::BTreeMap;
5+
use std::collections::{BTreeMap, HashMap};
66

77
#[derive(Serialize, Deserialize, Debug)]
88
pub struct RpcInitRequest<'a> {
@@ -41,6 +41,49 @@ impl ToRpcParams for RpcCloudConfigRequest<'_> {
4141
}
4242
}
4343

44+
// ============================================================================
45+
// Provider Registration RPC Data Structures
46+
// ============================================================================
47+
48+
/// Request to register an external provider
49+
#[derive(Serialize, Deserialize, Debug)]
50+
pub struct RpcRegisterProviderRequest<'a> {
51+
pub hub_uuid: &'a str,
52+
pub url: &'a str,
53+
}
54+
55+
impl ToRpcParams for RpcRegisterProviderRequest<'_> {
56+
fn to_rpc_params(self) -> Result<Option<Box<serde_json::value::RawValue>>, serde_json::Error> {
57+
to_raw_value(&self).map(Some)
58+
}
59+
}
60+
61+
/// Request to get download info for an app
62+
#[derive(Serialize, Deserialize, Debug)]
63+
pub struct RpcDownloadInfoRequest<'a> {
64+
pub hub_uuid: &'a str,
65+
pub app_data: BTreeMap<&'a str, &'a str>,
66+
pub hub_data: BTreeMap<&'a str, &'a str>,
67+
pub asset_index: Vec<i32>,
68+
}
69+
70+
impl ToRpcParams for RpcDownloadInfoRequest<'_> {
71+
fn to_rpc_params(self) -> Result<Option<Box<serde_json::value::RawValue>>, serde_json::Error> {
72+
to_raw_value(&self).map(Some)
73+
}
74+
}
75+
76+
/// Download item data returned by get_download
77+
#[derive(Debug, Clone, Serialize, Deserialize)]
78+
pub struct DownloadItemData {
79+
pub name: Option<String>,
80+
pub url: String,
81+
#[serde(default)]
82+
pub headers: Option<HashMap<String, String>>,
83+
#[serde(default)]
84+
pub cookies: Option<HashMap<String, String>>,
85+
}
86+
4487
// ============================================================================
4588
// Downloader RPC Data Structures
4689
// ============================================================================

src/rpc/server.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,44 @@ pub async fn run_server(
128128
}
129129
})?;
130130

131+
// register_provider: Dynamically register an external provider (e.g., Kotlin hub via HTTP JSON-RPC)
132+
module.register_async_method(
133+
"register_provider",
134+
|params, _context, _extensions| async move {
135+
let request = params.parse::<RpcRegisterProviderRequest>()?;
136+
api::add_outside_provider(request.hub_uuid, request.url);
137+
Ok::<bool, ErrorObjectOwned>(true)
138+
},
139+
)?;
140+
141+
// get_download: Get download info for an app's asset
142+
module.register_async_method("get_download", |params, _context, _extensions| async move {
143+
if let Ok(request) = params.parse::<RpcDownloadInfoRequest>() {
144+
if let Some(result) = api::get_download(
145+
request.hub_uuid,
146+
&request.app_data,
147+
&request.hub_data,
148+
&request.asset_index,
149+
)
150+
.await
151+
{
152+
Ok(result)
153+
} else {
154+
Err(ErrorObjectOwned::borrowed(
155+
ErrorCode::InvalidParams.code(),
156+
"Invalid params",
157+
None,
158+
))
159+
}
160+
} else {
161+
Err(ErrorObjectOwned::owned(
162+
ErrorCode::ParseError.code(),
163+
"Parse params error",
164+
Some(params.as_str().unwrap_or("None").to_string()),
165+
))
166+
}
167+
})?;
168+
131169
module.register_async_method(
132170
"get_cloud_config",
133171
|params, _context, _extensions| async move {

src/websdk/repo/api.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use super::provider::outside_rpc::OutsideProvider;
88
use super::provider::{self, add_provider};
99
use crate::cache::get_cache_manager;
1010
use crate::cache::manager::GroupType;
11+
use crate::rpc::data::DownloadItemData;
1112
use crate::utils::json::{bytes_to_json, json_to_bytes};
1213
use std::collections::HashMap;
1314

@@ -141,6 +142,21 @@ pub async fn get_releases<'a>(
141142
.unwrap_or(None)
142143
}
143144

145+
pub async fn get_download<'a>(
146+
uuid: &str,
147+
app_data: &AppDataMap<'a>,
148+
hub_data: &HubDataMap<'a>,
149+
asset_index: &[i32],
150+
) -> Option<Vec<DownloadItemData>> {
151+
let data_map = DataMap { app_data, hub_data };
152+
let fin = FIn::new(data_map, None);
153+
if let Some(fout) = provider::get_download(uuid, &fin, asset_index).await {
154+
fout.result.ok()
155+
} else {
156+
None
157+
}
158+
}
159+
144160
pub fn add_outside_provider(uuid: &str, url: &str) {
145161
let provider = OutsideProvider {
146162
uuid: uuid.to_string(),

src/websdk/repo/provider.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use self::github::GitHubProvider;
1515
use self::gitlab::GitLabProvider;
1616
use self::lsposed_repo::LsposedRepoProvider;
1717
use super::data::release::ReleaseData;
18+
use crate::rpc::data::DownloadItemData;
1819

1920
type ProviderMap = HashMap<&'static str, Arc<dyn BaseProvider + Send + Sync>>;
2021

@@ -84,3 +85,15 @@ pub async fn get_releases<'a>(uuid: &str, fin: &FIn<'a>) -> Option<FOut<Vec<Rele
8485
None
8586
}
8687
}
88+
89+
pub async fn get_download<'a>(
90+
uuid: &str,
91+
fin: &FIn<'a>,
92+
asset_index: &[i32],
93+
) -> Option<FOut<Vec<DownloadItemData>>> {
94+
if let Some(provider) = get_provider(uuid) {
95+
Some(provider.get_download(fin, asset_index).await)
96+
} else {
97+
None
98+
}
99+
}

src/websdk/repo/provider/base_provider.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::{
1010
};
1111

1212
use super::super::data::release::*;
13+
use crate::rpc::data::DownloadItemData;
1314

1415
pub type HubDataMap<'a> = BTreeMap<&'a str, &'a str>;
1516
pub type AppDataMap<'a> = BTreeMap<&'a str, &'a str>;
@@ -44,6 +45,7 @@ pub enum FunctionType {
4445
CheckAppAvailable,
4546
GetLatestRelease,
4647
GetReleases,
48+
GetDownload,
4749
}
4850

4951
pub struct FIn<'a> {
@@ -157,6 +159,12 @@ pub trait BaseProvider {
157159
}
158160

159161
async fn get_releases(&self, fin: &FIn) -> FOut<Vec<ReleaseData>>;
162+
163+
/// Get download info for an app's asset. Default returns empty (not supported).
164+
/// Only OutsideProvider (Kotlin hubs) needs to implement this.
165+
async fn get_download(&self, _fin: &FIn, _asset_index: &[i32]) -> FOut<Vec<DownloadItemData>> {
166+
FOut::new_empty()
167+
}
160168
}
161169

162170
pub trait BaseProviderExt: BaseProvider {
@@ -228,6 +236,7 @@ mod tests {
228236
FunctionType::CheckAppAvailable => "check_app_available",
229237
FunctionType::GetLatestRelease => "get_latest_release",
230238
FunctionType::GetReleases => "get_releases",
239+
FunctionType::GetDownload => "get_download",
231240
};
232241
let id_map = data_map.app_data;
233242
vec![format!(

src/websdk/repo/provider/fdroid.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl BaseProvider for FDroidProvider {
5151
url, id_map[ANDROID_APP_TYPE]
5252
)],
5353
FunctionType::GetLatestRelease | FunctionType::GetReleases => vec![api_url.to_string()],
54+
FunctionType::GetDownload => vec![],
5455
}
5556
}
5657

src/websdk/repo/provider/github.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl BaseProvider for GitHubProvider {
5959
"{}/repos/{}/{}/releases",
6060
GITHUB_API_URL, id_map["owner"], id_map["repo"]
6161
)],
62+
FunctionType::GetDownload => vec![],
6263
}
6364
}
6465

src/websdk/repo/provider/gitlab.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl BaseProvider for GitLabProvider {
104104
"{}/{}/{}/releases",
105105
GITLAB_API_URL, id_map["owner"], id_map["repo"]
106106
)],
107+
FunctionType::GetDownload => vec![],
107108
}
108109
}
109110

0 commit comments

Comments
 (0)