Conversation
Replace the flat, unpinned-boundary requirements.txt (which mixed direct runtime deps with transitive ones and a dead pylint/isort/black stack already superseded by ruff) with pyproject.toml + uv.lock. Only actual direct imports are declared; uv resolves and locks the full transitive tree instead of storing it flat. Drops unused deps (vk_api, Pillow, PyYAML, gspread) found to have no real usage in src/. Updates Dockerfile, Dockerfile.dev, and CI to install via uv instead of pip, and fixes .dockerignore to exclude .venv so local venvs don't get copied into the image. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JR68hNjowTEaMRzVFRh8Yi
sheetfu and our own drive_client both call googleapiclient's central discovery endpoint (www.googleapis.com/discovery/v1/...) on every process start. That endpoint is currently blocking our Hetzner host's IP with a generic anti-abuse 403, which crash-loops the bot on every restart since AppContext init can't get past GoogleSheetsClient. The per-API discovery endpoint ({api}.googleapis.com/\$discovery/rest) responds fine and is Google's documented replacement.
Reverts the ad hoc discoveryServiceUrl monkeypatch from the previous commit. Since v2.0, google-api-python-client ships static discovery documents for public APIs and uses them by default when no custom discoveryServiceUrl is passed - no network call at all in the normal path. We were pinned to 1.9.1 (2020), which predates that feature and always fetches discovery live on every process start. That live fetch is what crash-looped the bot when Google's endpoint rate-limited us. Verified offline (network calls forcibly blocked at the socket level) that both SheetsService and DriveService build successfully with the existing sheetfu/oauth2client code, unchanged.
The real bug behind the /help hang: TelegramSender and the Google/ Planka clients are synchronous and blocking, but every command handler ran them directly inline inside the single asyncio event loop thread that python-telegram-bot polls and dispatches updates on. A timeout would only cap how long one bad call blocks things - the actual design flaw is that ANY slow or stuck call there freezes command dispatch for every chat, not just the one being handled, since there's nothing else running on that thread to keep polling for new updates. Route sync handler calls through a dedicated ThreadPoolExecutor (_run_handler), awaited via loop.run_in_executor, so the event loop stays free to keep dispatching other updates while a handler blocks on I/O. Async handlers are awaited directly as before. Verified two 1s sync handlers now run concurrently instead of serializing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.