feat: 数据库改为sqlite,新增下载热榜功能

This commit is contained in:
lyz05
2024-04-27 11:36:36 +08:00
parent 7d7bb8529e
commit d3e7058f8f
10 changed files with 1848 additions and 143 deletions

View File

@@ -2,3 +2,4 @@ Dockerfile
.dockerignore
node_modules
.git
db

1
.gitignore vendored
View File

@@ -277,3 +277,4 @@ fabric.properties
upload
.s
db

View File

@@ -38,6 +38,7 @@ flyctl config env
flyctl secrets set DEBUG=true
flyctl ssh console
flyctl checks list
flyctl ssh sftp get /app/db/danmaku.db
```
# Node常用工具

8
app.js
View File

@@ -10,7 +10,6 @@ require("dotenv")
// 引入一个个路由模块
const danmakuRouter = require("./routes/danmaku");
const DEBUG = !(process.env.DEBUG === "false");
const app = express();
// 启用gzip压缩
app.use(compression());
@@ -32,7 +31,6 @@ app.use("/assets", [
express.static(__dirname + "/node_modules/axios/dist/"),
express.static(__dirname + "/node_modules/leancloud-storage/dist"),
]);
// app.use("/upload", express.static(__dirname + "/upload"));
// 加载路由
app.use("/", danmakuRouter);
@@ -53,10 +51,4 @@ app.use(function (err, req, res) {
res.render("error");
});
if (!DEBUG) {
console.log("PRODUCTION MODE!该模式下日志记录正常运行");
} else {
console.log("DEBUG MODE!该模式下将关闭日志记录功能");
}
module.exports = app;

View File

@@ -28,3 +28,7 @@ kill_timeout = "5s"
cpu_kind = "shared"
cpus = 1
memory_mb = 512
[mounts]
source="danmaku"
destination="/app/db"

1831
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,7 @@
"openai": "^3.2.1",
"pako": "^1.0.11",
"querystring": "^0.2.1",
"sqlite3": "^5.1.7",
"whacko": "^0.19.1",
"xml-js": "^1.6.11"
},

View File

@@ -11,20 +11,7 @@ const {
} = 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: 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),
// });
const db = require("../utils/db");
// 返回对象{msg: "ok", title: "标题", content: []}
async function build_response(url, req) {
@@ -62,8 +49,7 @@ async function build_response(url, req) {
} catch (e) {
console.log(e);
let err = JSON.stringify(e, Object.getOwnPropertyNames(e));
err = JSON.parse(err);
leancloud.add("DanmakuError", {
db.errorInsert({
ip: req.ip,
url,
err
@@ -78,49 +64,44 @@ async function resolve(req, res) {
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被封禁");
if (ret.msg !== "ok") {
res.status(403).send(ret.msg);
return;
} else if (download) {
res.attachment(ret.title + ".xml");
} else {
res.type("application/xml");
}
// 记录视频信息
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) {
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 resolve_info = await db.accesscountquery()
const hotlist = await db.hotlistquery()
console.log(hotlist)
res.render("danmaku", {
path,
urls
urls,
resolve_info,
hotlist
});
}
/* GET home page. */
router.get("/", async function (req, res) {
leancloud.add("DanmakuAccess", {
remoteIP: req.ip,
db.accessInsert({
ip: 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);
});

View File

@@ -1,8 +0,0 @@
const leancloud = require('../utils/leancloud');
async function main(ms) {
const count = await leancloud.danmakuQuery(leancloud.currentDay(),"1217")
console.log(count);
};

View File

@@ -35,7 +35,17 @@
</p>
</div>
<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 class="row">
@@ -82,63 +92,14 @@
</div>
<div class="row">
今日解析量:<span id="today_visited"></span><span class="post-meta-divider"> | </span>
昨日解析量:<span id="lastday_visited"></span><span class="post-meta-divider"> | </span>
月解析量:<span id="month_visited"></span>
今日解析量:<span id="today_visited"><%= resolve_info.today_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"><%= resolve_info.month_visited %></span>
</div>
</footer>
</div>
</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>