var express = require("express"); var fetch = require("node-fetch"); var qs = require("qs"); var serveFavicon = require("serve-favicon"); var gm = require("gm"); var fs = require("fs"); var app = express(); app.set("trust proxy", "127.0.0.1"); app.listen(process.env.PORT || 39, process.env.ADDRESS); app.use(serveFavicon("ミク.png")); app.use((req,res,next)=>{req.rawQuery = req.url.includes('?') && req.url.substr(req.url.indexOf('?')+1);next();}); var list = require("./list.json"); var list_r18_indices = [], list_safe_indices = []; for (let i = 0, h = list.length; i < h; i++) if (list[i][2]) list_r18_indices.push(i); else list_safe_indices.push(i); var ipa_lastload_map = {}; function getRandomId(allow_r18) { if (allow_r18?.toLowerCase() == "only") { return list[list_r18_indices[Math.floor(Math.random() * list_r18_indices.length)]][0]; } else if (allow_r18 != null) { return list[Math.floor(Math.random() * list.length)][0]; } else { return list[list_safe_indices[Math.floor(Math.random() * list_safe_indices.length)]][0]; } }; function getRandomUrl(req) { var s = req?.params.settings ? `/${req?.params.settings}` : ''; var d = getRandomId(req?.query.allow_r18); return `${s}/https://www.pixiv.net/en/artworks/${d}`; } async function serveId(id, req, res, next) { try { console.log(new Date().toLocaleString(), req.ip, req.url); let pages = list.find(x => x[0] == id)?.[1]; if (!pages) { let data = await (await fetch(`https://pixiv.net/ajax/illust/${id}/pages`, { headers: { "Host": "www.pixiv.net" } })).json(); if (data.error) { res.status(502).type("text").send(data.message); return; } pages = data.body; } var size = req.query.size || "original"; var url = pages[0].urls[size]; if (!url) return res.status(400).type("text").send(`size must be one of the following: ${Object.keys(pages[0].urls).join(', ')}`); var pxreq = await fetch(url, { headers: {"Referer": "https://www.pixiv.net"} }); //if (pxreq.status != 200 && size == "original") { // res.header("X-Using-Backup", '1'); // pxreq = await fetch(`https://39.hmbp.gq/https://www.pixiv.net/en/artworks/${id}?noredirect`); //} res.status(pxreq.status); res.type(pxreq.headers.get("Content-Type")); res.header("Content-Disposition", `filename=${url.split('/').pop()}`); res.header("X-Pixiv-Id", id); if (req.query.auto) res.header("Refresh", `${Number(req.query.auto)}; url=${getRandomUrl(req)}`); if (req.query.drawsource != null && pxreq.headers.get("Content-Type").startsWith("image")) { gm(pxreq.body).drawText(2, 12, size == "thumb_mini" ? id : `https://www.pixiv.net/en/artworks/${id}`).stream().pipe(res); } else pxreq.body.pipe(res); fs.appendFileSync(`logs/${req.ip.replace(/[:\/]/g, '-')}.csv`, `${new Date().toISOString()},${id}\n`); } catch(error) { next(error); } } // original HTML-less site for humans via web browser. // - click refresh to get different image // - delete left half of url to get to source // - hacked querystring so it's before source url app.get("(/:settings)?/https://www.pixiv.net/en/artworks/:id", function (req, res, next) { if (req.rawQuery) { let settings = req.params.settings || ''; if (settings) settings += "&"; settings += req.rawQuery; return res.redirect(`/${settings}/https://www.pixiv.net/en/artworks/${req.params.id}`); } if (req.params.settings) req.query = qs.parse(req.params.settings); if (ipa_lastload_map[req.ip] == req.url) return res.redirect(getRandomUrl(req)); else ipa_lastload_map[req.ip] = req.url; serveId(req.params.id, req, res, next); }); // initial randir app.get('/', (req, res) => { res.redirect((req.rawQuery ? `/${req.rawQuery}` : '') + getRandomUrl(req)); }); // direct random image without redirects app.get("/img/random", (req, res, next) => { serveId(getRandomId(req.query.allow_r18), req, res, next); }); // simple serve id without redirects app.get("/img/:id", (req, res, next) => { res.header("Cache-Control", "max-age=99999999999999"); serveId(req.params.id, req, res, next); }); // plaintext random id(s) for scripts app.get("/randomid", function (req, res) { var count = Number(req.query.count) || 1; count = Math.min(count, 100); var ids = []; for (let i = 0; i < count; i++) ids.push(getRandomId(req.query.allow_r18)); ids = ids.join(','); res.type("text/plain").send(ids); }); // log site app.get("/log", function (req, res) { res.redirect(`/log/${req.ip}`); }); var log_html = fs.readFileSync("log.html", "utf8"); app.get("/log/:ipa", function (req, res) { res.send(log_html); }); app.get("/log/:ipa/csv", function (req, res) { res.sendFile(req.params.ipa.replace(/[:\/]/g, '-') + '.csv', {root: process.cwd() + "/logs/"}); });