Add poll response counter
This commit is contained in:
parent
ad28cbd963
commit
a304f0a34d
|
@ -41,6 +41,9 @@ vetting:
|
||||||
space_id: "!xxx:xxx"
|
space_id: "!xxx:xxx"
|
||||||
# Voting time in seconds
|
# Voting time in seconds
|
||||||
voting_time: 172800
|
voting_time: 172800
|
||||||
|
# Requirements for getting accepted
|
||||||
|
min_yes_votes: 1
|
||||||
|
max_no_votes: 0
|
||||||
|
|
||||||
# Logging setup
|
# Logging setup
|
||||||
logging:
|
logging:
|
||||||
|
|
|
@ -117,6 +117,13 @@ class Config:
|
||||||
|
|
||||||
self.voting_time = int(self._get_cfg(["vetting", "voting_time"], required=True))
|
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(
|
def _get_cfg(
|
||||||
self,
|
self,
|
||||||
path: List[str],
|
path: List[str],
|
||||||
|
|
|
@ -2,8 +2,15 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
import time
|
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.config import Config
|
||||||
from vetting_bot.storage import Storage
|
from vetting_bot.storage import Storage
|
||||||
|
|
||||||
|
@ -48,6 +55,8 @@ class Timer:
|
||||||
asyncio.create_task(_task())
|
asyncio.create_task(_task())
|
||||||
|
|
||||||
async def _end_poll(self, mxid: str, poll_event_id: str):
|
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 = {
|
event_content = {
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
"rel_type": "m.reference",
|
"rel_type": "m.reference",
|
||||||
|
@ -65,7 +74,108 @@ class Timer:
|
||||||
logger.error(poll_resp, stack_info=True)
|
logger.error(poll_resp, stack_info=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.store.cursor.execute(
|
# Gather votes
|
||||||
"UPDATE vetting SET vote_ended = 1 WHERE mxid = ?",
|
message_filter = {
|
||||||
(mxid,),
|
# "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