Add timer to automatically end polls

This commit is contained in:
Panoramic 2024-06-11 16:27:20 +03:00
parent 29674b92eb
commit 5b233cb5b2
Signed by: Panoramic
GPG Key ID: 29FEDD73E66D32F1
6 changed files with 95 additions and 2 deletions

View File

@ -39,6 +39,8 @@ vetting:
room_id: "!xxx:xxx"
# A space which will house all the vetting rooms
space_id: "!xxx:xxx"
# Voting time in seconds
voting_time: 172800
# Logging setup
logging:

View File

@ -15,6 +15,7 @@ from nio import (
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
from vetting_bot.timer import Timer
logger = logging.getLogger(__name__)
@ -249,9 +250,16 @@ class Command:
await send_text_to_room(self.client, self.room.room_id, text)
return
voting_start_time = time.time()
self.store.cursor.execute(
"UPDATE vetting SET poll_event_id = ?, voting_start_time = ? WHERE mxid = ?",
(poll_resp.event_id, time.time(), vetted_user_id),
(poll_resp.event_id, voting_start_time, vetted_user_id),
)
timer = Timer(self.client, self.store, self.config)
await timer.wait_for_poll_end(
vetted_user_id, poll_resp.event_id, voting_start_time
)
async def _unknown_command(self):

View File

@ -115,6 +115,8 @@ class Config:
if not re.match("!.*:.*", self.vetting_space_id):
raise ConfigError("vetting.space_id must be in the form !xxx:domain")
self.voting_time = int(self._get_cfg(["vetting", "voting_time"], required=True))
def _get_cfg(
self,
path: List[str],

View File

@ -19,6 +19,7 @@ from nio import (
from vetting_bot.callbacks import Callbacks
from vetting_bot.config import Config
from vetting_bot.storage import Storage
from vetting_bot.timer import Timer
logger = logging.getLogger(__name__)
@ -108,6 +109,14 @@ async def main():
client.server = client.user_id.split(":", maxsplit=1)[1]
timer = Timer(client, store, config)
async def start_timer_with_delay():
await asyncio.sleep(5)
await timer.start_all_timers()
asyncio.create_task(start_timer_with_delay())
await client.sync_forever(timeout=30000, full_state=True)
except (ClientConnectionError, ServerDisconnectedError):

View File

@ -111,7 +111,8 @@ class Storage:
room_id VARCHAR(255) NOT NULL UNIQUE,
vetting_create_time INT(12),
voting_start_time INT(12),
poll_event_id VARCHAR(255)
poll_event_id VARCHAR(255),
vote_ended BOOLEAN NOT NULL DEFAULT FALSE
)
"""
)

71
vetting_bot/timer.py Normal file
View File

@ -0,0 +1,71 @@
import asyncio
import logging
import time
from nio import AsyncClient, RoomSendError
from vetting_bot.config import Config
from vetting_bot.storage import Storage
logger = logging.getLogger(__name__)
class Timer:
def __init__(
self,
client: AsyncClient,
store: Storage,
config: Config,
):
self.client = client
self.store = store
self.config = config
async def start_all_timers(self):
self.store.cursor.execute(
"""
SELECT mxid, poll_event_id, voting_start_time, vote_ended
FROM vetting
WHERE voting_start_time IS NOT NULL
"""
)
rows = self.store.cursor.fetchall()
for row in rows:
if row[3]:
continue
await self.wait_for_poll_end(
mxid=row[0], poll_event_id=row[1], start_time=row[2]
)
async def wait_for_poll_end(self, mxid: str, poll_event_id: str, start_time: int):
async def _task():
time_left = start_time + self.config.voting_time - time.time()
await asyncio.sleep(time_left)
await self._end_poll(mxid, poll_event_id)
asyncio.create_task(_task())
async def _end_poll(self, mxid: str, poll_event_id: str):
event_content = {
"m.relates_to": {
"rel_type": "m.reference",
"event_id": poll_event_id,
}
}
poll_resp = await self.client.room_send(
self.config.vetting_room_id,
message_type="org.matrix.msc3381.poll.end",
content=event_content,
)
if isinstance(poll_resp, RoomSendError):
logger.error(poll_resp, stack_info=True)
return
self.store.cursor.execute(
"UPDATE vetting SET vote_ended = 1 WHERE mxid = ?",
(mxid,),
)