remove server.log setting item

This commit is contained in:
undefined committed 2020-07-25 19:23:48 +08:00
1 parent e62e7b49a3
commit ee78271a84
27 files changed
+159 -114

No files matched your search

+20 -17
View File
@@ -1,21 +1,24 @@
/* eslint-disable func-names */ /* eslint-disable func-names */
const { isClass } = require('./utils'); import { isClass } from './utils';
interface IHydroError { interface IHydroError {
new(...args: any[]): HydroError new(...args: any[]): HydroError
} }
const Err = (name: string, ...info: Array<IHydroError | Function | string | number>) => { function isHydroError(item: any): item is IHydroError {
return isClass(item);
}
const Err = (name: string, ...info: Array<IHydroError | (() => string) | string | number>) => {
let Class: IHydroError; let Class: IHydroError;
let msg; let msg: () => string;
let code; let code: number;
for (const item of info) { for (const item of info) {
if (typeof item === 'number') { if (typeof item === 'number') {
code = item; code = item;
} else if (typeof item === 'string') { } else if (typeof item === 'string') {
msg = function () { return item; }; msg = function () { return item; };
} else if (isClass(item)) { } else if (isHydroError(item)) {
// @ts-ignore
Class = item; Class = item;
} else if (typeof item === 'function') { } else if (typeof item === 'function') {
msg = item; msg = item;
@@ -29,19 +32,19 @@ const Err = (name: string, ...info: Array<IHydroError | Function | string | numb
}; };
export class HydroError extends Error { export class HydroError extends Error {
params: any[]; params: any[];
code: number; code: number;
constructor(...params: any[]) { constructor(...params: any[]) {
super(); super();
this.params = params; this.params = params;
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
msg() { msg() {
return 'HydroError'; return 'HydroError';
} }
} }
export const UserFacingError = Err('UserFacingError', HydroError, 'UserFacingError', 400); export const UserFacingError = Err('UserFacingError', HydroError, 'UserFacingError', 400);
+6 -3
View File
@@ -106,7 +106,9 @@ class DomainUserHandler extends ManageHandler {
}; };
} }
async postSetUser({ domainId, uid, role }) { @param('uid', Types.Int)
@param('role', Types.String)
async postSetUser(domainId: string, uid: number, role: string) {
await domain.setUserRole(domainId, uid, role); await domain.setUserRole(domainId, uid, role);
this.back(); this.back();
} }
@@ -161,7 +163,8 @@ class DomainRoleHandler extends ManageHandler {
this.response.body = { roles, domain: this.domain, path }; this.response.body = { roles, domain: this.domain, path };
} }
async postAdd({ domainId, role }) { @param('role', Types.String)
async postAdd(domainId: string, role: string) {
const roles = await domain.getRoles(this.domain); const roles = await domain.getRoles(this.domain);
const rdict: any = {}; const rdict: any = {};
for (const r of roles) rdict[r._id] = r.perm; for (const r of roles) rdict[r._id] = r.perm;
@@ -183,7 +186,7 @@ class DomainRoleHandler extends ManageHandler {
class DomainSearchHandler extends Handler { class DomainSearchHandler extends Handler {
@param('q', Types.String) @param('q', Types.String)
async get(q: string) { async get(domainId: string, q: string) {
const ddocs = await domain.getPrefixSearch(q, 20); const ddocs = await domain.getPrefixSearch(q, 20);
for (let i = 0; i < ddocs.length; i++) { for (let i = 0; i < ddocs.length; i++) {
ddocs[i].gravatar = ddocs[i].gravatar ? gravatar(ddocs[i].gravatar) : '/img/team_avatar.png'; ddocs[i].gravatar = ddocs[i].gravatar ? gravatar(ddocs[i].gravatar) : '/img/team_avatar.png';
+2 -2
View File
@@ -150,9 +150,9 @@ class HomeSecurityHandler extends Handler {
@param('currentPassword', Types.String) @param('currentPassword', Types.String)
@param('mail', Types.String, isEmail) @param('mail', Types.String, isEmail)
async postChangeMail(domainId: string, currentPassword: string, email: string) { async postChangeMail(domainId: string, current: string, email: string) {
this.limitRate('send_mail', 3600, 30); this.limitRate('send_mail', 3600, 30);
this.user.checkPassword(currentPassword); this.user.checkPassword(current);
const udoc = await user.getByEmail(domainId, email); const udoc = await user.getByEmail(domainId, email);
if (udoc) throw new UserAlreadyExistError(email); if (udoc) throw new UserAlreadyExistError(email);
const [code] = await token.add( const [code] = await token.add(
-9
View File
@@ -158,13 +158,4 @@ export async function apply() {
Route('ui', '/extra.css', UiSettingsHandler); Route('ui', '/extra.css', UiSettingsHandler);
} }
apply.updateStatus = function updateStatus(args) {
args.type = 'judger';
return coll.updateOne(
{ mid: args.mid, type: 'judger' },
{ $set: args },
{ upsert: true },
);
};
global.Hydro.handler.misc = apply; global.Hydro.handler.misc = apply;
+3 -3
View File
@@ -15,8 +15,8 @@ import { sendMail } from '../lib/mail';
import * as misc from '../lib/misc'; import * as misc from '../lib/misc';
import { import {
UserAlreadyExistError, InvalidTokenError, VerifyPasswordError, UserAlreadyExistError, InvalidTokenError, VerifyPasswordError,
UserNotFoundError, LoginError, SystemError, UserNotFoundError, SystemError, BlacklistedError,
BlacklistedError, UserFacingError, UserFacingError,
} from '../error'; } from '../error';
class UserLoginHandler extends Handler { class UserLoginHandler extends Handler {
@@ -35,7 +35,7 @@ class UserLoginHandler extends Handler {
@param('rememberme', Types.Boolean, true) @param('rememberme', Types.Boolean, true)
async post(domainId: string, uname: string, password: string, rememberme = false) { async post(domainId: string, uname: string, password: string, rememberme = false) {
const udoc = await user.getByUname(domainId, uname); const udoc = await user.getByUname(domainId, uname);
if (!udoc) throw new LoginError(uname); if (!udoc) throw new UserNotFoundError(uname);
udoc.checkPassword(password); udoc.checkPassword(password);
await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip }); await user.setById(udoc._id, { loginat: new Date(), loginip: this.request.ip });
if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname); if (udoc.priv === PRIV.PRIV_NONE) throw new BlacklistedError(uname);
+36 -4
View File
@@ -141,7 +141,7 @@ export interface Pdoc {
acMsg?: string, acMsg?: string,
} }
export type Pdict = Dictionary<Pdoc>; export type Pdict = NumericDictionary<Pdoc>;
export interface TestCase { export interface TestCase {
time: number, time: number,
@@ -245,7 +245,38 @@ export interface Bdoc {
expireAt: Date, expireAt: Date,
} }
interface ContestStat extends Dictionary<any> { // Discussion
export interface Ddoc {
_id: ObjectID,
docType: number,
docId: ObjectID,
owner: number,
title: string,
content: string,
ip: string,
}
// Discussion reply
export interface Drdoc {
_id: ObjectID,
docType: number,
docId: ObjectID,
parentType: number,
parentId: ObjectID,
owner: number,
ip: string,
reply: Drrdoc[],
}
// Discussion Tail Reply
export interface Drrdoc {
_id: ObjectID,
owner: number,
content: string,
ip: string,
}
export interface ContestStat extends Dictionary<any> {
detail: any, detail: any,
} }
@@ -330,6 +361,7 @@ declare global {
gridfs: GridFSBucket, gridfs: GridFSBucket,
monitor: typeof import('./service/monitor'), monitor: typeof import('./service/monitor'),
server: typeof import('./service/server'), server: typeof import('./service/server'),
[key: string]: any,
}, },
lib: { lib: {
download: typeof import('./lib/download').default, download: typeof import('./lib/download').default,
@@ -363,9 +395,9 @@ declare global {
}, },
error: typeof import('./error'), error: typeof import('./error'),
locales: Dict<Dict<string>>, locales: Dict<Dict<string>>,
postInit: Function[], postInit: Array<() => Promise<any>>,
}, },
onDestory: Function[], onDestory: Array<() => void>,
addons: string[], addons: string[],
} }
} }
-1
View File
@@ -27,7 +27,6 @@ function decodeJWT(idToken: string) {
} }
} }
// eslint-disable-next-line import/prefer-default-export
export function decode(idToken: string) { export function decode(idToken: string) {
const decodedJWT = decodeJWT(idToken); const decodedJWT = decodeJWT(idToken);
return decodedJWT.payload; return decodedJWT.payload;
-6
View File
@@ -6,12 +6,6 @@ function wrap(func: Function, type: string) {
func(...args); func(...args);
if (global.Hydro.model.message) { if (global.Hydro.model.message) {
try { try {
for (let i = 0; i <= args.length; i++) {
if (args[i] instanceof Error) {
// js-yaml cannot dump [object Error]
args[i] = `${args[i].message}\n${args[i].stack}`;
}
}
global.Hydro.model.message.send(1, 1, serialize({ time, type, args }), 0); global.Hydro.model.message.send(1, 1, serialize({ time, type, args }), 0);
} catch (e) { } catch (e) {
func(e.message); func(e.message);
-1
View File
@@ -1,7 +1,6 @@
import nodemailer from 'nodemailer'; import nodemailer from 'nodemailer';
import { SendMailError } from '../error'; import { SendMailError } from '../error';
// eslint-disable-next-line import/prefer-default-export
export async function sendMail(to: string, subject: string, text: string, html: string) { export async function sendMail(to: string, subject: string, text: string, html: string) {
let t: unknown; let t: unknown;
try { try {
+12 -11
View File
@@ -1,19 +1,20 @@
import AnsiUp from 'ansi_up'; import AnsiUp from 'ansi_up';
import { ObjectID } from 'mongodb';
import md5 from './md5'; import md5 from './md5';
const AU = new AnsiUp(); const AU = new AnsiUp();
export function ansiToHtml(str) { export function ansiToHtml(str: string) {
return AU.ansi_to_html(str); return AU.ansi_to_html(str);
} }
export function gravatar(email, s = 32) { export function gravatar(email: string, s = 32) {
return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${s}`; return `//gravatar.loli.net/avatar/${md5((email || '').toString().trim().toLowerCase())}?d=mm&s=${s}`;
} }
export function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S') { export function datetimeSpan(dt: Date | ObjectID, relative = true, format = '%Y-%m-%d %H:%M:%S') {
if (!dt) return 'DATETIME_SPAN_ERROR'; if (!dt) return 'DATETIME_SPAN_ERROR';
if (dt.generationTime) dt = new Date(dt.generationTime * 1000); if (dt instanceof ObjectID) dt = new Date(dt.generationTime * 1000);
else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt); else if (typeof dt === 'number' || typeof dt === 'string') dt = new Date(dt);
return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format( return '<span class="time{0}" data-timestamp="{1}">{2}</span>'.format(
relative ? ' relative' : '', relative ? ' relative' : '',
@@ -22,9 +23,10 @@ export function datetimeSpan(dt, relative = true, format = '%Y-%m-%d %H:%M:%S')
); );
} }
export function* paginate(page, numPages) { export function* paginate(page: number, numPages: number) {
const radius = 2; let first; let const radius = 2;
last; let first: number;
let last: number;
if (page > 1) { if (page > 1) {
yield ['first', 1]; yield ['first', 1];
yield ['previous', page - 1]; yield ['previous', page - 1];
@@ -45,7 +47,7 @@ export function* paginate(page, numPages) {
yield ['last', numPages]; yield ['last', numPages];
} }
export function size(s, base = 1) { export function size(s: number, base = 1) {
s *= base; s *= base;
const unit = 1024; const unit = 1024;
const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; const unitNames = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
@@ -53,12 +55,11 @@ export function size(s, base = 1) {
if (s < unit) return '{0} {1}'.format(Math.round(s * 10) / 10, unitName); if (s < unit) return '{0} {1}'.format(Math.round(s * 10) / 10, unitName);
s /= unit; s /= unit;
} }
return '{0} {1}'.format(Math.round(s * unit), unitNames[unitNames.length - 1]); return `${Math.round(s * unit)} ${unitNames[unitNames.length - 1]}`;
} }
function _digit2(number: number) { function _digit2(number: number) {
if (number < 10) return `0${number}`; return number < 10 ? `0${number}` : number.toString();
return number.toString();
} }
export function formatSeconds(_seconds = '0') { export function formatSeconds(_seconds = '0') {
+1 -1
View File
@@ -12,7 +12,7 @@ const Checker = (perm: bigint, priv: number, checker: Function = trueChecker) =>
const Item = ( const Item = (
name: string, args: any, prefix: string, name: string, args: any, prefix: string,
...permPrivChecker: Array<number | bigint | Function | Array<bigint | string>> ...permPrivChecker: Array<number | bigint | Function>
) => { ) => {
let _priv: number; let _priv: number;
let _perm: bigint; let _perm: bigint;
+4 -2
View File
@@ -1,6 +1,9 @@
import { Cursor } from 'mongodb';
import { ValidationError } from '../error'; import { ValidationError } from '../error';
async function paginate(cursor: import('mongodb').Cursor, page: number, pageSize: number): Promise<[any[], number, number]> { export default async function paginate(
cursor: Cursor, page: number, pageSize: number,
): Promise<[any[], number, number]> {
if (page <= 0) throw new ValidationError('page'); if (page <= 0) throw new ValidationError('page');
const [count, pageDocs] = await Promise.all([ const [count, pageDocs] = await Promise.all([
cursor.count(), cursor.count(),
@@ -11,4 +14,3 @@ async function paginate(cursor: import('mongodb').Cursor, page: number, pageSize
} }
global.Hydro.lib.paginate = paginate; global.Hydro.lib.paginate = paginate;
export default paginate;
+11 -8
View File
@@ -1,12 +1,16 @@
class User { class User {
rank: any; rank: number;
old: any; old: number;
seed: number; seed: number;
uid: number; uid: number;
delta?: number;
new: number;
constructor(rank: number, old: number, uid = 0) { constructor(rank: number, old: number, uid = 0) {
this.rank = rank; this.rank = rank;
this.old = old; this.old = old;
@@ -16,7 +20,7 @@ class User {
} }
class RatingCalculator { class RatingCalculator {
users: any; users: User[];
constructor(users) { constructor(users) {
this.users = []; this.users = [];
@@ -26,11 +30,11 @@ class RatingCalculator {
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
calP(a, b) { calP(a: User, b: User) {
return 1 / (1 + 10 ** ((b.old - a.old) / 400)); return 1 / (1 + 10 ** ((b.old - a.old) / 400));
} }
getExSeed(rating, ownUser) { getExSeed(rating: number, ownUser: User) {
const exUser = new User(0.0, rating); const exUser = new User(0.0, rating);
let result = 1; let result = 1;
for (const user of this.users) { for (const user of this.users) {
@@ -39,7 +43,7 @@ class RatingCalculator {
return result; return result;
} }
calRating(rank, user) { calRating(rank: number, user: User) {
let left = 1; let left = 1;
let right = 8000; let right = 8000;
while (right - left > 1) { while (right - left > 1) {
@@ -101,10 +105,9 @@ interface RatingOutputUser {
uid: number, uid: number,
} }
function calculate(users: RatingInputUser[]): RatingOutputUser[] { export default function calculate(users: RatingInputUser[]): RatingOutputUser[] {
const calculator = new RatingCalculator(users); const calculator = new RatingCalculator(users);
return calculator.calculate(); return calculator.calculate();
} }
global.Hydro.lib.rating = calculate; global.Hydro.lib.rating = calculate;
export default calculate;
+2 -16
View File
@@ -67,22 +67,8 @@ function _validate(scheme: any, arg: any, base: string): void {
} }
} }
function descriptor(scheme: any): Function { export function validate(scheme: any, arg: any) {
return function desc(target: any, name: string, obj: any) { return _validate(scheme, arg, '');
const originalMethod = obj.value;
obj.value = function func(...args: any[]) {
_validate(scheme, args[0], '');
return originalMethod.call(this, ...args);
};
return obj;
};
}
export function validate(scheme: any): Function;
export function validate(scheme: any, arg: any): void;
export function validate(...args: any[]): any {
if (args.length === 1) return descriptor(args[0]);
return _validate(args[0], args[1], '');
} }
export const isTitle = (s) => s && s.length < 64; export const isTitle = (s) => s && s.length < 64;
+11 -1
View File
@@ -4,6 +4,11 @@ import { Bdoc } from '../interface';
const coll = db.collection('blacklist'); const coll = db.collection('blacklist');
export async function add(ip: string): Promise<Bdoc> { export async function add(ip: string): Promise<Bdoc> {
/**
* Add a ip into blacklist.
* @param {string} ip
* @returns {Promise<Bdoc>}
*/
const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000); const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000);
const res = await coll.findOneAndUpdate( const res = await coll.findOneAndUpdate(
{ _id: ip }, { _id: ip },
@@ -13,7 +18,12 @@ export async function add(ip: string): Promise<Bdoc> {
return res.value; return res.value;
} }
export function get(ip: string): Promise<Bdoc> { export function get(ip: string): Promise<Bdoc | null> {
/**
* Get a ip, return null if not.
* @param {string} ip
* @returns {Promise<Bdoc>}
*/
return coll.findOne({ _id: ip }); return coll.findOne({ _id: ip });
} }
+18 -10
View File
@@ -5,6 +5,7 @@ import * as training from './training';
import * as document from './document'; import * as document from './document';
import { PERM } from './builtin'; import { PERM } from './builtin';
import { DocumentNotFoundError } from '../error'; import { DocumentNotFoundError } from '../error';
import { Ddoc, Drdoc, Drrdoc } from '../interface';
export const typeDisplay = { export const typeDisplay = {
[document.TYPE_PROBLEM]: 'problem', [document.TYPE_PROBLEM]: 'problem',
@@ -18,7 +19,7 @@ export function add(
domainId: string, parentType: number, parentId: ObjectID | number | string, domainId: string, parentType: number, parentId: ObjectID | number | string,
owner: number, title: string, content: string, owner: number, title: string, content: string,
ip: string | null = null, highlight: boolean = false, ip: string | null = null, highlight: boolean = false,
) { ): Promise<ObjectID> {
return document.add( return document.add(
domainId, content, owner, document.TYPE_DISCUSSION, domainId, content, owner, document.TYPE_DISCUSSION,
null, parentType, parentId, null, parentType, parentId,
@@ -33,14 +34,14 @@ export function add(
); );
} }
export function get(domainId: string, did: ObjectID) { export function get(domainId: string, did: ObjectID): Promise<Ddoc | null> {
return document.get(domainId, document.TYPE_DISCUSSION, did); return document.get(domainId, document.TYPE_DISCUSSION, did);
} }
export function edit( export function edit(
domainId: string, did: ObjectID, domainId: string, did: ObjectID,
title: string, content: string, highlight: boolean, title: string, content: string, highlight: boolean,
) { ): Promise<Ddoc | null> {
return document.set(domainId, document.TYPE_DISCUSSION, did, { title, content, highlight }); return document.set(domainId, document.TYPE_DISCUSSION, did, { title, content, highlight });
} }
@@ -65,7 +66,7 @@ export function getMulti(domainId: string, query: any = {}) {
export async function addReply( export async function addReply(
domainId: string, did: ObjectID, owner: number, domainId: string, did: ObjectID, owner: number,
content: string, ip: string, content: string, ip: string,
) { ): Promise<Drdoc> {
const [drdoc] = await Promise.all([ const [drdoc] = await Promise.all([
document.add( document.add(
domainId, content, owner, document.TYPE_DISCUSSION_REPLY, domainId, content, owner, document.TYPE_DISCUSSION_REPLY,
@@ -76,11 +77,13 @@ export async function addReply(
return drdoc; return drdoc;
} }
export function getReply(domainId: string, drid: ObjectID) { export function getReply(domainId: string, drid: ObjectID): Promise<Drdoc | null> {
return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid); return document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
} }
export async function editReply(domainId: string, drid: ObjectID, content: string) { export async function editReply(
domainId: string, drid: ObjectID, content: string,
): Promise<Drdoc | null> {
return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content }); return document.set(domainId, document.TYPE_DISCUSSION_REPLY, drid, { content });
} }
@@ -100,14 +103,14 @@ export function getMultiReply(domainId: string, did: ObjectID) {
).sort('_id', -1); ).sort('_id', -1);
} }
export function getListReply(domainId: string, did: ObjectID) { export function getListReply(domainId: string, did: ObjectID): Promise<Drdoc[]> {
return getMultiReply(domainId, did).toArray(); return getMultiReply(domainId, did).toArray();
} }
export async function addTailReply( export async function addTailReply(
domainId: string, drid: ObjectID, domainId: string, drid: ObjectID,
owner: number, content: string, ip: string, owner: number, content: string, ip: string,
) { ): Promise<[Drdoc, ObjectID]> {
let drdoc = await document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid); let drdoc = await document.get(domainId, document.TYPE_DISCUSSION_REPLY, drid);
const sid = new ObjectID(); const sid = new ObjectID();
[drdoc] = await Promise.all([ [drdoc] = await Promise.all([
@@ -117,11 +120,16 @@ export async function addTailReply(
return [drdoc, sid]; return [drdoc, sid];
} }
export function getTailReply(domainId: string, drid: ObjectID, drrid: ObjectID) { export function getTailReply(
domainId: string, drid: ObjectID, drrid: ObjectID,
): Promise<[Drdoc, Drrdoc] | [null, null]> {
// @ts-ignore
return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid); return document.getSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid);
} }
export function editTailReply(domainId: string, drid: ObjectID, drrid: ObjectID, content: string) { export function editTailReply(
domainId: string, drid: ObjectID, drrid: ObjectID, content: string,
): Promise<Drrdoc> {
return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content }); return document.setSub(domainId, document.TYPE_DISCUSSION_REPLY, drid, 'reply', drrid, { content });
} }
+2 -2
View File
@@ -27,7 +27,7 @@ export async function send(
return mdoc; return mdoc;
} }
export async function get(_id: ObjectID): Promise<Mdoc> { export async function get(_id: ObjectID): Promise<Mdoc | null> {
return await coll.findOne({ _id }); return await coll.findOne({ _id });
} }
@@ -41,7 +41,7 @@ export async function getMany(query: any, sort: any, page: number, limit: number
.toArray(); .toArray();
} }
export async function setFlag(messageId: ObjectID, flag: number) { export async function setFlag(messageId: ObjectID, flag: number): Promise<Mdoc | null> {
const result = await coll.findOneAndUpdate( const result = await coll.findOneAndUpdate(
{ _id: messageId }, { _id: messageId },
{ $bit: { flag: { xor: flag } } }, { $bit: { flag: { xor: flag } } },
+6 -4
View File
@@ -77,7 +77,7 @@ export function edit(domainId: string, _id: number, $set: any): Promise<Pdoc> {
return document.set(domainId, document.TYPE_PROBLEM, _id, $set); return document.set(domainId, document.TYPE_PROBLEM, _id, $set);
} }
export function inc(domainId: string, _id: number, field: string, n: number) { export function inc(domainId: string, _id: number, field: string, n: number): Promise<Pdoc> {
return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n); return document.inc(domainId, document.TYPE_PROBLEM, _id, field, n);
} }
@@ -85,7 +85,7 @@ export function count(domainId: string, query: any) {
return document.count(domainId, document.TYPE_PROBLEM, query); return document.count(domainId, document.TYPE_PROBLEM, query);
} }
export async function random(domainId: string, query: any) { export async function random(domainId: string, query: any): Promise<string | null> {
const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query); const cursor = document.getMulti(domainId, document.TYPE_PROBLEM, query);
const pcount = await cursor.count(); const pcount = await cursor.count();
if (pcount) { if (pcount) {
@@ -100,16 +100,18 @@ export async function getList(
): Promise<Pdict> { ): Promise<Pdict> {
pids = Array.from(new Set(pids)); pids = Array.from(new Set(pids));
const r = {}; const r = {};
const l = {};
const q: any = { $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }] }; const q: any = { $or: [{ docId: { $in: pids } }, { pid: { $in: pids } }] };
if (!getHidden) q.hidden = false; if (!getHidden) q.hidden = false;
const pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q).toArray(); const pdocs = await document.getMulti(domainId, document.TYPE_PROBLEM, q).toArray();
for (const pdoc of pdocs) { for (const pdoc of pdocs) {
r[pdoc.docId] = pdoc; r[pdoc.docId] = pdoc;
r[pdoc.pid] = pdoc; l[pdoc.pid] = pdoc;
} }
// TODO enhance
if (pdocs.length !== pids.length) { if (pdocs.length !== pids.length) {
for (const pid of pids) { for (const pid of pids) {
if (!r[pid]) { if (!(r[pid] || l[pid])) {
if (doThrow) { if (doThrow) {
throw new ProblemNotFoundError(domainId, pid); throw new ProblemNotFoundError(domainId, pid);
} else { } else {
-2
View File
@@ -1,5 +1,3 @@
import _ from 'lodash';
import yaml from 'js-yaml';
import { ObjectID } from 'mongodb'; import { ObjectID } from 'mongodb';
import { STATUS } from './builtin'; import { STATUS } from './builtin';
import * as task from './task'; import * as task from './task';
-1
View File
@@ -121,7 +121,6 @@ SystemSetting(
Setting('setting_server', 'server.cdn', null, '/', 'text', 'CDN Prefix', 'Ends with /'), Setting('setting_server', 'server.cdn', null, '/', 'text', 'CDN Prefix', 'Ends with /'),
Setting('setting_server', 'server.port', null, 8888, 'number', 'Server Port'), Setting('setting_server', 'server.port', null, 8888, 'number', 'Server Port'),
Setting('setting_server', 'server.xff', null, null, 'text', 'IP Header', 'e.g. x-forwarded-for (lowercase)'), Setting('setting_server', 'server.xff', null, null, 'text', 'IP Header', 'e.g. x-forwarded-for (lowercase)'),
Setting('setting_server', 'server.log', null, false, 'boolean', 'Disable Access Log'),
Setting('setting_session', 'session.keys', null, [String.random(32)], 'text', 'session.keys', null, FLAG_DISABLED | FLAG_HIDDEN), Setting('setting_session', 'session.keys', null, [String.random(32)], 'text', 'session.keys', null, FLAG_DISABLED | FLAG_HIDDEN),
Setting('setting_session', 'session.secure', null, false, 'boolean', 'session.secure'), Setting('setting_session', 'session.secure', null, false, 'boolean', 'session.secure'),
Setting('setting_session', 'session.saved_expire_seconds', null, 3600 * 24 * 30, 'number', 'Saved session expire seconds'), Setting('setting_session', 'session.saved_expire_seconds', null, 3600 * 24 * 30, 'number', 'Saved session expire seconds'),
-1
View File
@@ -1,4 +1,3 @@
import { ValidationError } from '../error';
import * as db from '../service/db'; import * as db from '../service/db';
const coll = db.collection('token'); const coll = db.collection('token');
+8 -1
View File
@@ -8,5 +8,12 @@ export default function load() {
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.config', 'hydro', 'config.json'); if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.config', 'hydro', 'config.json');
if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.hydro', 'config.json'); if (!fs.existsSync(f)) f = path.resolve(os.homedir(), '.hydro', 'config.json');
if (!fs.existsSync(f)) f = path.resolve('/config/config.json'); if (!fs.existsSync(f)) f = path.resolve('/config/config.json');
return JSON.parse(fs.readFileSync(f).toString()); let result: any = {};
try {
result = JSON.parse(fs.readFileSync(f).toString());
} catch (e) {
console.error('Cannot read config file', e);
result = {};
}
return result;
} }
+1 -1
View File
@@ -15,7 +15,7 @@ type ND = NumericDictionary<number>
function calc(udict: ND, rankedDocs: [number, number][]) { function calc(udict: ND, rankedDocs: [number, number][]) {
const users = []; const users = [];
for (const [rank, uid] of rankedDocs) { for (const [rank, uid] of rankedDocs) {
users.push({ uid, rank, old: users[uid] || 1500 }); users.push({ uid, rank, old: udict[uid] || 1500 });
} }
const rated = rating(users); const rated = rating(users);
for (const udoc of rated) { for (const udoc of rated) {
+10 -1
View File
@@ -13,6 +13,15 @@ export async function update() {
global.Hydro.stat.reqCount = 0; global.Hydro.stat.reqCount = 0;
} }
export function updateJudger(args) {
args.type = 'judger';
return coll.updateOne(
{ mid: args.mid, type: 'judger' },
{ $set: args },
{ upsert: true },
);
}
global.Hydro.postInit.push( global.Hydro.postInit.push(
async () => { async () => {
const info = await sysinfo.get(); const info = await sysinfo.get();
@@ -25,4 +34,4 @@ global.Hydro.postInit.push(
}, },
); );
global.Hydro.service.monitor = { update }; global.Hydro.service.monitor = { update, updateJudger };
+2 -2
View File
@@ -743,8 +743,8 @@ export function Connection(
// TODO use postInit? // TODO use postInit?
export async function start() { export async function start() {
const [disableLog, port] = await system.getMany(['server.log', 'server.port']); const port = await system.get('server.port');
if (!disableLog) { if (!argv.debug) {
app.use(morgan(':method :url :status :res[content-length] - :response-time ms', { app.use(morgan(':method :url :status :res[content-length] - :response-time ms', {
skip: (req, res) => res.hasHeader('nolog'), skip: (req, res) => res.hasHeader('nolog'),
})); }));
+3 -3
View File
@@ -1,8 +1,8 @@
import fs from 'fs'; import fs from 'fs';
import { serialize } from 'v8';
import cluster from 'cluster'; import cluster from 'cluster';
import path from 'path'; import path from 'path';
import * as superagent from 'superagent'; import * as superagent from 'superagent';
import serialize from 'serialize-javascript';
import proxy from 'superagent-proxy'; import proxy from 'superagent-proxy';
import Lru from 'lru-cache'; import Lru from 'lru-cache';
@@ -147,13 +147,13 @@ const TIME_UNITS = { '': 1000, m: 1, u: 0.001 };
const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i; const MEMORY_RE = /^([0-9]+(?:\.[0-9]*)?)([kmg])b?$/i;
const MEMORY_UNITS = { k: 0.1, m: 1, g: 1024 }; const MEMORY_UNITS = { k: 0.1, m: 1, g: 1024 };
export function parseTimeMS(str) { export function parseTimeMS(str: string) {
const match = TIME_RE.exec(str); const match = TIME_RE.exec(str);
if (!match) throw new Error(`${str} error parsing time`); if (!match) throw new Error(`${str} error parsing time`);
return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]); return Math.floor(parseFloat(match[1]) * TIME_UNITS[match[2]]);
} }
export function parseMemoryMB(str) { export function parseMemoryMB(str: string) {
const match = MEMORY_RE.exec(str); const match = MEMORY_RE.exec(str);
if (!match) throw new Error(`${str} error parsing memory`); if (!match) throw new Error(`${str} error parsing memory`);
return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]); return Math.floor(parseFloat(match[1]) * MEMORY_UNITS[match[2]]);
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.10.7", "version": "2.10.8",
"main": "dist/loader.js", "main": "dist/loader.js",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"repository": "https://github.com/hydro-dev/Hydro.git", "repository": "https://github.com/hydro-dev/Hydro.git",