wyr: track real reaction votes and announce winner with counts
- Add _WYR_POLLS dict keyed by poll event_id to accumulate votes - record_wyr_vote() called from callbacks.reaction() on every reaction - reveal() reads actual vote counts and announces winner with percentage - Handles tie and zero-vote cases - Remove the useless 'check the reactions above' message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ from functools import wraps
|
|||||||
from nio import AsyncClient
|
from nio import AsyncClient
|
||||||
|
|
||||||
from config import BOT_PREFIX, MATRIX_USER_ID
|
from config import BOT_PREFIX, MATRIX_USER_ID
|
||||||
from commands import COMMANDS, metrics, check_scramble_answer, check_riddle_answer
|
from commands import COMMANDS, metrics, check_scramble_answer, check_riddle_answer, record_wyr_vote
|
||||||
from welcome import handle_welcome_reaction, handle_space_join, SPACE_ROOM_ID
|
from welcome import handle_welcome_reaction, handle_space_join, SPACE_ROOM_ID
|
||||||
|
|
||||||
logger = logging.getLogger("matrixbot")
|
logger = logging.getLogger("matrixbot")
|
||||||
@@ -94,6 +94,7 @@ class Callbacks:
|
|||||||
await handle_welcome_reaction(
|
await handle_welcome_reaction(
|
||||||
self.client, room.room_id, event.sender, reacted_event_id, key
|
self.client, room.room_id, event.sender, reacted_event_id, key
|
||||||
)
|
)
|
||||||
|
record_wyr_vote(reacted_event_id, event.sender, key)
|
||||||
|
|
||||||
async def member(self, room, event):
|
async def member(self, room, event):
|
||||||
"""Handle m.room.member events — watch for Space joins."""
|
"""Handle m.room.member events — watch for Space joins."""
|
||||||
|
|||||||
+51
-15
@@ -1558,6 +1558,22 @@ async def check_scramble_answer(client: AsyncClient, room_id: str, sender: str,
|
|||||||
# Would You Rather (WYR)
|
# Would You Rather (WYR)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Keyed by the poll event_id; each value: {"option_a": str, "option_b": str, "votes": {"🅰️": set(), "🅱️": set()}}
|
||||||
|
_WYR_POLLS: dict[str, dict] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def record_wyr_vote(event_id: str, sender: str, key: str) -> None:
|
||||||
|
"""Called from callbacks when a reaction is added to a WYR poll message."""
|
||||||
|
if event_id not in _WYR_POLLS:
|
||||||
|
return
|
||||||
|
poll = _WYR_POLLS[event_id]
|
||||||
|
# Remove sender from both buckets first (prevent double-voting)
|
||||||
|
for bucket in poll["votes"].values():
|
||||||
|
bucket.discard(sender)
|
||||||
|
if key in poll["votes"]:
|
||||||
|
poll["votes"][key].add(sender)
|
||||||
|
|
||||||
|
|
||||||
async def _generate_wyr() -> dict | None:
|
async def _generate_wyr() -> dict | None:
|
||||||
system_msg = (
|
system_msg = (
|
||||||
"You are a game host generating Would You Rather questions. "
|
"You are a game host generating Would You Rather questions. "
|
||||||
@@ -1625,25 +1641,45 @@ async def cmd_wyr(client: AsyncClient, room_id: str, sender: str, args: str):
|
|||||||
resp = await send_html(client, room_id, plain, html)
|
resp = await send_html(client, room_id, plain, html)
|
||||||
|
|
||||||
if hasattr(resp, "event_id"):
|
if hasattr(resp, "event_id"):
|
||||||
await send_reaction(client, room_id, resp.event_id, "🅰️")
|
poll_event_id = resp.event_id
|
||||||
await send_reaction(client, room_id, resp.event_id, "🅱️")
|
_WYR_POLLS[poll_event_id] = {
|
||||||
|
"option_a": wyr["option_a"],
|
||||||
|
"option_b": wyr["option_b"],
|
||||||
|
"votes": {"🅰️": set(), "🅱️": set()},
|
||||||
|
}
|
||||||
|
await send_reaction(client, room_id, poll_event_id, "🅰️")
|
||||||
|
await send_reaction(client, room_id, poll_event_id, "🅱️")
|
||||||
|
|
||||||
async def reveal():
|
async def reveal():
|
||||||
await asyncio.sleep(30)
|
await asyncio.sleep(30)
|
||||||
# Count reactions via room state — we just tally what we have
|
poll = _WYR_POLLS.pop(poll_event_id, None)
|
||||||
# Since we can't easily query reaction counts via nio without extra API calls,
|
votes_a = len(poll["votes"]["🅰️"]) if poll else 0
|
||||||
# we announce the results and encourage re-voting awareness
|
votes_b = len(poll["votes"]["🅱️"]) if poll else 0
|
||||||
plain_r = (
|
total = votes_a + votes_b
|
||||||
f"⏰ WYR Results!\n"
|
|
||||||
f"🅰️ {wyr['option_a']}\n"
|
opt_a = wyr["option_a"]
|
||||||
f"🅱️ {wyr['option_b']}\n"
|
opt_b = wyr["option_b"]
|
||||||
f"Check the reactions above to see which won!"
|
|
||||||
)
|
if total == 0:
|
||||||
|
result_line = "No votes — you're all cowards. 🐔"
|
||||||
|
result_html = "<em>No votes — you're all cowards. 🐔</em>"
|
||||||
|
elif votes_a > votes_b:
|
||||||
|
pct = round(votes_a / total * 100)
|
||||||
|
result_line = f"🅰️ {opt_a} wins! ({votes_a} vs {votes_b} — {pct}%)"
|
||||||
|
result_html = f'🅰️ <strong>{opt_a}</strong> wins! <em>({votes_a} vs {votes_b} — {pct}%)</em>'
|
||||||
|
elif votes_b > votes_a:
|
||||||
|
pct = round(votes_b / total * 100)
|
||||||
|
result_line = f"🅱️ {opt_b} wins! ({votes_b} vs {votes_a} — {pct}%)"
|
||||||
|
result_html = f'🅱️ <strong>{opt_b}</strong> wins! <em>({votes_b} vs {votes_a} — {pct}%)</em>'
|
||||||
|
else:
|
||||||
|
result_line = f"It's a tie! ({votes_a} each)"
|
||||||
|
result_html = f"It's a tie! <em>({votes_a} each)</em>"
|
||||||
|
|
||||||
|
plain_r = f"⏰ WYR Results!\n{wyr['question']}\n{result_line}"
|
||||||
html_r = (
|
html_r = (
|
||||||
f'<font color="#a855f7"><strong>⏰ WYR — Time\'s up!</strong></font><br>'
|
f'<font color="#a855f7"><strong>⏰ WYR — Results!</strong></font><br>'
|
||||||
f'🅰️ <strong>{wyr["option_a"]}</strong><br>'
|
f'<em>{wyr["question"]}</em><br><br>'
|
||||||
f'🅱️ <strong>{wyr["option_b"]}</strong><br>'
|
f'{result_html}'
|
||||||
f'<em>Check the reactions on the poll above to see which option won!</em>'
|
|
||||||
)
|
)
|
||||||
await send_html(client, room_id, plain_r, html_r)
|
await send_html(client, room_id, plain_r, html_r)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user