From 2bf6adbaa0ac9988edc8fdbeae9cfc98bd0a7546 Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 27 Jul 2020 17:45:32 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=87=8A=E6=94=BE=E9=94=81?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96record.getList()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hydro/entry/master.ts | 8 ++++++-- hydro/handler/contest.ts | 2 +- hydro/handler/discussion.ts | 12 ++++++++++++ hydro/handler/problem.ts | 6 +----- hydro/lib/misc.ts | 8 +++++--- hydro/lib/template.ts | 2 +- hydro/loader.ts | 2 +- hydro/model/discussion.ts | 9 ++++----- hydro/model/record.ts | 12 ++++++------ hydro/service/server.ts | 8 ++++++-- package.json | 5 +++-- yarn.lock | 5 +++++ 12 files changed, 51 insertions(+), 28 deletions(-) diff --git a/hydro/entry/master.ts b/hydro/entry/master.ts index 9e2df1c6c..d9eb40dd3 100644 --- a/hydro/entry/master.ts +++ b/hydro/entry/master.ts @@ -3,6 +3,7 @@ import os from 'os'; import path from 'path'; import fs from 'fs-extra'; +import pslist from 'ps-list'; import { argv } from 'yargs'; import { builtinModel } from './common'; import { Entry } from '../loader'; @@ -13,8 +14,11 @@ const lockfile = path.resolve(tmpdir, 'lock.json'); export async function load(call: Entry) { if (fs.existsSync(lockfile) && !argv.ignorelock) { const file = require(lockfile); - console.error(`Lockfile exists, pid=${file.pid}`); - process.exit(1); + const plist = await pslist(); + if (file.pid && plist.map((i) => i.pid).includes(file.pid)) { + console.error(`Lockfile exists, pid=${file.pid}`); + process.exit(1); + } } const context = { addons: global.addons, diff --git a/hydro/handler/contest.ts b/hydro/handler/contest.ts index 496a2b403..3374a006d 100644 --- a/hydro/handler/contest.ts +++ b/hydro/handler/contest.ts @@ -73,7 +73,7 @@ class ContestDetailHandler extends ContestHandler { if (this.canShowRecord(tdoc)) { const q = []; for (const i in psdict) q.push(psdict[i].rid); - rdict = await record.getList(domainId, q); + rdict = await record.getList(domainId, q, true); } else { for (const i in psdict) rdict[psdict[i].rid] = { _id: psdict[i].rid }; } diff --git a/hydro/handler/discussion.ts b/hydro/handler/discussion.ts index 47bf562f5..05405b7d9 100644 --- a/hydro/handler/discussion.ts +++ b/hydro/handler/discussion.ts @@ -1,9 +1,11 @@ import { ObjectID } from 'mongodb'; import { isSafeInteger } from 'lodash'; import { DiscussionNotFoundError, DocumentNotFoundError } from '../error'; +import { Drdoc, Mdoc } from '../interface'; import paginate from '../lib/paginate'; import * as system from '../model/system'; import * as user from '../model/user'; +import * as message from '../model/message'; import * as discussion from '../model/discussion'; import * as document from '../model/document'; import { PERM, PRIV } from '../model/builtin'; @@ -213,6 +215,16 @@ class DiscussionDetailHandler extends DiscussionHandler { async postReply(domainId: string, did: ObjectID, content: string) { this.checkPerm(PERM.PERM_REPLY_DISCUSSION); this.limitRate('add_discussion', 3600, 30); + // Notify related users + const replies: Drdoc[] = await discussion.getMultiReply(domainId, did).toArray(); + const uids = Array.from(new Set(replies.map((drdoc) => drdoc.owner))); + const tasks = uids.map((uid) => { + if (uid !== this.user._id) { + return message.send(1, uid, `Discussion update: ${domainId} ${did}`); + } + return Promise.resolve(null as Mdoc); + }); + await Promise.all(tasks); await discussion.addReply(domainId, did, this.user._id, content, this.request.ip); this.back(); } diff --git a/hydro/handler/problem.ts b/hydro/handler/problem.ts index a2d90e2a6..b197e9300 100644 --- a/hydro/handler/problem.ts +++ b/hydro/handler/problem.ts @@ -24,11 +24,7 @@ import { Route, Connection, Handler, ConnectionHandler, Types, param, multipart, } from '../service/server'; -const parseCategory = (value: string) => { - if (!value) return []; - console.log(value); - return flatten(value.split('+').map((e) => e.split(','))).map((e) => e.trim()); -}; +const parseCategory = (value: string) => flatten(value.split('+').map((e) => e.split(','))).map((e) => e.trim()); const parsePid = (value: string) => (isSafeInteger(value) ? parseInt(value, 10) : value); class ProblemHandler extends Handler { diff --git a/hydro/lib/misc.ts b/hydro/lib/misc.ts index 5de94f04a..c6c29cc2c 100644 --- a/hydro/lib/misc.ts +++ b/hydro/lib/misc.ts @@ -28,7 +28,7 @@ export function* paginate(page: number, numPages: number) { let first: number; let last: number; if (page > 1) { - yield ['first', 1]; + if (page > 2) yield ['first', 1]; yield ['previous', page - 1]; } if (page <= radius) [first, last] = [1, Math.min(1 + radius * 2, numPages)]; @@ -43,8 +43,10 @@ export function* paginate(page: number, numPages: number) { else yield ['current', page]; } if (last < numPages) yield ['ellipsis', 0]; - if (page < numPages) yield ['next', page + 1]; - yield ['last', numPages]; + if (page < numPages) { + yield ['next', page + 1]; + if (page < numPages - 1) yield ['last', numPages]; + } } export function size(s: number, base = 1) { diff --git a/hydro/lib/template.ts b/hydro/lib/template.ts index 97811fd27..bb19f663f 100644 --- a/hydro/lib/template.ts +++ b/hydro/lib/template.ts @@ -18,7 +18,7 @@ class Loader extends nunjucks.Loader { }; } let fullpath = null; - const p = path.resolve(argv.template as string, name); + const p = path.resolve(process.cwd(), argv.template as string, name); if (fs.existsSync(p)) fullpath = p; if (!fullpath) throw new Error(`Cannot get template ${name}`); return { diff --git a/hydro/loader.ts b/hydro/loader.ts index 728eb230b..b3a159608 100644 --- a/hydro/loader.ts +++ b/hydro/loader.ts @@ -133,7 +133,7 @@ const publicTemp = path.resolve(os.tmpdir(), 'hydro', 'public'); const tmp = path.resolve(os.tmpdir(), 'hydro', '__'); export function addon(addonPath: string) { - let modulePath = path.resolve(addonPath); + let modulePath = path.resolve(process.cwd(), addonPath); if (!(fs.existsSync(addonPath) && fs.statSync(addonPath).isFile())) { try { // Is a npm package diff --git a/hydro/model/discussion.ts b/hydro/model/discussion.ts index 37f7bcf8b..91dab2b65 100644 --- a/hydro/model/discussion.ts +++ b/hydro/model/discussion.ts @@ -200,11 +200,10 @@ export function getNodes(domainId: string) { export async function getListVnodes(domainId: string, ddocs: any, handler: any) { const tasks = []; const res = {}; - function task(ddoc) { - return getVnode(domainId, ddoc, handler).then((vnode) => { - if (!res[ddoc.parentType]) res[ddoc.parentType] = {}; - res[ddoc.parentType][ddoc.parentId] = vnode; - }); + async function task(ddoc) { + const vnode = await getVnode(domainId, ddoc, handler); + if (!res[ddoc.parentType]) res[ddoc.parentType] = {}; + res[ddoc.parentType][ddoc.parentId] = vnode; } for (const ddoc of ddocs) tasks.push(task(ddoc)); await Promise.all(tasks); diff --git a/hydro/model/record.ts b/hydro/model/record.ts index c7c41e98c..fa16a9710 100644 --- a/hydro/model/record.ts +++ b/hydro/model/record.ts @@ -140,14 +140,14 @@ export function count(domainId: string, query: any) { } export async function getList( - domainId: string, rids: ObjectID[], showHidden = false, + domainId: string, rids: ObjectID[], showHidden: boolean, ): Promise> { const r = {}; - for (const rid of rids) { - // eslint-disable-next-line no-await-in-loop - const rdoc = await get(domainId, rid); - if (rdoc.hidden && !showHidden) r[rid.toHexString()] = null; - else r[rid.toHexString()] = rdoc; + rids = Array.from(new Set(rids)); + const rdocs = await coll.find({ domainId, _id: { $in: rids } }).toArray(); + for (const rdoc of rdocs) { + if (rdoc.hidden && !showHidden) r[rdoc._id.toHexString()] = null; + else r[rdoc._id.toHexString()] = rdoc; } return r; } diff --git a/hydro/service/server.ts b/hydro/service/server.ts index c26f0ef16..2ae9929dc 100644 --- a/hydro/service/server.ts +++ b/hydro/service/server.ts @@ -391,8 +391,12 @@ export class Handler { this.response.status = error instanceof UserFacingError ? error.code : 500; if (this.request.json) this.response.body = { error }; else { - await this.render(error instanceof UserFacingError ? 'error.html' : 'bsod.html', { error }) - .catch(() => { }); + try { + await this.render(error instanceof UserFacingError ? 'error.html' : 'bsod.html', { error }); + } catch (e) { + console.error(e); + // this.response.body.error = {}; + } } } await this.putResponse(); diff --git a/package.json b/package.json index 10454f32a..df1d68534 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.10.9", + "version": "2.10.10", "main": "dist/loader.js", "bin": "bin/hydrooj.js", "repository": "https://github.com/hydro-dev/Hydro.git", @@ -33,6 +33,7 @@ "nodemailer": "^6.4.10", "nunjucks": "^3.2.2", "prismjs": "^1.20.0", + "ps-list": "^7.2.0", "serialize-javascript": "^4.0.0", "sockjs": "^0.3.20", "superagent": "^5.2.2", @@ -76,4 +77,4 @@ "build:watch": "tsc --watch", "lint": "eslint bin hydro tool --ext ts,js --fix" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index b3769275b..1cbe47349 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2270,6 +2270,11 @@ proxy-from-env@^1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +ps-list@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/ps-list/-/ps-list-7.2.0.tgz#3d110e1de8249a4b178c9b1cf2a215d1e4e42fc0" + integrity sha512-v4Bl6I3f2kJfr5o80ShABNHAokIgY+wFDTQfE+X3zWYgSGQOCBeYptLZUpoOALBqO5EawmDN/tjTldJesd0ujQ== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"