Skip to content

Commit 33aaf7e

Browse files
authored
feat: 评论长度限制 (#341 #342)
1 parent 9573ba0 commit 33aaf7e

13 files changed

Lines changed: 75 additions & 14 deletions

File tree

docs/.vuepress/theme/layouts/Layout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
<!-- Twikoo -->
1515
<div id="twikoo"></div>
16-
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.1/dist/twikoo.all.min.js" ref="twikooJs"></script>
16+
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.2/dist/twikoo.all.min.js" ref="twikooJs"></script>
1717
</div>
1818
</template>
1919
</ParentLayout>

docs/quick-start.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ exports.main = require('twikoo-func').main
4444
8. 创建完成后,点击“twikoo"进入云函数详情页,进入“函数代码”标签,点击“文件 - 新建文件”,输入 `package.json`,回车
4545
9. 复制以下代码、粘贴到代码框中,点击“保存并安装依赖”
4646
``` json
47-
{ "dependencies": { "twikoo-func": "1.5.1" } }
47+
{ "dependencies": { "twikoo-func": "1.5.2" } }
4848
```
4949

5050
### 命令行部署
@@ -174,7 +174,7 @@ twikoo:
174174

175175
``` html
176176
<div id="tcomment"></div>
177-
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.1/dist/twikoo.all.min.js"></script>
177+
<script src="https://cdn.jsdelivr.net/npm/twikoo@1.5.2/dist/twikoo.all.min.js"></script>
178178
<script>
179179
twikoo.init({
180180
envId: '您的环境id', // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
@@ -192,7 +192,7 @@ twikoo.init({
192192

193193
请参考爆米兔前端静态资源库 [https://cdn.baomitu.com/twikoo](https://cdn.baomitu.com/twikoo)
194194

195-
引入的 CDN 链接替换为如下即可:`https://lib.baomitu.com/twikoo/1.5.1/twikoo.all.min.js`
195+
引入的 CDN 链接替换为如下即可:`https://lib.baomitu.com/twikoo/1.5.2/twikoo.all.min.js`
196196

197197
## 开启管理面板
198198

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twikoo",
3-
"version": "1.5.1",
3+
"version": "1.5.2",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
55
"keywords": ["twikoojs", "comment", "comment-system", "cloudbase", "vercel"],
66
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",

src/function/twikoo/index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,24 @@ const RES_CODE = {
5050
UPLOAD_FAILED: 1040
5151
}
5252
const ADMIN_USER_ID = 'admin'
53+
const MAX_REQUEST_TIMES = parseInt(process.env.TWIKOO_THROTTLE) || 250
5354

5455
// 全局变量 / variables
5556
// 警告:全局定义的变量,会被云函数缓存,请慎重定义全局变量
5657
// 参考 https://docs.cloudbase.net/cloud-function/deep-principle.html 中的 “实例复用”
5758
let config
5859
let transporter
60+
const requestTimes = {}
5961

6062
// 云函数入口点 / entry point
6163
exports.main = async (event, context) => {
64+
console.log('请求IP:', auth.getClientIP())
6265
console.log('请求方法:', event.event)
6366
console.log('请求参数:', event)
6467
let res = {}
65-
await readConfig()
6668
try {
69+
protect()
70+
await readConfig()
6771
switch (event.event) {
6872
case 'GET_FUNC_VERSION':
6973
res = getFuncVersion()
@@ -1168,6 +1172,12 @@ async function limitFilter () {
11681172

11691173
// 预垃圾评论检测
11701174
function preCheckSpam (comment) {
1175+
// 长度限制
1176+
let limitLength = parseInt(config.LIMIT_LENGTH)
1177+
if (Number.isNaN(limitLength)) limitLength = 500
1178+
if (limitLength && comment.length > limitLength) {
1179+
throw new Error('评论内容过长')
1180+
}
11711181
if (config.AKISMET_KEY === 'MANUAL_REVIEW') {
11721182
// 人工审核
11731183
console.log('已使用人工审核模式,评论审核后才会发表~')
@@ -1497,7 +1507,8 @@ function getConfig () {
14971507
REQUIRED_FIELDS: config.REQUIRED_FIELDS,
14981508
HIDE_ADMIN_CRYPT: config.HIDE_ADMIN_CRYPT,
14991509
HIGHLIGHT: config.HIGHLIGHT || 'true',
1500-
HIGHLIGHT_THEME: config.HIGHLIGHT_THEME
1510+
HIGHLIGHT_THEME: config.HIGHLIGHT_THEME,
1511+
LIMIT_LENGTH: config.LIMIT_LENGTH
15011512
}
15021513
}
15031514
}
@@ -1534,6 +1545,18 @@ async function setConfig (event) {
15341545
}
15351546
}
15361547

1548+
function protect () {
1549+
// 防御
1550+
const ip = auth.getClientIP()
1551+
requestTimes[ip] = (requestTimes[ip] || 0) + 1
1552+
if (requestTimes[ip] > MAX_REQUEST_TIMES) {
1553+
console.log(`${ip} 当前请求次数为 ${requestTimes[ip]},已超过最大请求次数`)
1554+
throw new Error('Too Many Requests')
1555+
} else {
1556+
console.log(`${ip} 当前请求次数为 ${requestTimes[ip]}`)
1557+
}
1558+
}
1559+
15371560
// 读取配置
15381561
async function readConfig () {
15391562
try {

src/function/twikoo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twikoo-func",
3-
"version": "1.5.1",
3+
"version": "1.5.2",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
55
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",
66
"license": "MIT",

src/js/entites/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Config {
2424
this.QCLOUD_SECRET_KEY = model.QCLOUD_SECRET_KEY
2525
this.LIMIT_PER_MINUTE = model.LIMIT_PER_MINUTE
2626
this.LIMIT_PER_MINUTE_ALL = model.LIMIT_PER_MINUTE_ALL
27+
this.LIMIT_LENGTH = model.LIMIT_LENGTH
2728
this.FORBIDDEN_WORDS = model.FORBIDDEN_WORDS
2829
this.NOTIFY_SPAM = model.NOTIFY_SPAM
2930
this.SC_MAIL_NOTIFY = model.SC_MAIL_NOTIFY

src/js/utils/i18n/i18n.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,19 @@ export default {
341341
'单个 IP 发言频率限制(条/10分钟),0 为无限制,默认:10',
342342
'單個 IP 發言頻率限制(條/10分鐘),0 為無限制,預設:10',
343343
'單個 IP 發言頻率限制(條/10分鐘),0 為無限制,預設:10',
344-
'How many comments can be posted by each IP every 10 minutes, default: 0 (unlimited).'
344+
'How many comments can be posted by each IP every 10 minutes, 0 is unlimited, default: 10.'
345345
],
346346
[S.ACI + '_LIMIT_PER_MINUTE_ALL']: [
347347
'全站发言频率限制(条/10分钟),0 为无限制,默认:10',
348348
'全站發言頻率限制(條/10分鐘),0 為無限制,預設:10',
349349
'全站發言頻率限制(條/10分鐘),0 為無限制,預設:10',
350-
'How many comments can be posted by all IPs every 10 minutes, default: 0 (unlimited).'
350+
'How many comments can be posted by all IPs every 10 minutes, 0 is unlimited, default: 10.'
351+
],
352+
[S.ACI + '_LIMIT_LENGTH']: [
353+
'评论长度限制,0 为无限制,默认:500',
354+
'評論長度限制,0 為無限制,預設:500',
355+
'評論長度限制,0 為無限制,預設:500',
356+
'Comment length limitation, 0 is unlimited, default: 500.'
351357
],
352358
[S.ACI + '_MAIL_SUBJECT']: [
353359
'自定义通知邮件主题,留空则使用默认主题。',

src/vercel-min/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "dependencies": { "twikoo-vercel": "1.5.1" } }
1+
{ "dependencies": { "twikoo-vercel": "1.5.2" } }

src/vercel/api/index.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const RES_CODE = {
4646
AKISMET_ERROR: 1030,
4747
UPLOAD_FAILED: 1040
4848
}
49+
const MAX_REQUEST_TIMES = parseInt(process.env.TWIKOO_THROTTLE) || 250
4950

5051
// 全局变量 / variables
5152
let db = null
@@ -54,15 +55,18 @@ let transporter
5455
let request
5556
let response
5657
let accessToken
58+
const requestTimes = {}
5759

5860
module.exports = async (requestArg, responseArg) => {
5961
request = requestArg
6062
response = responseArg
6163
const event = request.body || {}
64+
console.log('请求IP:', request.headers['x-real-ip'])
6265
console.log('请求方法:', event.event)
6366
console.log('请求参数:', event)
6467
let res = {}
6568
try {
69+
protect()
6670
anonymousSignIn()
6771
await connectToDatabase(process.env.MONGODB_URI)
6872
await readConfig()
@@ -1174,6 +1178,12 @@ async function limitFilter () {
11741178

11751179
// 预垃圾评论检测
11761180
function preCheckSpam (comment) {
1181+
// 长度限制
1182+
let limitLength = parseInt(config.LIMIT_LENGTH)
1183+
if (Number.isNaN(limitLength)) limitLength = 500
1184+
if (limitLength && comment.length > limitLength) {
1185+
throw new Error('评论内容过长')
1186+
}
11771187
if (config.AKISMET_KEY === 'MANUAL_REVIEW') {
11781188
// 人工审核
11791189
console.log('已使用人工审核模式,评论审核后才会发表~')
@@ -1504,7 +1514,8 @@ async function getConfig () {
15041514
REQUIRED_FIELDS: config.REQUIRED_FIELDS,
15051515
HIDE_ADMIN_CRYPT: config.HIDE_ADMIN_CRYPT,
15061516
HIGHLIGHT: config.HIGHLIGHT || 'true',
1507-
HIGHLIGHT_THEME: config.HIGHLIGHT_THEME
1517+
HIGHLIGHT_THEME: config.HIGHLIGHT_THEME,
1518+
LIMIT_LENGTH: config.LIMIT_LENGTH
15081519
}
15091520
}
15101521
}
@@ -1541,6 +1552,18 @@ async function setConfig (event) {
15411552
}
15421553
}
15431554

1555+
function protect () {
1556+
// 防御
1557+
const ip = request.headers['x-real-ip']
1558+
requestTimes[ip] = (requestTimes[ip] || 0) + 1
1559+
if (requestTimes[ip] > MAX_REQUEST_TIMES) {
1560+
console.log(`${ip} 当前请求次数为 ${requestTimes[ip]},已超过最大请求次数`)
1561+
throw new Error('Too Many Requests')
1562+
} else {
1563+
console.log(`${ip} 当前请求次数为 ${requestTimes[ip]}`)
1564+
}
1565+
}
1566+
15441567
// 读取配置
15451568
async function readConfig () {
15461569
try {

src/vercel/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twikoo-vercel",
3-
"version": "1.5.1",
3+
"version": "1.5.2",
44
"description": "A simple comment system based on Tencent CloudBase (tcb).",
55
"author": "imaegoo <hello@imaegoo.com> (https://github.com/imaegoo)",
66
"license": "MIT",

0 commit comments

Comments
 (0)