mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
replace String.random with randomstring
This commit is contained in:
22 files changed
+64
-48
No files matched your search
@@ -142,6 +142,12 @@ Hydro 用户群:1085853538
|
|||||||
- ui: 支持使用自定义字体
|
- ui: 支持使用自定义字体
|
||||||
- framework: 添加 Subscription API
|
- framework: 添加 Subscription API
|
||||||
- core: 添加 fixStorage 脚本
|
- core: 添加 fixStorage 脚本
|
||||||
|
- core: websocket: 重构 Subscription API
|
||||||
|
- ui: 允许跨页选择题目
|
||||||
|
- judge: 重构 config.detail 设置
|
||||||
|
- core: 自动清理多余的静态文件
|
||||||
|
- ui: 优化比赛题目列表显示
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
@@ -155,6 +161,8 @@ Hydro 用户群:1085853538
|
|||||||
- ui: 修复高亮行号显示
|
- ui: 修复高亮行号显示
|
||||||
- core: 修复 `User.serialize()` 参数
|
- core: 修复 `User.serialize()` 参数
|
||||||
- ui: 修复更换邮箱功能
|
- ui: 修复更换邮箱功能
|
||||||
|
- ui: 修复比赛侧栏
|
||||||
|
- ui: 修复文档链接
|
||||||
|
|
||||||
### Breaking API Changes
|
### Breaking API Changes
|
||||||
|
|
||||||
@@ -174,6 +182,7 @@ Hydro 用户群:1085853538
|
|||||||
- framework: 移除 ready 与 dispose 事件 (使用 ctx.effect 代替)
|
- framework: 移除 ready 与 dispose 事件 (使用 ctx.effect 代替)
|
||||||
- core: 最低要求 node 22
|
- core: 最低要求 node 22
|
||||||
- core: 弃用 AdmZip
|
- core: 弃用 AdmZip
|
||||||
|
- utils: 移除 String.random 与 Array.isDiff
|
||||||
|
|
||||||
## Hydro 4.19.0 / UI 4.57.0
|
## Hydro 4.19.0 / UI 4.57.0
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@hydrooj/common",
|
"name": "@hydrooj/common",
|
||||||
"main": "./index.ts",
|
"main": "./index.ts",
|
||||||
"version": "0.0.2",
|
"version": "0.0.2",
|
||||||
|
"sideEffects": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hydrooj/utils": "workspace:^"
|
"@hydrooj/utils": "workspace:^"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
"name": "@hydrooj/components",
|
"name": "@hydrooj/components",
|
||||||
"version": "1.0.0-beta.3",
|
"version": "1.0.0-beta.3",
|
||||||
"main": "./frontend/index.ts",
|
"main": "./frontend/index.ts",
|
||||||
|
"sideEffects": [
|
||||||
|
"*.scss",
|
||||||
|
"*.css"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"allotment": "^1.20.4",
|
"allotment": "^1.20.4",
|
||||||
"diff": "^8.0.2",
|
"diff": "^8.0.2",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import decodeHTML from 'decode-html';
|
|||||||
import xml2js from 'xml2js';
|
import xml2js from 'xml2js';
|
||||||
import {
|
import {
|
||||||
_, BadRequestError, buildContent, Context, FileTooLargeError, fs, Handler, PERM, ProblemConfigFile,
|
_, BadRequestError, buildContent, Context, FileTooLargeError, fs, Handler, PERM, ProblemConfigFile,
|
||||||
ProblemModel, ProblemType, Schema, SolutionModel, SystemModel, ValidationError, yaml, Zip,
|
ProblemModel, ProblemType, randomstring, Schema, SolutionModel, SystemModel, ValidationError, yaml, Zip,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
|
|
||||||
const knownRemoteMapping = {
|
const knownRemoteMapping = {
|
||||||
@@ -65,7 +65,7 @@ class FpsProblemImportHandler extends Handler {
|
|||||||
}
|
}
|
||||||
if (p.img?.length) {
|
if (p.img?.length) {
|
||||||
for (const img of p.img) {
|
for (const img of p.img) {
|
||||||
const filename = String.random(8) + img.src[0].split('/').pop().split('.').pop();
|
const filename = randomstring(8) + img.src[0].split('/').pop().split('.').pop();
|
||||||
tasks.push(ProblemModel.addAdditionalFile(domainId, pid, filename, Buffer.from(img.base64[0], 'base64')));
|
tasks.push(ProblemModel.addAdditionalFile(domainId, pid, filename, Buffer.from(img.base64[0], 'base64')));
|
||||||
content = content.replace(img.src[0], `file://${filename}`);
|
content = content.replace(img.src[0], `file://${filename}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os from 'os';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import cac from 'cac';
|
import cac from 'cac';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
import { fs, yaml } from '@hydrooj/utils';
|
import { fs, randomstring, yaml } from '@hydrooj/utils';
|
||||||
|
|
||||||
const argv = cac().parse();
|
const argv = cac().parse();
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export const JudgeSettings = Schema.object({
|
|||||||
rate: Schema.number().default(1),
|
rate: Schema.number().default(1),
|
||||||
env: Schema.string().default(defaultEnv),
|
env: Schema.string().default(defaultEnv),
|
||||||
host: Schema.any(),
|
host: Schema.any(),
|
||||||
secret: Schema.string().description('Judge Token Secret').default(String.random(32)),
|
secret: Schema.string().description('Judge Token Secret').default(randomstring(32)),
|
||||||
disable: Schema.boolean().description('Disable builtin judge').default(false),
|
disable: Schema.boolean().description('Disable builtin judge').default(false),
|
||||||
detail: Schema.union([
|
detail: Schema.union([
|
||||||
Schema.const('full'),
|
Schema.const('full'),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { escapeRegExp, pick } from 'lodash';
|
|||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import {
|
import {
|
||||||
Counter, sortFiles, Time, yaml,
|
Counter, diffArray, randomstring, sortFiles, Time, yaml,
|
||||||
} from '@hydrooj/utils/lib/utils';
|
} from '@hydrooj/utils/lib/utils';
|
||||||
import { Context, Service } from '../context';
|
import { Context, Service } from '../context';
|
||||||
import {
|
import {
|
||||||
@@ -317,7 +317,7 @@ export class ContestEditHandler extends Handler {
|
|||||||
title, content, rule, beginAt, endAt, pids, rated, duration: contestDuration,
|
title, content, rule, beginAt, endAt, pids, rated, duration: contestDuration,
|
||||||
});
|
});
|
||||||
if (this.tdoc.beginAt !== beginAt || this.tdoc.endAt !== endAt
|
if (this.tdoc.beginAt !== beginAt || this.tdoc.endAt !== endAt
|
||||||
|| Array.isDiff(this.tdoc.pids, pids) || this.tdoc.rule !== rule
|
|| diffArray(this.tdoc.pids, pids) || this.tdoc.rule !== rule
|
||||||
|| lockAt !== this.tdoc.lockAt) {
|
|| lockAt !== this.tdoc.lockAt) {
|
||||||
await contest.recalcStatus(domainId, this.tdoc.docId);
|
await contest.recalcStatus(domainId, this.tdoc.docId);
|
||||||
}
|
}
|
||||||
@@ -484,7 +484,7 @@ export class ContestManagementHandler extends ContestManagementBaseHandler {
|
|||||||
if (size >= system.get('limit.contest_files_size')) {
|
if (size >= system.get('limit.contest_files_size')) {
|
||||||
throw new FileLimitExceededError('size');
|
throw new FileLimitExceededError('size');
|
||||||
}
|
}
|
||||||
filename ||= file.originalFilename || String.random(16);
|
filename ||= file.originalFilename || randomstring(16);
|
||||||
await storage.put(`contest/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
await storage.put(`contest/${domainId}/${tid}/${filename}`, file.filepath, this.user._id);
|
||||||
const meta = await storage.getMeta(`contest/${domainId}/${tid}/${filename}`);
|
const meta = await storage.getMeta(`contest/${domainId}/${tid}/${filename}`);
|
||||||
const payload = { _id: filename, name: filename, ...pick(meta, ['size', 'lastModified', 'etag']) };
|
const payload = { _id: filename, name: filename, ...pick(meta, ['size', 'lastModified', 'etag']) };
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { nanoid } from 'nanoid';
|
|||||||
import sanitize from 'sanitize-filename';
|
import sanitize from 'sanitize-filename';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
import parser from '@hydrooj/utils/lib/search';
|
import parser from '@hydrooj/utils/lib/search';
|
||||||
import { sortFiles, streamToBuffer } from '@hydrooj/utils/lib/utils';
|
import { randomstring, sortFiles, streamToBuffer } from '@hydrooj/utils/lib/utils';
|
||||||
import type { Context } from '../context';
|
import type { Context } from '../context';
|
||||||
import {
|
import {
|
||||||
BadRequestError, ContestNotAttendedError, ContestNotEndedError, ContestNotFoundError, ContestNotLiveError,
|
BadRequestError, ContestNotAttendedError, ContestNotEndedError, ContestNotFoundError, ContestNotLiveError,
|
||||||
@@ -709,7 +709,7 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
|
|||||||
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
||||||
const file = this.request.files.file;
|
const file = this.request.files.file;
|
||||||
if (!file) throw new ValidationError('file');
|
if (!file) throw new ValidationError('file');
|
||||||
filename ||= file.originalFilename || String.random(16);
|
filename ||= file.originalFilename || randomstring(16);
|
||||||
const files = [];
|
const files = [];
|
||||||
if (filename.endsWith('.zip') && type === 'testdata') {
|
if (filename.endsWith('.zip') && type === 'testdata') {
|
||||||
const zip = new ZipReader(Readable.toWeb(createReadStream(file.filepath)));
|
const zip = new ZipReader(Readable.toWeb(createReadStream(file.filepath)));
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { isoBase64URL } from '@simplewebauthn/server/helpers';
|
|||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import { Binary } from 'mongodb';
|
import { Binary } from 'mongodb';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
|
import { randomstring } from '@hydrooj/utils';
|
||||||
import type { Context } from '../context';
|
import type { Context } from '../context';
|
||||||
import {
|
import {
|
||||||
AuthOperationError, BadRequestError, BlacklistedError, BuiltinLoginError,
|
AuthOperationError, BadRequestError, BlacklistedError, BuiltinLoginError,
|
||||||
@@ -306,7 +307,7 @@ class UserRegisterWithCodeHandler extends Handler {
|
|||||||
if (provider.lockUsername) uname = this.tdoc.identity.username;
|
if (provider.lockUsername) uname = this.tdoc.identity.username;
|
||||||
if (!Types.Username[1](uname)) throw new ValidationError('uname');
|
if (!Types.Username[1](uname)) throw new ValidationError('uname');
|
||||||
if (password !== verify) throw new VerifyPasswordError();
|
if (password !== verify) throw new VerifyPasswordError();
|
||||||
const randomEmail = `${String.random(12)}@invalid.local`; // some random email to remove in the future
|
const randomEmail = `${randomstring(12)}@invalid.local`; // some random email to remove in the future
|
||||||
const uid = await user.create(this.tdoc.mail || randomEmail, uname, password, undefined, this.request.ip);
|
const uid = await user.create(this.tdoc.mail || randomEmail, uname, password, undefined, this.request.ip);
|
||||||
await token.del(code, token.TYPE_REGISTRATION);
|
await token.del(code, token.TYPE_REGISTRATION);
|
||||||
const [id, mailDomain] = this.tdoc.mail.split('@');
|
const [id, mailDomain] = this.tdoc.mail.split('@');
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Dictionary } from 'lodash';
|
|||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import Schema from 'schemastery';
|
import Schema from 'schemastery';
|
||||||
import { LangConfig, parseLang } from '@hydrooj/common';
|
import { LangConfig, parseLang } from '@hydrooj/common';
|
||||||
import { findFileSync, retry } from '@hydrooj/utils';
|
import { findFileSync, randomstring, retry } from '@hydrooj/utils';
|
||||||
import { Context } from '../context';
|
import { Context } from '../context';
|
||||||
import { Setting as _Setting } from '../interface';
|
import { Setting as _Setting } from '../interface';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
@@ -345,14 +345,14 @@ SystemSetting(
|
|||||||
Setting('setting_basic', 'pagination.reply', 50, 'number', 'pagination.reply', 'Replies per page'),
|
Setting('setting_basic', 'pagination.reply', 50, 'number', 'pagination.reply', 'Replies per page'),
|
||||||
Setting('setting_basic', 'hydrooj.homepage', settingFile.homepage.default, 'yaml', 'hydrooj.homepage', 'Homepage config'),
|
Setting('setting_basic', 'hydrooj.homepage', settingFile.homepage.default, 'yaml', 'hydrooj.homepage', 'Homepage config'),
|
||||||
Setting('setting_basic', 'hydrooj.langs', settingFile.langs.default, 'yaml', 'hydrooj.langs', 'Language config'),
|
Setting('setting_basic', 'hydrooj.langs', settingFile.langs.default, 'yaml', 'hydrooj.langs', 'Language config'),
|
||||||
Setting('setting_session', 'session.keys', [String.random(32)], 'text', 'session.keys', 'session.keys', FLAG_HIDDEN),
|
Setting('setting_session', 'session.keys', [randomstring(32)], 'text', 'session.keys', 'session.keys', FLAG_HIDDEN),
|
||||||
Setting('setting_session', 'session.domain', '', 'text', 'session.domain', 'session.domain', FLAG_HIDDEN),
|
Setting('setting_session', 'session.domain', '', 'text', 'session.domain', 'session.domain', FLAG_HIDDEN),
|
||||||
Setting('setting_session', 'session.saved_expire_seconds', 3600 * 24 * 30,
|
Setting('setting_session', 'session.saved_expire_seconds', 3600 * 24 * 30,
|
||||||
'number', 'session.saved_expire_seconds', 'Saved session expire seconds'),
|
'number', 'session.saved_expire_seconds', 'Saved session expire seconds'),
|
||||||
Setting('setting_session', 'session.unsaved_expire_seconds', 3600 * 3,
|
Setting('setting_session', 'session.unsaved_expire_seconds', 3600 * 3,
|
||||||
'number', 'session.unsaved_expire_seconds', 'Unsaved session expire seconds'),
|
'number', 'session.unsaved_expire_seconds', 'Unsaved session expire seconds'),
|
||||||
Setting('setting_storage', 'db.ver', 0, 'number', 'db.ver', 'Database version', FLAG_DISABLED | FLAG_HIDDEN),
|
Setting('setting_storage', 'db.ver', 0, 'number', 'db.ver', 'Database version', FLAG_DISABLED | FLAG_HIDDEN),
|
||||||
Setting('setting_storage', 'installid', String.random(64), 'text', 'installid', 'Installation ID', FLAG_HIDDEN | FLAG_DISABLED),
|
Setting('setting_storage', 'installid', randomstring(64), 'text', 'installid', 'Installation ID', FLAG_HIDDEN | FLAG_DISABLED),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const langs: Record<string, LangConfig> = {};
|
export const langs: Record<string, LangConfig> = {};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Filter } from 'mongodb';
|
|||||||
import { Context } from '../context';
|
import { Context } from '../context';
|
||||||
import { TokenDoc } from '../interface';
|
import { TokenDoc } from '../interface';
|
||||||
import db from '../service/db';
|
import db from '../service/db';
|
||||||
import { ArgMethod } from '../utils';
|
import { ArgMethod, randomstring } from '../utils';
|
||||||
|
|
||||||
class TokenModel {
|
class TokenModel {
|
||||||
static coll = db.collection('token');
|
static coll = db.collection('token');
|
||||||
@@ -26,7 +26,7 @@ class TokenModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static async add(
|
static async add(
|
||||||
tokenType: number, expireSeconds: number, data: any, id = String.random(32),
|
tokenType: number, expireSeconds: number, data: any, id = randomstring(32),
|
||||||
): Promise<[string, TokenDoc]> {
|
): Promise<[string, TokenDoc]> {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const payload = {
|
const payload = {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import pwhash from '../lib/hash.hydro';
|
|||||||
import bus from '../service/bus';
|
import bus from '../service/bus';
|
||||||
import db from '../service/db';
|
import db from '../service/db';
|
||||||
import { Value } from '../typeutils';
|
import { Value } from '../typeutils';
|
||||||
import { ArgMethod, buildProjection } from '../utils';
|
import { ArgMethod, buildProjection, randomstring } from '../utils';
|
||||||
import { PERM, PRIV } from './builtin';
|
import { PERM, PRIV } from './builtin';
|
||||||
import domain from './domain';
|
import domain from './domain';
|
||||||
import * as setting from './setting';
|
import * as setting from './setting';
|
||||||
@@ -285,7 +285,7 @@ class UserModel {
|
|||||||
|
|
||||||
@ArgMethod
|
@ArgMethod
|
||||||
static async setPassword(uid: number, password: string): Promise<Udoc> {
|
static async setPassword(uid: number, password: string): Promise<Udoc> {
|
||||||
const salt = String.random();
|
const salt = randomstring();
|
||||||
const res = await coll.findOneAndUpdate(
|
const res = await coll.findOneAndUpdate(
|
||||||
{ _id: uid },
|
{ _id: uid },
|
||||||
{ $set: { salt, hash: await pwhash(password, salt), hashType: 'hydro' } },
|
{ $set: { salt, hash: await pwhash(password, salt), hashType: 'hydro' } },
|
||||||
@@ -317,7 +317,7 @@ class UserModel {
|
|||||||
uid = Math.max((udoc?._id || 0) + 1, 2);
|
uid = Math.max((udoc?._id || 0) + 1, 2);
|
||||||
autoAlloc = true;
|
autoAlloc = true;
|
||||||
}
|
}
|
||||||
const salt = String.random();
|
const salt = randomstring();
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { DisposableList } from 'cordis';
|
import { DisposableList } from 'cordis';
|
||||||
|
import { randomstring } from '@hydrooj/utils';
|
||||||
import { Context, Service } from '../context';
|
import { Context, Service } from '../context';
|
||||||
import * as system from '../model/system';
|
import * as system from '../model/system';
|
||||||
import db from './db';
|
import db from './db';
|
||||||
@@ -55,7 +56,7 @@ export default class CheckService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async run(ctx, log, warn, error, cb: (id: string) => void) {
|
async run(ctx, log, warn, error, cb: (id: string) => void) {
|
||||||
const id = String.random(6);
|
const id = randomstring(6);
|
||||||
cb(id);
|
cb(id);
|
||||||
for (const check of this.checkers) {
|
for (const check of this.checkers) {
|
||||||
if (this.c[id]) {
|
if (this.c[id]) {
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import { pick } from 'lodash';
|
|
||||||
import moment from 'moment-timezone';
|
|
||||||
import { ObjectId } from 'mongodb';
|
import { ObjectId } from 'mongodb';
|
||||||
import { sleep } from '@hydrooj/utils';
|
import { randomstring, sleep } from '@hydrooj/utils';
|
||||||
import { buildContent } from './lib/content';
|
import { buildContent } from './lib/content';
|
||||||
import { Logger } from './logger';
|
import { Logger } from './logger';
|
||||||
import { PERM, PRIV, STATUS } from './model/builtin';
|
import { PERM, PRIV, STATUS } from './model/builtin';
|
||||||
@@ -42,10 +40,10 @@ export const coreScripts: MigrationScript[] = [
|
|||||||
// Mark as used
|
// Mark as used
|
||||||
async function init() {
|
async function init() {
|
||||||
if (!await user.getById('system', 0)) {
|
if (!await user.getById('system', 0)) {
|
||||||
await user.create('Guest@hydro.local', 'Guest', String.random(32), 0, '127.0.0.1', PRIV.PRIV_REGISTER_USER);
|
await user.create('Guest@hydro.local', 'Guest', randomstring(32), 0, '127.0.0.1', PRIV.PRIV_REGISTER_USER);
|
||||||
}
|
}
|
||||||
if (!await user.getById('system', 1)) {
|
if (!await user.getById('system', 1)) {
|
||||||
await user.create('Hydro@hydro.local', 'Hydro', String.random(32), 1, '127.0.0.1', PRIV.PRIV_USER_PROFILE);
|
await user.create('Hydro@hydro.local', 'Hydro', randomstring(32), 1, '127.0.0.1', PRIV.PRIV_USER_PROFILE);
|
||||||
}
|
}
|
||||||
const ddoc = await domain.get('system');
|
const ddoc = await domain.get('system');
|
||||||
if (!ddoc) await domain.add('system', 1, 'Hydro', 'Welcome to Hydro!');
|
if (!ddoc) await domain.add('system', 1, 'Hydro', 'Welcome to Hydro!');
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import path from 'path';
|
|||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import {
|
import {
|
||||||
buildContent, Context, extractZip, fs, Handler, PERM,
|
buildContent, Context, extractZip, fs, Handler, PERM,
|
||||||
ProblemConfigFile, ProblemModel, ValidationError, yaml, Zip,
|
ProblemConfigFile, ProblemModel, randomstring, ValidationError, yaml, Zip,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
|
|
||||||
const tmpdir = path.join(os.tmpdir(), 'hydro', 'import-hoj');
|
const tmpdir = path.join(os.tmpdir(), 'hydro', 'import-hoj');
|
||||||
@@ -13,7 +13,7 @@ fs.ensureDirSync(tmpdir);
|
|||||||
class ImportHojHandler extends Handler {
|
class ImportHojHandler extends Handler {
|
||||||
async fromFile(domainId: string, zipfile: string) {
|
async fromFile(domainId: string, zipfile: string) {
|
||||||
const zip = new Zip.ZipReader(Readable.toWeb(fs.createReadStream(zipfile)));
|
const zip = new Zip.ZipReader(Readable.toWeb(fs.createReadStream(zipfile)));
|
||||||
const tmp = path.resolve(tmpdir, String.random(32));
|
const tmp = path.resolve(tmpdir, randomstring(32));
|
||||||
await extractZip(zip, tmp, {
|
await extractZip(zip, tmp, {
|
||||||
strip: true,
|
strip: true,
|
||||||
parseError: (e) => new ValidationError('zip', null, e.message),
|
parseError: (e) => new ValidationError('zip', null, e.message),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import path from 'path';
|
|||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import {
|
import {
|
||||||
buildContent, Context, extractZip, FileTooLargeError, fs, Handler, PERM,
|
buildContent, Context, extractZip, FileTooLargeError, fs, Handler, PERM,
|
||||||
ProblemConfigFile, ProblemModel, Schema, ValidationError, yaml, Zip,
|
ProblemConfigFile, ProblemModel, randomstring, Schema, ValidationError, yaml, Zip,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
|
|
||||||
const tmpdir = path.join(os.tmpdir(), 'hydro', 'import-qduoj');
|
const tmpdir = path.join(os.tmpdir(), 'hydro', 'import-qduoj');
|
||||||
@@ -49,7 +49,7 @@ const ProblemSchema = Schema.object({
|
|||||||
class ImportQduojHandler extends Handler {
|
class ImportQduojHandler extends Handler {
|
||||||
async fromFile(domainId: string, zipfile: string) {
|
async fromFile(domainId: string, zipfile: string) {
|
||||||
const zip = new Zip.ZipReader(Readable.toWeb(fs.createReadStream(zipfile)));
|
const zip = new Zip.ZipReader(Readable.toWeb(fs.createReadStream(zipfile)));
|
||||||
const tmp = path.resolve(tmpdir, String.random(32));
|
const tmp = path.resolve(tmpdir, randomstring(32));
|
||||||
await extractZip(zip, tmp, {
|
await extractZip(zip, tmp, {
|
||||||
strip: true,
|
strip: true,
|
||||||
parseError: (e) => new ValidationError('zip', null, e.message),
|
parseError: (e) => new ValidationError('zip', null, e.message),
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
declare global {
|
declare global {
|
||||||
interface StringConstructor {
|
|
||||||
random: (digit?: number, dict?: string) => string;
|
|
||||||
}
|
|
||||||
interface String {
|
interface String {
|
||||||
format: (...args: Array<any>) => string;
|
format: (...args: Array<any>) => string;
|
||||||
formatFromArray: (args: any[]) => string;
|
formatFromArray: (args: any[]) => string;
|
||||||
rawformat: (object: any) => string;
|
rawformat: (object: any) => string;
|
||||||
}
|
}
|
||||||
interface ArrayConstructor {
|
|
||||||
isDiff: (a: any[], b: any[]) => boolean;
|
|
||||||
}
|
|
||||||
interface Math {
|
interface Math {
|
||||||
sum: (...args: Array<number[] | number>) => number;
|
sum: (...args: Array<number[] | number>) => number;
|
||||||
}
|
}
|
||||||
@@ -28,6 +22,7 @@ export function randomstring(digit = 32, dict = defaultDict) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
// @ts-ignore
|
||||||
String.random = randomstring;
|
String.random = randomstring;
|
||||||
} catch (e) { } // Cannot add property random, object is not extensible
|
} catch (e) { } // Cannot add property random, object is not extensible
|
||||||
|
|
||||||
@@ -63,7 +58,7 @@ String.prototype.rawformat = function rawFormat(object) {
|
|||||||
return [res[0], object, res[1]].join();
|
return [res[0], object, res[1]].join();
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.isDiff = function isDiff(a, b) {
|
export function diffArray(a, b) {
|
||||||
if (a.length !== b.length) return true;
|
if (a.length !== b.length) return true;
|
||||||
a.sort();
|
a.sort();
|
||||||
b.sort();
|
b.sort();
|
||||||
@@ -71,7 +66,12 @@ Array.isDiff = function isDiff(a, b) {
|
|||||||
if (a[i] !== b[i]) return true;
|
if (a[i] !== b[i]) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
Array.isDiff = diffArray;
|
||||||
|
} catch (e) { } // Cannot add property isDiff, object is not extensible
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
Date.prototype.format = function formatDate(fmt = '%Y-%m-%d %H:%M:%S') {
|
Date.prototype.format = function formatDate(fmt = '%Y-%m-%d %H:%M:%S') {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { PassThrough } from 'stream';
|
|||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import {
|
import {
|
||||||
buildContent, Logger, sleep, STATUS,
|
buildContent, Logger, randomstring, sleep, STATUS,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
@@ -186,7 +186,7 @@ export default class CodeforcesProvider extends BasicFetcher implements IBasicPr
|
|||||||
if (!src.startsWith('http')) continue;
|
if (!src.startsWith('http')) continue;
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import { Logger, sleep, STATUS } from 'hydrooj';
|
import {
|
||||||
|
Logger, randomstring, sleep, STATUS,
|
||||||
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
|
|
||||||
@@ -91,7 +93,7 @@ export default class CSGOJProvider extends BasicFetcher implements IBasicProvide
|
|||||||
}
|
}
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
images[src] = fid;
|
images[src] = fid;
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { JSDOM } from 'jsdom';
|
|||||||
import charset from 'superagent-charset';
|
import charset from 'superagent-charset';
|
||||||
import proxy from 'superagent-proxy';
|
import proxy from 'superagent-proxy';
|
||||||
import {
|
import {
|
||||||
htmlEncode, Logger, parseMemoryMB, parseTimeMS, sleep, STATUS, superagent,
|
htmlEncode, Logger, parseMemoryMB, parseTimeMS, randomstring, sleep, STATUS, superagent,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
@@ -67,7 +67,7 @@ export default class HDUOJProvider extends BasicFetcher implements IBasicProvide
|
|||||||
}
|
}
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
images[src] = fid;
|
images[src] = fid;
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import {
|
import {
|
||||||
htmlEncode, Logger, parseMemoryMB, parseTimeMS, sleep, STATUS,
|
htmlEncode, Logger, parseMemoryMB, parseTimeMS, randomstring, sleep, STATUS,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
@@ -95,7 +95,7 @@ export default class POJProvider extends BasicFetcher implements IBasicProvider
|
|||||||
}
|
}
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
images[src] = fid;
|
images[src] = fid;
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import {
|
import {
|
||||||
Logger, parseMemoryMB, sleep, STATUS,
|
Logger, parseMemoryMB, randomstring, sleep, STATUS,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
@@ -53,7 +53,7 @@ export default class SPOJProvider extends BasicFetcher implements IBasicProvider
|
|||||||
if (!src.startsWith('http')) continue;
|
if (!src.startsWith('http')) continue;
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { PassThrough } from 'stream';
|
import { PassThrough } from 'stream';
|
||||||
import { JSDOM } from 'jsdom';
|
import { JSDOM } from 'jsdom';
|
||||||
import {
|
import {
|
||||||
Logger, parseMemoryMB, parseTimeMS, sleep, STATUS,
|
Logger, parseMemoryMB, parseTimeMS, randomstring, sleep, STATUS,
|
||||||
} from 'hydrooj';
|
} from 'hydrooj';
|
||||||
import { BasicFetcher } from '../fetch';
|
import { BasicFetcher } from '../fetch';
|
||||||
import { IBasicProvider, RemoteAccount } from '../interface';
|
import { IBasicProvider, RemoteAccount } from '../interface';
|
||||||
@@ -74,7 +74,7 @@ export default class UOJProvider extends BasicFetcher implements IBasicProvider
|
|||||||
if (!src.startsWith('http')) continue;
|
if (!src.startsWith('http')) continue;
|
||||||
const file = new PassThrough();
|
const file = new PassThrough();
|
||||||
this.get(src).pipe(file);
|
this.get(src).pipe(file);
|
||||||
const fid = String.random(8);
|
const fid = randomstring(8);
|
||||||
files[`${fid}.png`] = file;
|
files[`${fid}.png`] = file;
|
||||||
ele.setAttribute('src', `file://${fid}.png`);
|
ele.setAttribute('src', `file://${fid}.png`);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user