一个Cloudflare Worker用来获取Pixiv图片, 基于HibiAPI
- URL:
/- 直接请求即可
- 支持附加请求参数, 请参考此处
- URL:
/<图片ID>- 直接请求即可
| addEventListener("fetch", (event) => { | |
| event.respondWith( | |
| handleRequest(event.request).catch( | |
| (err) => | |
| new Response(err.stack, { | |
| status: 500, | |
| }) | |
| ) | |
| ); | |
| }); | |
| /** | |
| * @param {Array} list | |
| */ | |
| function randomChoice(list) { | |
| return list[Math.floor(Math.random() * list.length)]; | |
| } | |
| /** | |
| * @param {RequestInfo} input | |
| * @param {RequestInit} init | |
| * @returns {any} | |
| */ | |
| async function requestJson(input, init) { | |
| const response = await fetch(input, init); | |
| return response.json(); | |
| } | |
| /** | |
| * @param {Number} id | |
| * @returns {Promise<Response>} | |
| */ | |
| async function getImage(id) { | |
| const data = await requestJson( | |
| `https://api.obfs.dev/api/pixiv/illust?id=${id}`, | |
| { | |
| headers: { "Cache-Control": "no-store" }, | |
| } | |
| ); | |
| const illust = data.illust; | |
| const image = !!illust.meta_pages.length | |
| ? randomChoice(illust.meta_pages).image_urls.original | |
| : illust.meta_single_page.original_image_url; | |
| return fetch(image, { | |
| headers: { | |
| Referer: "https://www.pixiv.net", | |
| }, | |
| }); | |
| } | |
| /** | |
| * @param {URLSearchParams} params | |
| * @returns {Promise<Response>} | |
| **/ | |
| async function rankImage(params) { | |
| const data = await requestJson( | |
| `https://api.obfs.dev/api/pixiv/rank?` + params.toString(), | |
| { | |
| headers: { | |
| "Cache-Control": "no-store", | |
| }, | |
| } | |
| ); | |
| const illust = randomChoice(data.illusts); | |
| const image = !!illust.meta_pages.length | |
| ? randomChoice(illust.meta_pages).image_urls.original | |
| : illust.meta_single_page.original_image_url; | |
| return fetch(image, { | |
| headers: { | |
| Referer: "https://www.pixiv.net", | |
| }, | |
| }); | |
| } | |
| /** | |
| * @param {Date} date | |
| * @returns {String} | |
| */ | |
| function formatDate(date) { | |
| var d = new Date(date), | |
| month = "" + (d.getMonth() + 1), | |
| day = "" + d.getDate(), | |
| year = d.getFullYear(); | |
| if (month.length < 2) month = "0" + month; | |
| if (day.length < 2) day = "0" + day; | |
| return [year, month, day].join("-"); | |
| } | |
| /** | |
| * @param {Request} request | |
| * @returns {Promise<Response>} | |
| */ | |
| async function handleRequest(request) { | |
| const url = new URL(request.url); | |
| const reg = /\/(?<id>\d+)\/?/; | |
| switch (url.pathname) { | |
| case "/": | |
| if (!url.searchParams.has("mode")) { | |
| url.searchParams.set("mode", randomChoice(["day", "week", "month"])); | |
| } | |
| if (!url.searchParams.has("date")) { | |
| const date = new Date(); | |
| date.setDate(date.getDate() - Math.ceil(Math.random() * 365 * 2)); | |
| url.searchParams.set("date", formatDate(date)); | |
| } | |
| return rankImage(url.searchParams); | |
| case "/teapot": | |
| return new Response("I'm a teapot", { status: 418 }); | |
| case "/favicon.ico": | |
| return fetch("https://www.google.com/favicon.ico"); | |
| default: | |
| if (reg.exec(url.pathname)) { | |
| const { id } = reg.exec(url.pathname).groups; | |
| return getImage(id); | |
| } | |
| return new Response(`Not Found: ${request.url}`, { status: 404 }); | |
| } | |
| } |