Files
danmaku/routes/danmaku.js

137 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;