mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: import from hydro
This commit is contained in:
1 parent
d5204eac9e
commit
664938c075
4 files changed
+72
-11
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.26.26",
|
"version": "2.26.27",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const builtinModel = [
|
|||||||
|
|
||||||
export const builtinHandler = [
|
export const builtinHandler = [
|
||||||
'home', 'problem', 'record', 'judge', 'user',
|
'home', 'problem', 'record', 'judge', 'user',
|
||||||
'contest', 'training', 'discussion', 'manage', 'import.syzoj',
|
'contest', 'training', 'discussion', 'manage', 'import',
|
||||||
'misc', 'homework', 'domain', 'remote', 'status',
|
'misc', 'homework', 'domain', 'remote', 'status',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
+69
-8
@@ -1,4 +1,5 @@
|
|||||||
import fs from 'fs';
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
@@ -10,7 +11,7 @@ import yaml from 'js-yaml';
|
|||||||
import { ValidationError, RemoteOnlineJudgeError } from '../error';
|
import { ValidationError, RemoteOnlineJudgeError } from '../error';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
import type { ContentNode } from '../interface';
|
import type { ContentNode } from '../interface';
|
||||||
import problem from '../model/problem';
|
import problem, { ProblemDoc } from '../model/problem';
|
||||||
import TaskModel from '../model/task';
|
import TaskModel from '../model/task';
|
||||||
import { PERM } from '../model/builtin';
|
import { PERM } from '../model/builtin';
|
||||||
import {
|
import {
|
||||||
@@ -19,11 +20,12 @@ import {
|
|||||||
import { isPid, parsePid } from '../lib/validator';
|
import { isPid, parsePid } from '../lib/validator';
|
||||||
import download from '../lib/download';
|
import download from '../lib/download';
|
||||||
import { buildContent } from '../lib/content';
|
import { buildContent } from '../lib/content';
|
||||||
|
import { ProblemAdd } from '../lib/ui';
|
||||||
|
|
||||||
const RE_SYZOJ = /(https?):\/\/([^/]+)\/(problem|p)\/([0-9]+)\/?/i;
|
const RE_SYZOJ = /(https?):\/\/([^/]+)\/(problem|p)\/([0-9]+)\/?/i;
|
||||||
const logger = new Logger('import.syzoj');
|
const logger = new Logger('import.syzoj');
|
||||||
|
|
||||||
async function syncFiles(info) {
|
async function syzojSync(info) {
|
||||||
const {
|
const {
|
||||||
protocol, host, body, pid, domainId, docId,
|
protocol, host, body, pid, domainId, docId,
|
||||||
} = info;
|
} = info;
|
||||||
@@ -67,7 +69,7 @@ async function syncFiles(info) {
|
|||||||
await problem.addAdditionalFile(domainId, docId, f.filename, p);
|
await problem.addAdditionalFile(domainId, docId, f.filename, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskModel.Worker.addHandler('import.syzoj', syncFiles);
|
TaskModel.Worker.addHandler('import.syzoj', syzojSync);
|
||||||
|
|
||||||
class ProblemImportSYZOJHandler extends Handler {
|
class ProblemImportSYZOJHandler extends Handler {
|
||||||
async get() {
|
async get() {
|
||||||
@@ -226,7 +228,7 @@ class ProblemImportSYZOJHandler extends Handler {
|
|||||||
const payload = {
|
const payload = {
|
||||||
protocol, host, pid, domainId, docId, body: result.body,
|
protocol, host, pid, domainId, docId, body: result.body,
|
||||||
};
|
};
|
||||||
if (wait) await syncFiles(payload);
|
if (wait) await syzojSync(payload);
|
||||||
else await TaskModel.add({ ...payload, type: 'schedule', subType: 'import.syzoj' });
|
else await TaskModel.add({ ...payload, type: 'schedule', subType: 'import.syzoj' });
|
||||||
return docId;
|
return docId;
|
||||||
}
|
}
|
||||||
@@ -272,8 +274,67 @@ class ProblemImportSYZOJHandler extends Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apply() {
|
class ProblemImportHydroHandler extends Handler {
|
||||||
Route('problem_import_syzoj', '/problem/import/syzoj', ProblemImportSYZOJHandler, PERM.PERM_CREATE_PROBLEM);
|
async get() {
|
||||||
|
this.response.template = 'problem_import.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
async post({ domainId }) {
|
||||||
|
if (!this.request.files.file) throw new ValidationError('file');
|
||||||
|
const tmpdir = path.join(os.tmpdir(), 'hydro', `${Math.random()}.import`);
|
||||||
|
const zip = new AdmZip(this.request.files.file.path);
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
zip.extractAllToAsync(tmpdir, true, (err) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const problems = await fs.readdir(tmpdir);
|
||||||
|
for (const i of problems) {
|
||||||
|
const files = await fs.readdir(path.join(tmpdir, i));
|
||||||
|
if (!files.includes('problem.yaml')) continue;
|
||||||
|
const content = fs.readFileSync(path.join(tmpdir, i, 'problem.yaml'), 'utf-8');
|
||||||
|
const pdoc: ProblemDoc = yaml.load(content) as any;
|
||||||
|
const current = await problem.get(domainId, pdoc.pid);
|
||||||
|
const pid = current ? undefined : pdoc.pid;
|
||||||
|
const docId = await problem.add(domainId, pid, pdoc.title, pdoc.content, pdoc.owner, pdoc.tag, pdoc.hidden);
|
||||||
|
if (files.includes('testdata')) {
|
||||||
|
const datas = await fs.readdir(path.join(tmpdir, i, 'testdata'), { withFileTypes: true });
|
||||||
|
for (const f of datas) {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
const sub = await fs.readdir(path.join(tmpdir, i, 'testdata', f.name));
|
||||||
|
for (const s of sub) {
|
||||||
|
const stream = fs.createReadStream(path.join(tmpdir, i, 'testdata', f.name, s));
|
||||||
|
await problem.addTestdata(domainId, docId, `${f.name}/${s}`, stream);
|
||||||
|
}
|
||||||
|
} else if (f.isFile()) {
|
||||||
|
const stream = fs.createReadStream(path.join(tmpdir, i, 'testdata', f.name));
|
||||||
|
await problem.addTestdata(domainId, docId, f.name, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (files.includes('additional_file')) {
|
||||||
|
const datas = await fs.readdir(path.join(tmpdir, i, 'additional_file'), { withFileTypes: true });
|
||||||
|
for (const f of datas) {
|
||||||
|
if (f.isFile()) {
|
||||||
|
const stream = fs.createReadStream(path.join(tmpdir, i, 'additional_file', f.name));
|
||||||
|
await problem.addAdditionalFile(domainId, docId, f.name, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await fs.remove(tmpdir);
|
||||||
|
}
|
||||||
|
this.response.redirect = this.url('problem_main');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.handler['import.syzoj'] = apply;
|
export async function apply() {
|
||||||
|
ProblemAdd('problem_import_hydro', {}, 'copy', 'Import From Hydro');
|
||||||
|
Route('problem_import_syzoj', '/problem/import/syzoj', ProblemImportSYZOJHandler, PERM.PERM_CREATE_PROBLEM);
|
||||||
|
Route('problem_import_hydro', '/problem/import/hydro', ProblemImportHydroHandler, PERM.PERM_CREATE_PROBLEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
global.Hydro.handler.import = apply;
|
||||||
@@ -182,7 +182,7 @@ export class ProblemReceiveHandler extends Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function apply() {
|
export async function apply() {
|
||||||
ProblemAdd('problem_receive', {}, 'copy', 'Import From Hydro');
|
ProblemAdd('problem_receive', {}, 'copy', 'Receive From Hydro');
|
||||||
Route('problem_receive', '/problem/receive', ProblemReceiveHandler);
|
Route('problem_receive', '/problem/receive', ProblemReceiveHandler);
|
||||||
Route('problem_send', '/problem/send', ProblemSendHandler);
|
Route('problem_send', '/problem/send', ProblemSendHandler);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user