diff --git a/Pipfile.lock b/Pipfile.lock
index 615d5a42b..91020093f 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "67adacda446396d91de50fe41c426c738226113aa0b3e3f16a00f2141ff7bc8a"
+ "sha256": "a187fb4a62ec0cc2dab78542af7c21eb559388bac49e0f84f35f656aa1e19200"
},
"pipfile-spec": 6,
"requires": {
diff --git a/server/exceptions.py b/server/exceptions.py
index ff7a7cc57..ad536fbff 100644
--- a/server/exceptions.py
+++ b/server/exceptions.py
@@ -2,10 +2,6 @@
Common exception definitions
"""
-import humanize
-
-from server.timing import datetime_now
-
class ClientError(Exception):
"""
@@ -33,21 +29,15 @@ def __init__(self, ban_expiry, ban_reason, *args, **kwargs):
def message(self):
return (
- f"You are banned from FAF {self._ban_duration_text()}.
"
- f"Reason:
{self.ban_reason}
"
- "If you would like to appeal this ban, please send an email to: "
- "moderation@faforever.com"
+ "User is banned until "
+ f"{self.ban_expiry.isoformat()} for reason: {self.ban_reason}"
)
- def _ban_duration_text(self):
- ban_duration = self.ban_expiry - datetime_now()
- if ban_duration.days > 365 * 100:
- return "forever"
- humanized_ban_duration = humanize.precisedelta(
- ban_duration,
- minimum_unit="hours"
- )
- return f"for {humanized_ban_duration}"
+ def response(self):
+ return {
+ "command": "banned",
+ "expires_at": self.ban_expiry.isoformat(),
+ }
class AuthenticationError(Exception):
diff --git a/server/lobbyconnection.py b/server/lobbyconnection.py
index 5b5ec2e10..2791c2e5a 100644
--- a/server/lobbyconnection.py
+++ b/server/lobbyconnection.py
@@ -222,11 +222,7 @@ async def on_message_received(self, message):
"text": e.message
})
except BanError as e:
- await self.send({
- "command": "notice",
- "style": "error",
- "text": e.message()
- })
+ await self.send(e.response())
await self.abort(e.message())
except ClientError as e:
self._logger.warning(
diff --git a/server/protocol/qdatastream.py b/server/protocol/qdatastream.py
index 999d2313c..6adea3227 100644
--- a/server/protocol/qdatastream.py
+++ b/server/protocol/qdatastream.py
@@ -92,7 +92,7 @@ def pack_message(*args: str) -> bytes:
raise NotImplementedError("Only string serialization is supported")
msg += QDataStreamProtocol.pack_qstring(arg)
- return QDataStreamProtocol.pack_block(msg)
+ return QDataStreamProtocol.pack_block(bytes(msg))
@staticmethod
def encode_message(message: dict) -> bytes:
diff --git a/tests/integration_tests/test_login.py b/tests/integration_tests/test_login.py
index 0d7c5c843..ae22bec16 100644
--- a/tests/integration_tests/test_login.py
+++ b/tests/integration_tests/test_login.py
@@ -1,3 +1,4 @@
+from datetime import datetime
from time import time
import jwt
@@ -38,15 +39,8 @@ async def test_server_ban(lobby_server, user):
proto = await connect_client(lobby_server)
await perform_login(proto, user)
msg = await proto.read_message()
- assert msg == {
- "command": "notice",
- "style": "error",
- "text": (
- "You are banned from FAF forever.
Reason:
Test permanent ban"
- "
If you would like to appeal this ban, please send an "
- "email to: moderation@faforever.com"
- )
- }
+ assert msg["command"] == "banned"
+ datetime.fromisoformat(msg["expires_at"])
@pytest.mark.parametrize("user", [
@@ -73,15 +67,8 @@ async def test_server_ban_token(lobby_server, user, jwk_priv_key, jwk_kid):
"unique_id": "some_id"
})
msg = await proto.read_message()
- assert msg == {
- "command": "notice",
- "style": "error",
- "text": (
- "You are banned from FAF forever.
Reason:
Test permanent ban"
- "
If you would like to appeal this ban, please send an "
- "email to: moderation@faforever.com"
- )
- }
+ assert msg["command"] == "banned"
+ datetime.fromisoformat(msg["expires_at"])
@pytest.mark.parametrize("user", ["ban_revoked", "ban_expired"])
diff --git a/tests/integration_tests/test_server.py b/tests/integration_tests/test_server.py
index ae00663bb..9a00b92e8 100644
--- a/tests/integration_tests/test_server.py
+++ b/tests/integration_tests/test_server.py
@@ -1,6 +1,7 @@
import asyncio
import contextlib
import re
+from datetime import datetime
import pytest
from sqlalchemy import and_, select
@@ -845,15 +846,8 @@ async def test_server_ban_prevents_hosting(lobby_server, database, command):
await proto.send_message({"command": command})
msg = await proto.read_message()
- assert msg == {
- "command": "notice",
- "style": "error",
- "text": (
- "You are banned from FAF forever.
Reason:
Test live ban
"
- "
If you would like to appeal this ban, please send an email "
- "to: moderation@faforever.com"
- )
- }
+ assert msg["command"] == "banned"
+ datetime.fromisoformat(msg["expires_at"])
@fast_forward(5)
diff --git a/tests/unit_tests/test_lobbyconnection.py b/tests/unit_tests/test_lobbyconnection.py
index ea764e84d..a77726f22 100644
--- a/tests/unit_tests/test_lobbyconnection.py
+++ b/tests/unit_tests/test_lobbyconnection.py
@@ -1,4 +1,4 @@
-import re
+from datetime import datetime
from hashlib import sha256
from unittest import mock
@@ -1303,18 +1303,14 @@ async def test_abort_connection_if_banned(
lobbyconnection.player.id = 203
with pytest.raises(BanError) as banned_error:
await lobbyconnection.abort_connection_if_banned()
- assert banned_error.value.message() == (
- "You are banned from FAF forever.
Reason:
Test permanent ban"
- "
If you would like to appeal this ban, please send an email "
- "to: moderation@faforever.com"
- )
+ response = banned_error.value.response()
+ assert response["command"] == "banned"
+ datetime.fromisoformat(response["expires_at"])
# test user who is banned for another 46 hours
lobbyconnection.player.id = 204
with pytest.raises(BanError) as banned_error:
await lobbyconnection.abort_connection_if_banned()
- assert re.match(
- r"You are banned from FAF for 1 day and 2[12]\.[0-9]+ hours.
"
- "Reason:
Test ongoing ban with 46 hours left",
- banned_error.value.message()
- )
+ response = banned_error.value.response()
+ assert response["command"] == "banned"
+ datetime.fromisoformat(response["expires_at"])