一个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 }); | |
} | |
} |