mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-08 13:38:41 +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 { apply } from './vjudge';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import child from 'child_process';
|
import child from 'child_process';
|
||||||
|
import htmlspecialchars from './utils/htmlspecialchars';
|
||||||
|
|
||||||
proxy(superagent);
|
proxy(superagent);
|
||||||
|
|
||||||
@ -146,7 +147,8 @@ export default async function daemon(config: UOJConfig) {
|
|||||||
config.remote_problem_id,
|
config.remote_problem_id,
|
||||||
config.answer_language,
|
config.answer_language,
|
||||||
code,
|
code,
|
||||||
judge_time
|
judge_time,
|
||||||
|
config
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await request('/submit', {
|
await request('/submit', {
|
||||||
@ -157,7 +159,7 @@ export default async function daemon(config: UOJConfig) {
|
|||||||
status: 'Judged',
|
status: 'Judged',
|
||||||
score: 0,
|
score: 0,
|
||||||
error: 'Judgment Failed',
|
error: 'Judgment Failed',
|
||||||
details: `<error>No details.</error>`,
|
details: `<error>${htmlspecialchars(err.message)}</error>`,
|
||||||
}),
|
}),
|
||||||
judge_time,
|
judge_time,
|
||||||
});
|
});
|
||||||
|
@ -73,6 +73,10 @@ export default class AtcoderProvider implements IBasicProvider {
|
|||||||
this.account.endpoint ||= 'https://atcoder.jp';
|
this.account.endpoint ||= 'https://atcoder.jp';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constructFromAccountData(data) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
cookie: string[] = ['language=en'];
|
cookie: string[] = ['language=en'];
|
||||||
csrf: string;
|
csrf: string;
|
||||||
|
|
||||||
|
@ -87,6 +87,10 @@ export default class CodeforcesProvider implements IBasicProvider {
|
|||||||
this.account.endpoint ||= 'https://codeforces.com';
|
this.account.endpoint ||= 'https://codeforces.com';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constructFromAccountData(data) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
cookie: string[] = [];
|
cookie: string[] = [];
|
||||||
csrf: string;
|
csrf: string;
|
||||||
|
|
||||||
|
@ -156,6 +156,10 @@ export default class LibreojProvider implements IBasicProvider {
|
|||||||
this.account.endpoint ||= 'https://api.loj.ac.cn/api';
|
this.account.endpoint ||= 'https://api.loj.ac.cn/api';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constructFromAccountData(data) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
get(url: string) {
|
get(url: string) {
|
||||||
logger.debug('get', url);
|
logger.debug('get', url);
|
||||||
if (!url.includes('//')) url = `${this.account.endpoint}${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;
|
if (account.cookie) this.cookie = account.cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constructFromAccountData(data) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
cookie: string[] = [];
|
cookie: string[] = [];
|
||||||
csrf: string;
|
csrf: string;
|
||||||
|
|
||||||
|
@ -8,11 +8,7 @@ const logger = new Logger('vjudge');
|
|||||||
class AccountService {
|
class AccountService {
|
||||||
api: IBasicProvider;
|
api: IBasicProvider;
|
||||||
|
|
||||||
constructor(
|
constructor(public Provider: BasicProvider, public account: RemoteAccount) {
|
||||||
public Provider: BasicProvider,
|
|
||||||
public account: RemoteAccount,
|
|
||||||
private request: any
|
|
||||||
) {
|
|
||||||
this.api = new Provider(account);
|
this.api = new Provider(account);
|
||||||
this.main().catch(e =>
|
this.main().catch(e =>
|
||||||
logger.error(`Error occured in ${account.type}/${account.handle}`, e)
|
logger.error(`Error occured in ${account.type}/${account.handle}`, e)
|
||||||
@ -24,7 +20,81 @@ class AccountService {
|
|||||||
problem_id: string,
|
problem_id: string,
|
||||||
language: string,
|
language: string,
|
||||||
code: 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 => {
|
const next = async payload => {
|
||||||
return await this.request('/submit', {
|
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 {
|
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,
|
problem_id,
|
||||||
language,
|
language,
|
||||||
code,
|
code,
|
||||||
@ -89,63 +177,21 @@ class AccountService {
|
|||||||
|
|
||||||
if (!rid) return;
|
if (!rid) return;
|
||||||
|
|
||||||
await this.api.waitForSubmission(problem_id, rid, next, end);
|
await provider.waitForSubmission(problem_id, rid, next, end);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(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() {
|
throw new Error(
|
||||||
const login = await this.api.ensureLogin();
|
'Unsupported remote submit type: ' + config.remote_submit_type
|
||||||
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 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