Skip to content

Commit

Permalink
!mp timer command implementation (#142)
Browse files Browse the repository at this point in the history
* !mp timer command implementation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix assert error when match is closed and timer is still running

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
lenforiee and pre-commit-ci[bot] authored May 25, 2024
1 parent a4fc529 commit bd8a063
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
106 changes: 106 additions & 0 deletions constants/chatbotCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2399,6 +2399,111 @@ async def mp_link(user_token: osuToken.Token) -> str | None:

return message

async def mp_timer(user_token: osuToken.Token) -> str | None:
if not user_token["match_id"]:
return None

multiplayer_match = await match.get_match(user_token["match_id"])
if multiplayer_match is None:
return None

referees = await match.get_referees(multiplayer_match["match_id"])
if user_token["user_id"] not in referees:
return None

if len(message) < 2:
raise exceptions.invalidArgumentsException(
"Incorrect syntax: !mp timer <time (in seconds)/stop>.",
)

if message[1] == "stop":
await match.update_match(
multiplayer_match["match_id"],
is_timer_running=False,
)
return "Countdown stopped."

if multiplayer_match["is_timer_running"]:
return "A countdown is already running."

if not message[1].isnumeric():
raise exceptions.invalidArgumentsException(
"Incorrect syntax: !mp timer <time (in seconds)/stop>.",
)
countdown_time = int(message[1])

if countdown_time < 1:
raise exceptions.invalidArgumentsException(
"Countdown time must be at least 1 second.",
)

if countdown_time > 300: # 5 mins
raise exceptions.invalidArgumentsException(
"Countdown time must be less than 5 minutes.",
)

def _get_countdown_message(t: int, force: bool = False) -> str | None:
minutes, seconds = divmod(t, 60)
if minutes > 0 and not seconds:
return f"Countdown ends in {minutes} minute(s)"

_, unit_digit = divmod(seconds, 10)
if force or (
not minutes and seconds <= 30 and (not unit_digit or seconds <= 5)
):
return f"Countdown ends in {seconds} second(s)"

return None

async def _decreaseTimer(t: int) -> None:
chatbot_token = await osuToken.get_token_by_user_id(CHATBOT_USER_ID)
assert chatbot_token is not None

multi_match = await match.get_match(multiplayer_match["match_id"])
if multi_match is None:
return # the match is gone

if not multi_match["is_timer_running"]:
return

if t <= 0:
await match.update_match(
multiplayer_match["match_id"],
is_timer_running=False,
)
await chat.send_message(
sender_token_id=chatbot_token["token_id"],
recipient_name=chan,
message=f"Countdown finished.",
)
return

message = _get_countdown_message(t)
if message:
await chat.send_message(
sender_token_id=chatbot_token["token_id"],
recipient_name=chan,
message=message,
)

loop = asyncio.get_running_loop()
loop.call_later(
1.00,
lambda: asyncio.create_task(_decreaseTimer(t - 1)),
)

await match.update_match(
multiplayer_match["match_id"],
is_timer_running=True,
)

loop = asyncio.get_running_loop()
loop.call_later(
1.00,
lambda: asyncio.create_task(_decreaseTimer(countdown_time - 1)),
)
return _get_countdown_message(countdown_time, True)

try:
subcommands: dict[str, Callable[[osuToken.Token], Awaitable[str | None]]] = {
"addref": mpAddReferee,
Expand Down Expand Up @@ -2426,6 +2531,7 @@ async def mp_link(user_token: osuToken.Token) -> str | None:
"scorev": mpScoreV,
"help": mpHelp,
"link": mp_link,
"timer": mp_timer,
}

requestedSubcommand = message[0].lower().strip()
Expand Down
6 changes: 6 additions & 0 deletions objects/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Match(TypedDict):
is_tourney: bool
is_locked: bool
is_starting: bool
is_timer_running: bool
is_in_progress: bool
creation_time: float

Expand Down Expand Up @@ -87,6 +88,7 @@ async def create_match(
is_tourney: bool,
is_locked: bool,
is_starting: bool,
is_timer_running: bool,
is_in_progress: bool,
creation_time: float,
current_game_id: int,
Expand Down Expand Up @@ -119,6 +121,7 @@ async def create_match(
"is_tourney": is_tourney,
"is_locked": is_locked,
"is_starting": is_starting,
"is_timer_running": is_timer_running,
"is_in_progress": is_in_progress,
"creation_time": creation_time,
"match_history_private": match_history_private,
Expand Down Expand Up @@ -159,6 +162,7 @@ async def update_match(
is_tourney: bool | None = None,
is_locked: bool | None = None,
is_starting: bool | None = None,
is_timer_running: bool | None = None,
is_in_progress: bool | None = None,
creation_time: float | None = None,
game_id: int | None = None,
Expand Down Expand Up @@ -200,6 +204,8 @@ async def update_match(
match["is_locked"] = is_locked
if is_starting is not None:
match["is_starting"] = is_starting
if is_timer_running is not None:
match["is_timer_running"] = is_timer_running
if is_in_progress is not None:
match["is_in_progress"] = is_in_progress
if creation_time is not None:
Expand Down
1 change: 1 addition & 0 deletions objects/matchList.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ async def createMatch(
is_tourney=is_tourney,
is_locked=False,
is_starting=False,
is_timer_running=False,
is_in_progress=False,
creation_time=time(),
current_game_id=0,
Expand Down

0 comments on commit bd8a063

Please sign in to comment.