mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
core: 整合tag与category
This commit is contained in:
1 parent
454afbcb08
commit
7a41fecb0e
15 files changed
+116
-117
No files matched your search
@@ -35,7 +35,7 @@ class FpsProblemImportHandler extends Handler {
|
||||
};
|
||||
const title = decodeHTML(p.title.join(' '));
|
||||
const tags = filter(p.source, (i: string) => i.trim());
|
||||
const pid = await problem.add(domainId, null, title, content, this.user._id, tags, []);
|
||||
const pid = await problem.add(domainId, null, title, content, this.user._id, tags);
|
||||
await problem.addTestdata(domainId, pid, 'config.yaml', Buffer.from(`time: ${config.time}\nmemory: ${config.memory}`));
|
||||
if (p.test_output) {
|
||||
for (let i = 0; i < p.test_input.length; i++) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/fps-importer",
|
||||
"version": "1.1.7",
|
||||
"version": "1.1.8",
|
||||
"description": "Import FPS problems",
|
||||
"main": "package.json",
|
||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||
@@ -17,7 +17,7 @@
|
||||
"bson": "^4.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hydrooj": "^2.15.0"
|
||||
"hydrooj": "^2.20.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "2.19.6",
|
||||
"version": "2.20.0",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"main": "dist/loader.js",
|
||||
"typings": "dist/loader.d.ts",
|
||||
|
||||
@@ -96,8 +96,7 @@ class ProblemImportSYZOJHandler extends Handler {
|
||||
});
|
||||
}
|
||||
const docId = await problem.add(
|
||||
domainId, target, p.title, content, this.user._id,
|
||||
p.tags || [], [], hidden,
|
||||
domainId, target, p.title, content, this.user._id, p.tags || [], hidden,
|
||||
);
|
||||
const r = download(`${url}testdata/download`);
|
||||
const file = path.resolve(os.tmpdir(), 'hydro', `import_${domainId}_${docId}.zip`);
|
||||
@@ -166,8 +165,7 @@ class ProblemImportSYZOJHandler extends Handler {
|
||||
...result.body.localizedContentsOfAllLocales,
|
||||
][0].title;
|
||||
const docId = await problem.add(
|
||||
domainId, target, title, content, this.user._id,
|
||||
tags || [], [], hidden,
|
||||
domainId, target, title, content, this.user._id, tags || [], hidden,
|
||||
);
|
||||
const syncFiles = async () => {
|
||||
const judge = result.body.judgeInfo;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { isSafeInteger, flatten } from 'lodash';
|
||||
import yaml from 'js-yaml';
|
||||
import { FilterQuery, ObjectID } from 'mongodb';
|
||||
import AdmZip from 'adm-zip';
|
||||
import {
|
||||
NoProblemError, PermissionError, ValidationError,
|
||||
SolutionNotFoundError, ProblemNotFoundError,
|
||||
SolutionNotFoundError, ProblemNotFoundError, BadRequestError,
|
||||
} from '../error';
|
||||
import {
|
||||
Pdoc, User, Rdoc, PathComponent,
|
||||
@@ -102,14 +101,7 @@ export class ProblemCategoryHandler extends ProblemHandler {
|
||||
async get(domainId: string, page = 1, category: string[]) {
|
||||
this.response.template = 'problem_main.html';
|
||||
const q: any = { $and: [] };
|
||||
for (const name of category) {
|
||||
q.$and.push({
|
||||
$or: [
|
||||
{ category: { $elemMatch: { $eq: name } } },
|
||||
{ tag: { $elemMatch: { $eq: name } } },
|
||||
],
|
||||
});
|
||||
}
|
||||
for (const tag of category) q.$and.push({ tag });
|
||||
let psdict = {};
|
||||
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) q.hidden = false;
|
||||
await bus.serial('problem/list', q, this);
|
||||
@@ -138,17 +130,8 @@ export class ProblemCategoryHandler extends ProblemHandler {
|
||||
export class ProblemRandomHandler extends ProblemHandler {
|
||||
@param('category', Types.String, true, null, parseCategory)
|
||||
async get(domainId: string, category: string[] = []) {
|
||||
const q: any = category.length ? { $and: [] } : {};
|
||||
for (const name of category) {
|
||||
if (name) {
|
||||
q.$and.push({
|
||||
$or: [
|
||||
{ category: { $elemMatch: { $eq: name } } },
|
||||
{ tag: { $elemMatch: { $eq: name } } },
|
||||
],
|
||||
});
|
||||
}
|
||||
}
|
||||
const q: FilterQuery<Pdoc> = 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);
|
||||
const pid = await problem.random(domainId, q);
|
||||
@@ -321,45 +304,6 @@ export class ProblemManageHandler extends ProblemDetailHandler {
|
||||
}
|
||||
}
|
||||
|
||||
export class ProblemSettingsHandler extends ProblemManageHandler {
|
||||
@param('pid', Types.String)
|
||||
async get(domainId: string, pid: string) {
|
||||
this.response.template = 'problem_settings.html';
|
||||
this.response.body.path = [
|
||||
['Hydro', 'homepage'],
|
||||
['problem_main', 'problem_main'],
|
||||
[this.pdoc.title, 'problem_detail', { pid }, true],
|
||||
['problem_settings', null],
|
||||
];
|
||||
}
|
||||
|
||||
@param('pid', Types.String, null, parsePid)
|
||||
@param('yaml', Types.String)
|
||||
async postConfig(domainId: string, pid: string | number, cfg: string) {
|
||||
const pdoc = await problem.get(domainId, pid);
|
||||
// TODO validate
|
||||
const config = yaml.load(cfg) as any;
|
||||
await problem.edit(domainId, pdoc.docId, { config });
|
||||
this.back();
|
||||
}
|
||||
|
||||
@param('pid', Types.String, null, parsePid)
|
||||
@param('hidden', Types.Boolean)
|
||||
@param('category', Types.String, true, null, parseCategory)
|
||||
@param('tag', Types.String, true, null, parseCategory)
|
||||
async postSetting(
|
||||
domainId: string, pid: string | number, hidden = false,
|
||||
category: string[] = [], tag: string[] = [],
|
||||
) {
|
||||
const pdoc = await problem.get(domainId, pid);
|
||||
const update: Partial<Pdoc> = { hidden, category, tag };
|
||||
await bus.serial('problem/setting', update, this);
|
||||
await problem.edit(domainId, pdoc.docId, update);
|
||||
await global.Hydro.script.difficulty.run({ domainId, pid }, console.log);
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
|
||||
export class ProblemEditHandler extends ProblemManageHandler {
|
||||
async get({ pid }) {
|
||||
this.response.template = 'problem_edit.html';
|
||||
@@ -371,17 +315,29 @@ export class ProblemEditHandler extends ProblemManageHandler {
|
||||
];
|
||||
}
|
||||
|
||||
@param('title', Types.String, isTitle)
|
||||
@param('content', Types.String, isContent)
|
||||
@route('pid', Types.String, null, parsePid)
|
||||
@post('title', Types.String, isTitle)
|
||||
@post('content', Types.String, isContent)
|
||||
@post('pid', Types.String, isPid, true)
|
||||
async post(domainId: string, title: string, content: string, newPid: string = '') {
|
||||
@post('hidden', Types.Boolean)
|
||||
@post('tag', Types.String, true, null, parseCategory)
|
||||
async post(
|
||||
domainId: string, pid: string | number, title: string, content: string,
|
||||
newPid: string = '', hidden = false, tag: string[],
|
||||
) {
|
||||
try {
|
||||
content = JSON.parse(content);
|
||||
} catch { /* Ignore */ }
|
||||
const $update: Partial<Pdoc> = { title, content, pid: newPid };
|
||||
let pdoc = await problem.get(domainId, this.request.params.pid);
|
||||
if (await problem.get(domainId, newPid)) throw new BadRequestError('new pid exists');
|
||||
const $update: Partial<Pdoc> = {
|
||||
title, content, pid: newPid, hidden, tag,
|
||||
};
|
||||
let pdoc = await problem.get(domainId, pid);
|
||||
await bus.serial('problem/before-edit', $update);
|
||||
pdoc = await problem.edit(domainId, pdoc.docId, $update);
|
||||
this.response.redirect = this.url('problem_detail', { pid: pdoc.pid || pdoc.docId });
|
||||
await bus.emit('problem/edit', pdoc);
|
||||
await global.Hydro.script.difficulty.run({ domainId, pid }, console.log);
|
||||
this.response.redirect = this.url('problem_detail', { pid: newPid || pdoc.docId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,20 +550,19 @@ export class ProblemCreateHandler extends Handler {
|
||||
};
|
||||
}
|
||||
|
||||
@param('title', Types.String, isTitle)
|
||||
@param('pid', Types.String, isPid, true)
|
||||
@param('content', Types.String, isContent)
|
||||
@param('hidden', Types.Boolean)
|
||||
async post(domainId: string, title: string, pid: string, content: string, hidden = false) {
|
||||
@post('title', Types.String, isTitle)
|
||||
@post('content', Types.String, isContent)
|
||||
@post('pid', Types.String, isPid, true)
|
||||
@post('hidden', Types.Boolean)
|
||||
@post('tag', Types.String, true, null, parseCategory)
|
||||
async post(domainId: string, title: string, content: string, pid: string, hidden = false, tag: string[] = []) {
|
||||
try {
|
||||
content = JSON.parse(content);
|
||||
} catch { /* Ignore */ }
|
||||
const docId = await problem.add(
|
||||
domainId, pid, title, content,
|
||||
this.user._id, [], [], hidden,
|
||||
);
|
||||
this.response.body = { pid: docId };
|
||||
this.response.redirect = this.url('problem_settings', { pid: docId });
|
||||
if (await problem.get(domainId, pid)) throw new BadRequestError('invalid pid');
|
||||
const docId = await problem.add(domainId, pid, title, content, this.user._id, tag, hidden);
|
||||
this.response.body = { pid: pid || docId };
|
||||
this.response.redirect = this.url('problem_settings', { pid: pid || docId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +573,6 @@ export async function apply() {
|
||||
Route('problem_detail', '/p/:pid', ProblemDetailHandler, PERM.PERM_VIEW_PROBLEM);
|
||||
Route('problem_submit', '/p/:pid/submit', ProblemSubmitHandler, PERM.PERM_SUBMIT_PROBLEM);
|
||||
Route('problem_pretest', '/p/:pid/pretest', ProblemPretestHandler, PERM.PERM_SUBMIT_PROBLEM);
|
||||
Route('problem_settings', '/p/:pid/settings', ProblemSettingsHandler);
|
||||
Route('problem_statistics', '/p/:pid/statistics', ProblemStatisticsHandler, PERM.PERM_VIEW_PROBLEM);
|
||||
Route('problem_edit', '/p/:pid/edit', ProblemEditHandler);
|
||||
Route('problem_files', '/p/:pid/files', ProblemFilesHandler, PERM.PERM_VIEW_PROBLEM);
|
||||
|
||||
@@ -141,7 +141,7 @@ export class ProblemReceiveHandler extends Handler {
|
||||
const exist = await problem.get(domainId, pdoc.pid);
|
||||
if (exist) pdoc.pid = undefined;
|
||||
}
|
||||
const pid = await problem.add(domainId, pdoc.pid, pdoc.title, pdoc.content, this.user._id, pdoc.tag, pdoc.category);
|
||||
const pid = await problem.add(domainId, pdoc.pid, pdoc.title, pdoc.content, this.user._id, pdoc.tag);
|
||||
pids.push(pid);
|
||||
this.syncFiles(domainId, baseUrl, pid, files[i]).catch(logAndReturn(logger));
|
||||
await problem.edit(domainId, pid, { html: pdoc.html });
|
||||
|
||||
@@ -174,7 +174,8 @@ declare module './model/problem' {
|
||||
nSubmit: number,
|
||||
nAccept: number,
|
||||
tag: string[],
|
||||
category: string[],
|
||||
/** @deprecated */
|
||||
category?: string[],
|
||||
data: FileInfo[],
|
||||
additional_file: FileInfo[],
|
||||
hidden: boolean,
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { inspect, format } from 'util';
|
||||
import { inspect, format, InspectOptions } from 'util';
|
||||
import { argv } from 'yargs';
|
||||
import { Time } from './utils';
|
||||
|
||||
const colors = [
|
||||
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62,
|
||||
63, 68, 69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113,
|
||||
129, 134, 135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168,
|
||||
169, 170, 171, 172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200,
|
||||
201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 220, 221,
|
||||
];
|
||||
const instances: Record<string, Logger> = {};
|
||||
type LogFunction = (format: any, ...param: any[]) => boolean;
|
||||
type LogFunction = (format: any, ...param: any[]) => void;
|
||||
type LogType = 'success' | 'error' | 'info' | 'warn' | 'debug';
|
||||
export interface Logger extends Record<LogType, LogFunction> { }
|
||||
|
||||
export class Logger {
|
||||
static readonly SUCCESS = 1;
|
||||
static readonly ERROR = 1;
|
||||
@@ -16,10 +24,24 @@ export class Logger {
|
||||
static showDiff = false;
|
||||
static levels: Record<string, number> = {};
|
||||
static lastTime = 0;
|
||||
static formatters: Record<string, (this: Logger, value: any) => string> = {
|
||||
o: (value) => inspect(value).replace(/\s*\n\s*/g, ' '),
|
||||
private code: number;
|
||||
private displayName: string;
|
||||
public stream: NodeJS.WritableStream = process.stderr;
|
||||
static options: InspectOptions = {
|
||||
colors: process.stderr.isTTY,
|
||||
};
|
||||
|
||||
static formatters: Record<string, (this: Logger, value: any) => string> = {
|
||||
c: Logger.prototype.color,
|
||||
C: (value) => Logger.color(15, value, ';1'),
|
||||
o: (value) => inspect(value, Logger.options).replace(/\s*\n\s*/g, ' '),
|
||||
};
|
||||
|
||||
static color(code: number, value: any, decoration = '') {
|
||||
if (!Logger.options.colors) return `${value}`;
|
||||
return `\u001B[3${code < 8 ? code : `8;5;${code}`}${decoration}m${value}\u001B[0m`;
|
||||
}
|
||||
|
||||
constructor(public name: string, private showDiff = false) {
|
||||
if (name in instances) return instances[name];
|
||||
let hash = 0;
|
||||
@@ -28,6 +50,8 @@ export class Logger {
|
||||
hash |= 0;
|
||||
}
|
||||
instances[name] = this;
|
||||
this.code = colors[Math.abs(hash) % colors.length];
|
||||
this.displayName = name ? this.color(`${name} `, ';1') : '';
|
||||
this.createMethod('success', '[S] ', Logger.SUCCESS);
|
||||
this.createMethod('error', '[E] ', Logger.ERROR);
|
||||
this.createMethod('info', '[I] ', Logger.INFO);
|
||||
@@ -35,10 +59,14 @@ export class Logger {
|
||||
this.createMethod('debug', '[D] ', Logger.DEBUG);
|
||||
}
|
||||
|
||||
private color(value: any, decoration = '') {
|
||||
return Logger.color(this.code, value, decoration);
|
||||
}
|
||||
|
||||
private createMethod(name: LogType, prefix: string, minLevel: number) {
|
||||
this[name] = (...args: [any, ...any[]]) => {
|
||||
if (this.level < minLevel) return false;
|
||||
const msg = `${prefix} ${this.name} ${this.format(...args)}`;
|
||||
const msg = `${prefix} ${this.displayName} ${this.format(...args)}`;
|
||||
if (process.send) process.send({ event: 'message/log', payload: [msg] });
|
||||
else global.Hydro.service.bus.parallel('message/log', msg);
|
||||
return true;
|
||||
@@ -68,7 +96,9 @@ export class Logger {
|
||||
}).split('\n').join('\n ');
|
||||
if (Logger.showDiff || this.showDiff) {
|
||||
const now = Date.now();
|
||||
if (Logger.lastTime) args.push(`+${Time.formatTimeShort(now - Logger.lastTime)}`);
|
||||
if (Logger.lastTime) {
|
||||
args.push(this.color(`+${Time.formatTimeShort(now - Logger.lastTime)}`));
|
||||
}
|
||||
Logger.lastTime = now;
|
||||
}
|
||||
return format(...args);
|
||||
|
||||
@@ -390,8 +390,6 @@ async function ensureIndexes() {
|
||||
await ic({ domainId: 1, docType: 1, owner: 1, docId: -1 });
|
||||
// For problem
|
||||
await ic({ domainId: 1, docType: 1, search: 'text', title: 'text' }, s);
|
||||
await ic({ domainId: 1, docType: 1, category: 1, docId: 1 }, s);
|
||||
await ic({ domainId: 1, docType: 1, hidden: 1, category: 1, docId: 1 }, s);
|
||||
await ic({ domainId: 1, docType: 1, tag: 1, docId: 1 }, s);
|
||||
await ic({ domainId: 1, docType: 1, hidden: 1, tag: 1, docId: 1 }, s);
|
||||
// For problem solution
|
||||
|
||||
@@ -38,7 +38,6 @@ export namespace Pdoc {
|
||||
nSubmit: 0,
|
||||
nAccept: 0,
|
||||
tag: [],
|
||||
category: [],
|
||||
data: [],
|
||||
additional_file: [],
|
||||
hidden: true,
|
||||
@@ -72,7 +71,7 @@ export const SETTING_DIFFICULTY_RANGE = [
|
||||
export const PROJECTION_LIST: Pdoc.Field[] = [
|
||||
'_id', 'domainId', 'docType', 'docId', 'pid',
|
||||
'owner', 'title', 'nSubmit', 'nAccept', 'difficulty',
|
||||
'tag', 'category', 'hidden',
|
||||
'tag', 'hidden',
|
||||
];
|
||||
|
||||
export const PROJECTION_PUBLIC: Pdoc.Field[] = [
|
||||
@@ -83,11 +82,11 @@ export const PROJECTION_PUBLIC: Pdoc.Field[] = [
|
||||
|
||||
export async function add(
|
||||
domainId: string, pid: string = null, title: string, content: Content, owner: number,
|
||||
tag: string[] = [], category: string[] = [], hidden = false,
|
||||
tag: string[] = [], hidden = false,
|
||||
) {
|
||||
const pidCounter = await domain.inc(domainId, 'pidCounter', 1);
|
||||
const args: Partial<Pdoc> = {
|
||||
title, category, tag, hidden, nSubmit: 0, nAccept: 0,
|
||||
title, tag, hidden, nSubmit: 0, nAccept: 0,
|
||||
};
|
||||
if (pid) args.pid = pid;
|
||||
return await document.add(domainId, content, owner, document.TYPE_PROBLEM, pidCounter, null, null, args);
|
||||
|
||||
@@ -52,9 +52,12 @@ export interface EventMap {
|
||||
'domain/update': (domainId: string, $set: Partial<DomainDoc>, ddoc: DomainDoc) => VoidReturn
|
||||
|
||||
'document/add': (doc: any) => VoidReturn
|
||||
'document/set': <T extends keyof DocType>
|
||||
(domainId: string, docType: T, docId: DocType[T], $set: any, $unset: OnlyFieldsOfType<DocType[T], any, true | '' | 1>) => VoidReturn
|
||||
'document/set': <T extends keyof DocType>(
|
||||
domainId: string, docType: T, docId: DocType[T],
|
||||
$set: any, $unset: OnlyFieldsOfType<DocType[T], any, true | '' | 1>
|
||||
) => VoidReturn
|
||||
|
||||
'problem/before-edit': (doc: Partial<Pdoc>) => VoidReturn
|
||||
'problem/edit': (doc: Pdoc) => VoidReturn
|
||||
'problem/list': (query: FilterQuery<Pdoc>, handler: any) => VoidReturn
|
||||
'problem/setting': (update: Partial<Pdoc>, handler: any) => VoidReturn
|
||||
|
||||
@@ -51,7 +51,6 @@ if (useTerminal) {
|
||||
process.stdin.on('data', (data) => {
|
||||
// Control Seq?
|
||||
const seq = data.toString('hex');
|
||||
logger.info(data.toString('hex'));
|
||||
if (seq === '7f') input = input.substr(0, input.length - 1);
|
||||
else if (seq === '1b5b41') {
|
||||
// Arrow up
|
||||
|
||||
@@ -25,15 +25,25 @@ async function iterateAllDomain(cb: (ddoc: DomainDoc, current?: number, total?:
|
||||
for (const i in ddocs) await cb(ddocs[i], +i, ddocs.length);
|
||||
}
|
||||
|
||||
async function iterateAllProblem(fields: problem.Pdoc.Field[], cb: (pdoc: problem.Pdoc, current?: number, total?: number) => Promise<any>) {
|
||||
interface PartialPdoc extends problem.Pdoc {
|
||||
[key: string]: any,
|
||||
}
|
||||
|
||||
async function iterateAllProblem(
|
||||
fields: (problem.Pdoc.Field | string)[],
|
||||
cb: (pdoc: PartialPdoc, current?: number, total?: number) => Promise<any>,
|
||||
) {
|
||||
if (!fields.includes('domainId')) fields.push('domainId');
|
||||
if (!fields.includes('docId')) fields.push('docId');
|
||||
await iterateAllDomain(async (d) => {
|
||||
const cursor = problem.getMulti(d._id, {}, fields);
|
||||
const cursor = problem.getMulti(d._id, {}, fields as any);
|
||||
const total = await problem.getMulti(d._id, {}).count();
|
||||
let i = 0;
|
||||
while (await cursor.hasNext()) {
|
||||
const doc = await cursor.next();
|
||||
i++;
|
||||
await cb(doc, i, total);
|
||||
const res = await cb(doc, i, total);
|
||||
if (res) await problem.edit(doc.domainId, doc.docId, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -162,7 +172,7 @@ const scripts: UpgradeScript[] = [
|
||||
},
|
||||
async function _8_9() {
|
||||
const _FRESH_INSTALL_IGNORE = 1;
|
||||
await iterateAllProblem(['docId', 'domainId'], async (pdoc) => {
|
||||
await iterateAllProblem([], async (pdoc) => {
|
||||
logger.info('%s/%s', pdoc.domainId, pdoc.docId);
|
||||
const [data, additional_file] = await Promise.all([
|
||||
storage.list(`problem/${pdoc.domainId}/${pdoc.docId}/testdata/`),
|
||||
@@ -174,7 +184,21 @@ const scripts: UpgradeScript[] = [
|
||||
for (let i = 0; i < additional_file.length; i++) {
|
||||
additional_file[i]._id = additional_file[i].name;
|
||||
}
|
||||
await problem.edit(pdoc.domainId, pdoc.docId, { data, additional_file });
|
||||
return { data, additional_file };
|
||||
});
|
||||
return true;
|
||||
},
|
||||
// Move category to tag
|
||||
async function _9_10() {
|
||||
const _FRESH_INSTALL_IGNORE = 1;
|
||||
await iterateAllProblem(['tag', 'category'], async (pdoc) => {
|
||||
await document.coll.updateOne(
|
||||
{ domainId: pdoc.domainId, docId: pdoc.docId },
|
||||
{
|
||||
$set: { tag: [...pdoc.tag || [], ...pdoc.category || []] },
|
||||
$unset: { category: '' },
|
||||
},
|
||||
);
|
||||
});
|
||||
return true;
|
||||
},
|
||||
|
||||
@@ -96,7 +96,7 @@ export async function run({
|
||||
hint: pdoc.hint,
|
||||
source: pdoc.source,
|
||||
}, 'html'),
|
||||
1, pdoc.source.split(' '), undefined, pdoc.defunct === 'Y',
|
||||
1, pdoc.source.split(' '), pdoc.defunct === 'Y',
|
||||
);
|
||||
const [cdoc] = await query(`SELECT * FROM 'privilege' WHERE rightstr = 'p${pdoc.problem_id}'`);
|
||||
await problem.edit('system', pid, {
|
||||
|
||||
@@ -30,14 +30,7 @@ export class QueryProblemSetAPIHandler extends Handler {
|
||||
}
|
||||
const query: FilterQuery<Pdoc> = {};
|
||||
if ($search) query.$text = { $search };
|
||||
if (tags?.length) {
|
||||
query.$and = tags.map(($eq) => ({
|
||||
$or: [
|
||||
{ category: { $elemMatch: { $eq } } },
|
||||
{ tag: { $elemMatch: { $eq } } },
|
||||
],
|
||||
}));
|
||||
}
|
||||
if (tags?.length) query.$and = tags.map((tag) => ({ tag }));
|
||||
if (owner) query.owner = owner;
|
||||
if (!nonpublic) query.hidden = false;
|
||||
const [raw, count] = await Promise.all([
|
||||
|
||||
Reference in new issue
Block a user