Merge branch 'remotejudge/uoj-custom-account'
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-02-09 22:05:21 +08:00
commit 50f3aaab9a
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
4 changed files with 105 additions and 3 deletions

View File

@ -100,45 +100,60 @@ export default class UOJProvider implements IBasicProvider {
}
static constructFromAccountData(data) {
throw new Error('Method not implemented.');
return new this({
type: 'uoj',
cookie: Object.entries(data).map(([key, value]) => `${key}=${value}`),
});
}
cookie: string[] = [];
csrf: string;
get(url: string) {
logger.debug('get', url);
logger.debug('get', url, this.cookie);
if (!url.includes('//'))
url = `${this.account.endpoint || 'https://uoj.ac'}${url}`;
const req = superagent
.get(url)
.set('Cookie', this.cookie)
.set('User-Agent', USER_AGENT);
if (this.account.proxy) return req.proxy(this.account.proxy);
return req;
}
post(url: string) {
logger.debug('post', url, this.cookie);
if (!url.includes('//'))
url = `${this.account.endpoint || 'https://uoj.ac'}${url}`;
const req = superagent
.post(url)
.set('Cookie', this.cookie)
.set('User-Agent', USER_AGENT)
.type('form');
if (this.account.proxy) return req.proxy(this.account.proxy);
return req;
}
async getCsrfToken(url: string) {
const { text: html, header } = await this.get(url);
if (header['set-cookie']) {
this.cookie = header['set-cookie'];
}
let value = /_token *: *"(.+?)"/g.exec(html);
if (value) return value[1];
value = /_token" value="(.+?)"/g.exec(html);
return value?.[1];
}
@ -150,7 +165,11 @@ export default class UOJProvider implements IBasicProvider {
async ensureLogin() {
if (await this.loggedIn) return true;
if (!this.account.handle) return false;
logger.info('retry login');
const _token = await this.getCsrfToken('/login');
const { header, text } = await this.post('/login').send({
_token,
@ -159,11 +178,14 @@ export default class UOJProvider implements IBasicProvider {
// NOTE: you should pass a pre-hashed key!
password: this.account.password,
});
if (header['set-cookie'] && this.cookie.length === 1) {
header['set-cookie'].push(...this.cookie);
this.cookie = header['set-cookie'];
}
if (text === 'ok') return true;
return text;
}
@ -175,6 +197,16 @@ export default class UOJProvider implements IBasicProvider {
next,
end
) {
if (!(await this.ensureLogin())) {
await end({
error: true,
status: 'Judgment Failed',
message: 'Login failed',
});
return null;
}
const programType = LANGS_MAP[lang] || LANGS_MAP['C++'];
const comment = programType.comment;

View File

@ -97,6 +97,29 @@ if ($type == 'luogu') {
return true;
}
return false;
}, 3);
} else if ($type == 'uoj') {
$curl->setFollowLocation();
$curl->setCookie('UOJSESSID', UOJRequest::post('UOJSESSID', 'is_string', ''));
retry_loop(function () use (&$curl, &$res) {
$curl->get(UOJRemoteProblem::$providers['uoj']['url'] . '/login');
if ($curl->error) {
return false;
}
if (str_starts_with($curl->responseHeaders['Content-Type'], 'text/html')) {
if (str_contains($curl->response, '<title>登录')) {
return false;
}
$res = true;
return true;
}
return false;
}, 3);
} else {

View File

@ -35,7 +35,7 @@ class UOJRemoteProblem {
'未找到该页面',
],
'languages' => ['C', 'C++03', 'C++11', 'C++', 'C++17', 'C++20', 'Python3', 'Python2.7', 'Java8', 'Java11', 'Java17', 'Pascal'],
'submit_type' => ['bot'],
'submit_type' => ['bot', 'my'],
],
'loj' => [
'name' => 'LibreOJ',

View File

@ -1271,6 +1271,53 @@ $.fn.remote_submit_type_group = function(oj, pid, url, submit_type) {
.append($('<div class="col-sm-4" />').append(input_loj_token))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请前往 <a href="https://loj.ac" target="_blank">LibreOJ</a> 登录账号,然后输入在控制台中运行 <code>console.log(JSON.parse(localStorage.appState).token)</code> 的输出结果。')))
);
} else if (oj == 'uoj') {
var uoj_account_data = {"UOJSESSID": ""};
var input_uoj_uojsessid = $('<input class="form-control font-monospace" type="text" name="uoj_uojsessid" id="input-uoj_uojsessid" />');
if ('localStorage' in window) {
try {
var uoj_account_data_str = localStorage.getItem('uoj_remote_judge_uoj_account_data');
if (uoj_account_data_str) {
uoj_account_data = JSON.parse(uoj_account_data_str);
}
} catch (e) {}
var save_uoj_account_data = function() {
localStorage.setItem('uoj_remote_judge_uoj_account_data', JSON.stringify(uoj_account_data));
}
}
input_uoj_uojsessid.change(function() {
uoj_account_data.UOJSESSID = $(this).val();
input_my_account_data.val(JSON.stringify(uoj_account_data));
save_uoj_account_data();
my_account_validation_status.html('<span class="text-secondary">待验证</span>');
});
my_account_validation_btn.click(function() {
validate_my_account({
type: 'uoj',
UOJSESSID: input_uoj_uojsessid.val(),
});
});
input_my_account_data.val(JSON.stringify(uoj_account_data));
input_uoj_uojsessid.val(uoj_account_data.UOJSESSID);
if (uoj_account_data.UOJSESSID) {
validate_my_account({
type: 'uoj',
UOJSESSID: uoj_account_data.UOJSESSID,
});
}
div_submit_type_my.append(
$('<div class="row mt-3 align-items-center" />')
.append($('<div class="col-sm-2" />').append('<label for="input-uoj_uojsessid" class="col-form-label">UOJSESSID</label>'))
.append($('<div class="col-sm-4" />').append(input_uoj_uojsessid))
.append($('<div class="col-sm-6" />').append($('<div class="form-text mt-0" />').append('请填入 Cookie 中的 <code>UOJSESSID</code>。')))
).append(input_my_account_data);
}
$(this).append(