migrate: add universaloj & hustoj upload file (#553)

Co-authored-by: undefined <i@undefined.moe>
This commit is contained in:
pandaandundefined authored and GitHub committed 2023-05-10 19:25:05 +08:00
1 parent e07fe63368
commit d20c405da9
5 files changed
+617 -22

No files matched your search

+41 -12
View File
@@ -1,10 +1,11 @@
/* eslint-disable no-tabs */
/* eslint-disable no-await-in-loop */
import path from 'path';
import mariadb from 'mariadb';
import TurndownService from 'turndown';
import {
buildContent, ContestModel, DomainModel, fs, noop, NotFoundError, ObjectId, postJudge, ProblemModel,
RecordDoc, RecordModel, SolutionModel, STATUS, SystemModel, Time, UserModel,
_, buildContent, ContestModel, DomainModel, fs, noop, NotFoundError, ObjectId, postJudge, ProblemModel,
RecordDoc, RecordModel, SolutionModel, STATUS, StorageModel, SystemModel, Time, UserModel,
} from 'hydrooj';
const turndown = new TurndownService({
@@ -48,10 +49,21 @@ const nameMap: Record<string, string> = {
'test.in': 'test0.in',
'test.out': 'test0.out',
};
async function addContestFile(domainId: string, tid: ObjectId, filename: string, filepath: string) {
const tdoc = await ContestModel.get(domainId, tid);
await StorageModel.put(`contest/${domainId}/${tid}/${filename}`, filepath, 1);
const meta = await StorageModel.getMeta(`contest/${domainId}/${tid}/${filename}`);
const payload = { _id: filename, name: filename, ..._.pick(meta, ['size', 'lastModified', 'etag']) };
if (!meta) return false;
await ContestModel.edit(domainId, tid, { files: [...(tdoc.files || []), payload] });
return true;
}
export async function run({
host = 'localhost', port = 3306, name = 'jol',
username, password, domainId, contestType = 'oi',
dataDir, rerun = true, randomMail = false,
dataDir, uploadDir = '/home/judge/src/web/upload/', rerun = true, randomMail = false,
}, report: Function) {
const src = await mariadb.createConnection({
host,
@@ -153,19 +165,28 @@ export async function run({
if (opdoc) pidMap[pdoc.problem_id] = opdoc.docId;
}
if (!pidMap[pdoc.problem_id]) {
const files = {};
let content = buildContent({
description: pdoc.description,
input: pdoc.input,
output: pdoc.output,
samples: [[pdoc.sample_input.trim(), pdoc.sample_output.trim()]],
hint: pdoc.hint,
source: pdoc.source,
}, 'html');
const uploadFiles = content.matchAll(/(?:src|href)="\/upload\/([^"]+\/([^"]+))"/g);
for (const file of uploadFiles) {
files[file[2]] = await fs.readFile(path.join(uploadDir, file[1]));
content = content.replace(`/upload/${file[1]}`, `file://${file[2]}`);
}
const pid = await ProblemModel.add(
domainId, `P${pdoc.problem_id}`,
pdoc.title, buildContent({
description: pdoc.description,
input: pdoc.input,
output: pdoc.output,
samples: [[pdoc.sample_input.trim(), pdoc.sample_output.trim()]],
hint: pdoc.hint,
source: pdoc.source,
}, 'html'),
pdoc.title, content,
1, pdoc.source.split(' ').map((i) => i.trim()).filter((i) => i), pdoc.defunct === 'Y',
);
pidMap[pdoc.problem_id] = pid;
await Promise.all(Object.keys(files).map((filename) => ProblemModel.addAdditionalFile(domainId, pid, filename, files[filename])));
if (Object.keys(files).length) report({ message: `move ${Object.keys(files).length} file for problem ${pid}` });
}
const cdoc = await query(`SELECT * FROM \`privilege\` WHERE \`rightstr\` = 'p${pdoc.problem_id}'`);
const maintainer = [];
@@ -203,15 +224,23 @@ export async function run({
for (const tdoc of tdocs) {
const pdocs = await query(`SELECT * FROM \`contest_problem\` WHERE \`contest_id\` = ${tdoc.contest_id}`);
const pids = pdocs.map((i) => pidMap[i.problem_id]).filter((i) => i);
const files = {};
let description = tdoc.description;
const uploadFiles = description.matchAll(/(?:src|href)="\/upload\/([^"]+\/([^"]+))"/g);
for (const file of uploadFiles) {
files[file[2]] = await fs.readFile(path.join(uploadDir, file[1]));
description = description.replace(`/upload/${file[1]}`, `file://${file[2]}`);
}
const tid = await ContestModel.add(
domainId, tdoc.title, tdoc.description || 'Description',
adminUids[0], contestType, tdoc.start_time, tdoc.end_time, pids, true,
{ _code: password },
);
tidMap[tdoc.contest_id] = tid.toHexString();
await Promise.all(Object.keys(files).map((filename) => addContestFile(domainId, tid, filename, files[filename])));
if (Object.keys(files).length) report({ message: `move ${Object.keys(files).length} file for contest ${tidMap[tdoc.contest_id]}` });
}
report({ message: 'contest finished' });
/*
solution 程序运行结果记录
字段名 类型 长度 是否允许为空 备注