use serde::Deserialize;
use super::classify::PublisherModel;
const PAGE_SIZE: &str = "300";
const MAX_PAGES: usize = 20;
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ListPage {
#[serde(default)]
publisher_models: Vec<PublisherModel>,
#[serde(default)]
next_page_token: Option<String>,
}
pub async fn list_publisher_models(
http: &reqwest::Client,
host: &str,
token: &str,
publisher: &str,
) -> Result<Vec<PublisherModel>, String> {
let url = format!(
"{}/v1beta1/publishers/{publisher}/models",
host.trim_end_matches('/')
);
let mut models = Vec::new();
let mut page_token: Option<String> = None;
for _ in 0..MAX_PAGES {
let mut request = http
.get(&url)
.bearer_auth(token)
.query(&[("pageSize", PAGE_SIZE)]);
if let Some(token) = page_token.as_deref() {
request = request.query(&[("pageToken", token)]);
}
let response = request
.send()
.await
.map_err(|e| format!("listing request failed: {e}"))?;
let status = response.status();
let body = response
.text()
.await
.map_err(|e| format!("listing returned an unreadable body: {e}"))?;
if !status.is_success() {
return Err(format!("listing returned {status}: {}", body.trim()));
}
let page: ListPage = serde_json::from_str(&body)
.map_err(|e| format!("listing returned an unreadable body: {e}"))?;
models.extend(page.publisher_models);
match page.next_page_token {
Some(next) if !next.is_empty() => page_token = Some(next),
_ => return Ok(models),
}
}
Err(format!(
"listing did not terminate after {MAX_PAGES} pages; {} models read are discarded",
models.len()
))
}
pub async fn list_all(
http: &reqwest::Client,
host: &str,
token: &str,
provider: &str,
publishers: &[String],
) -> (Vec<PublisherModel>, Vec<String>) {
let mut models = Vec::new();
let mut failures = Vec::new();
for publisher in publishers {
match list_publisher_models(http, host, token, publisher).await {
Ok(page) => models.extend(page),
Err(reason) => failures.push(format!("{provider}/{publisher}: {reason}")),
}
}
(models, failures)
}