From 2b63bc46a7f6cfad855ed8b559c1322d3402a538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 11 Aug 2026 21:10:32 +0200 Subject: [PATCH] [Protocol] Add moderation investigation commands Adds the protocol layer for the moderation investigation suite: - Command_GetUserSessions/GetUserAlts/GetModeratorLastLogins/ResetUserPassword/RemoveUserAvatar (1013-1017) - Response extensions 1215-1219 with ServerInfo messages for sessions, alts, and staff logins - last_login on Response_ReportUserInfo and warning_il on Response_WarnList Took 2 minutes --- .../libcockatrice/protocol/pb/CMakeLists.txt | 8 ++++ .../protocol/pb/moderator_commands.proto | 40 +++++++++++++++++++ .../pb/response_moderator_last_logins.proto | 10 +++++ .../pb/response_remove_user_avatar.proto | 9 +++++ .../pb/response_report_user_info.proto | 2 + .../pb/response_reset_user_password.proto | 12 ++++++ .../protocol/pb/response_user_alts.proto | 10 +++++ .../protocol/pb/response_user_sessions.proto | 10 +++++ .../protocol/pb/response_warn_list.proto | 3 ++ .../pb/serverinfo_moderator_login.proto | 11 +++++ .../protocol/pb/serverinfo_user_alt.proto | 16 ++++++++ .../protocol/pb/serverinfo_user_session.proto | 14 +++++++ 12 files changed, 145 insertions(+) create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/response_moderator_last_logins.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/response_remove_user_avatar.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/response_reset_user_password.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/response_user_alts.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/response_user_sessions.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_moderator_login.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_alt.proto create mode 100644 libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_session.proto diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt index 13b9f9184..3a193ae3c 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt @@ -156,6 +156,11 @@ set(PROTO_FILES response_report_my_list.proto response_report_stats.proto response_report_user_info.proto + response_moderator_last_logins.proto + response_remove_user_avatar.proto + response_reset_user_password.proto + response_user_alts.proto + response_user_sessions.proto response_viewlog_history.proto response_warn_history.proto response_warn_list.proto @@ -171,6 +176,7 @@ set(PROTO_FILES serverinfo_deckstorage.proto serverinfo_game.proto serverinfo_gametype.proto + serverinfo_moderator_login.proto serverinfo_player.proto serverinfo_playerping.proto serverinfo_playerproperties.proto @@ -179,6 +185,8 @@ set(PROTO_FILES serverinfo_report.proto serverinfo_room.proto serverinfo_user.proto + serverinfo_user_alt.proto + serverinfo_user_session.proto serverinfo_warning.proto serverinfo_zone.proto session_commands.proto diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto index fbd179d2c..11d16e9a4 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/moderator_commands.proto @@ -14,6 +14,11 @@ message ModeratorCommand { ADD_CARD_ART_RULE = 1010; REMOVE_CARD_ART_RULE = 1011; LIST_CARD_ART_RULES = 1012; + GET_USER_SESSIONS = 1013; + GET_USER_ALTS = 1014; + GET_MODERATOR_LAST_LOGINS = 1015; + RESET_USER_PASSWORD = 1016; + REMOVE_USER_AVATAR = 1017; REPORT_LIST = 1200; REPORT_ASSIGN = 1201; REPORT_RESOLVE = 1202; @@ -141,3 +146,38 @@ message Command_ListCardArtRules { optional Command_ListCardArtRules ext = 1012; } } + +message Command_GetUserSessions { + extend ModeratorCommand { + optional Command_GetUserSessions ext = 1013; + } + optional string user_name = 1; + optional uint32 limit = 2 [default = 110]; +} + +message Command_GetUserAlts { + extend ModeratorCommand { + optional Command_GetUserAlts ext = 1014; + } + optional string user_name = 1; +} + +message Command_GetModeratorLastLogins { + extend ModeratorCommand { + optional Command_GetModeratorLastLogins ext = 1015; + } +} + +message Command_ResetUserPassword { + extend ModeratorCommand { + optional Command_ResetUserPassword ext = 1016; + } + optional string user_name = 1; +} + +message Command_RemoveUserAvatar { + extend ModeratorCommand { + optional Command_RemoveUserAvatar ext = 1017; + } + optional string user_name = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_moderator_last_logins.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_moderator_last_logins.proto new file mode 100644 index 000000000..6288880c4 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_moderator_last_logins.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +import "response.proto"; +import "serverinfo_moderator_login.proto"; + +message Response_ModeratorLastLogins { + extend Response { + optional Response_ModeratorLastLogins ext = 1217; + } + repeated ServerInfo_ModeratorLogin logins = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_remove_user_avatar.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_remove_user_avatar.proto new file mode 100644 index 000000000..e5697d4e0 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_remove_user_avatar.proto @@ -0,0 +1,9 @@ +syntax = "proto2"; +import "response.proto"; + +message Response_RemoveUserAvatar { + extend Response { + optional Response_RemoveUserAvatar ext = 1219; + } + optional string user_name = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_report_user_info.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_report_user_info.proto index b1cae8f3a..5f9e8ec38 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/response_report_user_info.proto +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_report_user_info.proto @@ -16,4 +16,6 @@ message Response_ReportUserInfo { optional bool is_active = 7; optional string admin_notes = 8; repeated ServerInfo_Report recent_reports = 9; + // Last known login of the user, epoch seconds; 0 = unknown. + optional int64 last_login = 10; } diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_reset_user_password.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_reset_user_password.proto new file mode 100644 index 000000000..aa379e573 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_reset_user_password.proto @@ -0,0 +1,12 @@ +syntax = "proto2"; +import "response.proto"; + +message Response_ResetUserPassword { + extend Response { + optional Response_ResetUserPassword ext = 1218; + } + optional string user_name = 1; + // The generated temporary password, shown to the moderator who + // requested the reset. The affected user must change it on first login. + optional string temporary_password = 2; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_alts.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_alts.proto new file mode 100644 index 000000000..6bc48d6cb --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_alts.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +import "response.proto"; +import "serverinfo_user_alt.proto"; + +message Response_UserAlts { + extend Response { + optional Response_UserAlts ext = 1216; + } + repeated ServerInfo_UserAlt alts = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_sessions.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_sessions.proto new file mode 100644 index 000000000..7174fd3f7 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_user_sessions.proto @@ -0,0 +1,10 @@ +syntax = "proto2"; +import "response.proto"; +import "serverinfo_user_session.proto"; + +message Response_UserSessions { + extend Response { + optional Response_UserSessions ext = 1215; + } + repeated ServerInfo_UserSession sessions = 1; +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/response_warn_list.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/response_warn_list.proto index d48352529..cddd08a51 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/response_warn_list.proto +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/response_warn_list.proto @@ -8,4 +8,7 @@ message Response_WarnList { repeated string warning = 1; optional string user_name = 2; optional string user_clientid = 3; + // Recommended starting intervention level per warning category, + // aligned by index with `warning`. Absent or shorter lists default to 1. + repeated uint32 warning_il = 4; } diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_moderator_login.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_moderator_login.proto new file mode 100644 index 000000000..21db2d3fa --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_moderator_login.proto @@ -0,0 +1,11 @@ +syntax = "proto2"; + +/** + * The last login date of a staff member (moderator/judge/admin). + * Used by the moderation "Moderator Last Logins" tool. + */ +message ServerInfo_ModeratorLogin { + optional string user_name = 1; // staff account name + optional uint64 last_login = 2; // last known login, epoch seconds; 0 = unknown + optional uint32 user_level = 3; // ServerInfo_User::UserLevelFlag mask (moderator/judge/admin) +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_alt.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_alt.proto new file mode 100644 index 000000000..191dd5063 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_alt.proto @@ -0,0 +1,16 @@ +syntax = "proto2"; + +/** + * An account that shares an IP address, client id or eMail address with + * the account being investigated. Used by the moderation "Get User Alts" tool. + */ +message ServerInfo_UserAlt { + optional string user_name = 1; // account name + optional string email = 2; // registration eMail + optional string clientid = 3; // client id + optional uint64 registration_time = 4; // account registration, epoch seconds + optional uint64 last_login = 5; // last known login, epoch seconds; 0 = unknown + optional uint32 warn_count = 6; // number of warnings on record + optional uint32 ban_count = 7; // number of bans on record + optional bool is_active = 8; // account is not deactivated/banned +} diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_session.proto b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_session.proto new file mode 100644 index 000000000..7ce240050 --- /dev/null +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/serverinfo_user_session.proto @@ -0,0 +1,14 @@ +syntax = "proto2"; + +/** + * A single login session of a user on the server, as stored in the + * sessions table. Used by the moderation "Get User Sessions" tool. + */ +message ServerInfo_UserSession { + optional string user_name = 1; // account that was logged in + optional string ip_address = 2; // IP address used for the session + optional string clientid = 3; // client id used for the session + optional uint64 start_time = 4; // session start, epoch seconds + optional uint64 end_time = 5; // session end, epoch seconds; 0 = still active + optional string connection_type = 6; // "tcp" or "websocket" +}