From 76744e0584baf04659e85259aea2890fae113ecb Mon Sep 17 00:00:00 2001 From: undefined Date: Sat, 8 May 2021 23:23:59 +0800 Subject: [PATCH] core: use with hydro center --- packages/center/handler.ts | 80 +++++++++++++++++++++++++ packages/center/package.json | 12 ++++ packages/hydrooj/package.json | 2 +- packages/hydrooj/src/handler/remote.ts | 18 ++++-- packages/hydrooj/src/model/setting.ts | 2 + packages/hydrooj/src/service/monitor.ts | 15 ++--- 6 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 packages/center/handler.ts create mode 100644 packages/center/package.json diff --git a/packages/center/handler.ts b/packages/center/handler.ts new file mode 100644 index 000000000..b86d8a680 --- /dev/null +++ b/packages/center/handler.ts @@ -0,0 +1,80 @@ +import db from 'hydrooj/dist/service/db'; +import { + Handler, param, post, Route, Types, +} from 'hydrooj/dist/service/server'; +import { RemoteOnlineJudgeError } from 'hydrooj/dist/error'; +import crypto from 'crypto'; +import yaml from 'js-yaml'; +import superagent from 'superagent'; + +function decrypt(encrypted: string) { + if (!encrypted) throw new Error(); + const decipher = crypto.createDecipheriv('des-ecb', 'hydro-oj', ''); + let decrypted = decipher.update(encrypted, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + return decrypted; +} + +declare module 'hydrooj/dist/interface' { + interface Collections { + dataReport: any; + } +} + +const coll = db.collection('dataReport'); + +class DataReportHandler extends Handler { + noCheckPermView = true; + + @post('instanceId', Types.String) + @post('payload', Types.String) + async post(domainId: string, instanceId: string, _payload: string) { + const payload: any = yaml.load(decrypt(_payload)); + await coll.updateOne({ _id: instanceId }, { + $set: { + version: payload.version, + name: payload.name, + url: payload.url, + addons: payload.addons, + mem: payload.memory, + osinfo: payload.osinfo, + cpu: payload.cpu, + ip: this.request.ip, + flags: payload.flags, + update: new Date(), + domainCount: payload.domainCount, + userCount: payload.userCount, + problemCount: payload.problemCount, + discussionCount: payload.discussionCount, + recordCount: payload.recordCount, + }, + }, { upsert: true }); + this.response.body = 'success'; + } +} + +class ProxySendRequestHandler extends Handler { + @param('endpoint', Types.String) + @param('domainId', Types.String) + @param('url', Types.String) + @param('tokenId', Types.String) + @param('expire', Types.UnsignedInt) + async post(_d: string, endpoint: string, domainId: string, url: string, tokenId: string, expire: number) { + let res = await superagent.post(`${url}d/${domainId}/problem/send`) + .send({ operation: 'info', token: tokenId }) + .catch((e) => e); + if (res instanceof Error) throw new RemoteOnlineJudgeError(res.message); + res = await superagent.post(`${endpoint}/problem/receive`).send({ + operation: 'request', url: `${url}d/${domainId}/problem/send`, tokenId, expire, + }).catch((e) => e); + if (res instanceof Error) throw new RemoteOnlineJudgeError(res.message); + this.response.body = { code: 0 }; + } +} + +export function apply() { + Route('data_report', '/center/report', DataReportHandler); + Route('proxy_send', '/center/send', ProxySendRequestHandler); +} + +global.Hydro.handler.center = apply; diff --git a/packages/center/package.json b/packages/center/package.json new file mode 100644 index 000000000..e33bd8042 --- /dev/null +++ b/packages/center/package.json @@ -0,0 +1,12 @@ +{ + "name": "@hydrooj/center", + "version": "0.0.1", + "main": "package.json", + "repository": "https://github.com/hydro-dev/Hydro.git", + "author": "undefined ", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.0", + "superagent": "^6.1.0" + } +} diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index e1e6f093d..52af193ea 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.25.6", + "version": "2.25.7", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/handler/remote.ts b/packages/hydrooj/src/handler/remote.ts index 0d08e5d0f..0fbb1e8a9 100644 --- a/packages/hydrooj/src/handler/remote.ts +++ b/packages/hydrooj/src/handler/remote.ts @@ -43,10 +43,20 @@ export class ProblemSendHandler extends Handler { } const [url, expire] = system.getMany(['server.url', 'session.saved_expire_seconds']); const tokenId = await token.createOrUpdate(token.TYPE_EXPORT, expire, { domainId, pids: Array.from(pids) }); - await superagent.post(`${target[1]}/d/${target[0]}/problem/receive`) - .send({ - operation: 'request', url: `${url}d/${domainId}/problem/send`, tokenId, expire, - }).catch(logAndReturn(logger)); + const res = system.get('server.proxy') + ? await superagent.post(`${system.get('server.center')}/send`) + .send({ + endpoint: `${target[1]}/d/${target[0]}`, + domainId, + url, + tokenId, + expire, + }).catch(logAndReturn(logger)) + : await superagent.post(`${target[1]}/d/${target[0]}/problem/receive`) + .send({ + operation: 'request', url: `${url}d/${domainId}/problem/send`, tokenId, expire, + }).catch(logAndReturn(logger)); + if (res instanceof Error) throw new RemoteOnlineJudgeError(res.message); this.back(); } diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index 916a61e69..3c8879ef0 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -164,6 +164,8 @@ SystemSetting( Setting('setting_smtp', 'smtp.port', 465, 'number', 'smtp.port', 'SMTP Server Port'), Setting('setting_smtp', 'smtp.from', null, 'text', 'smtp.from', 'Mail From'), Setting('setting_smtp', 'smtp.secure', false, 'boolean', 'smtp.secure', 'SSL'), + Setting('setting_server', 'server.center', 'https://hydro.undefined.moe:8443/center', 'text', 'server.center', '', FLAG_HIDDEN), + Setting('setting_server', 'server.proxy', false, 'boolean', 'server.proxy', 'Use hydro center proxy to send problems'), Setting('setting_server', 'server.name', 'Hydro', 'text', 'server.name', 'Server Name'), Setting('setting_server', 'server.worker', 1, 'number', 'server.worker', 'Server Workers Number'), Setting('setting_server', 'server.hostname', 'oj.undefined.moe', 'text', 'server.hostname', 'Server Hostname'), diff --git a/packages/hydrooj/src/service/monitor.ts b/packages/hydrooj/src/service/monitor.ts index 2202b899a..43612bd52 100644 --- a/packages/hydrooj/src/service/monitor.ts +++ b/packages/hydrooj/src/service/monitor.ts @@ -24,7 +24,7 @@ export async function feedback(): Promise<[string, StatusUpdate]> { } = global.Hydro.model; const version = require('hydrooj/package.json').version; const [mid, $update, inf] = await sysinfo.update(); - const [installid, name, url] = system.getMany(['installid', 'server.name', 'server.url']); + const [installId, name, url] = system.getMany(['installid', 'server.name', 'server.url']); const [domainCount, userCount, problemCount, discussionCount, recordCount] = await Promise.all([ domain.getMulti().count(), user.getMulti().count(), @@ -33,7 +33,7 @@ export async function feedback(): Promise<[string, StatusUpdate]> { record.coll.find().count(), ]); const payload = crypt(dump({ - _id: installid + mid.toString(), + mid: mid.toString(), version, name, url, @@ -47,11 +47,12 @@ export async function feedback(): Promise<[string, StatusUpdate]> { osinfo: inf.osinfo, cpu: inf.cpu, })); - superagent.post('https://feedback.undefined.moe/') - .send({ payload }) - .catch(() => { - logger.warn('Cannot connect to hydro center.'); - }); + superagent.post(`${system.get('server.center')}/report`) + .send({ installId, payload }) + .then((res) => { + if (res.body.updateUrl) system.set('server.center', res.body.updateUrl); + }) + .catch(() => logger.warn('Cannot connect to hydro center.')); return [mid, $update]; }