From bfc2e95ef56e24dfa06f014ace7fef54d90abe26 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 21 Jul 2020 11:22:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=94=E8=B5=9B=E4=B8=BE=E5=8A=9E=E8=80=85?= =?UTF-8?q?=E5=8F=AF=E7=BB=99=E7=94=A8=E6=88=B7=E6=8E=A8=E9=80=81=E9=80=9A?= =?UTF-8?q?=E7=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO | 1 - hydro/handler/contest.ts | 35 +++++++++++++++++++++++++++++++++-- hydro/handler/home.ts | 5 +---- hydro/model/message.ts | 10 +++++++++- hydro/service/server.ts | 8 +++++--- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index 0de05d872..753b3d137 100644 --- a/TODO +++ b/TODO @@ -2,7 +2,6 @@ discussion前端权限节点显示异常? web端运行脚本异常? 讨论回复通知 -比赛举办者发布通知 举报功能 SETTINGS_PRIVACY.allowRegisteredUsers model.setting.ui.name diff --git a/hydro/handler/contest.ts b/hydro/handler/contest.ts index 1fc3b0c74..6771bafa8 100644 --- a/hydro/handler/contest.ts +++ b/hydro/handler/contest.ts @@ -4,7 +4,7 @@ import AdmZip from 'adm-zip'; import { isSafeInteger } from 'lodash'; import { ContestNotLiveError, ValidationError, ProblemNotFoundError, - ContestNotAttendedError, + ContestNotAttendedError, PermissionError, } from '../error'; import { isContent, isTitle } from '../lib/validator'; import paginate from '../lib/paginate'; @@ -14,6 +14,7 @@ import * as document from '../model/document'; import * as problem from '../model/problem'; import * as record from '../model/record'; import * as user from '../model/user'; +import * as message from '../model/message'; import * as system from '../model/system'; import { Route, Handler, Types, param, @@ -65,7 +66,7 @@ class ContestDetailHandler extends ContestHandler { ]); const psdict = {}; let rdict = {}; - let attended; + let attended: boolean; if (tsdoc) { attended = tsdoc.attend === 1; for (const pdetail of tsdoc.journal || []) psdict[pdetail.pid] = pdetail; @@ -97,6 +98,35 @@ class ContestDetailHandler extends ContestHandler { } } +class ContestBoardcastHandler extends ContestHandler { + @param('tid', Types.ObjectID) + async get(domainId: string, tid: ObjectID) { + const tdoc = await contest.get(domainId, tid); + if (tdoc.owner !== this.user._id) throw new PermissionError('Boardcast Message'); + const path = [ + ['Hydro', 'homepage'], + ['contest_main', 'contest_main'], + [tdoc.title, 'contest_detail', { tid }, true], + ['contest_boardcast'], + ]; + this.response.template = 'contest_boardcast.html'; + this.response.body = path; + } + + @param('tid', Types.ObjectID) + @param('content', Types.String, isContent) + async post(domainId: string, tid: ObjectID, content: string) { + const tdoc = await contest.get(domainId, tid); + if (tdoc.owner !== this.user._id) throw new PermissionError('Boardcast Message'); + const tsdocs = await contest.getMultiStatus(domainId, { docId: tid }).toArray(); + const uids = Array.from(new Set(tsdocs.map((tsdoc) => tsdoc.uid))); + await Promise.all( + uids.map((uid) => message.send(this.user._id, uid, content, message.FLAG_ALERT)), + ); + this.response.redirect = this.url('contest_detail', { tid }); + } +} + class ContestScoreboardHandler extends ContestHandler { @param('tid', Types.ObjectID) async get(domainId: string, tid: ObjectID) { @@ -383,6 +413,7 @@ export async function apply() { Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST); Route('contest_main', '/contest', ContestListHandler, PERM.PERM_VIEW_CONTEST); Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST); + Route('contest_boardcast', '/contest/:tid/boardcast', ContestBoardcastHandler); Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST); Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST); Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardDownloadHandler, PERM.PERM_VIEW_CONTEST); diff --git a/hydro/handler/home.ts b/hydro/handler/home.ts index 042838945..4a7f3430a 100644 --- a/hydro/handler/home.ts +++ b/hydro/handler/home.ts @@ -321,10 +321,7 @@ class HomeMessagesHandler extends Handler { if (!udoc) throw new UserNotFoundError(uid); if (udoc.gravatar) udoc.gravatar = misc.gravatar(udoc.gravatar); const mdoc = await message.send(this.user._id, uid, content, message.FLAG_UNREAD); - // TODO(twd2): improve here: projection - if (this.user._id !== uid) { - bus.publish(`user_message-${uid}`, { mdoc, udoc }); - } + // TODO(twd2): improve here: projection\ this.back({ mdoc, udoc }); } diff --git a/hydro/model/message.ts b/hydro/model/message.ts index cbd6ff90b..5920bb9be 100644 --- a/hydro/model/message.ts +++ b/hydro/model/message.ts @@ -1,6 +1,8 @@ import { ObjectID } from 'mongodb'; +import * as user from './user'; import { Mdoc } from '../interface'; import * as db from '../service/db'; +import * as bus from '../service/bus'; const coll = db.collection('message'); @@ -14,9 +16,15 @@ export async function send( const res = await coll.insertOne({ from, to, content, flag, }); - return { + const mdoc = { from, to, content, _id: res.insertedId, flag, }; + if (from !== to) { + // ENHANCE domainId? + const udoc = await user.getById('system', to); + bus.publish(`user_message-${to}`, { mdoc, udoc }); + } + return mdoc; } export async function get(_id: ObjectID): Promise { diff --git a/hydro/service/server.ts b/hydro/service/server.ts index b6b888337..e80028ae8 100644 --- a/hydro/service/server.ts +++ b/hydro/service/server.ts @@ -59,7 +59,8 @@ const Tools: Array<[Converter, Validator, boolean?]> = [ [(v) => parseInt(v, 10), (v) => parseInt(v, 10) > 0], [(v) => parseFloat(v), (v) => { const t = parseFloat(v); - return t && !Number.isNaN(t) && !Number.isFinite(t); + console.log(t); + return t && !Number.isNaN(t) && Number.isFinite(t); }], [(v) => new ObjectID(v), ObjectID.isValid], [(v) => !!v, null, true], @@ -72,7 +73,8 @@ const Tools: Array<[Converter, Validator, boolean?]> = [ (v) => { const d = v.split('-'); assert(d.length === 3); - return moment(`${d[0]}-${d[1].length === 1 ? '0' : ''}${d[1]}-${d[2].length === 1 ? '0' : ''}${d[2]}`).isValid(); + const st = `${d[0]}-${d[1].length === 1 ? '0' : ''}${d[1]}-${d[2].length === 1 ? '0' : ''}${d[2]}`; + return moment(st).isValid(); }], [ (v) => { @@ -83,7 +85,7 @@ const Tools: Array<[Converter, Validator, boolean?]> = [ (v) => { const t = v.split(':'); assert(t.length === 2); - return moment(`${(t[0].length === 1 ? '0' : '') + t[0]}:${t[1].length === 1 ? '0' : ''}${t[1]}`).isValid(); + return moment(`2020-01-01 ${(t[0].length === 1 ? '0' : '') + t[0]}:${t[1].length === 1 ? '0' : ''}${t[1]}`).isValid(); }, ], ];