From 24d091c163b6fdfb2ea999074726dacaf99d8318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schr=C3=B6dinger?= <132720404+Schrodinger71@users.noreply.github.com> Date: Sun, 29 Dec 2024 01:31:59 +0300 Subject: [PATCH 1/3] =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= =?UTF-8?q?,=20=D0=B1=D1=83=D0=B4=D0=B5=D1=82=20=D0=BF=D1=80=D0=B8=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D1=82=D1=8C=20=D1=81=D0=BE=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2?= =?UTF-8?q?=D1=83=D1=8E=D1=89=D0=B5=D0=B5=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D0=B4=D0=B8=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D0=B4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ServerUpdates/ServerUpdateManager.cs | 77 +++++++++++++++++++ .../ADT/CCVar/CCVars.WebhookDiscord.cs | 6 ++ 2 files changed, 83 insertions(+) diff --git a/Content.Server/ServerUpdates/ServerUpdateManager.cs b/Content.Server/ServerUpdates/ServerUpdateManager.cs index bf18428e25b..b18544daf0f 100644 --- a/Content.Server/ServerUpdates/ServerUpdateManager.cs +++ b/Content.Server/ServerUpdates/ServerUpdateManager.cs @@ -8,6 +8,9 @@ using Robust.Shared.Enums; using Robust.Shared.Player; using Robust.Shared.Timing; +using Content.Shared.ADT.CCVar; +using Content.Server.Discord; +using Content.Server.GameTicking; namespace Content.Server.ServerUpdates; @@ -27,6 +30,8 @@ public sealed class ServerUpdateManager : IPostInjectInit [Dependency] private readonly IBaseServer _server = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [Dependency] private readonly ILogManager _logManager = default!; + [Dependency] private readonly DiscordWebhook _discord = default!; + [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; private ISawmill _sawmill = default!; @@ -102,6 +107,7 @@ private void WatchdogOnUpdateReceived() _chatManager.DispatchServerAnnouncement(Loc.GetString("server-updates-received")); _updateOnRoundEnd = true; ServerEmptyUpdateRestartCheck("update notification"); + SendDiscordWebHookUpdateMessage(); // ADT-Tweak } /// @@ -148,4 +154,75 @@ void IPostInjectInit.PostInject() { _sawmill = _logManager.GetSawmill("restart"); } + // ADT-Tweak-start: Отправка сообщения в Discord при обновлении сервера + public async void SendDiscordWebHookUpdateMessage() + { + + if (!string.IsNullOrWhiteSpace(_cfg.GetCVar(ADTDiscordWebhookCCVars.DiscordServerUpdateWebhook))) + { + var webhookUrl = _cfg.GetCVar(ADTDiscordWebhookCCVars.DiscordServerUpdateWebhook); + if (webhookUrl == null) + return; + + if (await _discord.GetWebhook(webhookUrl) is not { } webhookData) + return; + + var serverName = _cfg.GetCVar("game.hostname"); + var serverDesc = _cfg.GetCVar("game.desc"); + var engineVersion = _cfg.GetCVar("build.engine_version"); + var buildVersion = _cfg.GetCVar("build.version"); + + var descContent = "Обновление получено, сервер автоматически перезапустится для обновления в конце этого раунда."; + + var gameTicker = _entitySystemManager.GetEntitySystem(); + var roundDescription = gameTicker.RunLevel switch + { + GameRunLevel.PreRoundLobby => gameTicker.RoundId == 0 + ? "pre-round lobby after server restart" + : $"pre-round lobby for round {gameTicker.RoundId + 1}", + GameRunLevel.InRound => $"round {gameTicker.RoundId}", + GameRunLevel.PostRound => $"post-round {gameTicker.RoundId}", + _ => throw new ArgumentOutOfRangeException(nameof(gameTicker.RunLevel), $"{gameTicker.RunLevel} was not matched."), + }; + + // Создание структуры сообщения для вебхука + var embed = new WebhookEmbed + { + Title = "Обновление пришло", + Description = descContent, + Color = 0x0e9c00, + Footer = new WebhookEmbedFooter + { + Text = $"{serverName} ({roundDescription})" + }, + Fields = new List() + }; + + // Добавление полей только если данные доступны + if (!string.IsNullOrWhiteSpace(serverName)) + embed.Fields.Add(new WebhookEmbedField { Name = "Название сервера", Value = serverName, Inline = true }); + + if (!string.IsNullOrWhiteSpace(serverDesc)) + embed.Fields.Add(new WebhookEmbedField { Name = "Описание сервера", Value = serverDesc, Inline = true }); + + if (!string.IsNullOrWhiteSpace(engineVersion)) + embed.Fields.Add(new WebhookEmbedField { Name = "RobustToolbox version", Value = engineVersion, Inline = true }); + + if (!string.IsNullOrWhiteSpace(buildVersion)) + embed.Fields.Add(new WebhookEmbedField { Name = "Build version", Value = buildVersion, Inline = true }); + + var payload = new WebhookPayload + { + Embeds = new List { embed }, + Username = Loc.GetString("username-webhook-update") + }; + + // Отправка сообщения в Discord + var identifier = webhookData.ToIdentifier(); + await _discord.CreateMessage(identifier, payload); + } + } + // ADT-Tweak-end } + + diff --git a/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs b/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs index 3924fee9abb..c933cf80dd2 100644 --- a/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs +++ b/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs @@ -11,4 +11,10 @@ public sealed class ADTDiscordWebhookCCVars : CVars /// public static readonly CVarDef DiscordAdminwhoWebhook = CVarDef.Create("discord.adminwho_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// This constant specifies a webhook that will send a message to Discord when a server updates. + /// + public static readonly CVarDef DiscordServerUpdateWebhook = + CVarDef.Create("discord.server_update_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); } From 0a6768c138c17f11767f9d3630daadd32d9819e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schr=C3=B6dinger?= <132720404+Schrodinger71@users.noreply.github.com> Date: Sun, 29 Dec 2024 03:13:53 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B=20=D0=B8=20?= =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=20+=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=20=D0=B4=D0=BB=D1=8F=20=D0=BF?= =?UTF-8?q?=D0=B8=D0=BD=D0=B3=D0=B0=20=D0=B2=20=D0=B4=D1=81=20=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=20=D0=BD=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Commands/SendUpdateServerCommand.cs | 26 ++++++++++++ .../ServerUpdates/ServerUpdateManager.cs | 42 ++++++++++++------- .../ADT/CCVar/CCVars.WebhookDiscord.cs | 12 +++++- 3 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 Content.Server/ADT/Administration/Commands/SendUpdateServerCommand.cs diff --git a/Content.Server/ADT/Administration/Commands/SendUpdateServerCommand.cs b/Content.Server/ADT/Administration/Commands/SendUpdateServerCommand.cs new file mode 100644 index 00000000000..74c294afda1 --- /dev/null +++ b/Content.Server/ADT/Administration/Commands/SendUpdateServerCommand.cs @@ -0,0 +1,26 @@ +using Content.Shared.Administration; +using Robust.Shared.Console; +using Content.Server.Administration; +using Content.Server.ServerUpdates; + +namespace Content.Server.ADT.Administration.Commands; + + +[AdminCommand(AdminFlags.Permissions)] +public sealed class SendUpdateServerCommand : LocalizedCommands +{ + [Dependency] private readonly ServerUpdateManager _serverManager = default!; + public override string Command => "send_updateserver_devtest"; + + public override async void Execute(IConsoleShell shell, string argStr, string[] args) + { + var player = shell.Player; + if (player == null) + { + shell.WriteError(LocalizationManager.GetString("shell-target-player-does-not-exist")); + return; + } + + _serverManager.SendDiscordWebHookUpdateMessage(); + } +} diff --git a/Content.Server/ServerUpdates/ServerUpdateManager.cs b/Content.Server/ServerUpdates/ServerUpdateManager.cs index b18544daf0f..2fc6d3f2fb8 100644 --- a/Content.Server/ServerUpdates/ServerUpdateManager.cs +++ b/Content.Server/ServerUpdates/ServerUpdateManager.cs @@ -157,7 +157,6 @@ void IPostInjectInit.PostInject() // ADT-Tweak-start: Отправка сообщения в Discord при обновлении сервера public async void SendDiscordWebHookUpdateMessage() { - if (!string.IsNullOrWhiteSpace(_cfg.GetCVar(ADTDiscordWebhookCCVars.DiscordServerUpdateWebhook))) { var webhookUrl = _cfg.GetCVar(ADTDiscordWebhookCCVars.DiscordServerUpdateWebhook); @@ -167,13 +166,16 @@ public async void SendDiscordWebHookUpdateMessage() if (await _discord.GetWebhook(webhookUrl) is not { } webhookData) return; + // Получение данных сервера var serverName = _cfg.GetCVar("game.hostname"); var serverDesc = _cfg.GetCVar("game.desc"); var engineVersion = _cfg.GetCVar("build.engine_version"); var buildVersion = _cfg.GetCVar("build.version"); + // Сообщение о перезапуске сервера var descContent = "Обновление получено, сервер автоматически перезапустится для обновления в конце этого раунда."; + // Определение состояния раунда var gameTicker = _entitySystemManager.GetEntitySystem(); var roundDescription = gameTicker.RunLevel switch { @@ -185,7 +187,7 @@ public async void SendDiscordWebHookUpdateMessage() _ => throw new ArgumentOutOfRangeException(nameof(gameTicker.RunLevel), $"{gameTicker.RunLevel} was not matched."), }; - // Создание структуры сообщения для вебхука + // Формирование структуры embed var embed = new WebhookEmbed { Title = "Обновление пришло", @@ -198,30 +200,42 @@ public async void SendDiscordWebHookUpdateMessage() Fields = new List() }; - // Добавление полей только если данные доступны - if (!string.IsNullOrWhiteSpace(serverName)) - embed.Fields.Add(new WebhookEmbedField { Name = "Название сервера", Value = serverName, Inline = true }); - - if (!string.IsNullOrWhiteSpace(serverDesc)) - embed.Fields.Add(new WebhookEmbedField { Name = "Описание сервера", Value = serverDesc, Inline = true }); - - if (!string.IsNullOrWhiteSpace(engineVersion)) - embed.Fields.Add(new WebhookEmbedField { Name = "RobustToolbox version", Value = engineVersion, Inline = true }); - - if (!string.IsNullOrWhiteSpace(buildVersion)) - embed.Fields.Add(new WebhookEmbedField { Name = "Build version", Value = buildVersion, Inline = true }); + // Добавление полей только если они не пустые + AddIfNotEmpty(embed.Fields, "Название сервера", serverName); + AddIfNotEmpty(embed.Fields, "Описание сервера", serverDesc); + AddIfNotEmpty(embed.Fields, "RobustToolbox version", engineVersion); + AddIfNotEmpty(embed.Fields, "Build version", buildVersion); + // Формирование полезной нагрузки var payload = new WebhookPayload { Embeds = new List { embed }, Username = Loc.GetString("username-webhook-update") }; + // Проверка, нужно ли добавлять пинг + var shouldPingOnUpdate = _cfg.GetCVar(ADTDiscordWebhookCCVars.ShouldPingOnUpdate); + if (shouldPingOnUpdate) + { + // Добавляем пинг в поле Content. Это будет сообщение, которое будет сверху + payload.Content = "<@&1275740664264659017>"; // ID роли "Обновления" + } + // Отправка сообщения в Discord var identifier = webhookData.ToIdentifier(); + payload.AllowedMentions.AllowRoleMentions(); await _discord.CreateMessage(identifier, payload); } } + + // Вспомогательный метод для добавления полей в embed + private void AddIfNotEmpty(List fields, string fieldName, string? fieldValue) + { + if (!string.IsNullOrWhiteSpace(fieldValue)) + { + fields.Add(new WebhookEmbedField { Name = fieldName, Value = fieldValue, Inline = true }); + } + } // ADT-Tweak-end } diff --git a/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs b/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs index c933cf80dd2..e27a7c4a2ba 100644 --- a/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs +++ b/Content.Shared/ADT/CCVar/CCVars.WebhookDiscord.cs @@ -10,11 +10,19 @@ public sealed class ADTDiscordWebhookCCVars : CVars /// URL of the Discord webhook which will relay adminwho info to the channel. /// public static readonly CVarDef DiscordAdminwhoWebhook = - CVarDef.Create("discord.adminwho_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + CVarDef.Create("discord.adminwho_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL | CVar.ARCHIVE); /// /// This constant specifies a webhook that will send a message to Discord when a server updates. /// public static readonly CVarDef DiscordServerUpdateWebhook = - CVarDef.Create("discord.server_update_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + CVarDef.Create("discord.server_update_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL | CVar.ARCHIVE); + + /// + /// This constant specifies whether a ping should be sent to a specific Discord role + /// when the server update notification is triggered. If set to true, a ping will be sent to the role. + /// If set to false, no ping will be sent. + /// + public static readonly CVarDef ShouldPingOnUpdate = + CVarDef.Create("discord.server_update_webhook_ping", true, CVar.SERVERONLY | CVar.ARCHIVE); } From 72679985ed5dc282303e73ee4bc07378cc2c3074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Schr=C3=B6dinger?= <132720404+Schrodinger71@users.noreply.github.com> Date: Sun, 29 Dec 2024 03:50:59 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D1=83=D0=B4=D0=BE=D0=BB=D0=B8=D0=BB=20"\n"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Content.Server/ServerUpdates/ServerUpdateManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Server/ServerUpdates/ServerUpdateManager.cs b/Content.Server/ServerUpdates/ServerUpdateManager.cs index 2fc6d3f2fb8..a333a7fcccd 100644 --- a/Content.Server/ServerUpdates/ServerUpdateManager.cs +++ b/Content.Server/ServerUpdates/ServerUpdateManager.cs @@ -238,5 +238,3 @@ private void AddIfNotEmpty(List fields, string fieldName, str } // ADT-Tweak-end } - -