比赛举办者可给用户推送通知

This commit is contained in:
undefined committed 2020-07-21 11:22:06 +08:00
1 parent 0f1f5f26e1
commit bfc2e95ef5
5 files changed
+48 -11

No files matched your search

-1
View File
@@ -2,7 +2,6 @@
discussion前端权限节点显示异常?
web端运行脚本异常?
讨论回复通知
比赛举办者发布通知
举报功能
SETTINGS_PRIVACY.allowRegisteredUsers
model.setting.ui.name
+33 -2
View File
@@ -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);
+1 -4
View File
@@ -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 });
}
+9 -1
View File
@@ -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<Mdoc> {
+5 -3
View File
@@ -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();
},
],
];