Skip to content

feat(participation): Participamos button and hp: callback handler (hackathon-participation 2/3) - #45

Merged
TOMOKI977 merged 6 commits into
mainfrom
feat/participation-button
Sep 29, 2026
Merged

TOMOKI977 merged 6 commits into
mainfrom
feat/participation-button

Conversation

@TOMOKI977

Copy link
Copy Markdown
Contributor

Summary

This is PR 2 of 3 for change 4, hackathon-participation, and the last implementation PR. It adds the "✅ Participamos" button. The team confirms participation with one tap from the General analysis, and the bot creates the 🏆 <name> topic, posts and pins the analysis there, confirms in General and removes the button.

  • PR 1b review follow-up: adds a test that an unknown create() error keeps the claim and rethrows.
  • src/domain/usecases/run-hackathon-job.ts: both General post sites go through postToGeneral.
    • They carry the button (hp:<slug>) and store the message id. Storing is best-effort: a failure is logged and the job still acks.
    • Posts inside a topic get no button.
  • src/adapters/telegram/context.ts: callbackCallerLocation reads the tapped message's chat and thread.
  • src/adapters/telegram/participation.ts: registerParticipationCallback handles hp: callbacks.
    • The team comes from the chat, never from the payload.
    • A non-admin gets the alert "Solo un administrador del equipo puede confirmar la participación." and nothing changes.
    • An admin is answered early, then runParticipation runs. Telegram allows only one answerCallbackQuery, so refusals before topic creation are sent as a best-effort chat reply.
    • Malformed data is ignored. The DM sel: team picker is unaffected.

Review

A bounded review at medium risk ran the reliability lens, including the security checks, on all 10 changed paths. It found no severe findings. It confirmed:

  • the admin check runs before any side effect;
  • the team is resolved from the chat;
  • both General sites and the best-effort store behave correctly;
  • the e2e test covers the real webhook route, redelivery, and the sel: picker.

One deferred warning, R3-001: resolveGroupMembership runs outside the safe() wrapper. If the D1 lookup throws, the callback is left unanswered and the webhook returns 500. This is a one-line follow-up.

Tests

  • Strict TDD.
  • The full suite passes (1027 tests), and the typecheck is clean.

Operator steps (Phase 4)

  1. Grant the bot the admin right "Manage Topics" in addition to "Pin Messages".
  2. Smoke test:
    • tap the button on a new General analysis;
    • run /hackathon join <slug> on an old analysis;
    • delete the topic and confirm again, which should recreate it;
    • open the t.me/c/… link.

🤖 Generated with Claude Code

@TOMOKI977 TOMOKI977 added the size:exception PR over the 400-line review budget, accepted explicitly label Sep 29, 2026
@TOMOKI977
TOMOKI977 merged commit 347f1ee into main Sep 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:exception PR over the 400-line review budget, accepted explicitly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant