diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 53c4918ea..b8c858a38 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.25.10", + "version": "2.25.11", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/contest.ts b/packages/hydrooj/src/handler/contest.ts index 57c795366..f74635c23 100644 --- a/packages/hydrooj/src/handler/contest.ts +++ b/packages/hydrooj/src/handler/contest.ts @@ -6,7 +6,7 @@ import { ContestNotLiveError, ValidationError, ProblemNotFoundError, ContestNotAttendedError, PermissionError, } from '../error'; -import { Pdoc, Tdoc, User } from '../interface'; +import { ProblemDoc, Tdoc, User } from '../interface'; import paginate from '../lib/paginate'; import { PERM, PRIV } from '../model/builtin'; import * as contest from '../model/contest'; @@ -240,7 +240,7 @@ class ContestEditHandler extends Handler { class ContestProblemHandler extends Handler { tdoc: Tdoc<30 | 60>; - pdoc: Pdoc; + pdoc: ProblemDoc; tsdoc: any; udoc: User; attended: boolean; diff --git a/packages/hydrooj/src/handler/discussion.ts b/packages/hydrooj/src/handler/discussion.ts index 3ee7ac88e..a863d0709 100644 --- a/packages/hydrooj/src/handler/discussion.ts +++ b/packages/hydrooj/src/handler/discussion.ts @@ -1,7 +1,7 @@ import { ObjectID } from 'mongodb'; import { isSafeInteger } from 'lodash'; import { DiscussionNotFoundError, DocumentNotFoundError, PermissionError } from '../error'; -import { Drdoc, Ddoc, Drrdoc } from '../interface'; +import { DiscussionReplyDoc, DiscussionDoc, DiscussionTailReplyDoc } from '../interface'; import paginate from '../lib/paginate'; import * as system from '../model/system'; import user from '../model/user'; @@ -23,9 +23,9 @@ export const typeMapper = { }; class DiscussionHandler extends Handler { - ddoc?: Ddoc; - drdoc?: Drdoc; - drrdoc?: Drrdoc; + ddoc?: DiscussionDoc; + drdoc?: DiscussionReplyDoc; + drrdoc?: DiscussionTailReplyDoc; vnode?: any; @param('type', Types.Name, true) @@ -214,7 +214,7 @@ class DiscussionDetailHandler extends DiscussionHandler { await this.limitRate('add_discussion', 3600, 60); // Notify related users await discussion.addReply(domainId, did, this.user._id, content, this.request.ip); - const replies: Drdoc[] = await discussion.getMultiReply(domainId, did).toArray(); + const replies: DiscussionReplyDoc[] = await discussion.getMultiReply(domainId, did).toArray(); const uids = new Set(replies.map((drdoc) => drdoc.owner)); uids.delete(this.user._id); const str = JSON.stringify({ message: '{0} replied to discussion {1}/{2}.', params: [this.user._id, domainId, did] }); diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index cd4ff0c85..0e35a7243 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -5,7 +5,7 @@ import { NotFoundError, UserNotFoundError, PermissionError, DomainAlreadyExistsError, ValidationError, BlacklistedError, } from '../error'; -import { Mdoc, Setting, DomainDoc } from '../interface'; +import { MessageDoc, Setting, DomainDoc } from '../interface'; import * as bus from '../service/bus'; import { Route, Connection, Handler, ConnectionHandler, param, Types, @@ -399,7 +399,7 @@ class HomeMessagesConnectionHandler extends ConnectionHandler { this.dispose = bus.on('user/message', this.onMessageReceived.bind(this)); } - async onMessageReceived(uid: number, mdoc: Mdoc) { + async onMessageReceived(uid: number, mdoc: MessageDoc) { if (uid !== this.user._id) return; const udoc = await user.getById(this.domainId, mdoc.from); udoc.avatarUrl = avatar(udoc.avatar, 64); diff --git a/packages/hydrooj/src/handler/homework.ts b/packages/hydrooj/src/handler/homework.ts index 0a28ff656..fa6e233d7 100644 --- a/packages/hydrooj/src/handler/homework.ts +++ b/packages/hydrooj/src/handler/homework.ts @@ -7,7 +7,7 @@ import { ValidationError, HomeworkNotLiveError, ProblemNotFoundError, HomeworkNotAttendedError, } from '../error'; -import { PenaltyRules, Tdoc, Pdoc } from '../interface'; +import { PenaltyRules, Tdoc, ProblemDoc } from '../interface'; import { Route, Handler, Types, param, } from '../service/server'; @@ -118,7 +118,7 @@ class HomeworkDetailHandler extends Handler { class HomeworkDetailProblemHandler extends Handler { tdoc: Tdoc<60>; - pdoc: Pdoc; + pdoc: ProblemDoc; tsdoc: any; @param('tid', Types.ObjectID) diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index 6c5a65d5f..0e5115703 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -1,5 +1,5 @@ import { ObjectID } from 'mongodb'; -import { JudgeResultBody, Rdoc, TestCase } from '../interface'; +import { JudgeResultBody, RecordDoc, TestCase } from '../interface'; import { sleep } from '../utils'; import { Logger } from '../logger'; import difficultyAlgorithm from '../lib/difficulty'; @@ -20,7 +20,7 @@ import { updateJudge } from '../service/monitor'; const logger = new Logger('judge'); -async function _postJudge(rdoc: Rdoc) { +async function _postJudge(rdoc: RecordDoc) { if (typeof rdoc.input === 'string') return; const accept = rdoc.status === builtin.STATUS.STATUS_ACCEPTED; const updated = await problem.updateStatus(rdoc.domainId, rdoc.pid, rdoc.uid, rdoc._id, rdoc.status, rdoc.score); @@ -45,7 +45,7 @@ async function _postJudge(rdoc: Rdoc) { export async function next(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); let rdoc = await record.get(body.domainId, body.rid); - const $set: Partial = {}; + const $set: Partial = {}; const $push: any = {}; if (body.case) { const c: TestCase = { @@ -77,7 +77,7 @@ export async function next(body: JudgeResultBody) { export async function end(body: JudgeResultBody) { if (body.rid) body.rid = new ObjectID(body.rid); let rdoc = await record.get(body.domainId, body.rid); - const $set: Partial = {}; + const $set: Partial = {}; const $push: any = {}; const $unset: any = { progress: '' }; if (body.message) { diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 79e40aa07..56351a371 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -8,7 +8,7 @@ import { ForbiddenError, } from '../error'; import { - Pdoc, User, Rdoc, PathComponent, ProblemStatusDoc, + ProblemDoc, User, RecordDoc, PathComponent, ProblemStatusDoc, } from '../interface'; import paginate from '../lib/paginate'; import { isPid } from '../lib/validator'; @@ -61,7 +61,7 @@ export class ProblemMainHandler extends ProblemHandler { async get(domainId: string, page = 1, q = '', category = []) { this.response.template = 'problem_main.html'; // eslint-disable-next-line @typescript-eslint/no-shadow - const query: FilterQuery = {}; + const query: FilterQuery = {}; let psdict = {}; const path: PathComponent[] = [ ['Hydro', 'homepage'], @@ -161,7 +161,7 @@ export class ProblemMainHandler extends ProblemHandler { export class ProblemRandomHandler extends ProblemHandler { @param('category', Types.Name, true, null, parseCategory) async get(domainId: string, category: string[] = []) { - const q: FilterQuery = category.length ? { $and: [] } : {}; + const q: FilterQuery = category.length ? { $and: [] } : {}; for (const tag of category) q.$and.push({ tag }); if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false; await bus.serial('problem/list', q, this); @@ -172,7 +172,7 @@ export class ProblemRandomHandler extends ProblemHandler { } } -export interface PdocWithPsdoc extends Pdoc { +export interface PdocWithPsdoc extends ProblemDoc { psdoc?: ProblemStatusDoc } @@ -309,7 +309,7 @@ export class ProblemPretestConnectionHandler extends ConnectionHandler { this.dispose = bus.on('record/change', this.onRecordChange.bind(this)); } - async onRecordChange(rdoc: Rdoc) { + async onRecordChange(rdoc: RecordDoc) { if ( rdoc.uid !== this.user._id || rdoc.pid.toString() !== this.pid @@ -366,7 +366,7 @@ export class ProblemEditHandler extends ProblemManageHandler { newPid: string = '', hidden = false, tag: string[] = [], ) { if (newPid !== this.pdoc.pid && await problem.get(domainId, newPid)) throw new BadRequestError('new pid exists'); - const $update: Partial = { + const $update: Partial = { title, content, pid: newPid, hidden, tag: tag ?? [], }; let pdoc = await problem.get(domainId, pid); diff --git a/packages/hydrooj/src/handler/record.ts b/packages/hydrooj/src/handler/record.ts index 4eade0bab..5170042a3 100644 --- a/packages/hydrooj/src/handler/record.ts +++ b/packages/hydrooj/src/handler/record.ts @@ -1,6 +1,6 @@ import { FilterQuery, ObjectID } from 'mongodb'; import { ContestNotFoundError, PermissionError, RecordNotFoundError } from '../error'; -import { Rdoc } from '../interface'; +import { RecordDoc } from '../interface'; import { PERM, STATUS, PRIV } from '../model/builtin'; import * as system from '../model/system'; import problem from '../model/problem'; @@ -24,7 +24,7 @@ class RecordListHandler extends Handler { @param('allDomain', Types.Boolean, true) async get(domainId: string, page = 1, pid?: string, tid?: ObjectID, uidOrName?: string, status?: number, all = false) { this.response.template = 'record_main.html'; - const q: FilterQuery = { 'contest.tid': tid, hidden: false }; + const q: FilterQuery = { 'contest.tid': tid, hidden: false }; if (tid) { const tdoc = await contest.get(domainId, tid, -1); if (!tdoc) throw new ContestNotFoundError(domainId, pid); @@ -178,7 +178,7 @@ class RecordMainConnectionHandler extends ConnectionHandler { if (this.dispose) this.dispose(); } - async onRecordChange(rdoc: Rdoc) { + async onRecordChange(rdoc: RecordDoc) { if (rdoc.input) return; if (rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return; if (rdoc.domainId !== this.domainId) return; @@ -212,7 +212,7 @@ class RecordDetailConnectionHandler extends ConnectionHandler { } // eslint-disable-next-line - async onRecordChange(rdoc: Rdoc, $set?: any, $push?: any) { + async onRecordChange(rdoc: RecordDoc, $set?: any, $push?: any) { if (rdoc._id.toString() !== this.rid) return; // TODO: frontend doesn't support incremental update // if ($set) this.send({ $set, $push }); diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index eeb1b65f1..f6cc1685c 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -12,7 +12,7 @@ import user from '../model/user'; import oauth from '../model/oauth'; import token from '../model/token'; import record from '../model/record'; -import problem, { Pdoc } from '../model/problem'; +import problem, { ProblemDoc } from '../model/problem'; import task from '../model/task'; import * as system from '../model/system'; import { PERM, PRIV } from '../model/builtin'; @@ -196,7 +196,7 @@ class UserDetailHandler extends Handler { 1, 100, ) - : [[], 0, 0] as [Pdoc[], number, number], + : [[], 0, 0] as [ProblemDoc[], number, number], ]); const pdict = this.user.hasPerm(PERM.PERM_VIEW_PROBLEM) ? await problem.getList( diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 4185ef855..ea9c2cac3 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -3,7 +3,7 @@ import type { Cursor, ObjectID } from 'mongodb'; import type fs from 'fs'; import type { Dictionary, NumericDictionary } from 'lodash'; import type * as Koa from 'koa'; -import type { Pdoc } from './model/problem'; +import type { ProblemDoc } from './model/problem'; type document = typeof import('./model/document'); @@ -187,7 +187,7 @@ export interface Document { } declare module './model/problem' { - interface Pdoc { + interface ProblemDoc { docType: document['TYPE_PROBLEM'], docId: number, pid: string, @@ -207,8 +207,8 @@ declare module './model/problem' { config: string, } } -export type { Pdoc } from './model/problem'; -export type Pdict = NumericDictionary; +export type { ProblemDoc } from './model/problem'; +export type ProblemDict = NumericDictionary; export interface StatusDoc { _id: ObjectID, @@ -241,7 +241,7 @@ export interface ContestInfo { tid: ObjectID, } -export interface Rdoc { +export interface RecordDoc { _id: ObjectID, domainId: string, pid: number @@ -318,7 +318,7 @@ export interface DomainDoc extends Record { } // Message -export interface Mdoc { +export interface MessageDoc { _id: ObjectID, from: number, to: number, @@ -326,31 +326,25 @@ export interface Mdoc { flag: number, } -// Userfile -export interface Ufdoc { - _id: ObjectID, - secret: string, - md5?: string, - owner: number, - size?: number, - filename: string, -} - // Blacklist -export interface Bdoc { - _id: string, // ip - expireAt: Date, +export interface BlacklistDoc { + /** + * @example ip:1.1.1.1 + * @example mail:foo.com + */ + _id: string; + expireAt: Date; } export interface HistoryDoc { - content: string, - time: Date, + content: string; + time: Date; } // Discussion -export type { Ddoc } from './model/discussion'; +export type { DiscussionDoc } from './model/discussion'; declare module './model/discussion' { - interface Ddoc { + interface DiscussionDoc { docType: document['TYPE_DISCUSSION'], docId: ObjectID, parentType: number, @@ -367,20 +361,18 @@ declare module './model/discussion' { } } -// Discussion reply -export interface Drdoc extends Document { +export interface DiscussionReplyDoc extends Document { docType: document['TYPE_DISCUSSION_REPLY'], docId: ObjectID, parentType: document['TYPE_DISCUSSION'], parentId: ObjectID, ip: string, content: string, - reply: Drrdoc[], + reply: DiscussionTailReplyDoc[], history: HistoryDoc[], } -// Discussion Tail Reply -export interface Drrdoc { +export interface DiscussionTailReplyDoc { _id: ObjectID, owner: number, content: string, @@ -415,13 +407,13 @@ export interface ContestRule { stat: (tdoc: Tdoc<30 | 60>, journal: any[]) => ContestStat; scoreboard: ( isExport: boolean, _: (s: string) => string, - tdoc: Tdoc<30 | 60>, pdict: Pdict, cursor: Cursor, page: number, + tdoc: Tdoc<30 | 60>, pdict: ProblemDict, cursor: Cursor, page: number, ) => Promise<[board: ScoreboardRow[], udict: Udict, nPages: number]>; ranked: (tdoc: Tdoc<30 | 60>, cursor: Cursor) => Promise; } export type ContestRules = Dictionary; -export type ProblemImporter = (url: string, handler: any) => Promise<[Pdoc, fs.ReadStream?]> | [Pdoc, fs.ReadStream?]; +export type ProblemImporter = (url: string, handler: any) => Promise<[ProblemDoc, fs.ReadStream?]> | [ProblemDoc, fs.ReadStream?]; export interface Script { run: (args: any, report: Function) => any, @@ -481,18 +473,17 @@ export interface BaseService { } export interface Collections { - 'blacklist': Bdoc, + 'blacklist': BlacklistDoc, 'contest': Tdoc, 'domain': DomainDoc, 'domain.user': any, - 'record': Rdoc, + 'record': RecordDoc, 'document': any, - 'problem': Pdoc, + 'problem': ProblemDoc, 'user': Udoc, 'check': any, - 'message': Mdoc, + 'message': MessageDoc, 'token': TokenDoc, - 'file': Ufdoc, 'status': any, 'oauth': any, 'system': System, diff --git a/packages/hydrooj/src/model/contest.ts b/packages/hydrooj/src/model/contest.ts index 440f0ad0f..eb78684e3 100644 --- a/packages/hydrooj/src/model/contest.ts +++ b/packages/hydrooj/src/model/contest.ts @@ -8,7 +8,7 @@ import { ContestNotAttendedError, ContestScoreboardHiddenError, } from '../error'; import { - ContestRule, ContestRules, Pdict, + ContestRule, ContestRules, ProblemDict, ScoreboardNode, ScoreboardRow, Tdoc, Udict, } from '../interface'; @@ -564,7 +564,7 @@ export function canShowScoreboard(tdoc: Tdoc<30 | 60>, allowPermOverride = true) export async function getScoreboard( domainId: string, tid: ObjectID, isExport = false, page: number, docType: 30 | 60 = document.TYPE_CONTEST, -): Promise<[Tdoc<30 | 60>, ScoreboardRow[], Udict, Pdict, number]> { +): Promise<[Tdoc<30 | 60>, ScoreboardRow[], Udict, ProblemDict, number]> { const tdoc = await get(domainId, tid, docType); if (!canShowScoreboard.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); if (!canShowRecord.call(this, tdoc)) throw new ContestScoreboardHiddenError(tid); diff --git a/packages/hydrooj/src/model/discussion.ts b/packages/hydrooj/src/model/discussion.ts index 3e514d80b..c10cee9e6 100644 --- a/packages/hydrooj/src/model/discussion.ts +++ b/packages/hydrooj/src/model/discussion.ts @@ -5,15 +5,15 @@ import * as contest from './contest'; import * as training from './training'; import * as document from './document'; import { DiscussionNodeNotFoundError, DocumentNotFoundError } from '../error'; -import { Drdoc, Drrdoc, Document } from '../interface'; +import { DiscussionReplyDoc, DiscussionTailReplyDoc, Document } from '../interface'; import { buildProjection } from '../utils'; import * as bus from '../service/bus'; -export interface Ddoc extends Document { } -export namespace Ddoc { - export type Field = keyof Ddoc; +export interface DiscussionDoc extends Document { } +export namespace DiscussionDoc { + export type Field = keyof DiscussionDoc; export const fields: Field[] = []; - type Getter = () => Partial; + type Getter = () => Partial; const getters: Getter[] = []; export function extend(getter: Getter) { getters.push(getter); @@ -39,7 +39,7 @@ export namespace Ddoc { })); export function create() { - const result = {} as Ddoc; + const result = {} as DiscussionDoc; for (const getter of getters) { Object.assign(result, getter()); } @@ -47,12 +47,12 @@ export namespace Ddoc { } } -export const PROJECTION_LIST: Ddoc.Field[] = [ +export const PROJECTION_LIST: DiscussionDoc.Field[] = [ '_id', 'domainId', 'docType', 'docId', 'highlight', 'nReply', 'views', 'pin', 'updateAt', 'owner', 'parentId', 'parentType', 'title', ]; -export const PROJECTION_PUBLIC: Ddoc.Field[] = [ +export const PROJECTION_PUBLIC: DiscussionDoc.Field[] = [ ...PROJECTION_LIST, 'content', 'history', ]; @@ -69,7 +69,7 @@ export async function add( owner: number, title: string, content: string, ip: string | null = null, highlight: boolean, pin: boolean, ): Promise { - const payload: Partial = { + const payload: Partial = { domainId, content, owner, @@ -93,15 +93,16 @@ export async function add( return payload.docId; } -// FIXME typings doesn't work -export async function get(domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any): Promise> { +export async function get( + domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any, +): Promise> { return await document.get(domainId, document.TYPE_DISCUSSION, did, projection); } export function edit( domainId: string, did: ObjectID, title: string, content: string, highlight: boolean, pin: boolean, -): Promise { +): Promise { const payload = { title, content, highlight, pin, }; @@ -118,11 +119,11 @@ export function del(domainId: string, did: ObjectID): Promise { ]) as any; } -export function count(domainId: string, query: FilterQuery) { +export function count(domainId: string, query: FilterQuery) { return document.count(domainId, document.TYPE_DISCUSSION, query); } -export function getMulti(domainId: string, query: FilterQuery = {}, projection = PROJECTION_LIST) { +export function getMulti(domainId: string, query: FilterQuery = {}, projection = PROJECTION_LIST) { return document.getMulti(domainId, document.TYPE_DISCUSSION, query) .sort({ pin: -1, updateAt: -1 }) .project(buildProjection(projection)); @@ -142,13 +143,13 @@ export async function addReply( return drid; } -export function getReply(domainId: string, drid: ObjectID): Promise { +export function getReply(domainId: string, drid: ObjectID): Promise { return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid); } export async function editReply( domainId: string, drid: ObjectID, content: string, -): Promise { +): Promise { return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content }); } @@ -168,14 +169,14 @@ export function getMultiReply(domainId: string, did: ObjectID) { ).sort('_id', -1); } -export function getListReply(domainId: string, did: ObjectID): Promise { +export function getListReply(domainId: string, did: ObjectID): Promise { return getMultiReply(domainId, did).toArray(); } export async function addTailReply( domainId: string, drid: ObjectID, owner: number, content: string, ip: string, -): Promise<[Drdoc, ObjectID]> { +): Promise<[DiscussionReplyDoc, ObjectID]> { const [drdoc, subId] = await document.push( domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', content, owner, { ip }, @@ -189,14 +190,14 @@ export async function addTailReply( export function getTailReply( domainId: string, drid: ObjectID, drrid: ObjectID, -): Promise<[Drdoc, Drrdoc] | [null, null]> { +): Promise<[DiscussionReplyDoc, DiscussionTailReplyDoc] | [null, null]> { // @ts-ignore return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid); } export function editTailReply( domainId: string, drid: ObjectID, drrid: ObjectID, content: string, -): Promise { +): Promise { return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content }); } @@ -249,7 +250,7 @@ export function getNodes(domainId: string) { export async function getListVnodes(domainId: string, ddocs: any, getHidden: boolean) { const tasks = []; const res = {}; - async function task(ddoc: Ddoc) { + async function task(ddoc: DiscussionDoc) { const vnode = await getVnode(domainId, ddoc.parentType, ddoc.parentId.toString()); if (!res[ddoc.parentType]) res[ddoc.parentType] = {}; if (vnode.hidden && !getHidden) return; @@ -278,7 +279,7 @@ bus.on('problem/delete', async (domainId, docId) => { global.Hydro.model.discussion = { typeDisplay, - Ddoc, + DiscussionDoc, PROJECTION_LIST, PROJECTION_PUBLIC, diff --git a/packages/hydrooj/src/model/document.ts b/packages/hydrooj/src/model/document.ts index 0e566d0d0..2a106ffa9 100644 --- a/packages/hydrooj/src/model/document.ts +++ b/packages/hydrooj/src/model/document.ts @@ -4,7 +4,7 @@ import { ObjectID, Cursor, FilterQuery, UpdateQuery, OnlyFieldsOfType, } from 'mongodb'; import { - Pdoc, Ddoc, Drdoc, Tdoc, TrainingDoc, + ProblemDoc, DiscussionDoc, DiscussionReplyDoc, Tdoc, TrainingDoc, ProblemStatusDoc, Content, } from '../interface'; import { buildProjection } from '../utils'; @@ -28,12 +28,12 @@ export const TYPE_TRAINING: 40 = 40; export const TYPE_HOMEWORK: 60 = 60; export interface DocType { - [TYPE_PROBLEM]: Pdoc, + [TYPE_PROBLEM]: ProblemDoc, [TYPE_PROBLEM_SOLUTION]: any, [TYPE_PROBLEM_LIST]: any, [TYPE_DISCUSSION_NODE]: any, - [TYPE_DISCUSSION]: Ddoc, - [TYPE_DISCUSSION_REPLY]: Drdoc, + [TYPE_DISCUSSION]: DiscussionDoc, + [TYPE_DISCUSSION_REPLY]: DiscussionReplyDoc, [TYPE_CONTEST]: Tdoc, [TYPE_TRAINING]: TrainingDoc, [TYPE_HOMEWORK]: Tdoc, diff --git a/packages/hydrooj/src/model/message.ts b/packages/hydrooj/src/model/message.ts index 0461a557f..bdd21d72b 100644 --- a/packages/hydrooj/src/model/message.ts +++ b/packages/hydrooj/src/model/message.ts @@ -1,6 +1,6 @@ import { FilterQuery, ObjectID } from 'mongodb'; import user from './user'; -import { Mdoc } from '../interface'; +import { MessageDoc } from '../interface'; import { ArgMethod } from '../utils'; import db from '../service/db'; import * as bus from '../service/bus'; @@ -15,7 +15,7 @@ class MessageModel { static async send( from: number, to: number, content: string, flag: number = MessageModel.FLAG_UNREAD, - ): Promise { + ): Promise { const res = await coll.insertOne({ from, to, content, flag, }); @@ -27,22 +27,22 @@ class MessageModel { return mdoc; } - static async get(_id: ObjectID): Promise { + static async get(_id: ObjectID): Promise { return await coll.findOne({ _id }); } @ArgMethod - static async getByUser(uid: number): Promise { + static async getByUser(uid: number): Promise { return await coll.find({ $or: [{ from: uid }, { to: uid }] }).sort('_id', 1).toArray(); } - static async getMany(query: FilterQuery, sort: any, page: number, limit: number): Promise { + static async getMany(query: FilterQuery, sort: any, page: number, limit: number): Promise { return await coll.find(query).sort(sort) .skip((page - 1) * limit).limit(limit) .toArray(); } - static async setFlag(messageId: ObjectID, flag: number): Promise { + static async setFlag(messageId: ObjectID, flag: number): Promise { const result = await coll.findOneAndUpdate( { _id: messageId }, { $bit: { flag: { xor: flag } } }, @@ -56,7 +56,7 @@ class MessageModel { } @ArgMethod - static count(query: FilterQuery = {}) { + static count(query: FilterQuery = {}) { return coll.find(query).count(); } diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index b1e895f1e..e5f2d0d74 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -5,7 +5,7 @@ import { streamToBuffer } from '@hydrooj/utils/lib/utils'; import * as document from './document'; import { STATUS } from './builtin'; import { buildProjection } from '../utils'; -import type { ProblemStatusDoc, Pdict, Document } from '../interface'; +import type { ProblemStatusDoc, ProblemDict, Document } from '../interface'; import { ArrayKeys, MaybeArray, NumberKeys, Projection, } from '../typeutils'; @@ -13,10 +13,10 @@ import { ProblemNotFoundError, ValidationError } from '../error'; import storage from '../service/storage'; import * as bus from '../service/bus'; -export interface Pdoc extends Document { } -export type Field = keyof Pdoc; +export interface ProblemDoc extends Document { } +export type Field = keyof ProblemDoc; const fields: Field[] = []; -export type Getter = (docId?: number, pid?: string) => Partial; +export type Getter = (docId?: number, pid?: string) => Partial; const getters: Getter[] = []; export class ProblemModel { @@ -37,7 +37,7 @@ export class ProblemModel { } static create(docId?: number, pid?: string) { - const result = {} as Pdoc; + const result = {} as ProblemDoc; for (const getter of getters) { Object.assign(result, getter(docId, pid)); } @@ -59,7 +59,7 @@ export class ProblemModel { domainId: string, docId: number, pid: string = null, title: string, content: string, owner: number, tag: string[] = [], hidden = false, ) { - const args: Partial = { + const args: Partial = { title, tag, hidden, nSubmit: 0, nAccept: 0, }; if (pid) args.pid = pid; @@ -74,8 +74,8 @@ export class ProblemModel { static async get( domainId: string, pid: string | number, - uid: number = null, projection: Projection = ProblemModel.PROJECTION_PUBLIC, - ): Promise { + uid: number = null, projection: Projection = ProblemModel.PROJECTION_PUBLIC, + ): Promise { if (typeof pid !== 'number') { if (Number.isSafeInteger(parseInt(pid, 10))) pid = parseInt(pid, 10); } @@ -89,15 +89,15 @@ export class ProblemModel { return pdoc; } - static getMulti(domainId: string, query: FilterQuery, projection = ProblemModel.PROJECTION_LIST) { + static getMulti(domainId: string, query: FilterQuery, projection = ProblemModel.PROJECTION_LIST) { return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection); } - static getMultiStatus(domainId: string, query: FilterQuery) { + static getMultiStatus(domainId: string, query: FilterQuery) { return document.getMultiStatus(domainId, document.TYPE_PROBLEM, query); } - static async edit(domainId: string, _id: number, $set: Partial): Promise { + static async edit(domainId: string, _id: number, $set: Partial): Promise { const delpid = $set.pid === ''; if (delpid) delete $set.pid; await bus.serial('problem/before-edit', $set); @@ -106,19 +106,19 @@ export class ProblemModel { return result; } - static push>(domainId: string, _id: number, key: ArrayKeys, value: Pdoc[T][0]) { + static push>(domainId: string, _id: number, key: ArrayKeys, value: ProblemDoc[T][0]) { return document.push(domainId, document.TYPE_PROBLEM, _id, key, value); } - static pull>(domainId: string, pid: number, key: ArrayKeys, values: Pdoc[T][0][]) { + static pull>(domainId: string, pid: number, key: ArrayKeys, values: ProblemDoc[T][0][]) { return document.deleteSub(domainId, document.TYPE_PROBLEM, pid, key, values); } - static inc(domainId: string, _id: number, field: NumberKeys, n: number): Promise { + static inc(domainId: string, _id: number, field: NumberKeys, n: number): Promise { return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n); } - static count(domainId: string, query: FilterQuery) { + static count(domainId: string, query: FilterQuery) { return document.count(domainId, document.TYPE_PROBLEM, query); } @@ -174,7 +174,7 @@ export class ProblemModel { await bus.emit('problem/delAdditionalFile', domainId, pid, names); } - static async random(domainId: string, query: FilterQuery): Promise { + static async random(domainId: string, query: FilterQuery): Promise { const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query); const pcount = await cursor.count(); if (pcount) { @@ -186,7 +186,7 @@ export class ProblemModel { static async getList( domainId: string, pids: Array, getHidden = false, doThrow = true, projection = ProblemModel.PROJECTION_PUBLIC, - ): Promise { + ): Promise { pids = Array.from(new Set(pids)).map((i) => (+i ? +i : i)); const r = {}; const l = {}; diff --git a/packages/hydrooj/src/model/record.ts b/packages/hydrooj/src/model/record.ts index 52992ff02..8aa783537 100644 --- a/packages/hydrooj/src/model/record.ts +++ b/packages/hydrooj/src/model/record.ts @@ -8,15 +8,15 @@ import moment from 'moment'; import { STATUS } from './builtin'; import task from './task'; import problem from './problem'; -import { Rdoc, ContestInfo, ProblemConfig } from '../interface'; +import { RecordDoc, ContestInfo, ProblemConfig } from '../interface'; import { ArgMethod, buildProjection, Time } from '../utils'; import { MaybeArray } from '../typeutils'; import * as bus from '../service/bus'; import db from '../service/db'; class RecordModel { - static coll: Collection = db.collection('record'); - static PROJECTION_LIST: (keyof Rdoc)[] = [ + static coll: Collection = db.collection('record'); + static PROJECTION_LIST: (keyof RecordDoc)[] = [ '_id', 'score', 'time', 'memory', 'lang', 'uid', 'pid', 'rejudged', 'hidden', 'progress', 'contest', 'effective', 'judger', 'judgeAt', 'status', @@ -29,7 +29,7 @@ class RecordModel { return base - ((pending + 0.5) * (sum(timeRecent.map((i) => i.time || 0)) / 10000)); } - static async get(domainId: string, _id: ObjectID): Promise { + static async get(domainId: string, _id: ObjectID): Promise { const res = await RecordModel.coll.findOne({ _id }); if (res && res.domainId === domainId) return res; return null; @@ -74,7 +74,7 @@ class RecordModel { domainId: string, pid: number, uid: number, lang: string, code: string, addTask: boolean, contestOrConfig?: ContestInfo | string, ) { - const data: Rdoc = { + const data: RecordDoc = { status: STATUS.STATUS_WAITING, _id: new ObjectID(), uid, @@ -116,11 +116,11 @@ class RecordModel { static async update( domainId: string, _id: MaybeArray, - $set?: MatchKeysAndValues, - $push?: PushOperator, - $unset?: OnlyFieldsOfType, - ): Promise { - const $update: UpdateQuery = {}; + $set?: MatchKeysAndValues, + $push?: PushOperator, + $unset?: OnlyFieldsOfType, + ): Promise { + const $update: UpdateQuery = {}; if ($set && Object.keys($set).length) $update.$set = $set; if ($push && Object.keys($push).length) $update.$push = $push; if ($unset && Object.keys($unset).length) $update.$unset = $unset; @@ -140,12 +140,12 @@ class RecordModel { } static async updateMulti( - domainId: string, $match: FilterQuery, - $set?: MatchKeysAndValues, - $push?: PushOperator, - $unset?: OnlyFieldsOfType, + domainId: string, $match: FilterQuery, + $set?: MatchKeysAndValues, + $push?: PushOperator, + $unset?: OnlyFieldsOfType, ) { - const $update: UpdateQuery = {}; + const $update: UpdateQuery = {}; if ($set && Object.keys($set).length) $update.$set = $set; if ($push && Object.keys($push).length) $update.$push = $push; if ($unset && Object.keys($unset).length) $update.$unset = $unset; @@ -174,8 +174,8 @@ class RecordModel { } static async getList( - domainId: string, rids: ObjectID[], showHidden: boolean, fields?: (keyof Rdoc)[], - ): Promise>> { + domainId: string, rids: ObjectID[], showHidden: boolean, fields?: (keyof RecordDoc)[], + ): Promise>> { const r = {}; rids = Array.from(new Set(rids)); let cursor = RecordModel.coll.find({ domainId, _id: { $in: rids } }); @@ -202,7 +202,7 @@ class RecordModel { } @ArgMethod - static getByUid(domainId: string, uid: number, limit: number): Promise { + static getByUid(domainId: string, uid: number, limit: number): Promise { return RecordModel.coll.find({ domainId, uid, hidden: false }).sort({ _id: -1 }).limit(limit).toArray(); } } diff --git a/packages/hydrooj/src/pipelineUtils.ts b/packages/hydrooj/src/pipelineUtils.ts index f9a773cc2..d14ea05b9 100644 --- a/packages/hydrooj/src/pipelineUtils.ts +++ b/packages/hydrooj/src/pipelineUtils.ts @@ -4,7 +4,7 @@ import type { DomainDoc, Udoc, ProblemStatusDoc } from './interface'; import domain from './model/domain'; import * as document from './model/document'; import user from './model/user'; -import problem, { Field, Pdoc } from './model/problem'; +import problem, { Field, ProblemDoc } from './model/problem'; export async function iterateAllDomain(cb: (ddoc: DomainDoc, current?: number, total?: number) => Promise) { const ddocs = await domain.getMulti().toArray(); @@ -26,14 +26,14 @@ export async function iterateAllPsdoc(filter: FilterQuery, cb: }); } -interface PartialPdoc extends Pdoc { +interface PartialProblemDoc extends ProblemDoc { [key: string]: any, } export async function iterateAllProblemInDomain( domainId: string, fields: (Field | string)[], - cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise, + cb: (pdoc: PartialProblemDoc, current?: number, total?: number) => Promise, ) { if (!fields.includes('domainId')) fields.push('domainId'); if (!fields.includes('docId')) fields.push('docId'); @@ -50,7 +50,7 @@ export async function iterateAllProblemInDomain( export async function iterateAllProblem( fields: (Field | string)[], - cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise, + cb: (pdoc: PartialProblemDoc, current?: number, total?: number) => Promise, ) { await iterateAllDomain(async (d) => { await iterateAllProblemInDomain(d._id, fields, cb); diff --git a/packages/hydrooj/src/script/rating.ts b/packages/hydrooj/src/script/rating.ts index 83774e7ed..b55335148 100644 --- a/packages/hydrooj/src/script/rating.ts +++ b/packages/hydrooj/src/script/rating.ts @@ -1,7 +1,7 @@ /* eslint-disable no-await-in-loop */ import { NumericDictionary } from 'lodash'; import { ObjectID, FilterQuery } from 'mongodb'; -import { Tdoc, Pdoc, Udoc } from '../interface'; +import { Tdoc, ProblemDoc, Udoc } from '../interface'; import domain from '../model/domain'; import * as contest from '../model/contest'; import problem from '../model/problem'; @@ -14,10 +14,10 @@ export const description = 'Calculate rp of a domain, or all domains'; type ND = NumericDictionary; -async function runProblem(pdoc: Pdoc, udict: ND): Promise; +async function runProblem(pdoc: ProblemDoc, udict: ND): Promise; async function runProblem(domainId: string, pid: number, udict: ND): Promise; async function runProblem(...arg: any[]) { - const pdoc: Pdoc = (typeof arg[0] === 'string') + const pdoc: ProblemDoc = (typeof arg[0] === 'string') ? await problem.get(arg[0], arg[1], -1) : arg[0]; const udict: ND = (typeof arg[0] === 'string') ? arg[2] : arg[1]; diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index 28bdb32a7..533cd09b2 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -6,7 +6,9 @@ import { argv } from 'yargs'; import type { Handler } from './server'; import { Logger } from '../logger'; import type { - Mdoc, Pdoc, Rdoc, TrainingDoc, User, Ddoc, DomainDoc, FileInfo, + MessageDoc, ProblemDoc, RecordDoc, + TrainingDoc, User, DiscussionDoc, + DomainDoc, FileInfo, } from '../interface'; import type { DocType } from '../model/document'; import type { ProblemSolutionHandler } from '../handler/problem'; @@ -45,7 +47,7 @@ export interface EventMap extends Record { 'monitor/update': (type: 'server' | 'judge', $set: any) => VoidReturn - 'user/message': (uid: number, mdoc: Mdoc) => void + 'user/message': (uid: number, mdoc: MessageDoc) => void 'user/get': (udoc: User) => void 'domain/create': (ddoc: DomainDoc) => VoidReturn @@ -68,17 +70,17 @@ export interface EventMap extends Record { 'handler/finish/UserRegister': (thisArg: UserRegisterHandler) => VoidReturn 'handler/solution/get': (thisArg: ProblemSolutionHandler) => VoidReturn - 'discussion/before-add': (payload: Partial) => VoidReturn - 'discussion/add': (payload: Partial) => VoidReturn + 'discussion/before-add': (payload: Partial) => VoidReturn + 'discussion/add': (payload: Partial) => VoidReturn - 'problem/before-add': (doc: Partial) => VoidReturn - 'problem/add': (doc: Partial, docId: number) => VoidReturn - 'problem/before-edit': (doc: Partial) => VoidReturn - 'problem/edit': (doc: Pdoc) => VoidReturn + 'problem/before-add': (doc: Partial) => VoidReturn + 'problem/add': (doc: Partial, docId: number) => VoidReturn + 'problem/before-edit': (doc: Partial) => VoidReturn + 'problem/edit': (doc: ProblemDoc) => VoidReturn 'problem/before-del': (domainId: string, docId: number) => VoidReturn 'problem/del': (domainId: string, docId: number) => VoidReturn - 'problem/list': (query: FilterQuery, handler: any) => VoidReturn - 'problem/get': (doc: Pdoc, handler: any) => VoidReturn + 'problem/list': (query: FilterQuery, handler: any) => VoidReturn + 'problem/get': (doc: ProblemDoc, handler: any) => VoidReturn 'problem/delete': (domainId: string, docId: number) => VoidReturn 'problem/addTestdata': (domainId: string, docId: number, name: string, payload: Omit) => VoidReturn 'problem/delTestdata': (domainId: string, docId: number, name: string[]) => VoidReturn @@ -88,8 +90,8 @@ export interface EventMap extends Record { 'training/list': (query: FilterQuery, handler: any) => VoidReturn 'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn - 'record/change': (rdoc: Rdoc, $set?: any, $push?: any) => void - 'record/judge': (rdoc: Rdoc, updated: boolean) => VoidReturn + 'record/change': (rdoc: RecordDoc, $set?: any, $push?: any) => void + 'record/judge': (rdoc: RecordDoc, updated: boolean) => VoidReturn } function getHooks(name: K) { diff --git a/packages/hydrooj/src/upgrade.ts b/packages/hydrooj/src/upgrade.ts index 610842f39..c7c6d84ea 100644 --- a/packages/hydrooj/src/upgrade.ts +++ b/packages/hydrooj/src/upgrade.ts @@ -7,7 +7,7 @@ import yaml from 'js-yaml'; import { pick } from 'lodash'; import { convertIniConfig } from '@hydrooj/utils/lib/cases'; import { Progress } from './ui'; -import { Rdoc } from './interface'; +import { RecordDoc } from './interface'; import { Logger } from './logger'; import { streamToBuffer } from './utils'; import { @@ -254,7 +254,7 @@ const scripts: UpgradeScript[] = [ while (await data.hasNext()) { const d: any = await data.next(); logger.info('%o', d); - const filter: FilterQuery = { domainId: d._id.domainId, pid: d._id.pid, uid: d._id.uid }; + const filter: FilterQuery = { domainId: d._id.domainId, pid: d._id.pid, uid: d._id.uid }; if (d.nAccept) { const [first] = await db.collection('record') .find({ ...filter, status: STATUS.STATUS_ACCEPTED })