use std::{
thread::{self},
time::Duration,
};
use anyhow::{Context, Result};
use json::JsonValue;
use crate::{declare, request};
use super::Downloader;
impl Downloader {
pub async fn get_posts_from_page(&mut self, url: &str) -> Result<Vec<String>> {
let mut posts = Vec::new();
let mut json_parse_retry = self.retry;
let mut http_retry = self.retry;
loop {
let client = request::new()?;
let res = match client.get(url).send().await {
Ok(v) => v,
Err(_) => {
if !http_retry == 0 {
http_retry -= 1;
thread::sleep(Duration::from_secs(declare::ERROR_REQUEST_DELAY_SEC));
continue;
}
return Err(anyhow::anyhow!(
"Failed http request in `get_posts_from_page`"
));
}
};
let text = res
.text()
.await
.context("Cannot convert response body to text [res.text()]")?;
let obj = match json::parse(&text).context("Cannot parse JSON from response body") {
Ok(v) => v,
Err(_) => {
if json_parse_retry > 0 {
json_parse_retry -= 1;
thread::sleep(Duration::from_secs(declare::TOO_MANY_REQUESTS_DELAY_SEC));
continue;
} else {
break;
}
}
};
if self.creator_name.lock().await.is_none()
&& let Some(creator_name) = obj["user"]["name"].as_str()
{
*self.creator_name.lock().await = Some(creator_name.to_string());
}
let mut is_skip = false;
if let JsonValue::Array(attachments) = &obj["attachments"] {
for atta in attachments {
if atta["server"].is_null() || atta["path"].is_null() {
is_skip = true;
} else {
posts.push(format!("{}/data{}", atta["server"], atta["path"]));
}
}
}
if let JsonValue::Array(previews) = &obj["previews"] {
for preview in previews {
if preview["server"].is_null() || preview["path"].is_null() {
if is_skip {
self.info.lock().await.add_skip_file(url.to_string());
}
} else {
posts.push(format!("{}/data{}", preview["server"], preview["path"]));
}
}
}
break;
}
Ok(posts)
}
}