mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-29 00:12:12 +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::media::Media;
|
||||||
use crate::site::{FetchError, Fetched, PixivError, Site, SiteFuture};
|
use crate::site::{FetchError, Fetched, PixivError, Site, SiteFuture};
|
||||||
use html_escape::{encode_double_quoted_attribute, encode_text};
|
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
|
// ffmpeg and appends it as a Video item (api.rs). This fallback
|
||||||
// keeps media empty when encoding fails or ffmpeg is missing.
|
// keeps media empty when encoding fails or ffmpeg is missing.
|
||||||
} else if model.page_count > 1 {
|
} 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| {
|
media.extend(model.meta_pages.iter().filter_map(|page| {
|
||||||
page.image_urls
|
page_illustration(page.image_urls.original.clone(), &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()),
|
|
||||||
})
|
|
||||||
}));
|
}));
|
||||||
} else if let Some(original) = model
|
} else {
|
||||||
.meta_single_page
|
// The single page names its original in one of two places, and
|
||||||
.original_image_url
|
// `large` is the last resort.
|
||||||
.clone()
|
let urls = &model.image_urls;
|
||||||
.or(model.image_urls.original.clone())
|
let original = model
|
||||||
{
|
.meta_single_page
|
||||||
media.push(Media::Illustration {
|
.original_image_url
|
||||||
url: original,
|
.clone()
|
||||||
thumbnail_url: Some(model.image_urls.medium.clone()),
|
.or_else(|| urls.original.clone());
|
||||||
fallback_url: Some(model.image_urls.large.clone()),
|
media.extend(page_illustration(original, urls));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
let nsfw = model.sanity_level > 5;
|
let nsfw = model.sanity_level > 5;
|
||||||
Self {
|
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 {
|
impl From<Illustration> for Fetched {
|
||||||
fn from(illustration: Illustration) -> Self {
|
fn from(illustration: Illustration) -> Self {
|
||||||
let url = illustration.url();
|
let url = illustration.url();
|
||||||
@@ -540,14 +551,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 v = illust_json("illust", 1, None, None, vec![], 0);
|
||||||
let fetched: Fetched = parse(v).into();
|
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]
|
#[test]
|
||||||
fn multi_page_skips_pages_without_original() {
|
fn multi_page_keeps_pages_without_original() {
|
||||||
let v = illust_json(
|
let v = illust_json(
|
||||||
"illust",
|
"illust",
|
||||||
2,
|
2,
|
||||||
@@ -560,17 +576,27 @@ mod tests {
|
|||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let fetched: Fetched = parse(v).into();
|
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] {
|
match &fetched.media[0] {
|
||||||
Media::Illustration {
|
Media::Illustration {
|
||||||
url,
|
|
||||||
thumbnail_url,
|
thumbnail_url,
|
||||||
fallback_url,
|
fallback_url,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
assert_eq!(url, "https://i.pximg.net/p2.jpg");
|
assert_eq!(thumbnail_url.as_deref(), Some("m1.jpg"));
|
||||||
assert_eq!(thumbnail_url.as_deref(), Some("m2.jpg"));
|
// `large` is the item itself here, so it is not also a
|
||||||
assert_eq!(fallback_url.as_deref(), Some("l2.jpg"));
|
// smaller variant of itself.
|
||||||
|
assert_eq!(fallback_url.as_deref(), Some("l1.jpg"));
|
||||||
}
|
}
|
||||||
other => panic!("expected Illustration, got {other:?}"),
|
other => panic!("expected Illustration, got {other:?}"),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user