diff --git a/Content.Server/Administration/Managers/AdminManager.cs b/Content.Server/Administration/Managers/AdminManager.cs index 371755dcef4..585b5aed782 100644 --- a/Content.Server/Administration/Managers/AdminManager.cs +++ b/Content.Server/Administration/Managers/AdminManager.cs @@ -19,12 +19,13 @@ using Robust.Shared.Toolshed; using Robust.Shared.Toolshed.Errors; using Robust.Shared.Utility; - +using Content.Server.Andromeda.AdministrationNotifications.GameTicking; //A-13 AdminNotifications namespace Content.Server.Administration.Managers { public sealed partial class AdminManager : IAdminManager, IPostInjectInit, IConGroupControllerImplementation { + [Dependency] private readonly IEntityManager _entityManager = default!; //A-13 AdminNotifications [Dependency] private readonly IPlayerManager _playerManager = default!; [Dependency] private readonly IServerDbManager _dbManager = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; @@ -342,7 +343,7 @@ private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e) } else if (e.NewStatus == SessionStatus.Disconnected) { - if (_admins.Remove(e.Session, out var reg ) && _cfg.GetCVar(CCVars.AdminAnnounceLogout)) + if (_admins.TryGetValue(e.Session, out var reg ) && _cfg.GetCVar(CCVars.AdminAnnounceLogout)) //A-13 AdminNotifications { if (reg.Data.Stealth) { @@ -355,6 +356,12 @@ private void PlayerStatusChanged(object? sender, SessionStatusEventArgs e) _chat.SendAdminAnnouncement(Loc.GetString("admin-manager-admin-logout-message", ("name", e.Session.Name))); } + //A-13 AdminNotifications start + var logoutEvent = new AdminLoggedOutEvent(e.Session); + _entityManager.EventBus.RaiseEvent(EventSource.Local, logoutEvent); + + _admins.Remove(e.Session); + //A-13 AdminNotifications end } } } @@ -398,6 +405,10 @@ private async void LoginAdminMaybe(ICommonSession session) _chat.SendAdminAnnouncement(Loc.GetString("admin-manager-admin-login-message", ("name", session.Name))); } + //A-13 AdminNotifications start + var loginEvent = new AdminLoggedInEvent(session); + _entityManager.EventBus.RaiseEvent(EventSource.Local, loginEvent); + //A-13 AdminNotifications end } SendPermsChangedEvent(session); diff --git a/Content.Server/Andromeda/AdministrationNotifications/AdminNotificationsSystem.cs b/Content.Server/Andromeda/AdministrationNotifications/AdminNotificationsSystem.cs new file mode 100644 index 00000000000..fc8b6404afd --- /dev/null +++ b/Content.Server/Andromeda/AdministrationNotifications/AdminNotificationsSystem.cs @@ -0,0 +1,82 @@ +using Content.Shared.Administration; +using Robust.Shared; +using Robust.Shared.Configuration; +using Robust.Shared.Player; +using System.Net.Http; +using System.Text.Json; +using System.Text; +using Content.Server.Discord; +using Content.Shared.CCVar; +using Content.Shared.Andromeda.CCVar; +using Content.Server.Andromeda.AdministrationNotifications.GameTicking; + +namespace Content.Server.Andromeda.AdministrationNotifications +{ + + public sealed class AdminNotificationsSystem : EntitySystem + { + [Dependency] private readonly IConfigurationManager _config = default!; + private ISawmill _sawmill = default!; + private readonly HttpClient _httpClient = new(); + private string _webhookUrl = String.Empty; + private int _adminCount = 0; + + public override void Initialize() + { + _sawmill = Logger.GetSawmill("admin_notifications"); + SubscribeLocalEvent(OnAdminLoggedIn); + SubscribeLocalEvent(OnAdminLoggedOut); + _config.OnValueChanged(AndromedaCCVars.DiscordAdminWebhook, value => _webhookUrl = value, true); + } + + private async void SendDiscordMessage(WebhookPayload payload) + { + var request = await _httpClient.PostAsync(_webhookUrl, + new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json")); + + _sawmill.Debug($"Вебхук Discord в формате json: {JsonSerializer.Serialize(payload)}"); + + var content = await request.Content.ReadAsStringAsync(); + if (!request.IsSuccessStatusCode) + { + _sawmill.Error($"Discord вернул неверный код статуса при публикации сообщения: {request.StatusCode}\nResponse: {content}"); + return; + } + } + + private void OnAdminLoggedIn(AdminLoggedInEvent e) + { + _adminCount++; + SendAdminStatusUpdate(e.Session, "вошёл", 0x00FF00); + } + + private void OnAdminLoggedOut(AdminLoggedOutEvent e) + { + _adminCount--; + SendAdminStatusUpdate(e.Session, "вышел", 0xFF0000); + } + + private void SendAdminStatusUpdate(ICommonSession session, string action, int color) + { + if (String.IsNullOrEmpty(_webhookUrl)) + return; + + var message = $"{session.Name} {action}. Всего администраторов онлайн: {_adminCount}"; + + var payload = new WebhookPayload + { + Username = "Отчёт входов админов", + Embeds = new List + { + new() + { + Description = message, + Color = color, + }, + }, + }; + + SendDiscordMessage(payload); + } + } +} \ No newline at end of file diff --git a/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedEvent.cs b/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedEvent.cs new file mode 100644 index 00000000000..2f197cd61f1 --- /dev/null +++ b/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedEvent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Player; + +namespace Content.Server.Andromeda.AdministrationNotifications.GameTicking; + +public sealed class AdminLoggedInEvent : EntityEventArgs +{ + public ICommonSession Session { get; } + + public AdminLoggedInEvent(ICommonSession session) + { + Session = session; + } +} \ No newline at end of file diff --git a/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedOutEvent.cs b/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedOutEvent.cs new file mode 100644 index 00000000000..1710beba018 --- /dev/null +++ b/Content.Server/Andromeda/AdministrationNotifications/GameTicking/AdminLoggedOutEvent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Player; + +namespace Content.Server.Andromeda.AdministrationNotifications.GameTicking; + +public sealed class AdminLoggedOutEvent : EntityEventArgs +{ + public ICommonSession Session { get; } + + public AdminLoggedOutEvent(ICommonSession session) + { + Session = session; + } +} \ No newline at end of file diff --git a/Content.Shared/Andromeda/CCVar/CCVars.cs b/Content.Shared/Andromeda/CCVar/CCVars.cs index 6580f5deec7..c315f08586b 100644 --- a/Content.Shared/Andromeda/CCVar/CCVars.cs +++ b/Content.Shared/Andromeda/CCVar/CCVars.cs @@ -27,5 +27,8 @@ public sealed class AndromedaCCVars : CVars /// public static readonly CVarDef DiscordBanWebhook = CVarDef.Create("discord.ban_webhook", string.Empty, CVar.SERVERONLY); + + public static readonly CVarDef DiscordAdminWebhook = + CVarDef.Create("discord.admin_webhook", string.Empty, CVar.SERVERONLY); } }