diff --git a/doc/cp.nvim.txt b/doc/cp.nvim.txt index 544923b..cf1195c 100644 --- a/doc/cp.nvim.txt +++ b/doc/cp.nvim.txt @@ -1056,13 +1056,17 @@ Set {version} globally or per-platform: < Available versions per platform ~ - Platform cpp python java rust - AtCoder c++20/23 python3, pypy3 java rust - Codeforces c++17/20/23 python3, pypy3 - - - CSES c++11/17/20 python3, pypy3 java rust2018/2021 - Kattis c++17/20/23 python3 java rust - USACO c++11/17 python3 java - - CodeChef c++20 python3, pypy3 java rust + Platform cpp python java rust + AtCoder c++20/23 python3, pypy3 java rust + Codeforces c++17/20/23 python3, pypy3 - - + CSES c++17 python3, pypy3 java rust2021 + Kattis c++17/20/23 python3, python2 java rust + USACO c++11/17 python3 java - + CodeChef c++20 python3, pypy3 java rust + +Kattis also supports: kotlin, go, haskell, csharp, typescript, javascript, +ocaml, ruby, scala, zig, swift, dart — use the language key as the version +key (e.g. version = "kotlin"). Using a raw platform ID ~ diff --git a/lua/cp/config.lua b/lua/cp/config.lua index 835da99..bf2daac 100644 --- a/lua/cp/config.lua +++ b/lua/cp/config.lua @@ -262,15 +262,8 @@ local function validate_language(id, lang) if lang.commands.build ~= nil then vim.validate({ build = { lang.commands.build, { 'table' } } }) - if not has_tokens(lang.commands.build, { '{source}', '{binary}' }) then - error(('[cp.nvim] languages.%s.commands.build must include {source} and {binary}'):format(id)) - end - for _, k in ipairs({ 'run', 'debug' }) do - if lang.commands[k] then - if not has_tokens(lang.commands[k], { '{binary}' }) then - error(('[cp.nvim] languages.%s.commands.%s must include {binary}'):format(id, k)) - end - end + if not has_tokens(lang.commands.build, { '{source}' }) then + error(('[cp.nvim] languages.%s.commands.build must include {source}'):format(id)) end else for _, k in ipairs({ 'run', 'debug' }) do diff --git a/lua/cp/constants.lua b/lua/cp/constants.lua index 4515270..cf62b37 100644 --- a/lua/cp/constants.lua +++ b/lua/cp/constants.lua @@ -75,14 +75,67 @@ M.signal_codes = { M.LANGUAGE_VERSIONS = { atcoder = { - cpp = { ['c++20'] = '6054', ['c++23'] = '6017' }, - python = { python3 = '6082', pypy3 = '6083' }, + cpp = { ['c++20'] = '6054', ['c++23'] = '6017', ['c++23-clang'] = '6116' }, + python = { python3 = '6082', pypy3 = '6083', codon = '6115' }, java = { java = '6056' }, rust = { rust = '6088' }, + c = { c23clang = '6013', c23gcc = '6014' }, + go = { go = '6051', gccgo = '6050' }, + haskell = { haskell = '6052' }, + csharp = { csharp = '6015', ['csharp-aot'] = '6016' }, + kotlin = { kotlin = '6062' }, + ruby = { ruby = '6087', truffleruby = '6086' }, + javascript = { bun = '6057', deno = '6058', nodejs = '6059' }, + typescript = { deno = '6100', bun = '6101', nodejs = '6102' }, + scala = { scala = '6090', ['scala-native'] = '6091' }, + ocaml = { ocaml = '6073' }, + dart = { dart = '6033' }, + elixir = { elixir = '6038' }, + erlang = { erlang = '6041' }, + fsharp = { fsharp = '6042' }, + swift = { swift = '6095' }, + zig = { zig = '6111' }, + nim = { nim = '6072', ['nim-old'] = '6071' }, + lua = { lua = '6067', luajit = '6068' }, + perl = { perl = '6076' }, + php = { php = '6077' }, + pascal = { pascal = '6075' }, + crystal = { crystal = '6028' }, + d = { dmd = '6030', gdc = '6031', ldc = '6032' }, + julia = { julia = '6114' }, + r = { r = '6084' }, + commonlisp = { commonlisp = '6027' }, + scheme = { chezscheme = '6092', gauche = '6093' }, + clojure = { clojure = '6022', ['clojure-aot'] = '6023', babashka = '6021' }, + ada = { ada = '6002' }, + bash = { bash = '6008' }, + fortran = { fortran2023 = '6047', fortran2018 = '6046', fortran77 = '6048' }, + gleam = { gleam = '6049' }, + lean = { lean = '6065' }, + pony = { pony = '6079' }, + prolog = { prolog = '6081' }, + vala = { vala = '6106' }, + v = { v = '6105' }, + sql = { duckdb = '6118' }, }, codeforces = { - cpp = { ['c++17'] = '54', ['c++20'] = '89', ['c++23'] = '91' }, - python = { python3 = '31', pypy3 = '70' }, + cpp = { ['c++17'] = '54', ['c++20'] = '89', ['c++23'] = '91', c11 = '43' }, + python = { python3 = '31', pypy3 = '70', python2 = '7', pypy2 = '40', ['pypy3-old'] = '41' }, + java = { java8 = '36', java21 = '87' }, + kotlin = { ['1.7'] = '83', ['1.9'] = '88', ['2.2'] = '99' }, + rust = { ['2021'] = '75', ['2024'] = '98' }, + go = { go = '32' }, + csharp = { mono = '9', dotnet3 = '65', dotnet6 = '79', dotnet9 = '96' }, + haskell = { haskell = '12' }, + javascript = { v8 = '34', nodejs = '55' }, + ruby = { ruby = '67' }, + scala = { scala = '20' }, + ocaml = { ocaml = '19' }, + d = { d = '28' }, + perl = { perl = '13' }, + php = { php = '6' }, + pascal = { freepascal = '4', pascalabc = '51' }, + fsharp = { fsharp = '97' }, }, cses = { cpp = { ['c++17'] = 'C++17' }, @@ -92,9 +145,58 @@ M.LANGUAGE_VERSIONS = { }, kattis = { cpp = { ['c++17'] = 'C++', ['c++20'] = 'C++', ['c++23'] = 'C++' }, - python = { python3 = 'Python 3' }, + python = { python3 = 'Python 3', python2 = 'Python 2' }, java = { java = 'Java' }, rust = { rust = 'Rust' }, + ada = { ada = 'Ada' }, + algol60 = { algol60 = 'Algol 60' }, + algol68 = { algol68 = 'Algol 68' }, + apl = { apl = 'APL' }, + bash = { bash = 'Bash' }, + bcpl = { bcpl = 'BCPL' }, + bqn = { bqn = 'BQN' }, + c = { c = 'C' }, + cobol = { cobol = 'COBOL' }, + commonlisp = { commonlisp = 'Common Lisp' }, + crystal = { crystal = 'Crystal' }, + csharp = { csharp = 'C#' }, + d = { d = 'D' }, + dart = { dart = 'Dart' }, + elixir = { elixir = 'Elixir' }, + erlang = { erlang = 'Erlang' }, + forth = { forth = 'Forth' }, + fortran = { fortran = 'Fortran' }, + fortran77 = { fortran77 = 'Fortran 77' }, + fsharp = { fsharp = 'F#' }, + gerbil = { gerbil = 'Gerbil' }, + go = { go = 'Go' }, + haskell = { haskell = 'Haskell' }, + icon = { icon = 'Icon' }, + javascript = { javascript = 'JavaScript (Node.js)', spidermonkey = 'JavaScript (SpiderMonkey)' }, + julia = { julia = 'Julia' }, + kotlin = { kotlin = 'Kotlin' }, + lua = { lua = 'Lua' }, + modula2 = { modula2 = 'Modula-2' }, + nim = { nim = 'Nim' }, + objectivec = { objectivec = 'Objective-C' }, + ocaml = { ocaml = 'OCaml' }, + octave = { octave = 'Octave' }, + odin = { odin = 'Odin' }, + pascal = { pascal = 'Pascal' }, + perl = { perl = 'Perl' }, + php = { php = 'PHP' }, + pli = { pli = 'PL/I' }, + prolog = { prolog = 'Prolog' }, + racket = { racket = 'Racket' }, + ruby = { ruby = 'Ruby' }, + scala = { scala = 'Scala' }, + simula = { simula = 'Simula 67' }, + smalltalk = { smalltalk = 'Smalltalk' }, + snobol = { snobol = 'SNOBOL' }, + swift = { swift = 'Swift' }, + typescript = { typescript = 'TypeScript' }, + visualbasic = { visualbasic = 'Visual Basic' }, + zig = { zig = 'Zig' }, }, usaco = { cpp = { ['c++11'] = 'cpp', ['c++17'] = 'cpp' }, diff --git a/lua/cp/init.lua b/lua/cp/init.lua index 4ffb530..cab16ad 100644 --- a/lua/cp/init.lua +++ b/lua/cp/init.lua @@ -21,7 +21,7 @@ local function ensure_initialized() local ok, result = pcall(config_module.setup, user_config) if not ok then local msg = tostring(result):gsub('^.+:%d+: ', '') - vim.notify(msg, vim.log.levels.ERROR) + logger.log(msg, { level = vim.log.levels.ERROR, override = true, sync = true }) return false end config_module.set_current_config(result) diff --git a/lua/cp/pickers/fzf_lua.lua b/lua/cp/pickers/fzf_lua.lua index e463d5a..218ba69 100644 --- a/lua/cp/pickers/fzf_lua.lua +++ b/lua/cp/pickers/fzf_lua.lua @@ -1,3 +1,4 @@ +local logger = require('cp.log') local picker_utils = require('cp.pickers') local M = {} @@ -9,10 +10,7 @@ local function contest_picker(platform, refresh, language) local contests = picker_utils.get_platform_contests(platform, refresh) if vim.tbl_isempty(contests) then - vim.notify( - ("No contests found for platform '%s'"):format(platform_display_name), - vim.log.levels.WARN - ) + logger.log(("No contests found for platform '%s'"):format(platform_display_name), { level = vim.log.levels.WARN }) return end diff --git a/lua/cp/pickers/telescope.lua b/lua/cp/pickers/telescope.lua index 0a7a676..b0a00b3 100644 --- a/lua/cp/pickers/telescope.lua +++ b/lua/cp/pickers/telescope.lua @@ -4,6 +4,7 @@ local conf = require('telescope.config').values local action_state = require('telescope.actions.state') local actions = require('telescope.actions') +local logger = require('cp.log') local picker_utils = require('cp.pickers') local M = {} @@ -14,10 +15,7 @@ local function contest_picker(opts, platform, refresh, language) local contests = picker_utils.get_platform_contests(platform, refresh) if vim.tbl_isempty(contests) then - vim.notify( - ('No contests found for platform: %s'):format(platform_display_name), - vim.log.levels.WARN - ) + logger.log(('No contests found for platform: %s'):format(platform_display_name), { level = vim.log.levels.WARN }) return end diff --git a/lua/cp/race.lua b/lua/cp/race.lua index 7b5698f..84333ed 100644 --- a/lua/cp/race.lua +++ b/lua/cp/race.lua @@ -239,13 +239,13 @@ function M.start(platform, contest_id, language) logger.log('Contest started!', { level = vim.log.levels.INFO, override = true }) race_try_setup(p, c, l, 1, token) elseif should_notify(r) then - vim.notify( - ('[cp.nvim]: %s race "%s" starts in %s'):format( + logger.log( + ('%s race "%s" starts in %s'):format( constants.PLATFORM_DISPLAY_NAMES[race_state.platform] or race_state.platform, race_state.contest_name, format_countdown(r) ), - vim.log.levels.INFO + { level = vim.log.levels.INFO, override = true } ) end end) diff --git a/lua/cp/submit.lua b/lua/cp/submit.lua index d76fbe2..c95f95f 100644 --- a/lua/cp/submit.lua +++ b/lua/cp/submit.lua @@ -78,7 +78,7 @@ function M.submit(opts) prompt_credentials(platform, function(creds) vim.cmd.update() - vim.notify('[cp.nvim] Submitting...', vim.log.levels.INFO) + logger.log('Submitting...', { level = vim.log.levels.INFO, override = true }) require('cp.scraper').submit( platform, @@ -89,7 +89,7 @@ function M.submit(opts) creds, function(ev) vim.schedule(function() - vim.notify('[cp.nvim] ' .. (STATUS_MSGS[ev.status] or ev.status), vim.log.levels.INFO) + logger.log(STATUS_MSGS[ev.status] or ev.status, { level = vim.log.levels.INFO, override = true }) end) end, function(result) diff --git a/lua/cp/utils.lua b/lua/cp/utils.lua index 48e5dc5..e93161a 100644 --- a/lua/cp/utils.lua +++ b/lua/cp/utils.lua @@ -142,7 +142,7 @@ local function discover_nix_submit_cmd() local plugin_path = M.get_plugin_path() vim.cmd.redraw() - vim.notify('Building submit environment...', vim.log.levels.INFO) + logger.log('Building submit environment...', { level = vim.log.levels.INFO, override = true, sync = true }) vim.cmd.redraw() local result = vim .system( @@ -209,7 +209,7 @@ local function discover_nix_python() end local plugin_path = M.get_plugin_path() - vim.notify('[cp.nvim] Building Python environment with nix...', vim.log.levels.INFO) + logger.log('Building Python environment with nix...', { level = vim.log.levels.INFO, override = true, sync = true }) vim.cmd.redraw() local result = vim .system( @@ -263,7 +263,7 @@ function M.setup_python_env() if not on_nixos and vim.fn.executable('uv') == 1 then local plugin_path = M.get_plugin_path() logger.log('Python env: uv sync (dir=' .. plugin_path .. ')') - vim.notify('[cp.nvim] Setting up Python environment...', vim.log.levels.INFO) + logger.log('Setting up Python environment...', { level = vim.log.levels.INFO, override = true, sync = true }) vim.cmd.redraw() local env = vim.fn.environ() diff --git a/scrapers/atcoder.py b/scrapers/atcoder.py index c31a6ee..92252fa 100644 --- a/scrapers/atcoder.py +++ b/scrapers/atcoder.py @@ -36,9 +36,29 @@ from .timeouts import ( HTTP_TIMEOUT, ) -_LANGUAGE_ID_EXTENSION = { - "6017": "cc", - "6082": "py", +_LANGUAGE_ID_EXTENSION: dict[str, str] = { + "6002": "ada", "6003": "apl", "6004": "asm", "6005": "asm", + "6006": "awk", "6008": "sh", "6009": "bas", "6010": "bc", + "6012": "bf", "6013": "c", "6014": "c", + "6015": "cs", "6016": "cs", + "6017": "cc", "6021": "clj", "6022": "clj", "6023": "clj", "6025": "cljs", + "6026": "cob", "6027": "lisp", "6028": "cr", "6030": "d", "6031": "d", + "6032": "d", "6033": "dart", "6038": "ex", "6039": "el", "6041": "erl", + "6042": "fs", "6043": "factor", "6044": "fish", "6045": "fth", + "6046": "f90", "6047": "f90", "6048": "f", "6049": "gleam", + "6050": "go", "6051": "go", "6052": "hs", "6053": "hx", "6054": "cc", + "6056": "java", "6057": "js", "6058": "js", "6059": "js", + "6060": "jule", "6061": "kk", "6062": "kt", "6065": "lean", + "6066": "ll", "6067": "lua", "6068": "lua", "6071": "nim", "6072": "nim", + "6073": "ml", "6074": "m", "6075": "pas", "6076": "pl", "6077": "php", + "6079": "pony", "6080": "ps1", "6081": "pro", + "6082": "py", "6083": "py", "6084": "r", "6085": "re", + "6086": "rb", "6087": "rb", "6088": "rs", "6089": "py", + "6090": "scala", "6091": "scala", "6092": "scm", "6093": "scm", + "6094": "sd7", "6095": "swift", "6096": "tcl", + "6100": "ts", "6101": "ts", "6102": "ts", + "6105": "v", "6106": "vala", "6107": "v", "6109": "wat", + "6111": "zig", "6114": "jl", "6115": "py", "6116": "cc", "6118": "sql", } MIB_TO_MB = 1.048576 @@ -304,9 +324,6 @@ def _login_headless(credentials: dict[str, str]) -> LoginResult: _ensure_browser() - cookie_cache = Path.home() / ".cache" / "cp-nvim" / "atcoder-cookies.json" - cookie_cache.parent.mkdir(parents=True, exist_ok=True) - logged_in = False login_error: str | None = None @@ -352,13 +369,6 @@ def _login_headless(credentials: dict[str, str]) -> LoginResult: success=False, error="Login failed (bad credentials?)" ) - try: - browser_cookies = session.context.cookies() - if any(c["name"] == "REVEL_SESSION" for c in browser_cookies): - cookie_cache.write_text(json.dumps(browser_cookies)) - except Exception: - pass - return LoginResult(success=True, error="") except Exception as e: return LoginResult(success=False, error=str(e)) @@ -370,7 +380,6 @@ def _submit_headless( file_path: str, language_id: str, credentials: dict[str, str], - _retried: bool = False, ) -> "SubmitResult": try: from scrapling.fetchers import StealthySession # type: ignore[import-untyped,unresolved-import] @@ -382,25 +391,8 @@ def _submit_headless( _ensure_browser() - cookie_cache = Path.home() / ".cache" / "cp-nvim" / "atcoder-cookies.json" - cookie_cache.parent.mkdir(parents=True, exist_ok=True) - saved_cookies: list[dict[str, Any]] = [] - if cookie_cache.exists(): - try: - saved_cookies = json.loads(cookie_cache.read_text()) - except Exception: - pass - - logged_in = cookie_cache.exists() and not _retried login_error: str | None = None submit_error: str | None = None - needs_relogin = False - - def check_login(page): - nonlocal logged_in - logged_in = page.evaluate( - "() => Array.from(document.querySelectorAll('a')).some(a => a.textContent.trim() === 'Sign Out')" - ) def login_action(page): nonlocal login_error @@ -416,9 +408,9 @@ def _submit_headless( login_error = str(e) def submit_action(page): - nonlocal submit_error, needs_relogin + nonlocal submit_error if "/login" in page.url: - needs_relogin = True + submit_error = "Not logged in after login step" return try: _solve_turnstile(page) @@ -430,9 +422,13 @@ def _submit_headless( f'select[name="data.LanguageId"] option[value="{language_id}"]' ).wait_for(state="attached", timeout=BROWSER_ELEMENT_WAIT) page.select_option('select[name="data.LanguageId"]', language_id) - page.set_input_files("#input-open-file", file_path) + ext = _LANGUAGE_ID_EXTENSION.get(language_id, Path(file_path).suffix.lstrip(".") or "txt") + page.set_input_files( + "#input-open-file", + {"name": f"solution.{ext}", "mimeType": "text/plain", "buffer": Path(file_path).read_bytes()}, + ) page.wait_for_timeout(BROWSER_SETTLE_DELAY) - page.locator('button[type="submit"]').click() + page.locator('button[type="submit"]').click(no_wait_after=True) page.wait_for_url( lambda url: "/submissions/me" in url, timeout=BROWSER_SUBMIT_NAV_TIMEOUT["atcoder"], @@ -445,25 +441,15 @@ def _submit_headless( headless=True, timeout=BROWSER_SESSION_TIMEOUT, google_search=False, - cookies=saved_cookies if (cookie_cache.exists() and not _retried) else [], ) as session: - if not (cookie_cache.exists() and not _retried): - print(json.dumps({"status": "checking_login"}), flush=True) - session.fetch( - f"{BASE_URL}/home", page_action=check_login, network_idle=True - ) - - if not logged_in: - print(json.dumps({"status": "logging_in"}), flush=True) - session.fetch( - f"{BASE_URL}/login", - page_action=login_action, - solve_cloudflare=True, - ) - if login_error: - return SubmitResult( - success=False, error=f"Login failed: {login_error}" - ) + print(json.dumps({"status": "logging_in"}), flush=True) + session.fetch( + f"{BASE_URL}/login", + page_action=login_action, + solve_cloudflare=True, + ) + if login_error: + return SubmitResult(success=False, error=f"Login failed: {login_error}") print(json.dumps({"status": "submitting"}), flush=True) session.fetch( @@ -472,24 +458,6 @@ def _submit_headless( solve_cloudflare=True, ) - try: - browser_cookies = session.context.cookies() - if any(c["name"] == "REVEL_SESSION" for c in browser_cookies): - cookie_cache.write_text(json.dumps(browser_cookies)) - except Exception: - pass - - if needs_relogin and not _retried: - cookie_cache.unlink(missing_ok=True) - return _submit_headless( - contest_id, - problem_id, - file_path, - language_id, - credentials, - _retried=True, - ) - if submit_error: return SubmitResult(success=False, error=submit_error) diff --git a/scrapers/kattis.py b/scrapers/kattis.py index 2c5c1fc..3ace5ba 100644 --- a/scrapers/kattis.py +++ b/scrapers/kattis.py @@ -338,13 +338,14 @@ class KattisScraper(BaseScraper): await _save_kattis_cookies(client) print(json.dumps({"status": "submitting"}), flush=True) - ext = "py" if "python" in language_id.lower() else "cpp" + lang_lower = language_id.lower() + mainclass = Path(file_path).stem if "java" in lang_lower else "" data: dict[str, str] = { "submit": "true", "script": "true", "language": language_id, "problem": problem_id, - "mainclass": "", + "mainclass": mainclass, "submit_ctr": "2", } if contest_id != problem_id: @@ -354,7 +355,7 @@ class KattisScraper(BaseScraper): return await client.post( f"{BASE_URL}/submit", data=data, - files={"sub_file[]": (f"solution.{ext}", source, "text/plain")}, + files={"sub_file[]": (Path(file_path).name, source, "text/plain")}, headers=HEADERS, timeout=HTTP_TIMEOUT, ) diff --git a/scrapers/language_ids.py b/scrapers/language_ids.py index f1e0491..f69c4d9 100644 --- a/scrapers/language_ids.py +++ b/scrapers/language_ids.py @@ -4,10 +4,60 @@ LANGUAGE_IDS = { "python": "6082", "java": "6056", "rust": "6088", + "c": "6014", + "go": "6051", + "haskell": "6052", + "csharp": "6015", + "kotlin": "6062", + "ruby": "6087", + "javascript": "6059", + "typescript": "6100", + "scala": "6090", + "ocaml": "6073", + "dart": "6033", + "elixir": "6038", + "erlang": "6041", + "fsharp": "6042", + "swift": "6095", + "zig": "6111", + "nim": "6072", + "lua": "6067", + "perl": "6076", + "php": "6077", + "pascal": "6075", + "crystal": "6028", + "d": "6030", + "julia": "6114", + "r": "6084", + "commonlisp": "6027", + "scheme": "6092", + "clojure": "6022", + "ada": "6002", + "bash": "6008", + "fortran": "6047", + "gleam": "6049", + "lean": "6065", + "vala": "6106", + "v": "6105", }, "codeforces": { "cpp": "89", "python": "70", + "java": "87", + "kotlin": "99", + "rust": "75", + "go": "32", + "csharp": "96", + "haskell": "12", + "javascript": "55", + "ruby": "67", + "scala": "20", + "ocaml": "19", + "d": "28", + "perl": "13", + "php": "6", + "pascal": "4", + "fsharp": "97", }, "cses": { "cpp": "C++17", @@ -25,6 +75,55 @@ LANGUAGE_IDS = { "python": "Python 3", "java": "Java", "rust": "Rust", + "ada": "Ada", + "algol60": "Algol 60", + "algol68": "Algol 68", + "apl": "APL", + "bash": "Bash", + "bcpl": "BCPL", + "bqn": "BQN", + "c": "C", + "cobol": "COBOL", + "commonlisp": "Common Lisp", + "crystal": "Crystal", + "csharp": "C#", + "d": "D", + "dart": "Dart", + "elixir": "Elixir", + "erlang": "Erlang", + "forth": "Forth", + "fortran": "Fortran", + "fortran77": "Fortran 77", + "fsharp": "F#", + "gerbil": "Gerbil", + "go": "Go", + "haskell": "Haskell", + "icon": "Icon", + "javascript": "JavaScript (Node.js)", + "julia": "Julia", + "kotlin": "Kotlin", + "lua": "Lua", + "modula2": "Modula-2", + "nim": "Nim", + "objectivec": "Objective-C", + "ocaml": "OCaml", + "octave": "Octave", + "odin": "Odin", + "pascal": "Pascal", + "perl": "Perl", + "php": "PHP", + "pli": "PL/I", + "prolog": "Prolog", + "racket": "Racket", + "ruby": "Ruby", + "scala": "Scala", + "simula": "Simula 67", + "smalltalk": "Smalltalk", + "snobol": "SNOBOL", + "swift": "Swift", + "typescript": "TypeScript", + "visualbasic": "Visual Basic", + "zig": "Zig", }, "codechef": { "cpp": "C++", diff --git a/scrapers/timeouts.py b/scrapers/timeouts.py index 1862349..fa1e7ce 100644 --- a/scrapers/timeouts.py +++ b/scrapers/timeouts.py @@ -7,6 +7,7 @@ BROWSER_NAV_TIMEOUT = 10000 BROWSER_SUBMIT_NAV_TIMEOUT: defaultdict[str, int] = defaultdict( lambda: BROWSER_NAV_TIMEOUT ) +BROWSER_SUBMIT_NAV_TIMEOUT["atcoder"] = BROWSER_NAV_TIMEOUT * 4 BROWSER_SUBMIT_NAV_TIMEOUT["codeforces"] = BROWSER_NAV_TIMEOUT * 2 BROWSER_TURNSTILE_POLL = 5000 BROWSER_ELEMENT_WAIT = 10000