mirror of
https://github.com/lyz05/danmaku.git
synced 2026-02-02 17:59:53 +08:00
feat: 数据库改为sqlite,新增下载热榜功能
This commit is contained in:
@@ -2,3 +2,4 @@ Dockerfile
|
|||||||
.dockerignore
|
.dockerignore
|
||||||
node_modules
|
node_modules
|
||||||
.git
|
.git
|
||||||
|
db
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -276,4 +276,5 @@ fabric.properties
|
|||||||
# End of https://www.toptal.com/developers/gitignore/api/node,webstorm,visualstudiocode
|
# End of https://www.toptal.com/developers/gitignore/api/node,webstorm,visualstudiocode
|
||||||
upload
|
upload
|
||||||
|
|
||||||
.s
|
.s
|
||||||
|
db
|
||||||
@@ -38,6 +38,7 @@ flyctl config env
|
|||||||
flyctl secrets set DEBUG=true
|
flyctl secrets set DEBUG=true
|
||||||
flyctl ssh console
|
flyctl ssh console
|
||||||
flyctl checks list
|
flyctl checks list
|
||||||
|
flyctl ssh sftp get /app/db/danmaku.db
|
||||||
```
|
```
|
||||||
|
|
||||||
# Node常用工具
|
# Node常用工具
|
||||||
|
|||||||
8
app.js
8
app.js
@@ -10,7 +10,6 @@ require("dotenv")
|
|||||||
|
|
||||||
// 引入一个个路由模块
|
// 引入一个个路由模块
|
||||||
const danmakuRouter = require("./routes/danmaku");
|
const danmakuRouter = require("./routes/danmaku");
|
||||||
const DEBUG = !(process.env.DEBUG === "false");
|
|
||||||
const app = express();
|
const app = express();
|
||||||
// 启用gzip压缩
|
// 启用gzip压缩
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
@@ -32,7 +31,6 @@ app.use("/assets", [
|
|||||||
express.static(__dirname + "/node_modules/axios/dist/"),
|
express.static(__dirname + "/node_modules/axios/dist/"),
|
||||||
express.static(__dirname + "/node_modules/leancloud-storage/dist"),
|
express.static(__dirname + "/node_modules/leancloud-storage/dist"),
|
||||||
]);
|
]);
|
||||||
// app.use("/upload", express.static(__dirname + "/upload"));
|
|
||||||
|
|
||||||
// 加载路由
|
// 加载路由
|
||||||
app.use("/", danmakuRouter);
|
app.use("/", danmakuRouter);
|
||||||
@@ -53,10 +51,4 @@ app.use(function (err, req, res) {
|
|||||||
res.render("error");
|
res.render("error");
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!DEBUG) {
|
|
||||||
console.log("PRODUCTION MODE!该模式下日志记录正常运行");
|
|
||||||
} else {
|
|
||||||
console.log("DEBUG MODE!该模式下将关闭日志记录功能");
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|||||||
4
fly.toml
4
fly.toml
@@ -28,3 +28,7 @@ kill_timeout = "5s"
|
|||||||
cpu_kind = "shared"
|
cpu_kind = "shared"
|
||||||
cpus = 1
|
cpus = 1
|
||||||
memory_mb = 512
|
memory_mb = 512
|
||||||
|
|
||||||
|
[mounts]
|
||||||
|
source="danmaku"
|
||||||
|
destination="/app/db"
|
||||||
1831
package-lock.json
generated
1831
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,7 @@
|
|||||||
"openai": "^3.2.1",
|
"openai": "^3.2.1",
|
||||||
"pako": "^1.0.11",
|
"pako": "^1.0.11",
|
||||||
"querystring": "^0.2.1",
|
"querystring": "^0.2.1",
|
||||||
|
"sqlite3": "^5.1.7",
|
||||||
"whacko": "^0.19.1",
|
"whacko": "^0.19.1",
|
||||||
"xml-js": "^1.6.11"
|
"xml-js": "^1.6.11"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,20 +11,7 @@ const {
|
|||||||
} = require("./api/base");
|
} = require("./api/base");
|
||||||
const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
|
const list = [bilibili, mgtv, tencentvideo, youku, iqiyi];
|
||||||
const memory = require("../utils/memory");
|
const memory = require("../utils/memory");
|
||||||
const leancloud = require("../utils/leancloud");
|
const db = require("../utils/db");
|
||||||
// const rateLimit = require('express-rate-limit');
|
|
||||||
|
|
||||||
// 访问频率限制
|
|
||||||
// const MAX_count_today = 1000;
|
|
||||||
// const allowlist = ['::1', '::ffff:127.0.0.1'];
|
|
||||||
// const apiLimiter = rateLimit({
|
|
||||||
// windowMs: 2 * 60 * 1000, // 2 minutes
|
|
||||||
// max: 10, // limit each IP to 10 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),
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 返回对象{msg: "ok", title: "标题", content: []}
|
// 返回对象{msg: "ok", title: "标题", content: []}
|
||||||
async function build_response(url, req) {
|
async function build_response(url, req) {
|
||||||
@@ -62,8 +49,7 @@ async function build_response(url, req) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
let err = JSON.stringify(e, Object.getOwnPropertyNames(e));
|
let err = JSON.stringify(e, Object.getOwnPropertyNames(e));
|
||||||
err = JSON.parse(err);
|
db.errorInsert({
|
||||||
leancloud.add("DanmakuError", {
|
|
||||||
ip: req.ip,
|
ip: req.ip,
|
||||||
url,
|
url,
|
||||||
err
|
err
|
||||||
@@ -78,49 +64,44 @@ async function resolve(req, res) {
|
|||||||
const download = (req.query.download === "on");
|
const download = (req.query.download === "on");
|
||||||
const ret = await build_response(url, req);
|
const ret = await build_response(url, req);
|
||||||
memory(); //显示内存使用量
|
memory(); //显示内存使用量
|
||||||
try {
|
if (ret.msg !== "ok") {
|
||||||
if (ret.msg !== "ok") {
|
res.status(403).send(ret.msg);
|
||||||
res.status(403).send(ret.msg);
|
return;
|
||||||
return;
|
} else if (download) {
|
||||||
} else if (download) {
|
res.attachment(ret.title + ".xml");
|
||||||
res.attachment(ret.title + ".xml");
|
} else {
|
||||||
} else {
|
res.type("application/xml");
|
||||||
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被封禁");
|
|
||||||
}
|
}
|
||||||
|
// 记录视频信息
|
||||||
|
db.videoinfoInsert({url,title:ret.title})
|
||||||
|
//B站视频,直接重定向
|
||||||
|
if (ret.url)
|
||||||
|
res.redirect(ret.url);
|
||||||
|
else
|
||||||
|
res.render("danmaku-xml", { contents: ret.content });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function index(req, res) {
|
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 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;
|
const path = req.protocol + "://" + req.headers.host + req.originalUrl;
|
||||||
|
const resolve_info = await db.accesscountquery()
|
||||||
|
const hotlist = await db.hotlistquery()
|
||||||
|
console.log(hotlist)
|
||||||
res.render("danmaku", {
|
res.render("danmaku", {
|
||||||
path,
|
path,
|
||||||
urls
|
urls,
|
||||||
|
resolve_info,
|
||||||
|
hotlist
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GET home page. */
|
/* GET home page. */
|
||||||
router.get("/", async function (req, res) {
|
router.get("/", async function (req, res) {
|
||||||
leancloud.add("DanmakuAccess", {
|
db.accessInsert({
|
||||||
remoteIP: req.ip,
|
ip: req.ip,
|
||||||
url: req.query.url,
|
url: req.query.url,
|
||||||
UA: req.headers["user-agent"]
|
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参数
|
//检查是否包含URL参数
|
||||||
if (!req.query.url) index(req, res); else resolve(req, res);
|
if (!req.query.url) index(req, res); else resolve(req, res);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
const leancloud = require('../utils/leancloud');
|
|
||||||
|
|
||||||
async function main(ms) {
|
|
||||||
const count = await leancloud.danmakuQuery(leancloud.currentDay(),"1217")
|
|
||||||
console.log(count);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +35,17 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
|
<h4>最近一天下载热榜</h4>
|
||||||
|
<ul id="hotlist">
|
||||||
|
<% hotlist.forEach(function(item) { %>
|
||||||
|
<li>
|
||||||
|
<a href="<%= item.url %>">
|
||||||
|
<%= item.title %>
|
||||||
|
</a> - <%= item.count %> 次访问
|
||||||
|
</li>
|
||||||
|
<% }); %>
|
||||||
|
<!-- 更多列表项 -->
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -82,63 +92,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
今日解析量:<span id="today_visited"></span><span class="post-meta-divider"> | </span>
|
今日解析量:<span id="today_visited"><%= resolve_info.today_visited %></span><span class="post-meta-divider"> | </span>
|
||||||
昨日解析量:<span id="lastday_visited"></span><span class="post-meta-divider"> | </span>
|
昨日解析量:<span id="lastday_visited"><%= resolve_info.lastday_visited %></span><span class="post-meta-divider"> | </span>
|
||||||
当月解析量:<span id="month_visited"></span>
|
近一个月解析量:<span id="month_visited"><%= resolve_info.month_visited %></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
<script>
|
|
||||||
AV.init({
|
|
||||||
appId: "DBvUNEk87tttf0zxelzVRfuW-9Nh9j0Va",
|
|
||||||
appKey: "CnqCkxWUFTmxwzCqu1alwFEm",
|
|
||||||
serverURL: "https://dbvunek8.lc-cn-n1-shared.com"
|
|
||||||
});
|
|
||||||
|
|
||||||
function currentDay() {
|
|
||||||
const date = new Date(), y = date.getFullYear(), m = date.getMonth();
|
|
||||||
const start = new Date(date.setHours(0, 0, 0, 0));
|
|
||||||
const end = new Date(date.setHours(23, 59, 59, 999));
|
|
||||||
return [start, end, y, m+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
function lastDay() {
|
|
||||||
const currentday = currentDay();
|
|
||||||
currentday[0].setDate(currentday[0].getDate() - 1);
|
|
||||||
currentday[1].setDate(currentday[1].getDate() - 1);
|
|
||||||
return currentday;
|
|
||||||
}
|
|
||||||
|
|
||||||
function currentMonth() {
|
|
||||||
const date = new Date(), y = date.getFullYear(), m = date.getMonth();
|
|
||||||
const firstDay = new Date(y, m, 1);
|
|
||||||
const lastDay = new Date(y, m + 1, 0);
|
|
||||||
return [firstDay, lastDay];
|
|
||||||
}
|
|
||||||
|
|
||||||
function danmakuQuery(date, ip) {
|
|
||||||
const className = `DanmakuAccess_${currentDay()[2]}_${currentDay()[3]}`;
|
|
||||||
const query = new AV.Query(className);
|
|
||||||
query.greaterThanOrEqualTo("createdAt", date[0]);
|
|
||||||
query.lessThan("createdAt", date[1]);
|
|
||||||
if (ip) query.equalTo("remoteIP", ip);
|
|
||||||
|
|
||||||
query.exists("url");
|
|
||||||
return query.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
danmakuQuery(currentDay()).then((count)=>{
|
|
||||||
$('#today_visited').text(count);
|
|
||||||
});
|
|
||||||
danmakuQuery(lastDay()).then((count)=>{
|
|
||||||
$('#lastday_visited').text(count);
|
|
||||||
});
|
|
||||||
danmakuQuery(currentMonth()).then((count)=>{
|
|
||||||
$('#month_visited').text(count);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user