mirror of
https://github.com/lyz05/danmaku.git
synced 2026-02-02 17:59:53 +08:00
feat: 添加速率限制,单ip1分钟6次
This commit is contained in:
23
app.js
23
app.js
@@ -3,15 +3,17 @@ const express = require("express");
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const cookieParser = require("cookie-parser");
|
const cookieParser = require("cookie-parser");
|
||||||
const logger = require("morgan");
|
const logger = require("morgan");
|
||||||
|
const rateLimit = require("express-rate-limit");
|
||||||
|
|
||||||
// 引入环境变量
|
// 引入环境变量
|
||||||
require("dotenv").config();
|
require("dotenv")
|
||||||
|
.config();
|
||||||
|
|
||||||
// 引入一个个路由模块
|
// 引入一个个路由模块
|
||||||
const danmakuRouter = require("./routes/danmaku");
|
const danmakuRouter = require("./routes/danmaku");
|
||||||
const ipinfoRouter = require("./routes/ipinfo");
|
const ipinfoRouter = require("./routes/ipinfo");
|
||||||
const airportsubRouter = require("./routes/airportsub");
|
const airportsubRouter = require("./routes/airportsub");
|
||||||
const DEBUG = process.env.DEBUG==="true" || false;
|
const DEBUG = process.env.DEBUG === "true" || false;
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@@ -22,14 +24,26 @@ app.set("trust proxy", true);
|
|||||||
|
|
||||||
app.use(logger("dev"));
|
app.use(logger("dev"));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.urlencoded({extended: false}));
|
app.use(express.urlencoded({ extended: false }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
|
// 加载静态资源
|
||||||
app.use(express.static(path.join(__dirname, "public")));
|
app.use(express.static(path.join(__dirname, "public")));
|
||||||
app.use("/assets", [
|
app.use("/assets", [
|
||||||
express.static(__dirname + "/node_modules/jquery/dist/"),
|
express.static(__dirname + "/node_modules/jquery/dist/"),
|
||||||
express.static(__dirname + "/node_modules/bootstrap/dist/"),
|
express.static(__dirname + "/node_modules/bootstrap/dist/"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Rate Limit
|
||||||
|
const apiLimiter = rateLimit({
|
||||||
|
windowMs: 60 * 1000, // 1 minute
|
||||||
|
max: 6, // limit each IP to 6 requests per windowMs
|
||||||
|
message: "Too many requests from this IP, please try again after an minute",
|
||||||
|
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
|
||||||
|
skipFailedRequests: true, // Don't count failed requests (status >= 400)
|
||||||
|
});
|
||||||
|
app.use(apiLimiter);
|
||||||
|
|
||||||
|
// 加载路由
|
||||||
app.use("/", danmakuRouter);
|
app.use("/", danmakuRouter);
|
||||||
app.use("/ipinfo", ipinfoRouter);
|
app.use("/ipinfo", ipinfoRouter);
|
||||||
app.use("/sub", airportsubRouter);
|
app.use("/sub", airportsubRouter);
|
||||||
@@ -57,7 +71,8 @@ if (!DEBUG) {
|
|||||||
console.log("PRODUCTION MODE!该模式下TG机器人正常运行");
|
console.log("PRODUCTION MODE!该模式下TG机器人正常运行");
|
||||||
// 引入TG机器人
|
// 引入TG机器人
|
||||||
require("./tgbot/tgbot");
|
require("./tgbot/tgbot");
|
||||||
} else
|
} else {
|
||||||
console.log("DEBUG MODE!该模式下将关闭TG机器人");
|
console.log("DEBUG MODE!该模式下将关闭TG机器人");
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|||||||
4
bin/www
4
bin/www
@@ -22,7 +22,9 @@ const server = http.createServer(app);
|
|||||||
* Listen on provided port, on all network interfaces.
|
* Listen on provided port, on all network interfaces.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
server.listen(port);
|
server.listen(port, () => {
|
||||||
|
console.log(`Listening on port ${port}`);
|
||||||
|
});
|
||||||
server.on('error', onError);
|
server.on('error', onError);
|
||||||
server.on('listening', onListening);
|
server.on('listening', onListening);
|
||||||
|
|
||||||
|
|||||||
18
package-lock.json
generated
18
package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.8",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
"filesize": "^10.0.5",
|
"filesize": "^10.0.5",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
@@ -2959,6 +2960,17 @@
|
|||||||
"node": ">= 0.10.0"
|
"node": ">= 0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/express-rate-limit": {
|
||||||
|
"version": "6.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
||||||
|
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": "^4 || ^5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/express/node_modules/http-errors": {
|
"node_modules/express/node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
@@ -10381,6 +10393,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"express-rate-limit": {
|
||||||
|
"version": "6.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
|
||||||
|
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.8",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
"filesize": "^10.0.5",
|
"filesize": "^10.0.5",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
|
|||||||
@@ -1,106 +1,120 @@
|
|||||||
const axios = require('axios');
|
const axios = require("axios");
|
||||||
const tgbot = require("../tgbot/tgbot.js");
|
const tgbot = require("../tgbot/tgbot.js");
|
||||||
|
|
||||||
const rootPath = 'https://eservice.ssm.gov.mo/covidvacbook/'
|
const rootPath = "https://eservice.ssm.gov.mo/covidvacbook/";
|
||||||
const chatID = [619935997, 5646988443];
|
const chatID = [619935997, 5646988443];
|
||||||
const IDTYPES = ["J", "f", "M", "h", "O", "n"]
|
const IDTYPES = ["J", "f", "M", "h", "O", "n"];
|
||||||
|
|
||||||
console.log('covidbook.js loaded')
|
console.log("covidbook.js loaded");
|
||||||
|
|
||||||
function sendMessage(msg) {
|
function sendMessage(msg) {
|
||||||
const bot = tgbot.hkaliyun;
|
const bot = tgbot.hkaliyun;
|
||||||
chatID.forEach(id => {
|
chatID.forEach(id => {
|
||||||
bot.sendMessage(id, msg);
|
bot.sendMessage(id, msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetLocationQuotaList() {
|
async function GetLocationQuotaList() {
|
||||||
const url = rootPath + 'Booking/GetLocationQuotaList';
|
const url = rootPath + "Booking/GetLocationQuotaList";
|
||||||
const res = await axios.post(url, {});
|
const res = await axios.post(url, {});
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
const mrnalocationquotalist = data.filter(locationquota => (locationquota.rspsrv === 'HC6' || locationquota.rspsrv === 'HC8' || locationquota.rspsrv === 'CHCSJ(MRNA)' || locationquota.rspsrv === 'CHCSJ2(MRNA)' || locationquota.rspsrv === 'SSM1(MRNA)'));
|
const mrnalocationquotalist = data.filter(locationquota => (locationquota.rspsrv === "HC6" || locationquota.rspsrv === "HC8" || locationquota.rspsrv === "CHCSJ(MRNA)" || locationquota.rspsrv === "CHCSJ2(MRNA)" || locationquota.rspsrv === "SSM1(MRNA)"));
|
||||||
const ivlocationquotalist = data.filter(locationquota => (locationquota.rspsrv === 'HC1' || locationquota.rspsrv === 'HC2' || locationquota.rspsrv === 'HC3' || locationquota.rspsrv === 'HC4' || locationquota.rspsrv === 'HC5' || locationquota.rspsrv === 'HC7' || locationquota.rspsrv === 'HC9' || locationquota.rspsrv === 'HC11' || locationquota.rspsrv === 'CHCSJ' || locationquota.rspsrv === 'CHCSJ2' || locationquota.rspsrv === 'KW1' || locationquota.rspsrv === 'SSM1' || locationquota.rspsrv === 'MUST1' || locationquota.rspsrv === 'FAOM1' || locationquota.rspsrv === 'FAOM2' || locationquota.rspsrv === 'SSM2'));
|
const ivlocationquotalist = data.filter(locationquota => (locationquota.rspsrv === "HC1" || locationquota.rspsrv === "HC2" || locationquota.rspsrv === "HC3" || locationquota.rspsrv === "HC4" || locationquota.rspsrv === "HC5" || locationquota.rspsrv === "HC7" || locationquota.rspsrv === "HC9" || locationquota.rspsrv === "HC11" || locationquota.rspsrv === "CHCSJ" || locationquota.rspsrv === "CHCSJ2" || locationquota.rspsrv === "KW1" || locationquota.rspsrv === "SSM1" || locationquota.rspsrv === "MUST1" || locationquota.rspsrv === "FAOM1" || locationquota.rspsrv === "FAOM2" || locationquota.rspsrv === "SSM2"));
|
||||||
return { ivlocationquotalist, mrnalocationquotalist };
|
return {
|
||||||
|
ivlocationquotalist,
|
||||||
|
mrnalocationquotalist
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetLocationPeriodByIdtype(idtype) {
|
async function GetLocationPeriodByIdtype(idtype) {
|
||||||
const url = rootPath + 'Booking/GetLocationPeriodByIdtype';
|
const url = rootPath + "Booking/GetLocationPeriodByIdtype";
|
||||||
var data = { idtype: idtype };
|
var data = { idtype: idtype };
|
||||||
const res = await axios.post(url, data);
|
const res = await axios.post(url, data);
|
||||||
return { periodlist: res.data }
|
return { periodlist: res.data };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getlocationbyidtype(idtype) {
|
async function getlocationbyidtype(idtype) {
|
||||||
var data = { idtype: idtype };
|
var data = { idtype: idtype };
|
||||||
var url = rootPath + 'Booking/GetLocationByIdtype';
|
var url = rootPath + "Booking/GetLocationByIdtype";
|
||||||
const res = await axios.post(url, data);
|
const res = await axios.post(url, data);
|
||||||
return { location: res.data }
|
return { location: res.data };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetBookDate(idtype) {
|
async function GetBookDate(idtype) {
|
||||||
var url = rootPath + 'Booking/GetBookDate';
|
var url = rootPath + "Booking/GetBookDate";
|
||||||
var checkquota = false;
|
var checkquota = false;
|
||||||
|
|
||||||
let date = new Date()
|
let date = new Date();
|
||||||
let year = date.getFullYear()
|
let year = date.getFullYear();
|
||||||
let month = (date.getMonth() + 1).toString().padStart(2, '0')
|
let month = (date.getMonth() + 1).toString()
|
||||||
let day = date.getDate().toString().padStart(2, '0')
|
.padStart(2, "0");
|
||||||
var time2 = `${year}${month}${day}`
|
let day = date.getDate()
|
||||||
|
.toString()
|
||||||
|
.padStart(2, "0");
|
||||||
|
var time2 = `${year}${month}${day}`;
|
||||||
|
|
||||||
var data = { idtype: idtype, afterdate: time2, checkquota: checkquota };
|
var data = {
|
||||||
const res = await axios.post(url, data);
|
idtype: idtype,
|
||||||
return { bookdatelist: res.data }
|
afterdate: time2,
|
||||||
|
checkquota: checkquota
|
||||||
|
};
|
||||||
|
const res = await axios.post(url, data);
|
||||||
|
return { bookdatelist: res.data };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetlocationList() {
|
async function GetlocationList() {
|
||||||
var url = rootPath + 'Booking/GetlocationList';
|
var url = rootPath + "Booking/GetlocationList";
|
||||||
const res = await axios.post(url, {});
|
const res = await axios.post(url, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const { ivlocationquotalist, mrnalocationquotalist } = await GetLocationQuotaList();
|
const {
|
||||||
const quotalist = mrnalocationquotalist;
|
ivlocationquotalist,
|
||||||
|
mrnalocationquotalist
|
||||||
|
} = await GetLocationQuotaList();
|
||||||
|
const quotalist = mrnalocationquotalist;
|
||||||
|
|
||||||
console.log('covidbook query')
|
console.log("covidbook query");
|
||||||
//筛选出可预约的日期
|
//筛选出可预约的日期
|
||||||
for (const idtype of IDTYPES) {
|
for (const idtype of IDTYPES) {
|
||||||
const { bookdatelist } = await GetBookDate(idtype);
|
const { bookdatelist } = await GetBookDate(idtype);
|
||||||
const { location } = await getlocationbyidtype(idtype)
|
const { location } = await getlocationbyidtype(idtype);
|
||||||
const name = location[0].name_c;
|
const name = location[0].name_c;
|
||||||
if (bookdatelist.length != 0) {
|
if (bookdatelist.length != 0) {
|
||||||
sendMessage(name + "\n" + bookdatelist.join('\n'));
|
sendMessage(name + "\n" + bookdatelist.join("\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// // 筛选出当日有余量的接种站
|
// // 筛选出当日有余量的接种站
|
||||||
// const quotalistfilter = quotalist.filter(x => x.sum != '0')
|
// const quotalistfilter = quotalist.filter(x => x.sum != '0')
|
||||||
// if (quotalistfilter.length != 0) {
|
// if (quotalistfilter.length != 0) {
|
||||||
// console.log('有余量');
|
// console.log('有余量');
|
||||||
// const time2 = new Date().toLocaleTimeString();
|
// const time2 = new Date().toLocaleTimeString();
|
||||||
// bot.sendMessage(chatID, `当前时间:${time2},以下是有余量的接种站:`);
|
// bot.sendMessage(chatID, `当前时间:${time2},以下是有余量的接种站:`);
|
||||||
// for (const l of quotalistfilter) {
|
// for (const l of quotalistfilter) {
|
||||||
// bot.sendMessage(chatID, `${l.name_c} : ${l.sum}`);
|
// bot.sendMessage(chatID, `${l.name_c} : ${l.sum}`);
|
||||||
// }
|
// }
|
||||||
// } else console.log('无余量');
|
// } else console.log('无余量');
|
||||||
|
|
||||||
// 遍历每个接种站尚有余额之时段
|
// 遍历每个接种站尚有余额之时段
|
||||||
// for (const item of quotalist) {
|
// for (const item of quotalist) {
|
||||||
// const { location } = await getlocationbyidtype(item.idtype)
|
// const { location } = await getlocationbyidtype(item.idtype)
|
||||||
// const { periodlist } = await GetLocationPeriodByIdtype(item.idtype)
|
// const { periodlist } = await GetLocationPeriodByIdtype(item.idtype)
|
||||||
// if (periodlist.length != 0) {
|
// if (periodlist.length != 0) {
|
||||||
// const name = location[0].name_c;
|
// const name = location[0].name_c;
|
||||||
// const periodlisttext = periodlist.map(l => `${l.booktime} 餘額 : ${l.ava_quota}`)
|
// const periodlisttext = periodlist.map(l => `${l.booktime} 餘額 : ${l.ava_quota}`)
|
||||||
// bot.sendMessage(chatID, name + '\n' + periodlisttext.join('\n'));
|
// bot.sendMessage(chatID, name + '\n' + periodlisttext.join('\n'));
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = main;
|
module.exports = main;
|
||||||
|
|
||||||
if (!module.parent) {
|
if (!module.parent) {
|
||||||
// 引入环境变量
|
// 引入环境变量
|
||||||
require("dotenv").config('../.env');
|
require("dotenv")
|
||||||
main()
|
.config("../.env");
|
||||||
sendMessage('测试')
|
main();
|
||||||
}
|
sendMessage("测试");
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user