Compare commits

..

43 Commits

Author SHA1 Message Date
881ee4568d Update 'README.md' 2023-02-04 21:44:02 -06:00
7ac32d6dff update urls 2023-02-05 03:35:33 +00:00
175a86b490 Merge branch 'proxy' of gitea.moe:lamp/random-miku-server into proxy 2023-02-05 03:29:25 +00:00
8f1c789c8e remove backup origin 2023-02-05 03:28:29 +00:00
c4d55ec6c7 update url 2022-10-14 02:13:53 -05:00
3ab1623bed multiple random id 2022-07-31 17:23:18 -07:00
88a6e5e692 rip 39 commits
update fallback uri
2021-12-08 15:02:21 -06:00
99f05ea2e0 39 2021-12-04 22:29:27 -08:00
3ef1d4bdcb draw only id on thumb_mini 2021-11-25 18:16:10 -08:00
091197e7c7 hmm 2021-11-25 20:08:30 -06:00
63a9916a03 add option to draw url 2021-11-25 17:56:00 -08:00
0219cc7f83 Merge branch 'proxy' of gitea.moe:lamp/random-miku-server into proxy 2021-11-25 17:02:05 -08:00
47a05b243f relocate cache-control 2021-11-25 17:02:02 -08:00
93017002b9 Update 'README.md' 2021-11-25 18:55:28 -06:00
f5e734a9c9 Update 'README.md' 2021-11-25 18:38:55 -06:00
42566713cf add r18 only 2021-11-25 16:32:42 -08:00
9d8d5c078e rewrite readme 2021-11-25 16:12:55 -08:00
77221513b5 refactor api 2021-11-25 15:36:32 -08:00
9ecdae240b proxy alternative server if pximg not OK
use status 203
add content-disposition
fix error handler i forgot to un-debug
2021-11-25 14:58:39 -08:00
8fac3fedcc Merge branch 'proxy' of gitea.moe:lamp/random-miku-server into proxy 2021-11-21 23:31:27 -08:00
04cbf250b0 add history page and rewrite readme 2021-11-21 23:30:36 -08:00
ebb2071a12 move querystring to left of pixiv url; add auto 2021-11-21 16:12:37 -08:00
c018ca12de fix table 2021-11-18 23:06:06 -06:00
66ab01429a /?noredirect for direct 2021-11-18 21:00:27 -08:00
9fee2a7852 use the url data that I downloaded already
and now including r18
2021-11-18 18:23:19 -08:00
4c8ee7b20a asdfuhsdfg 2021-10-20 17:31:03 -05:00
a75c37731f preserve params in redir 2021-10-20 17:20:45 -05:00
ebf6a8ffc4 Merge branch 'aaaaaaaaa' of gitea.moe:lamp/random-miku-server into aaaaaaaaa 2021-10-20 17:03:18 -05:00
6ed02a4740 log query & ref 2021-10-20 17:03:16 -05:00
1b616bb6d9 favicon 2021-10-20 17:00:54 -05:00
7fe64b6c12 Upload files to '' 2021-10-20 16:59:29 -05:00
b6ff950214 Update 'README.md' 2021-10-12 01:39:34 -05:00
1d88a293ae Add 'README.md' 2021-10-12 00:57:06 -05:00
df44cd1d3e change lastload map to use url 2021-10-12 00:33:57 -05:00
df89043a59 bug 2021-10-12 00:31:44 -05:00
f2dadbb019 change cache to work with size query 2021-10-12 00:28:54 -05:00
0bb834a492 add query params 2021-10-12 00:12:56 -05:00
0e9c70c55e hmm let's not do /:id 2021-10-11 23:48:59 -05:00
3233f32810 api 2021-10-11 23:45:52 -05:00
a2152d2936 cache url 2021-10-05 13:09:00 -07:00
ced093e63c tidy 2021-10-05 12:12:35 -07:00
72599b5cdf handle api error and set content type 2021-10-05 14:04:52 -05:00
019170eb1c proxy edition, because system with db went down :( 2021-10-02 10:18:55 -07:00
9 changed files with 860 additions and 589 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules
.env
output.log
logs

22
README.md Normal file
View File

@ -0,0 +1,22 @@
A simple no-HTML random Hatsune Miku image server. Example: https://rms.owo69.me/
- Click reload to get a different one. Delete left half of URL to get to source.
- Include pornographic results: https://rms.owo69.me/?allow_r18([=only](https://rms.owo69.me/?allow_r18=only))
- Get different sizes (original, regular, small, or thumb_mini): https://rms.owo69.me/?size=thumb_mini
- Auto-refresh using HTTP Refresh header: https://rms.owo69.me/?auto=3
- kek: https://rms.owo69.me/?allow_r18&size=thumb_mini&auto=0
- See your history: https://rms.owo69.me/log
- Load image by id without redirect thing: https://rms.owo69.me/img/51586149
- Load random image directly without redirect thing: https://rms.owo69.me/img/random
- Draw Pixiv URL onto upper left corner of image: https://rms.owo69.me/img/random?drawsource&size=regular
Here is an HTML site that makes use of it: https://lamp.tk/miku.html
### Prerequisites
- Node.js
- GraphicsMagick for ?drawsource option
### todo
- Option to limit range to get more higher-ranked illustrations

File diff suppressed because one or more lines are too long

165
index.js
View File

@ -1,35 +1,138 @@
require("dotenv").config();
var {MongoClient, GridFSBucket} = require("mongodb");
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");
var dbclient = new MongoClient(process.env.DB_URI);
dbclient.connect().then(async () => {
var db = dbclient.db("mikudb");
var collection = db.collection("illustration_collection");
var bucket = new GridFSBucket(db);
var idlist = require("./idlist.json");
var ipa_lastload_map = {};
let redirectRandom = (req, res) => {
let random_id = idlist[Math.floor(Math.random() * idlist.length)];
res.redirect(`/https://www.pixiv.net/en/artworks/${random_id}`);
};
app.get('/', redirectRandom);
app.get("/https://www.pixiv.net/en/artworks/:id", async (req, res) => {
//if (req.headers["cache-control"] == "max-age=0") { // this indicates a reload in chrome
// but chrome still sends it after redirect
if (ipa_lastload_map[req.ip] == req.params.id && req.query.noredirect == null) {
return redirectRandom(req, res);
} else ipa_lastload_map[req.ip] = req.params.id;
console.log(new Date().toLocaleString(), req.ip, req.params.id);
var asdf = await collection.findOne({_id: req.params.id}, {downloaded_images: 1});
if (!asdf) return res.sendStatus(404);
var filename = Object.keys(asdf.downloaded_images)[0];
res.type(filename.split('.').pop());
res.header("Content-Disposition", `filename=${filename}`);
var gfsid = Object.values(asdf.downloaded_images)[0];
bucket.openDownloadStream(gfsid).pipe(res);
});
app.listen(39);
console.log("server ready");
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/"});
});

1
list.json Normal file

File diff suppressed because one or more lines are too long

34
log.html Normal file
View File

@ -0,0 +1,34 @@
<title>history</title>
<style>
.i {
width: 128px;
height: 128px;
display: inline-block;
}
</style>
<h1>history for <span id="ipa">???</span></h1>
<p>in reverse-chronological order. hover for dates</p>
<script>
let ipa = location.pathname.split("/").pop().trim();
document.getElementById("ipa").innerText = ipa;
fetch(location.pathname + "/csv").then(r => r.text()).then(csv => {
csv = csv.trim();
csv = csv.split("\n").map(x => x.split(','));
var imgs = [];
for (let row of csv) {
let date = new Date(row[0]).toLocaleString();
let pixiv_id = row[1];
let pixiv_url = `https://www.pixiv.net/en/artworks/${pixiv_id}`;
let thumb_url = `/img/${pixiv_id}?size=thumb_mini`;
//imgs.unshift(`<a href="${pixiv_url}"><img src="${thumb_url}" alt="${pixiv_id}" title="${date}" /></a>`);
imgs.unshift(`<a href="${pixiv_url}"><div class="i" style="background-image: url(${thumb_url})" title="${date}">${pixiv_id}</div></a>`);
}
document.body.innerHTML += imgs.join('');
});
</script>

1216
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
{
"dependencies": {
"dotenv": "^10.0.0",
"express": "^4.17.1",
"mongodb": "^4.1.2"
"gm": "^1.23.1",
"node-fetch": "^2.6.5",
"serve-favicon": "^2.5.0"
}
}

BIN
ミク.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB