mirror of
https://github.com/lyz05/danmaku.git
synced 2026-02-03 02:04:38 +08:00
137 lines
3.8 KiB
JavaScript
137 lines
3.8 KiB
JavaScript
const express = require("express");
|
||
const axios = require("axios");
|
||
const router = express.Router();
|
||
const URL = require("url");
|
||
const {
|
||
bilibili,
|
||
mgtv,
|
||
tencentvideo,
|
||
youku,
|
||
iqiyi
|
||
} = require("./api/base");
|
||
const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
|
||
const memory = require("../utils/memory");
|
||
const leancloud = require("../utils/leancloud");
|
||
const rateLimit = require('express-rate-limit');
|
||
|
||
// 访问频率限制
|
||
const MAX_count_today = 1000;
|
||
const allowlist = ['::1', '::ffff:127.0.0.1'];
|
||
const apiLimiter = rateLimit({
|
||
windowMs: 5 * 60 * 1000, // 5 minutes
|
||
max: 20, // limit each IP to 20 requests per windowMs
|
||
message: 'Too many requests from this IP, please try again later',
|
||
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
||
skipFailedRequests: true, // Don't count failed requests (status >= 400)
|
||
skip: (request, response) => allowlist.includes(request.ip),
|
||
});
|
||
|
||
async function build_response(url, req) {
|
||
for (let q = new URLSearchParams(URL.parse(url).query); q.has("url");) {
|
||
console.log("Redirecting to", url);
|
||
url = q.get("url");
|
||
q = new URLSearchParams(URL.parse(url).query);
|
||
}
|
||
console.log("Real url:", url);
|
||
try {
|
||
await axios.get(url, {
|
||
headers: { "Accept-Encoding": "gzip,deflate,compress" }
|
||
});
|
||
} catch (e) {
|
||
console.log(e);
|
||
return { msg: "传入的链接非法!请检查链接是否能在浏览器正常打开" };
|
||
}
|
||
let fc = undefined;
|
||
for (let item of list) {
|
||
if (url.indexOf(item.domain) !== -1) {
|
||
fc = item;
|
||
}
|
||
}
|
||
if (fc === undefined) {
|
||
return { "msg": "不支持的视频网址" };
|
||
}
|
||
let ret;
|
||
try {
|
||
ret = await fc.work(url);
|
||
} catch (e) {
|
||
console.log(e);
|
||
let err = JSON.stringify(e, Object.getOwnPropertyNames(e));
|
||
err = JSON.parse(err);
|
||
leancloud.add("DanmakuError", {
|
||
ip: req.ip,
|
||
url,
|
||
err
|
||
});
|
||
return { msg: "弹幕解析过程中程序报错退出,请等待管理员修复!或者换条链接试试!" };
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
async function resolve(req, res) {
|
||
const url = req.query.url;
|
||
const download = (req.query.download === "on");
|
||
const ret = await build_response(url, req);
|
||
memory(); //显示内存使用量
|
||
try {
|
||
if (ret.msg !== "ok") {
|
||
res.status(403).send(ret.msg);
|
||
return;
|
||
} else if (download) {
|
||
res.attachment(ret.title + ".xml");
|
||
} else {
|
||
res.type("application/xml");
|
||
}
|
||
//B站视频,直接重定向
|
||
if (ret.url)
|
||
res.redirect(ret.url);
|
||
else
|
||
res.render("danmaku-xml", { contents: ret.content });
|
||
} catch (e) {
|
||
console.log("返回响应出错,可能ip被封禁");
|
||
}
|
||
}
|
||
|
||
async function index(req, res) {
|
||
const urls = [mgtv.example_urls[0], bilibili.example_urls[0], tencentvideo.example_urls[0], youku.example_urls[0], iqiyi.example_urls[0]];
|
||
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
|
||
res.render("danmaku", {
|
||
path,
|
||
urls
|
||
});
|
||
}
|
||
|
||
/* GET home page. */
|
||
router.get("/", apiLimiter, async function (req, res) {
|
||
leancloud.add("DanmakuAccess", {
|
||
remoteIP: req.ip,
|
||
url: req.query.url,
|
||
UA: req.headers["user-agent"]
|
||
});
|
||
// 查询该IP今日访问次数,异步查询
|
||
leancloud.danmakuQuery(leancloud.currentDay(), req.ip).then((count) => {
|
||
console.log("访问次数:", req.ip, count);
|
||
if (count > MAX_count_today) {
|
||
res.status(403).send("今日访问次数过多,请明日再试!");
|
||
return;
|
||
}
|
||
});
|
||
//检查是否包含URL参数
|
||
if (!req.query.url) index(req, res); else resolve(req, res);
|
||
});
|
||
|
||
router.get("/pageinfo", async function (req, res) {
|
||
const promises = [
|
||
leancloud.danmakuQuery(leancloud.currentDay()),
|
||
leancloud.danmakuQuery(leancloud.lastDay()),
|
||
leancloud.danmakuQuery(leancloud.currentMonth())
|
||
];
|
||
const [today_visited, lastday_visited, month_visited] = await Promise.all(promises);
|
||
res.json({
|
||
today_visited,
|
||
lastday_visited,
|
||
month_visited
|
||
});
|
||
});
|
||
|
||
module.exports = router;
|