Add poll response counter
This commit is contained in:
parent
ad28cbd963
commit
a304f0a34d
|
@ -41,6 +41,9 @@ vetting:
|
|||
space_id: "!xxx:xxx"
|
||||
# Voting time in seconds
|
||||
voting_time: 172800
|
||||
# Requirements for getting accepted
|
||||
min_yes_votes: 1
|
||||
max_no_votes: 0
|
||||
|
||||
# Logging setup
|
||||
logging:
|
||||
|
|
|
@ -117,6 +117,13 @@ class Config:
|
|||
|
||||
self.voting_time = int(self._get_cfg(["vetting", "voting_time"], required=True))
|
||||
|
||||
self.min_yes_votes = int(
|
||||
self._get_cfg(["vetting", "min_yes_votes"], required=True)
|
||||
)
|
||||
self.max_no_votes = int(
|
||||
self._get_cfg(["vetting", "max_no_votes"], required=True)
|
||||
)
|
||||
|
||||
def _get_cfg(
|
||||
self,
|
||||
path: List[str],
|
||||
|
|
|
@ -2,8 +2,15 @@ import asyncio
|
|||
import logging
|
||||
import time
|
||||
|
||||
from nio import AsyncClient, RoomSendError
|
||||
from nio import (
|
||||
AsyncClient,
|
||||
RoomMessagesError,
|
||||
RoomSendError,
|
||||
RoomSendResponse,
|
||||
UnknownEvent,
|
||||
)
|
||||
|
||||
from vetting_bot.chat_functions import react_to_event, send_text_to_room
|
||||
from vetting_bot.config import Config
|
||||
from vetting_bot.storage import Storage
|
||||
|
||||
|
@ -48,6 +55,8 @@ class Timer:
|
|||
asyncio.create_task(_task())
|
||||
|
||||
async def _end_poll(self, mxid: str, poll_event_id: str):
|
||||
logger.info("Ending poll for %s - %s", mxid, poll_event_id)
|
||||
# Send poll end event
|
||||
event_content = {
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
|
@ -65,7 +74,108 @@ class Timer:
|
|||
logger.error(poll_resp, stack_info=True)
|
||||
return
|
||||
|
||||
self.store.cursor.execute(
|
||||
"UPDATE vetting SET vote_ended = 1 WHERE mxid = ?",
|
||||
(mxid,),
|
||||
# Gather votes
|
||||
message_filter = {
|
||||
# "types": ["org.matrix.msc3381.poll.response"], # this doesn't work for some reason :/
|
||||
"rooms": [self.config.vetting_room_id],
|
||||
}
|
||||
|
||||
vote_count = {
|
||||
"yes": 0,
|
||||
"no": 0,
|
||||
"blank": 0,
|
||||
}
|
||||
|
||||
users_voted = set()
|
||||
|
||||
# Loop until we find all events that could be related to the poll
|
||||
# (max 20 times: 20 * 20 = up to 400 events deep or until we find the poll event)
|
||||
start_token = ""
|
||||
for _ in range(0, 20):
|
||||
logger.debug("Requesting events")
|
||||
message_resp = await self.client.room_messages(
|
||||
room_id=self.config.vetting_room_id,
|
||||
start=start_token,
|
||||
limit=20,
|
||||
message_filter=message_filter,
|
||||
)
|
||||
|
||||
if isinstance(message_resp, RoomMessagesError):
|
||||
logging.error(message_resp, stack_info=True)
|
||||
text = "Unable to gather votes."
|
||||
await send_text_to_room(self.client, self.config.vetting_room_id, text)
|
||||
return
|
||||
|
||||
# Resume next request where this ends
|
||||
start_token = message_resp.end
|
||||
|
||||
# Count votes
|
||||
for event in message_resp.chunk:
|
||||
# Only process poll response events
|
||||
if not isinstance(event, UnknownEvent):
|
||||
continue
|
||||
if event.type != "org.matrix.msc3381.poll.response":
|
||||
continue
|
||||
content = event.source.get("content")
|
||||
try:
|
||||
# Check if this response is for the correct poll
|
||||
related_event_id = content["m.relates_to"]["event_id"]
|
||||
if related_event_id != poll_event_id:
|
||||
continue
|
||||
|
||||
# Add vote to count
|
||||
answer = content["org.matrix.msc3381.poll.response"]["answers"][0]
|
||||
|
||||
# Only count the last poll response event
|
||||
if event.sender in users_voted:
|
||||
continue
|
||||
users_voted.add(event.sender)
|
||||
vote_count[answer] += 1
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# Check if we found the initial poll event
|
||||
if any([event.event_id == poll_event_id for event in message_resp.chunk]):
|
||||
break
|
||||
|
||||
votes_responses = "".join(
|
||||
[f"\n{answer.title()}: {count};" for answer, count in vote_count.items()]
|
||||
)
|
||||
|
||||
# Make the decision by checking requirements
|
||||
decision = (
|
||||
vote_count["yes"] >= self.config.min_yes_votes
|
||||
and vote_count["no"] <= self.config.max_no_votes
|
||||
)
|
||||
|
||||
decision_text = (
|
||||
"Confirm inviting this person to the Federation by reacting."
|
||||
if decision
|
||||
else "Votes do not match the requirements, not inviting."
|
||||
)
|
||||
|
||||
text = (
|
||||
f"Voting for `{mxid}` has ended. Counted votes are:\n"
|
||||
f"{votes_responses}\n\n{decision_text}"
|
||||
)
|
||||
decision_resp = await send_text_to_room(
|
||||
self.client, self.config.vetting_room_id, text
|
||||
)
|
||||
|
||||
if not isinstance(decision_resp, RoomSendResponse):
|
||||
logger.error(decision_resp)
|
||||
return
|
||||
|
||||
if decision:
|
||||
await react_to_event(
|
||||
self.client,
|
||||
self.config.vetting_room_id,
|
||||
decision_resp.event_id,
|
||||
"confirm",
|
||||
)
|
||||
|
||||
# Finally - update database
|
||||
# self.store.cursor.execute(
|
||||
# "UPDATE vetting SET vote_ended = 1 WHERE mxid = ?",
|
||||
# (mxid,),
|
||||
# )
|
||||
|
|
Loading…
Reference in New Issue