mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-22 08:58:42 +00:00
refactor(remote_judger): remote_submit_type
This commit is contained in:
parent
2ab8d07683
commit
7bc29d60c9
@ -7,6 +7,7 @@ import * as TIME from './utils/time';
|
||||
import { apply } from './vjudge';
|
||||
import path from 'path';
|
||||
import child from 'child_process';
|
||||
import htmlspecialchars from './utils/htmlspecialchars';
|
||||
|
||||
proxy(superagent);
|
||||
|
||||
@ -146,7 +147,8 @@ export default async function daemon(config: UOJConfig) {
|
||||
config.remote_problem_id,
|
||||
config.answer_language,
|
||||
code,
|
||||
judge_time
|
||||
judge_time,
|
||||
config
|
||||
);
|
||||
} catch (err) {
|
||||
await request('/submit', {
|
||||
@ -157,7 +159,7 @@ export default async function daemon(config: UOJConfig) {
|
||||
status: 'Judged',
|
||||
score: 0,
|
||||
error: 'Judgment Failed',
|
||||
details: `<error>No details.</error>`,
|
||||
details: `<error>${htmlspecialchars(err.message)}</error>`,
|
||||
}),
|
||||
judge_time,
|
||||
});
|
||||
|
@ -73,6 +73,10 @@ export default class AtcoderProvider implements IBasicProvider {
|
||||
this.account.endpoint ||= 'https://atcoder.jp';
|
||||
}
|
||||
|
||||
static constructFromAccountData(data) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
cookie: string[] = ['language=en'];
|
||||
csrf: string;
|
||||
|
||||
|
@ -87,6 +87,10 @@ export default class CodeforcesProvider implements IBasicProvider {
|
||||
this.account.endpoint ||= 'https://codeforces.com';
|
||||
}
|
||||
|
||||
static constructFromAccountData(data) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
cookie: string[] = [];
|
||||
csrf: string;
|
||||
|
||||
|
@ -156,6 +156,10 @@ export default class LibreojProvider implements IBasicProvider {
|
||||
this.account.endpoint ||= 'https://api.loj.ac.cn/api';
|
||||
}
|
||||
|
||||
static constructFromAccountData(data) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
get(url: string) {
|
||||
logger.debug('get', url);
|
||||
if (!url.includes('//')) url = `${this.account.endpoint}${url}`;
|
||||
|
@ -99,6 +99,10 @@ export default class UOJProvider implements IBasicProvider {
|
||||
if (account.cookie) this.cookie = account.cookie;
|
||||
}
|
||||
|
||||
static constructFromAccountData(data) {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
cookie: string[] = [];
|
||||
csrf: string;
|
||||
|
||||
|
@ -8,11 +8,7 @@ const logger = new Logger('vjudge');
|
||||
class AccountService {
|
||||
api: IBasicProvider;
|
||||
|
||||
constructor(
|
||||
public Provider: BasicProvider,
|
||||
public account: RemoteAccount,
|
||||
private request: any
|
||||
) {
|
||||
constructor(public Provider: BasicProvider, public account: RemoteAccount) {
|
||||
this.api = new Provider(account);
|
||||
this.main().catch(e =>
|
||||
logger.error(`Error occured in ${account.type}/${account.handle}`, e)
|
||||
@ -24,7 +20,81 @@ class AccountService {
|
||||
problem_id: string,
|
||||
language: string,
|
||||
code: string,
|
||||
judge_time: string
|
||||
next,
|
||||
end
|
||||
) {
|
||||
try {
|
||||
const rid = await this.api.submitProblem(
|
||||
problem_id,
|
||||
language,
|
||||
code,
|
||||
id,
|
||||
next,
|
||||
end
|
||||
);
|
||||
|
||||
if (!rid) return;
|
||||
|
||||
await this.api.waitForSubmission(problem_id, rid, next, end);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
|
||||
await end({ error: true, status: 'Judgment Failed', message: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
async login() {
|
||||
const login = await this.api.ensureLogin();
|
||||
if (login === true) {
|
||||
logger.info(`${this.account.type}/${this.account.handle}: logged in`);
|
||||
return true;
|
||||
}
|
||||
logger.warn(
|
||||
`${this.account.type}/${this.account.handle}: login fail`,
|
||||
login || ''
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
async main() {
|
||||
const res = await this.login();
|
||||
if (!res) return;
|
||||
setInterval(() => this.login(), Time.hour);
|
||||
}
|
||||
}
|
||||
|
||||
class VJudge {
|
||||
private p_imports: Record<string, any> = {};
|
||||
private providers: Record<string, AccountService> = {};
|
||||
|
||||
constructor(private request: any) {}
|
||||
|
||||
async importProvider(type: string) {
|
||||
if (this.p_imports[type]) throw new Error(`duplicate provider ${type}`);
|
||||
const provider = await import(`./providers/${type}`);
|
||||
|
||||
this.p_imports[type] = provider.default;
|
||||
}
|
||||
|
||||
async addProvider(type: string) {
|
||||
if (this.p_imports[type]) throw new Error(`duplicate provider ${type}`);
|
||||
const provider = await import(`./providers/${type}`);
|
||||
const account = provider.getAccountInfoFromEnv();
|
||||
|
||||
if (!account) throw new Error(`no account info for ${type}`);
|
||||
|
||||
this.p_imports[type] = provider.default;
|
||||
this.providers[type] = new AccountService(provider.default, account);
|
||||
}
|
||||
|
||||
async judge(
|
||||
id: number,
|
||||
type: string,
|
||||
problem_id: string,
|
||||
language: string,
|
||||
code: string,
|
||||
judge_time: string,
|
||||
config
|
||||
) {
|
||||
const next = async payload => {
|
||||
return await this.request('/submit', {
|
||||
@ -77,8 +147,26 @@ class AccountService {
|
||||
});
|
||||
};
|
||||
|
||||
if (!config.remote_submit_type || config.remote_submit_type == 'bot') {
|
||||
if (!this.providers[type]) throw new Error(`No provider ${type}`);
|
||||
|
||||
await this.providers[type].judge(
|
||||
id,
|
||||
problem_id,
|
||||
language,
|
||||
code,
|
||||
next,
|
||||
end
|
||||
);
|
||||
} else if (config.remote_submit_type == 'my') {
|
||||
if (!this.p_imports[type]) throw new Error(`No provider ${type}`);
|
||||
|
||||
try {
|
||||
const rid = await this.api.submitProblem(
|
||||
const provider = this.p_imports[type].constructFromAccountData(
|
||||
JSON.parse(config.remote_account_data)
|
||||
);
|
||||
|
||||
const rid = await provider.submitProblem(
|
||||
problem_id,
|
||||
language,
|
||||
code,
|
||||
@ -89,63 +177,21 @@ class AccountService {
|
||||
|
||||
if (!rid) return;
|
||||
|
||||
await this.api.waitForSubmission(problem_id, rid, next, end);
|
||||
await provider.waitForSubmission(problem_id, rid, next, end);
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
await end({ error: true, status: 'Judgment Failed', message: e.message });
|
||||
|
||||
await end({
|
||||
error: true,
|
||||
status: 'Judgment Failed',
|
||||
message: e.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async login() {
|
||||
const login = await this.api.ensureLogin();
|
||||
if (login === true) {
|
||||
logger.info(`${this.account.type}/${this.account.handle}: logged in`);
|
||||
return true;
|
||||
}
|
||||
logger.warn(
|
||||
`${this.account.type}/${this.account.handle}: login fail`,
|
||||
login || ''
|
||||
throw new Error(
|
||||
'Unsupported remote submit type: ' + config.remote_submit_type
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
async main() {
|
||||
const res = await this.login();
|
||||
if (!res) return;
|
||||
setInterval(() => this.login(), Time.hour);
|
||||
}
|
||||
}
|
||||
|
||||
class VJudge {
|
||||
private providers: Record<string, AccountService> = {};
|
||||
|
||||
constructor(private request: any) {}
|
||||
|
||||
async addProvider(type: string) {
|
||||
if (this.providers[type]) throw new Error(`duplicate provider ${type}`);
|
||||
const provider = await import(`./providers/${type}`);
|
||||
const account = provider.getAccountInfoFromEnv();
|
||||
|
||||
if (!account) throw new Error(`no account info for ${type}`);
|
||||
|
||||
this.providers[type] = new AccountService(
|
||||
provider.default,
|
||||
account,
|
||||
this.request
|
||||
);
|
||||
}
|
||||
|
||||
async judge(
|
||||
id: number,
|
||||
type: string,
|
||||
problem_id: string,
|
||||
language: string,
|
||||
code: string,
|
||||
judge_time: string
|
||||
) {
|
||||
if (!this.providers[type]) throw new Error(`no provider ${type}`);
|
||||
|
||||
await this.providers[type].judge(id, problem_id, language, code, judge_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user