feat: Update quiz stat and enhance on-demand quiz handling#74
feat: Update quiz stat and enhance on-demand quiz handling#74Bayashat wants to merge 10 commits into
Conversation
π Infrastructure Changes Preview (Zerde Telegram Bot)This PR will modify the following AWS resources: βΉοΈ No infrastructure changes detectedThis PR only contains code changes (Lambda functions, etc.) π Full CDK Diff Outputb'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'
b'!! !!\n'
b'!! Node 20 has reached end-of-life on 2026-04-30 and will no longer be supported in new releases after 2026-10-30. !!\n'
b'!! Please upgrade to a supported node version as soon as possible. !!\n'
b'!! !!\n'
b'!! This software is currently running on node v20.20.0. !!\n'
b'!! As of the current release of this software, supported node releases are: !!\n'
b'!! - ^24.0.0 (Planned end-of-life: 2028-04-30) !!\n'
b'!! - ^22.0.0 (Planned end-of-life: 2027-04-30) !!\n'
b'!! - ^20.0.0 (Planned end-of-life: 2026-04-30) [DEPRECATED] !!\n'
b'!! !!\n'
b'!! This warning can be silenced by setting the JSII_SILENCE_WARNING_DEPRECATED_NODE_VERSION environment variable. !!\n'
b'!! !!\n'
b'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 1.82kB done
#1 DONE 0.0s
#2 [internal] load metadata for public.ecr.aws/sam/build-python3.13:latest
#2 DONE 0.1s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [1/2] FROM public.ecr.aws/sam/build-python3.13:latest@sha256:be015b4dbfce398c76feb589c307073a48aed25b6accee4db41a481b78a490d2
#4 DONE 0.0s
#5 [2/2] RUN python -m venv /usr/app/venv && mkdir /tmp/pip-cache && chmod -R 777 /tmp/pip-cache && pip install --upgrade pip && mkdir /tmp/poetry-cache && chmod -R 777 /tmp/poetry-cache && mkdir /tmp/uv-cache && chmod -R 777 /tmp/uv-cache && pip install pipenv==2022.4.8 poetry==1.5.1 uv==0.6.9 && rm -rf /tmp/pip-cache/* /tmp/poetry-cache/* /tmp/uv-cache/*
#5 CACHED
#6 exporting to image
#6 exporting layers done
#6 writing image sha256:061e0ba905fce6c09d786a1a1e023320dc3da30ff1300cf2664af3760f85f75c done
#6 naming to docker.io/library/cdk-2f59e732e8ae4d02a5184d9228e694ce8e11ea332b6fffa637cf82fc00d887dc done
#6 DONE 0.0s
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 1.82kB done
#1 DONE 0.0s
#2 [internal] load metadata for public.ecr.aws/sam/build-python3.13:latest
#2 DONE 0.1s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [1/2] FROM public.ecr.aws/sam/build-python3.13:latest@sha256:be015b4dbfce398c76feb589c307073a48aed25b6accee4db41a481b78a490d2
#4 DONE 0.0s
#5 [2/2] RUN python -m venv /usr/app/venv && mkdir /tmp/pip-cache && chmod -R 777 /tmp/pip-cache && pip install --upgrade pip && mkdir /tmp/poetry-cache && chmod -R 777 /tmp/poetry-cache && mkdir /tmp/uv-cache && chmod -R 777 /tmp/uv-cache && pip install pipenv==2022.4.8 poetry==1.5.1 uv==0.6.9 && rm -rf /tmp/pip-cache/* /tmp/poetry-cache/* /tmp/uv-cache/*
#5 CACHED
#6 exporting to image
#6 exporting layers done
#6 writing image sha256:061e0ba905fce6c09d786a1a1e023320dc3da30ff1300cf2664af3760f85f75c done
#6 naming to docker.io/library/cdk-2f59e732e8ae4d02a5184d9228e694ce8e11ea332b6fffa637cf82fc00d887dc 0.0s done
#6 DONE 0.0s
#0 building with "default" instance using docker driver
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 1.82kB done
#1 DONE 0.0s
#2 [internal] load metadata for public.ecr.aws/sam/build-python3.13:latest
#2 DONE 0.1s
#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s
#4 [1/2] FROM public.ecr.aws/sam/build-python3.13:latest@sha256:be015b4dbfce398c76feb589c307073a48aed25b6accee4db41a481b78a490d2
#4 DONE 0.0s
#5 [2/2] RUN python -m venv /usr/app/venv && mkdir /tmp/pip-cache && chmod -R 777 /tmp/pip-cache && pip install --upgrade pip && mkdir /tmp/poetry-cache && chmod -R 777 /tmp/poetry-cache && mkdir /tmp/uv-cache && chmod -R 777 /tmp/uv-cache && pip install pipenv==2022.4.8 poetry==1.5.1 uv==0.6.9 && rm -rf /tmp/pip-cache/* /tmp/poetry-cache/* /tmp/uv-cache/*
#5 CACHED
#6 exporting to image
#6 exporting layers done
#6 writing image sha256:061e0ba905fce6c09d786a1a1e023320dc3da30ff1300cf2664af3760f85f75c done
#6 naming to docker.io/library/cdk-2f59e732e8ae4d02a5184d9228e694ce8e11ea332b6fffa637cf82fc00d887dc done
#6 DONE 0.0s
start: Building zerde-serverless-telegram-bot-dev Template
success: Built zerde-serverless-telegram-bot-dev Template
start: Publishing zerde-serverless-telegram-bot-dev Template (current_account-current_region-f07c48c1)
success: Published zerde-serverless-telegram-bot-dev Template (current_account-current_region-f07c48c1)
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --method=template to use a less accurate but faster template-only diff)
Stack ZerdeServerlessTelegramBotStack-dev (zerde-serverless-telegram-bot-dev)
Resources
[~] AWS::Lambda::LayerVersion ZerdeServerlessZerdeCommonLayer ZerdeServerlessZerdeCommonLayer41490F86 replace
ββ [~] Content (requires replacement)
ββ [~] .S3Key:
ββ [-] 0dcc5891de830f6f76afa33dfb31eed76e8777a2639f009c03225b20751af5e3.zip
ββ [+] f8f2950830663974b9f717aca59d0b7537ee8cf4e11e3a77bb43eb681492056a.zip
[~] AWS::SQS::Queue ZerdeServerlessMessaging/ZerdeServerlessTimeoutTasksQueue ZerdeServerlessMessagingZerdeServerlessTimeoutTasksQueueF4025D17
ββ [~] VisibilityTimeout
ββ [-] 180
ββ [+] 1800
[~] AWS::Lambda::Function ZerdeServerlessBot/ZerdeServerlessBotLambda ZerdeServerlessBotZerdeServerlessBotLambdaA4D02A14
ββ [~] Code
β ββ [~] .S3Key:
β ββ [-] df87ab2e1e02879d3be2c59b3598082f9e21c7b1efa245cdbe230096d7d9e4fb.zip
β ββ [+] 21ce7df272fb44d8cf2ab46b857179461122b101e3c5983cd0bb5ccb2e6a2c63.zip
ββ [~] Timeout
ββ [-] 90
ββ [+] 300
[~] AWS::Lambda::Function ZerdeServerlessQuiz/ZerdeServerlessQuizLambda ZerdeServerlessQuizZerdeServerlessQuizLambda4D9EA339
ββ [~] Code
ββ [~] .S3Key:
ββ [-] d9d7c1ef28c4be304708c4a3e7fae5d324d5b70daf1c3eb4d2355715272c9f83.zip
ββ [+] e2d6dd7fb44af1be6765cc98e84619cdca446c78ea57f416cbabe9764c82f643.zip
β¨ Number of stacks with differences: 1
|
There was a problem hiding this comment.
Pull request overview
Updates the quiz stats presentation in the Bot Lambda and enhances Quiz Lambda on-demand (/genquiz) behavior by sourcing certain topics from the bank with an independent per-chat rotation queue.
Changes:
- Extend
/quizstatsto display weekly score, season wins, and all-time score (and update localized strings accordingly). - Add a genquiz-specific DynamoDB-backed question queue and selection flow so
/genquizbank picks donβt interfere with daily rotation. - Introduce topic aliases mapping
/genquiztopics (e.g.aws,clf-c02) to the bankedcloudcategory, and adjust tests for the new output.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_quiz_handler.py | Updates /quizstats test expectations for new fields and week-based ranking. |
| src/quiz/services/repository.py | Adds DynamoDB read/write helpers for a genquiz-specific bank question queue. |
| src/quiz/services/quiz_service.py | Adds bank-topic alias mapping and a genquiz bank-pick path with independent rotation seed/keys. |
| src/bot/services/handlers/quiz.py | Passes new stat fields into the translation template for /quizstats. |
| src/bot/core/translations.py | Updates quizstats_response strings across languages to the new stats layout/fields. |
π‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| announcement = self.build_announcement(lang, difficulty, source_label=question.get("source_label")) | ||
| self._sender.send_message(str(chat_id), announcement) | ||
| poll_result = self._sender.send_quiz_poll( | ||
| chat_id=chat_id, | ||
| question=question["question"], | ||
| options=question["options"], | ||
| correct_option_id=question["correct_option_index"], | ||
| explanation=question.get("explanation"), | ||
| ) |
There was a problem hiding this comment.
process_on_demand_quiz() sends the announcement for bank-sourced genquiz but ignores the return value of self._sender.send_message(...). Since send_message() returns None on failure, this can silently proceed to send a poll even when the announcement failed (unlike process_daily_quiz, which treats announcement failure as a hard failure). Consider checking the result and returning an error (or at least recording a failed step) to keep failure handling consistent and debuggable.
| def _pick_banked_question_for_genquiz(self, category: str, chat_id: str, difficulty: str) -> dict | None: | ||
| """Pick the next on-demand question from the bank using a genquiz-specific per-chat queue. | ||
|
|
||
| Uses a different DynamoDB key and shuffle seed from the daily rotation so that | ||
| genquiz picks are unlikely to collide with upcoming daily questions. | ||
| Daily category queue is never read or written by this method. | ||
| """ | ||
| sources = _BANKED_CATEGORIES[category] | ||
| remaining = self._repo.get_genquiz_question_queue(category, chat_id) | ||
| if not remaining: | ||
| all_keys = self._repo.get_bank_question_ids(category, sources) | ||
| if not all_keys: | ||
| return None | ||
| # Different seed from daily ("genquiz:" prefix) β different shuffle order | ||
| rng = random.Random(f"genquiz:{chat_id}::{len(all_keys)}") | ||
| remaining = rng.sample(all_keys, len(all_keys)) | ||
| logger.info( |
There was a problem hiding this comment.
_pick_banked_question_for_genquiz() duplicates almost all of _pick_banked_question_for_chat() with only the queue getter/saver and seed differing. This duplication increases the chance of the two paths drifting (e.g., bug fixes or new return fields added to one but not the other). Consider factoring out a shared helper that accepts the queue read/write functions and seed prefix, so both daily and genquiz bank selection stay in sync.
β¦ncy across multiple languages.
π Description
π Type of Change
ποΈ Infrastructure Changes (Crucial)
β Checklist
pre-commit run --all-fileslocally and fixed all issues.pytest).cdk difflocally to verify changes.π Related Issues