")
except (OSError, ValueError):
draft_html = ""
placeholder = ("只输入姓名,例如:高瑶"
if payload.get("kind") == "voiceprint"
else ("背景不准时,在这里写明正确背景并提交重跑"
if payload.get("kind") == "background_check"
else "输入正确名称或补充说明"))
body = f"""
剩余 {len(rows)} 个 · 问题 #{row['id']}
{html.escape(row['question'])}
{source_html}{draft_html}
"""
self._send(_page("ASR 快速确认", body))
def do_POST(self):
if not self._valid_path():
self._send(b"Not found", HTTPStatus.NOT_FOUND)
return
try:
length = min(int(self.headers.get("Content-Length", "0")), 4096)
form = urllib.parse.parse_qs(self.rfile.read(length).decode("utf-8"))
qid = int(form.get("id", ["0"])[0])
custom = form.get("custom", [""])[0].strip()
answer = custom or form.get("answer", [""])[0].strip()
if not qid or not answer or len(answer) > 120:
raise ValueError("invalid answer")
pending_ids = {r["id"] for r in review.pending(1000)}
if qid not in pending_ids:
raise ValueError("问题已处理或不存在")
review.answer(qid, answer)
self.server.last_activity = time.time()
self.send_response(HTTPStatus.SEE_OTHER)
self.send_header("Location", f"/r/{self.server.token}/")
self.send_header("Cache-Control", "no-store")
self.end_headers()
except Exception as e:
self._send(_page("提交失败",
f'
提交失败
{html.escape(str(e))}
'),
HTTPStatus.BAD_REQUEST)
def serve() -> int:
rows = review.pending(100)
if not rows:
log("review web: no pending questions")
return 0
token = secrets.token_urlsafe(32)
started = time.time()
try:
server = Server((CFG.review_host, CFG.review_port), Handler, token)
except OSError as e:
STATE.unlink(missing_ok=True)
log(f"review web bind failed on {CFG.review_host}:{CFG.review_port}: {e}",
level="ERROR")
return 1
_write_state(token, started)
server.timeout = 1
url = _url(token)
log(f"review web listening on {CFG.review_public_host}:{CFG.review_port} "
f"({len(rows)} question(s))")
try:
from . import vault
vault.notify("ASR 快速确认",
f"{len(rows)} 个问题待确认:{url}\n"
f"链接最多保留 {CFG.review_max_seconds // 60} 分钟,完成后自动销毁。",
redact_log=True)
except Exception as e:
log(f"review web notification failed: {e}", level="WARN")
try:
while True:
server.handle_request()
now = time.time()
if server.finish_at and now >= server.finish_at:
# A new recording can enqueue work during the 10-second grace
# period while systemd still considers this unit active.
if review.pending(1):
server.finish_at = None
log("review web received new work during shutdown grace")
else:
break
if now - started >= CFG.review_max_seconds:
log("review web reached maximum lifetime")
break
if server.opened and now - server.last_activity >= CFG.review_idle_seconds:
log("review web idle timeout")
break
finally:
server.server_close()
try:
STATE.unlink(missing_ok=True)
except OSError:
pass
return 0
if __name__ == "__main__":
sys.exit(serve())