UNPKG

cf-wrapper

Version:

The definitive CF wrapper to be able to perform anything that can be done through the UI.

230 lines (217 loc) 8.19 kB
import client from "./client.js"; import qs from 'qs'; import { genFtaa, genBfaa, } from "./utils.js"; import xpath from "xpath-html"; export default class Cf { static csrf = ''; static ftaa = genFtaa(); static bfaa = genBfaa(); static isLoggedIn() { return Cf.csrf.length > 0; }; constructor (username, password) { this.username = username; this.password = password; } async getCsrf() { const config = { method: 'get', url: 'https://codeforces.com', }; const response = await client(config); Cf.csrf = response.data.match(/(?<=data-csrf=')[\s\S]*?(?='>&)/)[1]; return; } async login() { await this.getCsrf(); const data = qs.stringify({ csrf_token: Cf.csrf, action: 'enter', handleOrEmail: this.username, password: this.password, ftaa: Cf.ftaa, bfaa: Cf.bfaa, _tta: "176", remember: "on", }); const config = { method: 'post', url: 'https://codeforces.com/enter', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, data : data }; await client(config) .then(function (response) { if ( response.data.match(/handle = "([\s\S]+?)"/) ) { // console.log('Login success'); } else { // console.log('Login failed'); throw new Error('Login failed'); } }) .catch(function (error) { // console.log(error); return error; }); } async submit(contestId, problemId, language, source) { await this.getCsrf(); const data = qs.stringify({ csrf_token: Cf.csrf, ftaa: Cf.ftaa, bfaa: Cf.bfaa, action: 'submitSolutionFormSubmitted', submittedProblemIndex: problemId, // problemId is the problem index in the contest (A, B, C, ...) contestId: contestId, // contestId is the id of the contest source: source, // source code programTypeId: language, // Language index _tta: '594', sourceCodeConfirmed: 'true' }); const config = { method: 'post', url: 'https://codeforces.com/problemset/submit?csrf_token=' + Cf.csrf, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, data : data, }; const submission = await client(config) .then(function (response) { if ( response.data.match(/<table class="status-frame-datatable">/) ) { const submissionRegex = /(?<=submissionId=")[\d]*?(?=">)/; const submissionId = response.data.match(submissionRegex)[0]; // console.log('Submission success, submissionId: ' + submissionId); return submissionId; } else { // console.log('Submit failed'); if ( response.data.match(/You have submitted exactly the same code before/) ) { // console.log('You have submitted exactly the same code before'); } throw new Error('Submit failed'); } }) .catch(function (error) { // console.log(error); return error; } ); return submission; } async getContestList(gym) { const config = { method: 'get', url: `https://codeforces.com/api/contest.list?gym=${gym}`, }; const contestList = await client(config) .then(function (response) { if(response.data.status === 'OK') { return response.data; } else { // console.log('Get contest list failed'); throw new Error('Get contest list failed'); } }) .catch(function (error) { // console.log('Get contest list failed'); throw new Error('Get contest list failed'); }); return contestList.result; }; async getContestProblems(contestId){ const config = { method: 'get', url: `https://codeforces.com/api/contest.standings?contestId=${contestId}&from=1&count=1`, }; const contest = await client(config) .then(function (response) { if(response.data.status === 'OK') { return response.data; } else { // console.log('Get contest problems failed'); throw new Error('Get contest problems failed'); } }) .catch(function (error) { // console.log('Get contest problems failed'); throw new Error('Get contest problems failed'); }); return contest.result.problems; }; async getProblemsList() { const config = { method: 'get', url: 'https://codeforces.com/api/problemset.problems', }; const problemsList = await client(config) .then(function (response) { if(response.data.status === 'OK') { return response.data; } else { throw new Error('Get problems list failed'); } }) .catch(function (error) { throw new Error('Get problems list failed'); }); return problemsList.result.problems; } async getProblemStatement(contestId, problemId) { const config = { method: 'get', url: `https://codeforces.com/problemset/problem/${contestId}/${problemId}`, }; const problemStatement = await client(config) .then(function (response) { if (response.data !== undefined) { const data = response.data; const node = xpath.fromPageSource(data).findElement('//div[@class="problem-statement"]'); return node.toString(); } else { throw new Error('Get problem statement failed'); } }) .catch(function (error) { throw new Error('Get problem statement failed'); } ); return problemStatement; } async checkSubmission(contestId, submissionId) { const config = { method: 'get', url: `https://codeforces.com/contest/${contestId}/submission/${submissionId}`, } const status = await client(config) .then(function (response) { if (response.data !== undefined) { const data = response.data; let verdict = xpath.fromPageSource(data).findElement('//td[5]').getText(); if (verdict.trim().length < 1) { verdict = xpath.fromPageSource(data).findElement('//td[5]/span').getText(); } else { verdict = verdict.split('\n')[1].trim(); } const runtime = xpath.fromPageSource(data).findElement('//td[6]'); const memory = xpath.fromPageSource(data).findElement('//td[7]'); return [ verdict, runtime.getText().split('\n')[1].trim(), memory.getText().split('\n')[1].trim(), ]; } else { throw new Error('Get problem statement failed'); } }) .catch(function (error) { console.log(error); throw new Error('Get problem statement failed'); }); return status; } }