Add webhook for votekicks (#32513)

* Initial commit

* Localization
This commit is contained in:
SlamBamActionman
2024-09-29 15:23:53 +02:00
committed by GitHub
parent cc9202bbb2
commit d0c4d5a93a
7 changed files with 224 additions and 170 deletions

View File

@@ -1,11 +1,8 @@
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using Content.Server.Administration;
using Content.Server.Administration.Logs;
using Content.Server.Chat.Managers;
using Content.Server.Discord;
using Content.Server.GameTicking;
using Content.Server.Discord.WebhookMessages;
using Content.Server.Voting.Managers;
using Content.Shared.Administration;
using Content.Shared.CCVar;
@@ -76,11 +73,9 @@ namespace Content.Server.Voting
{
[Dependency] private readonly IVoteManager _voteManager = default!;
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly DiscordWebhook _discord = default!;
[Dependency] private readonly GameTicker _gameTicker = default!;
[Dependency] private readonly IBaseServer _baseServer = default!;
[Dependency] private readonly IChatManager _chatManager = default!;
[Dependency] private readonly VoteWebhooks _voteWebhooks = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
private ISawmill _sawmill = default!;
@@ -120,7 +115,7 @@ namespace Content.Server.Voting
var vote = _voteManager.CreateVote(options);
var webhookState = CreateWebhookIfConfigured(options);
var webhookState = _voteWebhooks.CreateWebhookIfConfigured(options, _cfg.GetCVar(CCVars.DiscordVoteWebhook));
vote.OnFinished += (_, eventArgs) =>
{
@@ -136,12 +131,12 @@ namespace Content.Server.Voting
_chatManager.DispatchServerAnnouncement(Loc.GetString("cmd-customvote-on-finished-win", ("winner", args[(int) eventArgs.Winner])));
}
UpdateWebhookIfConfigured(webhookState, eventArgs);
_voteWebhooks.UpdateWebhookIfConfigured(webhookState, eventArgs);
};
vote.OnCancelled += _ =>
{
UpdateCancelledWebhookIfConfigured(webhookState);
_voteWebhooks.UpdateCancelledWebhookIfConfigured(webhookState);
};
}
@@ -156,159 +151,6 @@ namespace Content.Server.Voting
var n = args.Length - 1;
return CompletionResult.FromHint(Loc.GetString("cmd-customvote-arg-option-n", ("n", n)));
}
private WebhookState? CreateWebhookIfConfigured(VoteOptions voteOptions)
{
// All this webhook code is complete garbage.
// I tried to clean it up somewhat, at least to fix the glaring bugs in it.
// Jesus christ man what is with our code review process.
var webhookUrl = _cfg.GetCVar(CCVars.DiscordVoteWebhook);
if (string.IsNullOrEmpty(webhookUrl))
return null;
// Set up the webhook payload
var serverName = _baseServer.ServerName;
var fields = new List<WebhookEmbedField>();
foreach (var voteOption in voteOptions.Options)
{
var newVote = new WebhookEmbedField
{
Name = voteOption.text,
Value = Loc.GetString("custom-vote-webhook-option-pending")
};
fields.Add(newVote);
}
var runLevel = Loc.GetString($"game-run-level-{_gameTicker.RunLevel}");
var payload = new WebhookPayload()
{
Username = Loc.GetString("custom-vote-webhook-name"),
Embeds = new List<WebhookEmbed>
{
new()
{
Title = voteOptions.InitiatorText,
Color = 13438992, // #CD1010
Description = voteOptions.Title,
Footer = new WebhookEmbedFooter
{
Text = Loc.GetString(
"custom-vote-webhook-footer",
("serverName", serverName),
("roundId", _gameTicker.RoundId),
("runLevel", runLevel)),
},
Fields = fields,
},
},
};
var state = new WebhookState
{
WebhookUrl = webhookUrl,
Payload = payload,
};
CreateWebhookMessage(state, payload);
return state;
}
private void UpdateWebhookIfConfigured(WebhookState? state, VoteFinishedEventArgs finished)
{
if (state == null)
return;
var embed = state.Payload.Embeds![0];
embed.Color = 2353993; // #23EB49
for (var i = 0; i < finished.Votes.Count; i++)
{
var oldName = embed.Fields[i].Name;
var newValue = finished.Votes[i].ToString();
embed.Fields[i] = new WebhookEmbedField { Name = oldName, Value = newValue, Inline = true};
}
state.Payload.Embeds[0] = embed;
UpdateWebhookMessage(state, state.Payload, state.MessageId);
}
private void UpdateCancelledWebhookIfConfigured(WebhookState? state)
{
if (state == null)
return;
var embed = state.Payload.Embeds![0];
embed.Color = 13356304; // #CBCD10
embed.Description += "\n\n" + Loc.GetString("custom-vote-webhook-cancelled");
for (var i = 0; i < embed.Fields.Count; i++)
{
var oldName = embed.Fields[i].Name;
embed.Fields[i] = new WebhookEmbedField { Name = oldName, Value = Loc.GetString("custom-vote-webhook-option-cancelled"), Inline = true};
}
state.Payload.Embeds[0] = embed;
UpdateWebhookMessage(state, state.Payload, state.MessageId);
}
// Sends the payload's message.
private async void CreateWebhookMessage(WebhookState state, WebhookPayload payload)
{
try
{
if (await _discord.GetWebhook(state.WebhookUrl) is not { } identifier)
return;
state.Identifier = identifier.ToIdentifier();
_sawmill.Debug(JsonSerializer.Serialize(payload));
var request = await _discord.CreateMessage(identifier.ToIdentifier(), payload);
var content = await request.Content.ReadAsStringAsync();
state.MessageId = ulong.Parse(JsonNode.Parse(content)?["id"]!.GetValue<string>()!);
}
catch (Exception e)
{
_sawmill.Error($"Error while sending vote webhook to Discord: {e}");
}
}
// Edits a pre-existing payload message, given an ID
private async void UpdateWebhookMessage(WebhookState state, WebhookPayload payload, ulong id)
{
if (state.MessageId == 0)
{
_sawmill.Warning("Failed to deliver update to custom vote webhook: message ID was zero. This likely indicates a previous connection error sending the original message.");
return;
}
DebugTools.Assert(state.Identifier != default);
try
{
await _discord.EditMessage(state.Identifier, id, payload);
}
catch (Exception e)
{
_sawmill.Error($"Error while updating vote webhook on Discord: {e}");
}
}
private sealed class WebhookState
{
public required string WebhookUrl;
public required WebhookPayload Payload;
public WebhookIdentifier Identifier;
public ulong MessageId;
}
}
[AnyCommand]