tkserver 1.7.16 → 1.7.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +78 -2
  2. package/mongo.js +78 -2
  3. package/package.json +2 -2
package/index.js CHANGED
@@ -291,11 +291,30 @@ async function login (password) {
291
291
  }
292
292
  }
293
293
 
294
+ function getSearchKeyword (event) {
295
+ if (event.keyword === undefined || event.keyword === null) return ''
296
+ if (typeof event.keyword !== 'string') throw new Error('搜索关键词必须是字符串')
297
+ const keyword = event.keyword.trim()
298
+ if (keyword.length > 100) throw new Error('搜索关键词不能超过 100 个字符')
299
+ return keyword
300
+ }
301
+
302
+ function commentMatchesKeyword (comment, keyword) {
303
+ return [comment.nick, comment.comment].some(value =>
304
+ typeof value === 'string' && value.toLowerCase().includes(keyword)
305
+ )
306
+ }
307
+
308
+ function escapeRegExp (value) {
309
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
310
+ }
311
+
294
312
  // 读取评论
295
313
  async function commentGet (event) {
296
314
  const res = {}
297
315
  try {
298
316
  validate(event, ['url'])
317
+ if (getSearchKeyword(event)) return commentSearch(event)
299
318
  const uid = event.accessToken
300
319
  const isAdminUser = isAdmin(event.accessToken)
301
320
  const limit = parseInt(config.COMMENT_PAGE_SIZE) || 8
@@ -383,6 +402,62 @@ async function commentGet (event) {
383
402
  return res
384
403
  }
385
404
 
405
+ async function commentSearch (event) {
406
+ const res = {}
407
+ try {
408
+ validate(event, ['url'])
409
+ const keyword = getSearchKeyword(event).toLowerCase()
410
+ const page = Math.max(parseInt(event.page) || 1, 1)
411
+ const uid = event.accessToken
412
+ const isAdminUser = isAdmin(event.accessToken)
413
+ const limit = parseInt(config.COMMENT_PAGE_SIZE) || 8
414
+ const sort = event.sort || 'newest'
415
+ let more = false
416
+
417
+ const visible = db.getCollection('comment').chain()
418
+ .find(getCommentQuery({ condition: { url: { $in: getUrlQuery(event.url) } }, uid, isAdminUser }))
419
+ .data()
420
+ const matchedRoots = new Set(visible
421
+ .filter(comment => commentMatchesKeyword(comment, keyword))
422
+ .map(comment => String(comment.rid || comment._id)))
423
+ let main = visible.filter(comment => !comment.rid && matchedRoots.has(String(comment._id)))
424
+ const count = main.length
425
+ let replies = visible
426
+
427
+ if (sort === 'oldest') {
428
+ main.sort((a, b) => a.created - b.created)
429
+ } else if (sort === 'popular') {
430
+ main.sort((a, b) => {
431
+ const ups = (b.ups || []).length - (a.ups || []).length
432
+ return ups || b.created - a.created
433
+ })
434
+ } else {
435
+ main.sort((a, b) => b.created - a.created)
436
+ }
437
+ let top = []
438
+ if (!config.TOP_DISABLED) {
439
+ if (page === 1) top = main.filter(comment => comment.top === true)
440
+ main = main.filter(comment => comment.top !== true)
441
+ }
442
+ main = main.slice((page - 1) * limit, page * limit + 1)
443
+ if (main.length > limit) {
444
+ more = true
445
+ main = main.slice(0, limit)
446
+ }
447
+ main = [...top, ...main]
448
+
449
+ const mainIds = new Set(main.map(comment => comment._id.toString()))
450
+ replies = replies.filter(comment => mainIds.has(String(comment.rid)))
451
+ res.data = parseComment([...main, ...replies], uid, config)
452
+ res.more = more
453
+ res.count = count
454
+ } catch (e) {
455
+ res.data = []
456
+ res.message = e.message
457
+ }
458
+ return res
459
+ }
460
+
386
461
  function getCommentQuery ({ condition, uid, isAdminUser }) {
387
462
  return {
388
463
  $or: [
@@ -431,9 +506,10 @@ function getCommentSearchCondition (event) {
431
506
  break
432
507
  }
433
508
  }
434
- if (event.keyword) {
509
+ const keyword = getSearchKeyword(event)
510
+ if (keyword) {
435
511
  const regExp = {
436
- $regex: event.keyword,
512
+ $regex: escapeRegExp(keyword),
437
513
  $options: 'i'
438
514
  }
439
515
  condition = {
package/mongo.js CHANGED
@@ -281,11 +281,30 @@ async function login (password) {
281
281
  }
282
282
  }
283
283
 
284
+ function getSearchKeyword (event) {
285
+ if (event.keyword === undefined || event.keyword === null) return ''
286
+ if (typeof event.keyword !== 'string') throw new Error('搜索关键词必须是字符串')
287
+ const keyword = event.keyword.trim()
288
+ if (keyword.length > 100) throw new Error('搜索关键词不能超过 100 个字符')
289
+ return keyword
290
+ }
291
+
292
+ function commentMatchesKeyword (comment, keyword) {
293
+ return [comment.nick, comment.comment].some(value =>
294
+ typeof value === 'string' && value.toLowerCase().includes(keyword)
295
+ )
296
+ }
297
+
298
+ function escapeRegExp (value) {
299
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
300
+ }
301
+
284
302
  // 读取评论
285
303
  async function commentGet (event) {
286
304
  const res = {}
287
305
  try {
288
306
  validate(event, ['url'])
307
+ if (getSearchKeyword(event)) return commentSearch(event)
289
308
  const uid = event.accessToken
290
309
  const isAdminUser = isAdmin(event.accessToken)
291
310
  const limit = parseInt(config.COMMENT_PAGE_SIZE) || 8
@@ -371,6 +390,62 @@ async function commentGet (event) {
371
390
  return res
372
391
  }
373
392
 
393
+ async function commentSearch (event) {
394
+ const res = {}
395
+ try {
396
+ validate(event, ['url'])
397
+ const keyword = getSearchKeyword(event).toLowerCase()
398
+ const page = Math.max(parseInt(event.page) || 1, 1)
399
+ const uid = event.accessToken
400
+ const isAdminUser = isAdmin(event.accessToken)
401
+ const limit = parseInt(config.COMMENT_PAGE_SIZE) || 8
402
+ const sort = event.sort || 'newest'
403
+ let more = false
404
+
405
+ const condition = { url: { $in: getUrlQuery(event.url) } }
406
+ const query = getCommentQuery({ condition, uid, isAdminUser })
407
+ const searchComments = await db.collection('comment').find(query).toArray()
408
+ const matchedRoots = new Set(searchComments
409
+ .filter(comment => commentMatchesKeyword(comment, keyword))
410
+ .map(comment => String(comment.rid || comment._id)))
411
+ let main = searchComments.filter(comment =>
412
+ (!comment.rid || comment.rid === '') && matchedRoots.has(String(comment._id))
413
+ )
414
+ const count = main.length
415
+
416
+ main.sort((a, b) => {
417
+ if (sort === 'oldest') return a.created - b.created
418
+ if (sort === 'popular') {
419
+ const ups = (b.ups || []).length - (a.ups || []).length
420
+ if (ups) return ups
421
+ }
422
+ return b.created - a.created
423
+ })
424
+ let top = []
425
+ if (!config.TOP_DISABLED) {
426
+ if (page === 1) top = main.filter(comment => comment.top === true)
427
+ main = main.filter(comment => comment.top !== true)
428
+ }
429
+ main = main.slice((page - 1) * limit, page * limit + 1)
430
+
431
+ if (main.length > limit) {
432
+ more = true
433
+ main = main.slice(0, limit)
434
+ }
435
+ main = [...top, ...main]
436
+
437
+ const mainIds = new Set(main.map(comment => comment._id.toString()))
438
+ const reply = searchComments.filter(comment => mainIds.has(String(comment.rid)))
439
+ res.data = parseComment([...main, ...reply], uid, config)
440
+ res.more = more
441
+ res.count = count
442
+ } catch (e) {
443
+ res.data = []
444
+ res.message = e.message
445
+ }
446
+ return res
447
+ }
448
+
374
449
  function getCommentQuery ({ condition, uid, isAdminUser }) {
375
450
  return {
376
451
  $or: [
@@ -418,9 +493,10 @@ function getCommentSearchCondition (event) {
418
493
  break
419
494
  }
420
495
  }
421
- if (event.keyword) {
496
+ const keyword = getSearchKeyword(event)
497
+ if (keyword) {
422
498
  const regExp = {
423
- $regex: event.keyword,
499
+ $regex: escapeRegExp(keyword),
424
500
  $options: 'i'
425
501
  }
426
502
  condition = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tkserver",
3
- "version": "1.7.16",
3
+ "version": "1.7.18",
4
4
  "description": "A simple comment system.",
5
5
  "keywords": [
6
6
  "twikoo",
@@ -31,7 +31,7 @@
31
31
  "get-user-ip": "^1.0.1",
32
32
  "lokijs": "^1.5.12",
33
33
  "mongodb": "^6.3.0",
34
- "twikoo-func": "1.7.16",
34
+ "twikoo-func": "1.7.18",
35
35
  "uuid": "^8.3.2"
36
36
  }
37
37
  }