78 lines
3.1 KiB
TypeScript
78 lines
3.1 KiB
TypeScript
import { ScrapeEngineBase, ScrapeResult, ScrapedPost, ScrapeEngineFeature } from "../ScrapeEngine.js";
|
|
import { guessContentType } from "../Utility.js";
|
|
|
|
export function upgradeUrlToOriginalQuality(imgLink: string) {
|
|
if (imgLink.indexOf("img-master") != -1) {
|
|
// Example:
|
|
// Input: https://i.pximg.net/img-master/img/2022/02/15/06/50/28/96268450_p2_master1200.jpg
|
|
// Input: https://i.pximg.net/c/600x1200_90_webp/img-master/img/2022/02/15/06/50/28/96268450_p2_master1200.jpg
|
|
// Output: https://i.pximg.net/img-original/img/2022/02/15/06/50/28/96268450_p2.jpg
|
|
//
|
|
// Warning:
|
|
// This will NOT work for a srcset like this:
|
|
// https://i.pximg.net/c/540x540_70/img-master/img/2022/02/15/06/50/28/96268450_p0_master1200.jpg 540w,https://i.pximg.net/img-master/img/2022/02/15/06/50/28/96268450_p0_master1200.jpg
|
|
//
|
|
// See regexr.com/6rcag for an example.
|
|
|
|
// TODO: Add a check to verify the newly constructed/guessed url?
|
|
return imgLink.replace(/(https?:\/\/i\.pximg\.net).*\/img-master\/(.*)_master\d+(.*)/, "$1/img-original/$2$3");
|
|
}
|
|
|
|
return imgLink;
|
|
}
|
|
|
|
export default class Pixiv extends ScrapeEngineBase {
|
|
name = "pixiv";
|
|
features: ScrapeEngineFeature[] = ["content"];
|
|
notes = [];
|
|
supportedHosts = ["pixiv.net"];
|
|
|
|
scrapeDocument(document: Document): ScrapeResult {
|
|
const result = new ScrapeResult(this.name);
|
|
const imgLinks = [] as string[];
|
|
|
|
// Query for when the user is on the desktop site, is logged in, and has optionally clicked on "Show all".
|
|
// If the user has not clicked on "Show all" then this will only grab the first post.
|
|
imgLinks.push(
|
|
...Array.from(document.querySelectorAll<HTMLAnchorElement>("div[role='presentation'] > a")).map((x) => x.href)
|
|
);
|
|
|
|
if (imgLinks.length == 0) {
|
|
// Query for when the user is on the desktop site and not logged in.
|
|
imgLinks.push(
|
|
...Array.from(document.querySelectorAll<HTMLImageElement>("div[role='presentation'] img")).map((x) => x.src)
|
|
);
|
|
}
|
|
|
|
if (imgLinks.length == 0) {
|
|
// Query for when the user is on the mobile site, and has clicked on "Show all".
|
|
// This only works on pages with multiple posts. The user can optionally be logged in.
|
|
imgLinks.push(
|
|
...Array.from(document.querySelectorAll<HTMLImageElement>(".manga-page > a > img[data-big]")).map(
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
(x) => x.getAttribute("data-big")!
|
|
)
|
|
);
|
|
}
|
|
|
|
if (imgLinks.length == 0) {
|
|
// Query for when the user is on the mobile site, and has not clicked on "See all" -or- there is only one post.
|
|
const imgLink = document.querySelector<HTMLImageElement>(".work-main-image img")?.src;
|
|
if (imgLink) {
|
|
imgLinks.push(imgLink);
|
|
}
|
|
}
|
|
|
|
for (const imgLink of imgLinks) {
|
|
const post = new ScrapedPost();
|
|
post.pageUrl = document.location.href;
|
|
post.contentUrl = upgradeUrlToOriginalQuality(imgLink);
|
|
post.contentType = guessContentType(post.contentUrl);
|
|
post.referrer = document.location.origin;
|
|
result.tryAddPost(post);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|