mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-24 23:42:18 +00:00
feat(pixiv): fall back to the large variant when a page has no original
A page whose `original` the API left out (the restricted ones) was dropped whole by the multi-page branch's filter_map — a missing picture in the album while `large` sat right there — and the single-page branch produced no media at all when both places it looks for an original were empty. Both now share one builder that falls back to `large` (the same picture, lower resolution). The two tests that pinned the old behaviour now pin the fallback.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use super::model::IllustrationModel;
|
||||
use super::model::{IllustrationModel, ImageUrlsModel};
|
||||
use crate::media::Media;
|
||||
use crate::site::{FetchError, Fetched, PixivError, Site, SiteFuture};
|
||||
use html_escape::{encode_double_quoted_attribute, encode_text};
|
||||
@@ -230,27 +230,23 @@ impl Illustration {
|
||||
// ffmpeg and appends it as a Video item (api.rs). This fallback
|
||||
// keeps media empty when encoding fails or ffmpeg is missing.
|
||||
} else if model.page_count > 1 {
|
||||
// Every page is kept: `original` is the only URL the API may leave
|
||||
// out (typically the restricted ones), and a page without it used
|
||||
// to be dropped whole — losing a page of the work while `large`
|
||||
// sat right there.
|
||||
media.extend(model.meta_pages.iter().filter_map(|page| {
|
||||
page.image_urls
|
||||
.original
|
||||
.clone()
|
||||
.map(|original| Media::Illustration {
|
||||
url: original,
|
||||
thumbnail_url: Some(page.image_urls.medium.clone()),
|
||||
fallback_url: Some(page.image_urls.large.clone()),
|
||||
})
|
||||
page_illustration(page.image_urls.original.clone(), &page.image_urls)
|
||||
}));
|
||||
} else if let Some(original) = model
|
||||
.meta_single_page
|
||||
.original_image_url
|
||||
.clone()
|
||||
.or(model.image_urls.original.clone())
|
||||
{
|
||||
media.push(Media::Illustration {
|
||||
url: original,
|
||||
thumbnail_url: Some(model.image_urls.medium.clone()),
|
||||
fallback_url: Some(model.image_urls.large.clone()),
|
||||
});
|
||||
} else {
|
||||
// The single page names its original in one of two places, and
|
||||
// `large` is the last resort.
|
||||
let urls = &model.image_urls;
|
||||
let original = model
|
||||
.meta_single_page
|
||||
.original_image_url
|
||||
.clone()
|
||||
.or_else(|| urls.original.clone());
|
||||
media.extend(page_illustration(original, urls));
|
||||
}
|
||||
let nsfw = model.sanity_level > 5;
|
||||
Self {
|
||||
@@ -267,6 +263,21 @@ impl Illustration {
|
||||
}
|
||||
}
|
||||
|
||||
/// One artwork page as a media item: `original` when the API sent one, else the
|
||||
/// `large` variant (the same picture at a lower resolution), with `medium` as
|
||||
/// the thumbnail. `None` when the API gave no usable URL at all.
|
||||
fn page_illustration(original: Option<String>, urls: &ImageUrlsModel) -> Option<Media> {
|
||||
let url = original.unwrap_or_else(|| urls.large.clone());
|
||||
if url.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(Media::Illustration {
|
||||
url,
|
||||
thumbnail_url: Some(urls.medium.clone()),
|
||||
fallback_url: Some(urls.large.clone()),
|
||||
})
|
||||
}
|
||||
|
||||
impl From<Illustration> for Fetched {
|
||||
fn from(illustration: Illustration) -> Self {
|
||||
let url = illustration.url();
|
||||
@@ -540,14 +551,19 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_page_without_any_original_is_empty() {
|
||||
fn single_page_without_any_original_falls_back_to_large() {
|
||||
let v = illust_json("illust", 1, None, None, vec![], 0);
|
||||
let fetched: Fetched = parse(v).into();
|
||||
assert!(fetched.media.is_empty());
|
||||
// Neither `meta_single_page.original_image_url` nor `image_urls.
|
||||
// original` is set: the work is still deliverable as `large`.
|
||||
match fetched.media.as_slice() {
|
||||
[Media::Illustration { url, .. }] => assert_eq!(url, "large.jpg"),
|
||||
other => panic!("expected the large variant, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_page_skips_pages_without_original() {
|
||||
fn multi_page_keeps_pages_without_original() {
|
||||
let v = illust_json(
|
||||
"illust",
|
||||
2,
|
||||
@@ -560,17 +576,27 @@ mod tests {
|
||||
0,
|
||||
);
|
||||
let fetched: Fetched = parse(v).into();
|
||||
assert_eq!(fetched.media.len(), 1);
|
||||
// Both pages arrive: the restricted one (no `original`) sends its
|
||||
// `large` instead of vanishing — a dropped page is a missing picture.
|
||||
let urls: Vec<&str> = fetched
|
||||
.media
|
||||
.iter()
|
||||
.map(|media| match media {
|
||||
Media::Illustration { url, .. } => url.as_str(),
|
||||
other => panic!("expected Illustration, got {other:?}"),
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(urls, vec!["l1.jpg", "https://i.pximg.net/p2.jpg"]);
|
||||
match &fetched.media[0] {
|
||||
Media::Illustration {
|
||||
url,
|
||||
thumbnail_url,
|
||||
fallback_url,
|
||||
..
|
||||
} => {
|
||||
assert_eq!(url, "https://i.pximg.net/p2.jpg");
|
||||
assert_eq!(thumbnail_url.as_deref(), Some("m2.jpg"));
|
||||
assert_eq!(fallback_url.as_deref(), Some("l2.jpg"));
|
||||
assert_eq!(thumbnail_url.as_deref(), Some("m1.jpg"));
|
||||
// `large` is the item itself here, so it is not also a
|
||||
// smaller variant of itself.
|
||||
assert_eq!(fallback_url.as_deref(), Some("l1.jpg"));
|
||||
}
|
||||
other => panic!("expected Illustration, got {other:?}"),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user