Commit graph

36 commits

Author SHA1 Message Date
Barrett Ruth
a202725cc5
fix(submit): use file path over stdin; fix CF CodeMirror textarea (#305)
## Problem

After the initial submit hardening, two issues remained: source code was
read in Lua and piped as stdin to the scraper (unnecessary roundtrip
since
the file exists on disk), and CF's `page.fill()` timed out on the hidden
`textarea[name="source"]` because CodeMirror owns the editor state.

## Solution

Pass the source file path as a CLI arg instead — AtCoder calls
`page.set_input_files(file_path)` directly, CF reads it with
`Path(file_path).read_text()`. Fix CF source injection via
`page.evaluate()`
into the CodeMirror instance. Extract `BROWSER_SUBMIT_NAV_TIMEOUT` as a
per-platform `defaultdict` (CF defaults to 2× nav timeout). Save the
buffer
with `vim.cmd.update()` before submitting.
2026-03-05 14:34:14 -05:00
Barrett Ruth
127089c57f
fix(submit): harden atcoder and codeforces submit flow (#304)
## Problem

AtCoder file upload always wrote a `.cpp` temp file regardless of
language. CF submit used `solve_cloudflare=True` on the submit page,
causing a spurious "No Cloudflare challenge found" error;
`_wait_for_gate_reload` in `login_action` was dead code. Stale cookies
caused silent auth failures with no recovery path. The `uv.spawn` ndjson
path for submit had no overall timeout.

## Solution

Replace AtCoder's temp file with `page.set_input_files` using an
in-memory buffer and correct extension via `_LANGUAGE_ID_EXTENSION`.
Replace CF's temp-file/fallback dance with a direct
`textarea[name="source"]` fill and set `solve_cloudflare=False` on the
submit fetch. Add a login fast-path that skips the homepage check when
cookies exist, with automatic stale-cookie recovery via `_retried` flag
on redirect-to-login detection. Remove `_wait_for_gate_reload`. Fix
`_ensure_browser` to propagate install errors. Add a 120s kill timer to
the ndjson `uv.spawn` submit path in `scraper.lua`.
2026-03-05 11:18:34 -05:00
Barrett Ruth
e9f72dfbbc
feat(cses): implement submit via REST API (#299)
## Problem

CSES submit was a stub returning "not yet implemented".

## Solution

Authenticate via web login + API token bridge (POST `/login` form, then
POST `/api/login` and confirm the auth page), submit source to
`/api/courses/problemset/submissions` with base64-encoded content, and
poll for verdict. Uses the same username/password credential model as
AtCoder — no browser dependencies needed. Tested end-to-end with a real
CSES account (verdict: `ACCEPTED`).

Also updates `scraper.lua` to pass the full ndjson event object to
`on_status` and handle `credentials` events for future platform use.
2026-03-05 01:07:57 -05:00
Barrett Ruth
c194f12eee
feat(atcoder): extract submit helpers; add live status notifications (#294)
## Problem

`_submit_sync` was a 170-line nested closure with `_solve_turnstile` and
the browser-install block further nested inside it. Status events went
to
stderr, which `run_scraper()` silently discards, leaving the user with a
10–30s silent hang after credential entry. The NDJSON spawn path also
lacked stdin support, so submit had no streaming path at all.

## Solution

Extract `_TURNSTILE_JS`, `_solve_turnstile`, `_ensure_browser`, and
`_submit_headless` to module level in `atcoder.py`; status events
(`installing_browser`, `checking_login`, `logging_in`, `submitting`) now
print to stdout as NDJSON. Add stdin pipe support to the NDJSON spawn
path in `scraper.lua` and switch `M.submit` to streaming with an
`on_status` callback. Wire `on_status` in `submit.lua` to fire
`vim.notify` for each phase transition.
2026-03-04 19:27:29 -05:00
Barrett Ruth
18a60da2d8
misc (#290)
fix atcoder :CP logins
propagate scraper error codes
2026-03-04 12:47:48 -05:00
217476f5f3 fix(scraper): coerce vim.NIL precision to nil before cache write
Problem: vim.json.decode maps JSON null to vim.NIL (userdata), but
cache.set_test_cases validates precision as number|nil, causing a
type error on every scrape where precision is absent.

Solution: guard the precision field when building the callback
table, converting vim.NIL to nil.
2026-03-04 00:26:22 -05:00
e79f992e0b fix: resolve lua typecheck warnings in race and scraper
Problem: luals flagged undefined-field on uv timer methods because
race_state.timer was untyped, and undefined-field on env_extra/stdin
because they were missing from the run_scraper opts annotation.

Solution: hoist race_state.timer into a typed local before the nil
check so luals can narrow through it; add env_extra and stdin to the
opts inline type in run_scraper.
2026-03-03 15:09:41 -05:00
90bd13580b feat(scraper): add precision extraction, start_time, and submit support
Problem: problem pages contain floating-point precision requirements and
contest start timestamps that were not being extracted or stored. The
submit workflow also needed a foundation in the scraper layer.

Solution: add extract_precision() to base.py and propagate through all
scrapers into cache. Add start_time to ContestSummary and extract it
from AtCoder and Codeforces. Add SubmitResult model, abstract submit()
method, submit CLI case with get_language_id() resolution, stdin/env_extra
support in run_scraper, and a full AtCoder submit implementation; stub
the remaining platforms.
2026-03-03 15:09:41 -05:00
3cb872a65f fix: replace deprecated vim.loop with vim.uv
Problem: vim.loop is deprecated since Neovim 0.10 in favour of vim.uv.
Five call sites across scraper.lua, setup.lua, utils.lua, and health.lua
still referenced the old alias.

Solution: replace every vim.loop reference with vim.uv directly.
2026-02-26 22:45:07 -05:00
Harivansh Rathi
9fc34cb6fd chore(scraper): add LuaCATS types for env helper
Add LuaCATS annotations to the env conversion helper and drop the table.sort call since ordering is not required by uv.spawn.

Co-authored-by: Codex <noreply@openai.com>
2026-02-22 12:06:01 -05:00
Harivansh Rathi
484a4a56d0 fix(scraper): pass uv.spawn env as KEY=VALUE list
Neovim/libuv spawn expects env as a list of KEY=VALUE strings. Passing the map from vim.fn.environ() can fail process startup with ENOENT, which breaks NDJSON test scraping and surfaces as 'Failed to start scraper process'.\n\nConvert env map to a deterministic list before uv.spawn in the NDJSON scraper path.

Co-authored-by: Codex <noreply@openai.com>
2026-02-22 12:06:01 -05:00
49e4233b3f fix: decouple python env setup from config init
Problem: setup_python_env() is called from check_required_runtime()
during config.setup(), which runs on the very first :CP command. The
uv sync and nix build calls use vim.system():wait(), blocking the
Neovim event loop. During the block the UI is frozen and
vim.schedule-based log messages never render, so the user sees an
unresponsive editor with no feedback.

Solution: remove setup_python_env() from check_required_runtime() so
config init is instant. Call it lazily from run_scraper() instead,
only when a scraper subprocess is actually needed. Use vim.notify +
vim.cmd.redraw() before blocking calls so the notification renders
immediately via a forced screen repaint, rather than being queued
behind vim.schedule.
2026-02-18 17:49:04 -05:00
622620f6d0 feat: add debug logging to python env, scraper, and runner
Problem: with debug = true, there is not enough diagnostic output to
troubleshoot environment or execution issues. The resolved python path,
scraper commands, and compile/run shell commands are not logged.

Solution: add logger.log calls at key decision points: python env
resolution (nix vs uv vs discovery), uv sync stderr output, scraper
subprocess commands, and compile/run shell strings. All gated behind
the existing debug flag so they only appear when debug = true.
2026-02-18 17:40:06 -05:00
c192afc5d7 fix(ci): format 2026-02-18 14:13:37 -05:00
b6f3398bbc fix(ci): formatting and typing 2026-02-18 14:13:37 -05:00
1162e7046b try to fix the setup 2026-02-18 14:13:37 -05:00
c8f735617a misc bugfixes 2026-02-02 13:13:08 -05:00
Barrett Ruth
bbe04589b8 fix: fix uv conflict 2025-11-28 23:45:17 -05:00
Barrett Ruth
00987bb0ff feat(io): cleanup view 2025-11-06 01:31:50 -05:00
Barrett Ruth
aab211902e feat: multi-test case view 2025-11-04 21:32:40 -05:00
Barrett Ruth
fef73887e4 feat(io): multi-test case view 2025-11-04 08:15:08 -05:00
6ae9488761 fix: typing 2025-10-05 23:55:23 -04:00
a0b5264761 fix: improve error handling 2025-10-05 16:06:08 -04:00
aae98a5796 disable scraper disabling 2025-10-04 17:45:49 -04:00
ef8ee26edf remove per-problem language config 2025-10-04 16:26:01 -04:00
88315ed6e6 fix(ci): pre declare on lint 2025-10-03 23:30:56 -04:00
179b333505 update pyproject 2025-10-03 22:38:24 -04:00
1520939d4b some refactors 2025-10-03 14:34:49 -04:00
91e6fbe455 fix caching 2025-10-02 10:18:29 -04:00
e6c09a4897 fix some cachign 2025-10-01 17:08:36 -04:00
a925686a17 fix(log): improve logging 2025-10-01 16:41:24 -04:00
62af1965f8 fix a lot of logic 2025-10-01 15:15:04 -04:00
b406c0ce4e fix: synchronous problem fetch 2025-10-01 12:25:07 -04:00
f9cf5b1614 possibly working 2025-09-23 10:17:22 -04:00
545793df39 remove ai comments 2025-09-23 09:43:21 -04:00
e171017ab0 fixup 2025-09-23 09:42:45 -04:00