From 0f1cbb58675247ad9a291a8701e68a2ac02ad8fa Mon Sep 17 00:00:00 2001
From: dinhkien0701 <24021540@vnu.edu.vn>
Date: Tue, 12 May 2026 20:56:37 +0700
Subject: [PATCH 1/3] Add localizable metadata to ban notice
---
server/exceptions.py | 20 +++++++++++++++++---
server/lobbyconnection.py | 10 +++++++---
tests/integration_tests/test_login.py | 16 ++++++++++++++--
tests/integration_tests/test_server.py | 8 +++++++-
4 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/server/exceptions.py b/server/exceptions.py
index ff7a7cc57..7854332bf 100644
--- a/server/exceptions.py
+++ b/server/exceptions.py
@@ -6,6 +6,9 @@
from server.timing import datetime_now
+BAN_NOTICE_I18N_KEY = "notice.ban"
+BAN_APPEAL_EMAIL = "moderation@faforever.com"
+
class ClientError(Exception):
"""
@@ -31,12 +34,23 @@ def __init__(self, ban_expiry, ban_reason, *args, **kwargs):
self.ban_expiry = ban_expiry
self.ban_reason = ban_reason
+ def localization(self):
+ return {
+ "i18n_key": BAN_NOTICE_I18N_KEY,
+ "i18n_args": {
+ "duration": self._ban_duration_text(),
+ "reason": self.ban_reason,
+ "appeal_email": BAN_APPEAL_EMAIL
+ }
+ }
+
def message(self):
+ data = self.localization()["i18n_args"]
return (
- f"You are banned from FAF {self._ban_duration_text()}.
"
- f"Reason:
{self.ban_reason}
"
+ f"You are banned from FAF {data['duration']}.
"
+ f"Reason:
{data['reason']}
"
"If you would like to appeal this ban, please send an email to: "
- "moderation@faforever.com"
+ f"{data['appeal_email']}"
)
def _ban_duration_text(self):
diff --git a/server/lobbyconnection.py b/server/lobbyconnection.py
index 5b5ec2e10..476a2eff0 100644
--- a/server/lobbyconnection.py
+++ b/server/lobbyconnection.py
@@ -222,12 +222,16 @@ async def on_message_received(self, message):
"text": e.message
})
except BanError as e:
- await self.send({
+ ban_notice = {
"command": "notice",
"style": "error",
- "text": e.message()
+ "text": e.message(),
+ **e.localization()
+ }
+ await self.send({
+ **ban_notice
})
- await self.abort(e.message())
+ await self.abort(ban_notice["text"])
except ClientError as e:
self._logger.warning(
"ClientError[%s]: %s",
diff --git a/tests/integration_tests/test_login.py b/tests/integration_tests/test_login.py
index 0d7c5c843..2a631ad32 100644
--- a/tests/integration_tests/test_login.py
+++ b/tests/integration_tests/test_login.py
@@ -45,7 +45,13 @@ async def test_server_ban(lobby_server, user):
"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"
- )
+ ),
+ "i18n_key": "notice.ban",
+ "i18n_args": {
+ "duration": "forever",
+ "reason": "Test permanent ban",
+ "appeal_email": "moderation@faforever.com"
+ }
}
@@ -80,7 +86,13 @@ async def test_server_ban_token(lobby_server, user, jwk_priv_key, jwk_kid):
"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"
- )
+ ),
+ "i18n_key": "notice.ban",
+ "i18n_args": {
+ "duration": "forever",
+ "reason": "Test permanent ban",
+ "appeal_email": "moderation@faforever.com"
+ }
}
diff --git a/tests/integration_tests/test_server.py b/tests/integration_tests/test_server.py
index ae00663bb..fe4f9ccf2 100644
--- a/tests/integration_tests/test_server.py
+++ b/tests/integration_tests/test_server.py
@@ -852,7 +852,13 @@ async def test_server_ban_prevents_hosting(lobby_server, database, command):
"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"
- )
+ ),
+ "i18n_key": "notice.ban",
+ "i18n_args": {
+ "duration": "forever",
+ "reason": "Test live ban",
+ "appeal_email": "moderation@faforever.com"
+ }
}
From 6baab4c9b0a957803462bc4f5e2a86265c56778b Mon Sep 17 00:00:00 2001
From: dinhkien0701 <24021540@vnu.edu.vn>
Date: Tue, 12 May 2026 21:34:36 +0700
Subject: [PATCH 2/3] Fix mypy arg type in QDataStream pack_message
---
server/protocol/qdatastream.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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:
From 7ab837e568da5cbd3a38995a6852ce4de773a1aa Mon Sep 17 00:00:00 2001
From: dinhkien0701 <24021540@vnu.edu.vn>
Date: Tue, 12 May 2026 21:45:59 +0700
Subject: [PATCH 3/3] Update Pipfile.lock hash for pipenv verify
---
Pipfile.lock | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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": {