mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: feat: problem_delete
This commit is contained in:
1 parent
3d9acf2c1a
commit
1543a374e3
12 files changed
+151
-174
No files matched your search
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "2.15.16",
|
||||
"version": "2.15.17",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"main": "dist/loader.js",
|
||||
"typings": "dist/loader.d.ts",
|
||||
|
||||
@@ -73,16 +73,14 @@ class RecordDetailHandler extends RecordHandler {
|
||||
const tdoc = await contest.get(domainId, rdoc.contest.tid, rdoc.contest.type);
|
||||
if (!this.canShowRecord(tdoc, true)) throw new PermissionError(rid);
|
||||
}
|
||||
if (rdoc.uid !== this.user.uid && !this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) {
|
||||
rdoc.code = null;
|
||||
}
|
||||
if (rdoc.uid !== this.user.uid && !this.user.hasPerm(PERM.PERM_READ_RECORD_CODE)) rdoc.code = null;
|
||||
// eslint-disable-next-line prefer-const
|
||||
let [pdoc, udoc] = await Promise.all([
|
||||
problem.get(domainId, rdoc.pid),
|
||||
user.getById(domainId, rdoc.uid),
|
||||
]);
|
||||
if (!rdoc.contest && pdoc.hidden && pdoc.owner !== this.user._id) {
|
||||
if (this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) {
|
||||
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) {
|
||||
pdoc = problem.Pdoc.create(pdoc.docId, pdoc.pid);
|
||||
}
|
||||
}
|
||||
@@ -130,22 +128,6 @@ class RecordDetailHandler extends RecordHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* use RecordDetailHandler.postRejudge instead.
|
||||
*/
|
||||
class RecordRejudgeHandler extends Handler {
|
||||
@param('rid', Types.ObjectID)
|
||||
async post(domainId: string, rid: ObjectID) {
|
||||
const rdoc = await record.get(domainId, rid);
|
||||
if (rdoc) {
|
||||
await record.reset(domainId, rid, true);
|
||||
await record.judge(domainId, rid, 0);
|
||||
}
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
|
||||
const RecordConnectionHandler = contest.ContestHandlerMixin(ConnectionHandler);
|
||||
|
||||
class RecordMainConnectionHandler extends RecordConnectionHandler {
|
||||
@@ -230,7 +212,6 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti
|
||||
export async function apply() {
|
||||
Route('record_main', '/record', RecordListHandler);
|
||||
Route('record_detail', '/record/:rid', RecordDetailHandler);
|
||||
Route('record_rejudge', '/record/:rid/rejudge', RecordRejudgeHandler);
|
||||
Connection('record_conn', '/record-conn', RecordMainConnectionHandler);
|
||||
Connection('record_detail_conn', '/record-detail-conn', RecordDetailConnectionHandler);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface SystemKeys {
|
||||
'server.worker': number,
|
||||
'server.port': number,
|
||||
'server.language': string,
|
||||
'problem.categories': string,
|
||||
'session.keys': string[],
|
||||
'session.secure': boolean,
|
||||
'session.expire_seconds': number,
|
||||
|
||||
@@ -4,11 +4,6 @@ import * as bus from '../service/bus';
|
||||
const coll = db.collection('blacklist');
|
||||
|
||||
export async function add(ip: string) {
|
||||
/**
|
||||
* Add a ip into blacklist.
|
||||
* @param {string} ip
|
||||
* @returns {Promise<Bdoc>}
|
||||
*/
|
||||
const expireAt = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000);
|
||||
const res = await coll.findOneAndUpdate(
|
||||
{ _id: ip },
|
||||
@@ -18,21 +13,16 @@ export async function add(ip: string) {
|
||||
return res.value;
|
||||
}
|
||||
|
||||
export function get(ip: string) {
|
||||
/**
|
||||
* Get a ip, return null if not.
|
||||
* @param {string} ip
|
||||
* @returns {Promise<Bdoc>}
|
||||
*/
|
||||
return coll.findOne({ _id: ip });
|
||||
export async function get(ip: string) {
|
||||
return await coll.findOne({ _id: ip });
|
||||
}
|
||||
|
||||
export function del(ip: string) {
|
||||
return coll.deleteOne({ _id: ip });
|
||||
export async function del(ip: string) {
|
||||
return await coll.deleteOne({ _id: ip });
|
||||
}
|
||||
|
||||
function ensureIndexes() {
|
||||
return coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
||||
async function ensureIndexes() {
|
||||
return await coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
||||
}
|
||||
|
||||
bus.once('app/started', ensureIndexes);
|
||||
|
||||
@@ -5,6 +5,7 @@ import * as training from './training';
|
||||
import * as document from './document';
|
||||
import { DocumentNotFoundError } from '../error';
|
||||
import { Ddoc, Drdoc, Drrdoc } from '../interface';
|
||||
import * as bus from '../service/bus';
|
||||
|
||||
export const typeDisplay = {
|
||||
[document.TYPE_PROBLEM]: 'problem',
|
||||
@@ -215,6 +216,22 @@ export async function getListVnodes(domainId: string, ddocs: any, getHidden: boo
|
||||
return res;
|
||||
}
|
||||
|
||||
bus.on('problem/delete', async (domainId, docId) => {
|
||||
const dids = await document.getMulti(
|
||||
domainId, document.TYPE_DISCUSSION,
|
||||
{ parentType: document.TYPE_PROBLEM, parentId: docId },
|
||||
).project({ docId: 1 }).map((ddoc) => ddoc.docId).toArray();
|
||||
const drids = await document.getMulti(
|
||||
domainId, document.TYPE_DISCUSSION_REPLY,
|
||||
{ parentType: document.TYPE_DISCUSSION, parentId: { $in: dids } },
|
||||
).project({ docId: 1 }).map((drdoc) => drdoc.docId).toArray();
|
||||
return await Promise.all([
|
||||
document.deleteMultiStatus(domainId, document.TYPE_DISCUSSION, { docId: { $in: dids } }),
|
||||
document.deleteMulti(domainId, document.TYPE_DISCUSSION, { docId: { $in: dids } }),
|
||||
document.deleteMulti(domainId, document.TYPE_DISCUSSION_REPLY, { docId: { $in: drids } }),
|
||||
]);
|
||||
});
|
||||
|
||||
global.Hydro.model.discussion = {
|
||||
typeDisplay,
|
||||
add,
|
||||
|
||||
@@ -25,7 +25,6 @@ export const TYPE_DISCUSSION = 21;
|
||||
export const TYPE_DISCUSSION_REPLY = 22;
|
||||
export const TYPE_CONTEST = 30;
|
||||
export const TYPE_TRAINING = 40;
|
||||
export const TYPE_FILE = 50;
|
||||
export const TYPE_HOMEWORK = 60;
|
||||
|
||||
export interface DocType {
|
||||
@@ -37,7 +36,6 @@ export interface DocType {
|
||||
[TYPE_DISCUSSION_REPLY]: Drdoc,
|
||||
[TYPE_CONTEST]: Tdoc,
|
||||
[TYPE_TRAINING]: TrainingDoc,
|
||||
[TYPE_FILE]: any,
|
||||
[TYPE_HOMEWORK]: Tdoc,
|
||||
}
|
||||
|
||||
@@ -457,6 +455,5 @@ global.Hydro.model.document = {
|
||||
TYPE_PROBLEM,
|
||||
TYPE_PROBLEM_LIST,
|
||||
TYPE_PROBLEM_SOLUTION,
|
||||
TYPE_FILE,
|
||||
TYPE_TRAINING,
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import { Content } from '../loader';
|
||||
import { ArrayKeys, NumberKeys, Projection } from '../typeutils';
|
||||
import { ProblemNotFoundError } from '../error';
|
||||
import storage from '../service/storage';
|
||||
import * as bus from '../service/bus';
|
||||
|
||||
export interface Pdoc {
|
||||
_id: ObjectID
|
||||
@@ -207,6 +208,11 @@ export function setStar(domainId: string, pid: number, uid: number, star: boolea
|
||||
return document.setStatus(domainId, document.TYPE_PROBLEM, pid, uid, { star });
|
||||
}
|
||||
|
||||
bus.on('problem/delete', (domainId, docId) => Promise.all([
|
||||
document.deleteOne(domainId, document.TYPE_PROBLEM, docId),
|
||||
document.deleteMultiStatus(domainId, document.TYPE_PROBLEM, { docId }),
|
||||
]));
|
||||
|
||||
global.Hydro.model.problem = {
|
||||
Pdoc,
|
||||
|
||||
|
||||
@@ -2,12 +2,15 @@ import {
|
||||
ObjectID, Collection, UpdateQuery, PushOperator, MatchKeysAndValues, OnlyFieldsOfType,
|
||||
} from 'mongodb';
|
||||
import { Dictionary } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { STATUS } from './builtin';
|
||||
import * as task from './task';
|
||||
import * as problem from './problem';
|
||||
import {
|
||||
Rdoc, TestCase, RunConfig, ContestInfo, ProblemConfig,
|
||||
} from '../interface';
|
||||
import { Time } from '../utils';
|
||||
import * as bus from '../service/bus';
|
||||
import db from '../service/db';
|
||||
import storage from '../service/storage';
|
||||
|
||||
@@ -55,6 +58,19 @@ export async function get(domainId: string, _id: ObjectID): Promise<Rdoc | null>
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function stat(domainId?: string) {
|
||||
const [d5min, d1h, d1d, d1m, total] = await Promise.all([
|
||||
coll.find({ _id: { $gte: Time.getObjectID(moment().add(-5, 'minutes')) }, ...domainId ? { domainId } : {} }).count(),
|
||||
coll.find({ _id: { $gte: Time.getObjectID(moment().add(-1, 'hour')) }, ...domainId ? { domainId } : {} }).count(),
|
||||
coll.find({ _id: { $gte: Time.getObjectID(moment().add(-1, 'day')) }, ...domainId ? { domainId } : {} }).count(),
|
||||
coll.find({ _id: { $gte: Time.getObjectID(moment().add(-1, 'month')) }, ...domainId ? { domainId } : {} }).count(),
|
||||
coll.find(domainId ? { domainId } : {}).count(),
|
||||
]);
|
||||
return {
|
||||
d5min, d1h, d1d, d1m, total,
|
||||
};
|
||||
}
|
||||
|
||||
export async function judge(domainId: string, rid: ObjectID, priority = 1) {
|
||||
const rdoc = await get(domainId, rid);
|
||||
let config: RunConfig | ProblemConfig = rdoc.config;
|
||||
@@ -186,11 +202,14 @@ export function getByUid(domainId: string, uid: number, limit: number): Promise<
|
||||
return coll.find({ domainId, uid }).limit(limit).toArray();
|
||||
}
|
||||
|
||||
bus.on('problem/delete', (domainId, docId) => coll.deleteMany({ domainId, pid: docId }));
|
||||
|
||||
global.Hydro.model.record = {
|
||||
coll,
|
||||
add,
|
||||
get,
|
||||
getMulti,
|
||||
stat,
|
||||
update,
|
||||
count,
|
||||
reset,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ObjectID } from 'mongodb';
|
||||
import * as document from './document';
|
||||
import { SolutionNotFoundError } from '../error';
|
||||
import * as bus from '../service/bus';
|
||||
|
||||
export function add(domainId: string, pid: number, owner: number, content: string) {
|
||||
return document.add(
|
||||
@@ -26,8 +27,11 @@ export function edit(domainId: string, psid: ObjectID, content: string) {
|
||||
return document.set(domainId, document.TYPE_PROBLEM_SOLUTION, psid, { content });
|
||||
}
|
||||
|
||||
export function del(domainId: string, psid: ObjectID) {
|
||||
return document.deleteOne(domainId, document.TYPE_PROBLEM_SOLUTION, psid);
|
||||
export async function del(domainId: string, psid: ObjectID) {
|
||||
return await Promise.all([
|
||||
document.deleteOne(domainId, document.TYPE_PROBLEM_SOLUTION, psid),
|
||||
document.deleteMultiStatus(domainId, document.TYPE_PROBLEM_SOLUTION, { docId: psid }),
|
||||
]);
|
||||
}
|
||||
|
||||
export function count(domainId: string, query: any) {
|
||||
@@ -75,6 +79,17 @@ export async function getListStatus(domainId: string, psids: ObjectID[], uid: nu
|
||||
return result;
|
||||
}
|
||||
|
||||
bus.on('problem/delete', async (domainId, docId) => {
|
||||
const psids = await document.getMulti(
|
||||
domainId, document.TYPE_PROBLEM_SOLUTION,
|
||||
{ parentType: document.TYPE_PROBLEM, parentId: docId },
|
||||
).project({ docId: 1 }).map((psdoc) => psdoc.docId).toArray();
|
||||
return await Promise.all([
|
||||
document.deleteMulti(domainId, document.TYPE_PROBLEM_SOLUTION, { docId: { $in: psids } }),
|
||||
document.deleteMultiStatus(domainId, document.TYPE_PROBLEM_SOLUTION, { docId: { $in: psids } }),
|
||||
]);
|
||||
});
|
||||
|
||||
global.Hydro.model.solution = {
|
||||
count,
|
||||
add,
|
||||
|
||||
@@ -17,7 +17,7 @@ function isBailed(value: any) {
|
||||
}
|
||||
|
||||
export type Disposable = () => void
|
||||
export type VoidReturn = Promise<void> | void
|
||||
export type VoidReturn = Promise<any> | any
|
||||
|
||||
export interface EventMap {
|
||||
'app/started': () => void
|
||||
@@ -57,6 +57,7 @@ export interface EventMap {
|
||||
'problem/list': (query: FilterQuery<Pdoc>, handler: any) => VoidReturn
|
||||
'problem/setting': (update: Partial<Pdoc>, handler: any) => VoidReturn
|
||||
'problem/get': (doc: Pdoc, handler: any) => VoidReturn
|
||||
'problem/delete': (domainId: string, docId: number) => VoidReturn
|
||||
|
||||
'training/list': (query: FilterQuery<TrainingDoc>, handler: any) => VoidReturn
|
||||
'training/get': (tdoc: TrainingDoc, handler: any) => VoidReturn
|
||||
|
||||
@@ -293,13 +293,68 @@ export async function prepare() {
|
||||
}));
|
||||
}
|
||||
|
||||
export class Handler {
|
||||
UIContext: any;
|
||||
|
||||
args: any;
|
||||
|
||||
export class HandlerCommon {
|
||||
domainId: string;
|
||||
domain: DomainDoc;
|
||||
user: User;
|
||||
session: Record<string, any>;
|
||||
request: Record<string, any>;
|
||||
|
||||
async limitRate(op: string, periodSecs: number, maxOperations: number) {
|
||||
await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
|
||||
}
|
||||
|
||||
translate(str: string) {
|
||||
if (!str) return '';
|
||||
return str.toString().translate(this.user.viewLang, this.session.viewLang);
|
||||
}
|
||||
|
||||
renderTitle(str: string) {
|
||||
return `${this.translate(str)} - ${system.get('server.name')}`;
|
||||
}
|
||||
|
||||
checkPerm(...args: bigint[]) {
|
||||
// @ts-ignore
|
||||
if (!this.user.hasPerm(...args)) throw new PermissionError(...args);
|
||||
}
|
||||
|
||||
checkPriv(...args: number[]) {
|
||||
// @ts-ignore
|
||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||
}
|
||||
|
||||
url(name: string, kwargs: any = {}) {
|
||||
let res = '#';
|
||||
const args: any = {};
|
||||
const query: any = {};
|
||||
for (const key in kwargs) {
|
||||
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
|
||||
else args[key] = kwargs[key].toString();
|
||||
}
|
||||
for (const key in kwargs.query || {}) {
|
||||
if (query[key] instanceof ObjectID) query[key] = kwargs.query[key].toHexString();
|
||||
else query[key] = kwargs.query[key].toString();
|
||||
}
|
||||
try {
|
||||
if (this.domainId !== 'system' || args.domainId) {
|
||||
name += '_with_domainId';
|
||||
args.domainId = args.domainId || this.domainId;
|
||||
}
|
||||
const { anchor } = args;
|
||||
res = router.url(name, args, { query });
|
||||
if (anchor) return `${res}#${anchor}`;
|
||||
} catch (e) {
|
||||
logger.warn(e.message);
|
||||
logger.info('%s %o', name, args);
|
||||
logger.info('%s', e.stack);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
export class Handler extends HandlerCommon {
|
||||
UIContext: any;
|
||||
args: any;
|
||||
ctx: Koa.Context;
|
||||
|
||||
request: {
|
||||
@@ -327,19 +382,12 @@ export class Handler {
|
||||
attachment: (name: string, stream?: any) => void,
|
||||
};
|
||||
|
||||
session: any;
|
||||
|
||||
csrfToken: string;
|
||||
|
||||
user: User;
|
||||
|
||||
domain: DomainDoc;
|
||||
|
||||
loginMethods: any;
|
||||
|
||||
__param: Record<string, ParamOption[]>;
|
||||
|
||||
constructor(ctx: Koa.Context) {
|
||||
super();
|
||||
this.ctx = ctx;
|
||||
this.request = {
|
||||
host: ctx.request.host,
|
||||
@@ -405,57 +453,6 @@ export class Handler {
|
||||
return res;
|
||||
}
|
||||
|
||||
async limitRate(op: string, periodSecs: number, maxOperations: number) {
|
||||
await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
|
||||
}
|
||||
|
||||
translate(str: string) {
|
||||
if (!str) return '';
|
||||
return str.toString().translate(this.user.viewLang, this.session.viewLang);
|
||||
}
|
||||
|
||||
renderTitle(str: string) {
|
||||
return `${this.translate(str)} - ${system.get('server.name')}`;
|
||||
}
|
||||
|
||||
checkPerm(...args: bigint[]) {
|
||||
// @ts-ignore
|
||||
if (!this.user.hasPerm(...args)) throw new PermissionError(...args);
|
||||
}
|
||||
|
||||
checkPriv(...args: number[]) {
|
||||
// @ts-ignore
|
||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||
}
|
||||
|
||||
url(name: string, kwargs: any = {}) {
|
||||
let res = '#';
|
||||
const args: any = {};
|
||||
const query: any = {};
|
||||
for (const key in kwargs) {
|
||||
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
|
||||
else args[key] = kwargs[key].toString();
|
||||
}
|
||||
for (const key in kwargs.query || {}) {
|
||||
if (query[key] instanceof ObjectID) query[key] = kwargs.query[key].toHexString();
|
||||
else query[key] = kwargs.query[key].toString();
|
||||
}
|
||||
try {
|
||||
if (this.domainId !== 'system' || args.domainId) {
|
||||
name += '_with_domainId';
|
||||
args.domainId = args.domainId || this.domainId;
|
||||
}
|
||||
const { anchor } = args;
|
||||
res = router.url(name, args, { query });
|
||||
if (anchor) return `${res}#${anchor}`;
|
||||
} catch (e) {
|
||||
logger.warn(e.message);
|
||||
logger.info('%s %o', name, args);
|
||||
logger.info('%s', e.stack);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
async render(name: string, context: any) {
|
||||
this.response.body = await this.renderHTML(name, context);
|
||||
this.response.type = 'text/html';
|
||||
@@ -584,8 +581,8 @@ export class Handler {
|
||||
|
||||
async saveCookie() {
|
||||
const expireSeconds = this.session.save
|
||||
? system.get('session.expire_seconds') as number
|
||||
: system.get('session.unsaved_expire_seconds') as number;
|
||||
? system.get('session.expire_seconds')
|
||||
: system.get('session.unsaved_expire_seconds');
|
||||
if (this.session._id) {
|
||||
await token.update(
|
||||
this.session._id,
|
||||
@@ -614,10 +611,6 @@ export class Handler {
|
||||
secure: !!system.get('session.secure'),
|
||||
httpOnly: false,
|
||||
};
|
||||
if (this.session.save) {
|
||||
cookie.expires = this.session.expireAt;
|
||||
cookie.maxAge = expireSeconds;
|
||||
}
|
||||
this.ctx.cookies.set('sid', this.session._id, cookie);
|
||||
}
|
||||
|
||||
@@ -717,26 +710,17 @@ export function Route(name: string, path: string, RouteHandler: any, ...permPriv
|
||||
router.all(`${name}_with_domainId`, `/d/:domainId${path}`, (ctx) => handle(ctx, RouteHandler, checker));
|
||||
}
|
||||
|
||||
export class ConnectionHandler {
|
||||
export class ConnectionHandler extends HandlerCommon {
|
||||
conn: sockjs.Connection;
|
||||
|
||||
args: any;
|
||||
request: {
|
||||
params: any;
|
||||
headers: any;
|
||||
ip: string;
|
||||
}
|
||||
|
||||
domainId: string;
|
||||
|
||||
session: any;
|
||||
|
||||
args: any;
|
||||
|
||||
user: User;
|
||||
|
||||
domain: DomainDoc;
|
||||
|
||||
constructor(conn: sockjs.Connection) {
|
||||
super();
|
||||
this.conn = conn;
|
||||
this.request = {
|
||||
params: {},
|
||||
@@ -758,54 +742,6 @@ export class ConnectionHandler {
|
||||
return res;
|
||||
}
|
||||
|
||||
async limitRate(op: string, periodSecs: number, maxOperations: number) {
|
||||
await opcount.inc(op, this.request.ip, periodSecs, maxOperations);
|
||||
}
|
||||
|
||||
translate(str: string) {
|
||||
return str ? str.toString().translate(this.user.viewLang || this.session.viewLang) : '';
|
||||
}
|
||||
|
||||
renderTitle(str: string) {
|
||||
return `${this.translate(str)} - ${system.get('server.name')}`;
|
||||
}
|
||||
|
||||
checkPerm(...args: bigint[]) {
|
||||
if (!this.user.hasPerm(...args)) throw new PermissionError(...args);
|
||||
}
|
||||
|
||||
checkPriv(...args: number[]) {
|
||||
// @ts-ignore
|
||||
if (!this.user.hasPriv(...args)) throw new PrivilegeError(...args);
|
||||
}
|
||||
|
||||
url(name: string, kwargs: any = {}) {
|
||||
let res = '#';
|
||||
const args: any = {};
|
||||
const query: any = {};
|
||||
for (const key in kwargs) {
|
||||
if (kwargs[key] instanceof ObjectID) args[key] = kwargs[key].toHexString();
|
||||
else args[key] = kwargs[key].toString();
|
||||
}
|
||||
for (const key in kwargs.query || {}) {
|
||||
if (query[key] instanceof ObjectID) query[key] = kwargs.query[key].toHexString();
|
||||
else query[key] = kwargs.query[key].toString();
|
||||
}
|
||||
try {
|
||||
if (this.args.domainId !== 'system' || args.domainId) {
|
||||
name += '_with_domainId';
|
||||
args.domainId = args.domainId || this.args.domainId;
|
||||
}
|
||||
const { anchor } = args;
|
||||
res = router.url(name, args, { query });
|
||||
if (anchor) return `${res}#${anchor}`;
|
||||
} catch (e) {
|
||||
logger.error(e.message);
|
||||
logger.info(name, args);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
send(data: any) {
|
||||
this.conn.write(JSON.stringify(data));
|
||||
}
|
||||
@@ -934,6 +870,7 @@ global.Hydro.service.server = {
|
||||
route,
|
||||
param,
|
||||
requireCsrfToken,
|
||||
HandlerCommon,
|
||||
Handler,
|
||||
ConnectionHandler,
|
||||
Route,
|
||||
|
||||
@@ -4,6 +4,9 @@ import cluster from 'cluster';
|
||||
import path from 'path';
|
||||
import serialize from 'serialize-javascript';
|
||||
import Lru from 'lru-cache';
|
||||
import { ObjectID } from 'mongodb';
|
||||
import { isMoment } from 'moment';
|
||||
import { Moment } from 'moment-timezone';
|
||||
|
||||
declare global {
|
||||
interface StringConstructor {
|
||||
@@ -240,4 +243,14 @@ export namespace Time {
|
||||
}
|
||||
return `${ms}ms`;
|
||||
}
|
||||
|
||||
export function getObjectID(timestamp: string | Date | Moment) {
|
||||
let _timestamp: number;
|
||||
if (typeof timestamp === 'string') _timestamp = new Date(timestamp).getTime();
|
||||
else if (isMoment(timestamp)) _timestamp = timestamp.toDate().getTime();
|
||||
else _timestamp = timestamp.getTime();
|
||||
const hexSeconds = Math.floor(_timestamp / 1000).toString(16);
|
||||
const constructedObjectId = new ObjectID(`${hexSeconds}0000000000000000`);
|
||||
return constructedObjectId;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user