fix(scrapers): bad credentials detection and error message cleanup (#367)

## Problem

Wrong credentials produced garbled error messages (`"login failed: Login
failed: bad_credentials"`) and stale credentials remained cached after
failure, causing silent re-use on the next invocation.

## Solution

Standardize all scrapers to emit `"bad_credentials"` as a plain error
code, mapped to a human-readable string via `LOGIN_ERRORS` in
`constants.lua`. Fix `credentials.lua` to clear cached credentials on
failure in both the fresh-prompt and re-prompt paths. For AtCoder and
Codeforces, replace `wait_for_url` with `wait_for_function` to detect
the login error element immediately rather than sitting the full 10s
navigation timeout. Add "Remember me" checkbox on Codeforces login.
This commit is contained in:
Barrett Ruth 2026-03-07 17:58:25 -05:00 committed by GitHub
parent 573b335646
commit 771dbc7753
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 67 additions and 40 deletions

View file

@ -221,4 +221,8 @@ M.DEFAULT_VERSIONS = { cpp = 'c++20', python = 'python3' }
M.COOKIE_FILE = vim.fn.expand('~/.cache/cp-nvim/cookies.json')
M.LOGIN_ERRORS = {
bad_credentials = 'bad credentials',
}
return M

View file

@ -14,13 +14,13 @@ local STATUS_MESSAGES = {
---@param platform string
---@param display string
local function prompt_and_login(platform, display)
vim.ui.input({ prompt = display .. ' username: ' }, function(username)
vim.ui.input({ prompt = '[cp.nvim]: ' .. display .. ' username: ' }, function(username)
if not username or username == '' then
logger.log('Cancelled', { level = vim.log.levels.WARN })
return
end
vim.fn.inputsave()
local password = vim.fn.inputsecret(display .. ' password: ')
local password = vim.fn.inputsecret('[cp.nvim]: ' .. display .. ' password: ')
vim.fn.inputrestore()
if not password or password == '' then
logger.log('Cancelled', { level = vim.log.levels.WARN })
@ -45,7 +45,11 @@ local function prompt_and_login(platform, display)
)
else
local err = result.error or 'unknown error'
logger.log(display .. ' login failed: ' .. err, { level = vim.log.levels.ERROR })
cache.clear_credentials(platform)
logger.log(
display .. ' login failed: ' .. (constants.LOGIN_ERRORS[err] or err),
{ level = vim.log.levels.ERROR }
)
end
end)
end)
@ -83,6 +87,7 @@ function M.login(platform)
{ level = vim.log.levels.INFO, override = true }
)
else
cache.clear_credentials(platform)
prompt_and_login(platform, display)
end
end)

View file

@ -110,10 +110,13 @@ function M.submit(opts)
logger.log('Submitted successfully', { level = vim.log.levels.INFO, override = true })
else
local err = result and result.error or 'unknown error'
if err:match('^Login failed') then
if err == 'bad_credentials' or err:match('^Login failed') then
cache.clear_credentials(platform)
end
logger.log('Submit failed: ' .. err, { level = vim.log.levels.ERROR })
logger.log(
'Submit failed: ' .. (constants.LOGIN_ERRORS[err] or err),
{ level = vim.log.levels.ERROR }
)
end
end)
end