Follow Picture Agent gallery data URL
This commit is contained in:
@@ -14,12 +14,15 @@ use axum::{
|
||||
routing::{get, post},
|
||||
};
|
||||
use reqwest::Client;
|
||||
use reqwest::Url;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{Value, json};
|
||||
use std::time::Duration;
|
||||
|
||||
const TEMPLATE_GALLERY_URL: &str =
|
||||
"https://weiyyin.github.io/linux-do-gpt-image/linux_do_2036927_prompts_images.filtered.json";
|
||||
const TEMPLATE_GALLERY_PAGE_URL: &str =
|
||||
"https://weiyyin.github.io/linux-do-gpt-image/prompt_gallery.html";
|
||||
const TEMPLATE_GALLERY_FALLBACK_DATA_URL: &str =
|
||||
"https://weiyyin.github.io/linux-do-gpt-image/linux_do_2036927_prompts_images.with_tags.json";
|
||||
const TASK_TYPE_PICTURE_GENERATION: &str = "picture-agent-generation";
|
||||
const TEMPLATE_GALLERY_TIMEOUT_SECS: u64 = 30;
|
||||
const PICTURE_GENERATION_TIMEOUT_SECS: u64 = 300;
|
||||
@@ -285,6 +288,23 @@ mod tests {
|
||||
assert!(!is_picture_model_pattern("deepseek-chat"));
|
||||
assert!(!is_picture_model_pattern("qwen-plus"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_gallery_data_url_from_page_script() {
|
||||
let html = r#"
|
||||
<script>
|
||||
const DATA_URL = "./linux_do_2036927_prompts_images.with_tags.json";
|
||||
</script>
|
||||
"#;
|
||||
assert_eq!(
|
||||
extract_gallery_data_url(html).as_deref(),
|
||||
Some("./linux_do_2036927_prompts_images.with_tags.json")
|
||||
);
|
||||
assert_eq!(
|
||||
absolute_gallery_url("./linux_do_2036927_prompts_images.with_tags.json").unwrap(),
|
||||
"https://weiyyin.github.io/linux-do-gpt-image/linux_do_2036927_prompts_images.with_tags.json"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn prompt_title(prompt: &str, post_number: Option<i64>) -> String {
|
||||
@@ -364,7 +384,7 @@ async fn templates_handler(
|
||||
|
||||
Ok(Json(json!({
|
||||
"success": true,
|
||||
"sourceUrl": "https://weiyyin.github.io/linux-do-gpt-image/prompt_gallery.html",
|
||||
"sourceUrl": TEMPLATE_GALLERY_PAGE_URL,
|
||||
"fallback": remote_status.get("ok").and_then(Value::as_bool) != Some(true),
|
||||
"remote": remote_status,
|
||||
"templates": templates,
|
||||
@@ -378,13 +398,15 @@ async fn fetch_remote_gallery_templates(
|
||||
if limit == 0 {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let items = crate::template_http::client(config, TEMPLATE_GALLERY_TIMEOUT_SECS)
|
||||
.get(TEMPLATE_GALLERY_URL)
|
||||
let client = crate::template_http::client(config, TEMPLATE_GALLERY_TIMEOUT_SECS);
|
||||
let data_url = resolve_gallery_data_url(&client).await?;
|
||||
let items = client
|
||||
.get(&data_url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("failed to fetch templates: {err}"))?
|
||||
.map_err(|err| format!("failed to fetch templates from {data_url}: {err}"))?
|
||||
.error_for_status()
|
||||
.map_err(|err| format!("template gallery returned {err}"))?
|
||||
.map_err(|err| format!("template gallery data returned {err}"))?
|
||||
.json::<Vec<GalleryItem>>()
|
||||
.await
|
||||
.map_err(|err| format!("failed to parse templates: {err}"))?;
|
||||
@@ -427,6 +449,45 @@ async fn fetch_remote_gallery_templates(
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn resolve_gallery_data_url(client: &Client) -> Result<String, String> {
|
||||
let html = client
|
||||
.get(TEMPLATE_GALLERY_PAGE_URL)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| format!("failed to fetch template gallery page: {err}"))?
|
||||
.error_for_status()
|
||||
.map_err(|err| format!("template gallery page returned {err}"))?
|
||||
.text()
|
||||
.await
|
||||
.map_err(|err| format!("failed to read template gallery page: {err}"))?;
|
||||
|
||||
let data_url = extract_gallery_data_url(&html)
|
||||
.ok_or_else(|| "template gallery page did not expose DATA_URL".to_string())?;
|
||||
absolute_gallery_url(&data_url)
|
||||
}
|
||||
|
||||
fn extract_gallery_data_url(html: &str) -> Option<String> {
|
||||
let regex = regex::Regex::new(r#"(?m)\bDATA_URL\s*=\s*["']([^"']+)["']"#).ok()?;
|
||||
regex
|
||||
.captures(html)
|
||||
.and_then(|captures| captures.get(1))
|
||||
.map(|match_| match_.as_str().trim().to_string())
|
||||
.filter(|value| !value.is_empty())
|
||||
}
|
||||
|
||||
fn absolute_gallery_url(value: &str) -> Result<String, String> {
|
||||
if value.starts_with("http://") || value.starts_with("https://") {
|
||||
return Ok(value.to_string());
|
||||
}
|
||||
|
||||
let base = Url::parse(TEMPLATE_GALLERY_PAGE_URL)
|
||||
.map_err(|err| format!("invalid template gallery page URL: {err}"))?;
|
||||
base.join(value)
|
||||
.map(|url| url.to_string())
|
||||
.or_else(|_| Url::parse(TEMPLATE_GALLERY_FALLBACK_DATA_URL).map(|url| url.to_string()))
|
||||
.map_err(|err| format!("invalid template gallery data URL: {err}"))
|
||||
}
|
||||
|
||||
fn builtin_picture_templates(limit: usize) -> Vec<Value> {
|
||||
[
|
||||
(
|
||||
|
||||
Reference in New Issue
Block a user