Documentation
¶
Overview ¶
Package cfweb provides web scraping and submission for Codeforces
Index ¶
- Constants
- Variables
- func GetHTMLDocument(r io.Reader) (*html.Node, error)
- type ContestSelectors
- type Language
- type LoginSelectors
- type ParsedProblem
- type Parser
- type ProblemSelectors
- type Sample
- type SelectorVersion
- type Selectors
- type Session
- func (s *Session) CFClearanceExpiresAt() time.Time
- func (s *Session) CFClearanceExpiresIn() time.Duration
- func (s *Session) Client() *http.Client
- func (s *Session) ExpiresAt() time.Time
- func (s *Session) GetCFClearance() string
- func (s *Session) GetCSRFToken() string
- func (s *Session) GetUserAgent() string
- func (s *Session) Handle() string
- func (s *Session) HasSessionCookies() bool
- func (s *Session) IsAuthenticated() bool
- func (s *Session) IsCFClearanceValid() bool
- func (s *Session) IsReadyForSubmission() bool
- func (s *Session) RefreshCSRFToken() error
- func (s *Session) SetCFClearance(clearance, userAgent string, expiresAt time.Time)
- func (s *Session) SetFullAuth(cfClearance, userAgent string, cfClearExp time.Time, ...)
- func (s *Session) SetSessionCookies(jsessionID, ce7Cookie, handle string)
- func (s *Session) Validate() error
- type SubmissionResult
- type SubmitSelectors
- type Submitter
- func (s *Submitter) GetSubmission(submissionID int64, contestID int) (*SubmissionResult, error)
- func (s *Submitter) Submit(contestID int, problemIndex string, langID int, sourceCode string) (*SubmissionResult, error)
- func (s *Submitter) SubmitToGym(gymID int, problemIndex string, langID int, sourceCode string) (*SubmissionResult, error)
- func (s *Submitter) VerifySubmitPage(contestID int) error
- func (s *Submitter) WaitForVerdict(submissionID int64, contestID int, timeout time.Duration) (*SubmissionResult, error)
Constants ¶
const ( BaseURL = "https://codeforces.com" UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" SessionExpiry = 24 * time.Hour MaxPageSize = 5 * 1024 * 1024 // 5MB max page size to prevent OOM )
Variables ¶
var CurrentSelectors = Selectors{ Problem: ProblemSelectors{ Title: ".problem-statement .title", TimeLimit: ".problem-statement .time-limit", MemoryLimit: ".problem-statement .memory-limit", Statement: ".problem-statement", InputSpec: ".problem-statement .input-specification", OutputSpec: ".problem-statement .output-specification", Note: ".problem-statement .note", SampleTests: ".sample-tests", SampleInput: ".sample-tests .input pre", SampleOutput: ".sample-tests .output pre", Tags: ".tag-box", Rating: "span.tag-box[title='Difficulty']", }, Login: LoginSelectors{ Form: "form#enterForm, form.enter-form", HandleOrEmail: "input[name='handleOrEmail']", Password: "input[name='password']", CSRFToken: "input[name='csrf_token'], meta[name='X-Csrf-Token']", Remember: "input[name='remember']", SubmitButton: "input[type='submit']", }, Submit: SubmitSelectors{ Form: "form.submit-form", ProblemIndex: "select[name='submittedProblemIndex'], input[name='submittedProblemIndex']", LanguageSelect: "select[name='programTypeId']", SourceCode: "textarea[name='source'], #sourceCodeTextarea", CSRFToken: "input[name='csrf_token']", SubmitButton: "input[type='submit']", FTAA: "input[name='ftaa']", BFAA: "input[name='bfaa']", }, Contest: ContestSelectors{ ProblemList: ".problems", ProblemRow: ".problems tr", ProblemLink: "td.id a", ProblemName: "td a", StandingsTable: ".standings", }, }
CurrentSelectors returns the current set of selectors
var CurrentVersion = SelectorVersion{
Version: "2024.12",
ValidFrom: "2024-12-01",
ValidUntil: "",
Description: "CF selectors as of December 2024",
}
CurrentVersion returns the current selector version
var SupportedLanguages = []Language{
{ID: "cpp17", Name: "GNU G++17 7.3.0", Extension: ".cpp", CompilerID: 54},
{ID: "cpp20", Name: "GNU G++20 11.2.0 (64 bit)", Extension: ".cpp", CompilerID: 89},
{ID: "cpp23", Name: "GNU G++23 14.2 (64 bit)", Extension: ".cpp", CompilerID: 91},
{ID: "python3", Name: "Python 3.8.10", Extension: ".py", CompilerID: 31},
{ID: "pypy3", Name: "PyPy 3.10 (7.3.15)", Extension: ".py", CompilerID: 70},
{ID: "java17", Name: "Java 17 64bit", Extension: ".java", CompilerID: 87},
{ID: "java21", Name: "Java 21 64bit", Extension: ".java", CompilerID: 88},
{ID: "go", Name: "Go 1.22.2", Extension: ".go", CompilerID: 32},
{ID: "rust", Name: "Rust 1.75.0 (2021)", Extension: ".rs", CompilerID: 75},
{ID: "kotlin", Name: "Kotlin 1.9.21", Extension: ".kt", CompilerID: 83},
{ID: "csharp", Name: "C# 10, .NET SDK 6.0", Extension: ".cs", CompilerID: 79},
{ID: "ruby", Name: "Ruby 3.2.2", Extension: ".rb", CompilerID: 67},
{ID: "js", Name: "JavaScript V8 4.8.0", Extension: ".js", CompilerID: 34},
{ID: "php", Name: "PHP 8.1.7", Extension: ".php", CompilerID: 6},
{ID: "haskell", Name: "Haskell GHC 8.10.1", Extension: ".hs", CompilerID: 12},
{ID: "scala", Name: "Scala 2.12.8", Extension: ".scala", CompilerID: 20},
}
SupportedLanguages lists all supported languages for submission
Functions ¶
Types ¶
type ContestSelectors ¶
type ContestSelectors struct {
ProblemList string
ProblemRow string
ProblemLink string
ProblemName string
StandingsTable string
}
ContestSelectors for contest page
type Language ¶
Language represents a programming language
func GetLanguageByCompilerID ¶
GetLanguageByCompilerID returns language info by compiler ID
func GetLanguageByExtension ¶
GetLanguageByExtension returns language info by file extension
func GetLanguageByID ¶
GetLanguageByID returns language info by ID
type LoginSelectors ¶
type LoginSelectors struct {
Form string
HandleOrEmail string
Password string
CSRFToken string
Remember string
SubmitButton string
}
LoginSelectors for login page
type ParsedProblem ¶
type ParsedProblem struct {
ContestID int
Index string
Name string
TimeLimit string
MemoryLimit string
Statement string
InputSpec string
OutputSpec string
Note string
Samples []Sample
Tags []string
Rating int
URL string
}
ParsedProblem contains parsed problem data
func (*ParsedProblem) ToSchemaProblem ¶
func (p *ParsedProblem) ToSchemaProblem() *v1.Problem
ToSchemaProblem converts ParsedProblem to schema v1 Problem
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser scrapes problem data from CF web pages
func NewParserWithClient ¶
NewParserWithClient creates a parser with a custom HTTP client
func (*Parser) ParseContestProblems ¶
func (p *Parser) ParseContestProblems(contestID int) ([]ParsedProblem, error)
ParseContestProblems parses all problems from a contest
func (*Parser) ParseProblem ¶
func (p *Parser) ParseProblem(contestID int, index string) (*ParsedProblem, error)
ParseProblem parses a problem page
func (*Parser) ParseProblemset ¶
func (p *Parser) ParseProblemset(contestID int, index string) (*ParsedProblem, error)
ParseProblemset parses a problem from the problemset
func (*Parser) VerifyPageStructure ¶
VerifyPageStructure checks if the page structure matches expected selectors
type ProblemSelectors ¶
type ProblemSelectors struct {
// Main content
Title string
TimeLimit string
MemoryLimit string
Statement string
InputSpec string
OutputSpec string
Note string
// Sample tests
SampleTests string
SampleInput string
SampleOutput string
// Tags and rating
Tags string
Rating string
}
ProblemSelectors for problem page parsing
type SelectorVersion ¶
type SelectorVersion struct {
Version string
ValidFrom string // Date when these selectors became valid
ValidUntil string // Empty if current
Description string
}
SelectorVersion represents a versioned set of CSS selectors When CF changes their HTML structure, we add a new version
type Selectors ¶
type Selectors struct {
// Problem page selectors
Problem ProblemSelectors
// Login page selectors
Login LoginSelectors
// Submit page selectors
Submit SubmitSelectors
// Contest page selectors
Contest ContestSelectors
}
Selectors contains all CSS selectors for scraping CF pages
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session manages CF web authentication using pre-extracted cookies No login functionality - users extract cookies from browser
func NewSessionWithUserAgent ¶
NewSessionWithUserAgent creates a new CF session with custom User-Agent This is important for Cloudflare bypass - the User-Agent MUST match the one used to obtain the cf_clearance cookie
func (*Session) CFClearanceExpiresAt ¶
CFClearanceExpiresAt returns when cf_clearance expires
func (*Session) CFClearanceExpiresIn ¶
CFClearanceExpiresIn returns time until cf_clearance expires
func (*Session) GetCFClearance ¶
GetCFClearance returns the current cf_clearance value
func (*Session) GetCSRFToken ¶
GetCSRFToken returns the current CSRF token
func (*Session) GetUserAgent ¶
GetUserAgent returns the User-Agent tied to this session
func (*Session) HasSessionCookies ¶
HasSessionCookies returns true if session cookies are set
func (*Session) IsAuthenticated ¶
IsAuthenticated returns true if session has valid cf_clearance and session cookies
func (*Session) IsCFClearanceValid ¶
IsCFClearanceValid returns true if cf_clearance is set and not expired
func (*Session) IsReadyForSubmission ¶
IsReadyForSubmission returns true if session can submit solutions
func (*Session) RefreshCSRFToken ¶
RefreshCSRFToken fetches a fresh CSRF token from any CF page
func (*Session) SetCFClearance ¶
SetCFClearance sets the cf_clearance cookie for Cloudflare bypass The userAgent parameter MUST match the User-Agent used to obtain the cookie
func (*Session) SetFullAuth ¶
func (s *Session) SetFullAuth(cfClearance, userAgent string, cfClearExp time.Time, jsessionID, ce7Cookie, handle string)
SetFullAuth sets all authentication cookies at once (cf_clearance + session) This is the primary method for cookie-based auth
func (*Session) SetSessionCookies ¶
SetSessionCookies sets session cookies directly (extracted from browser)
type SubmissionResult ¶
type SubmissionResult struct {
SubmissionID int64
ContestID int
ProblemIndex string
Verdict string
Time time.Duration
Memory int64 // bytes
PassedTests int
SubmittedAt time.Time
Status string
}
SubmissionResult contains the result of a submission
type SubmitSelectors ¶
type SubmitSelectors struct {
Form string
ProblemIndex string
LanguageSelect string
SourceCode string
CSRFToken string
SubmitButton string
FTAA string
BFAA string
}
SubmitSelectors for submit page
type Submitter ¶
type Submitter struct {
// contains filtered or unexported fields
}
Submitter handles solution submission to CF
func NewSubmitter ¶
NewSubmitter creates a new submitter with an authenticated session Requires session to have cf_clearance + session cookies set
func (*Submitter) GetSubmission ¶
func (s *Submitter) GetSubmission(submissionID int64, contestID int) (*SubmissionResult, error)
GetSubmission gets a specific submission's status
func (*Submitter) Submit ¶
func (s *Submitter) Submit(contestID int, problemIndex string, langID int, sourceCode string) (*SubmissionResult, error)
Submit submits a solution to a problem
func (*Submitter) SubmitToGym ¶
func (s *Submitter) SubmitToGym(gymID int, problemIndex string, langID int, sourceCode string) (*SubmissionResult, error)
SubmitToGym submits a solution to a gym problem
func (*Submitter) VerifySubmitPage ¶
VerifySubmitPage checks if the submit page structure is valid
func (*Submitter) WaitForVerdict ¶
func (s *Submitter) WaitForVerdict(submissionID int64, contestID int, timeout time.Duration) (*SubmissionResult, error)
WaitForVerdict waits for the submission to be judged