Skip to content

Commit

Permalink
Ban Discord
Browse files Browse the repository at this point in the history
  • Loading branch information
xtray85 committed Nov 5, 2023
1 parent 59fc3f7 commit fa9a488
Show file tree
Hide file tree
Showing 3 changed files with 404 additions and 2 deletions.
125 changes: 125 additions & 0 deletions Content.Server/Administration/Commands/BanCommand.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Content.Server.Administration.Managers;
using Content.Server.Database;
using Content.Server.Discord;
using Content.Server.GameTicking;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Player;


namespace Content.Server.Administration.Commands;
Expand All @@ -18,14 +25,34 @@ public sealed class BanCommand : LocalizedCommands
[Dependency] private readonly IBanManager _bans = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;

private readonly HttpClient _httpClient = new();
public override string Command => "ban";

public override async void Execute(IConsoleShell shell, string argStr, string[] args)
{
string target;
string reason;
uint minutes;

var webhookUrl = _cfg.GetCVar(CCVars.DiscordBansWebhook);
var serverName = _cfg.GetCVar(CCVars.GameHostName);

serverName = serverName[..Math.Min(serverName.Length, 1500)];

var gameTicker = _entitySystemManager.GetEntitySystem<GameTicker>();
var round = gameTicker.RunLevel switch
{
GameRunLevel.PreRoundLobby => gameTicker.RoundId == 0
? "pre-round lobby after server restart" // first round after server restart has ID == 0
: $"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."),
};

if (!Enum.TryParse(_cfg.GetCVar(CCVars.ServerBanDefaultSeverity), out NoteSeverity severity))
{
Logger.WarningS("admin.server_ban", "Server ban severity could not be parsed from config! Defaulting to high.");
Expand Down Expand Up @@ -89,6 +116,38 @@ public override async void Execute(IConsoleShell shell, string argStr, string[]
var targetHWid = located.LastHWId;

_bans.CreateServerBan(targetUid, target, player?.UserId, null, targetHWid, minutes, severity, reason);

var banId = await _dbManager.GetLastServerBanId();

DateTimeOffset? expires = null;
if (minutes > 0)
{
expires = DateTimeOffset.Now + TimeSpan.FromMinutes(minutes);
}

if (webhookUrl != null)
{
var payload = new WebhookPayload
{
Username = "Это бан",
AvatarUrl = "",
Embeds = new List<WebhookEmbed>
{
new WebhookEmbed
{
Color = 0xff0000,
Description = GenerateBanDescription(banId, target, shell.Player, minutes, reason, expires),
Footer = new WebhookEmbedFooter
{
Text = $"{serverName} ({round})"
}
}
}
};

await _httpClient.PostAsync($"{webhookUrl}?wait=true",
new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"));
}
}

public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
Expand Down Expand Up @@ -132,4 +191,70 @@ public override CompletionResult GetCompletion(IConsoleShell shell, string[] arg

return CompletionResult.Empty;
}

private string GenerateBanDescription(int banId, string target, ICommonSession? player, uint minutes, string reason, DateTimeOffset? expires)
{
var builder = new StringBuilder();

builder.AppendLine($"### **Бан | ID {banId}**");
builder.AppendLine($"**Нарушитель:** *{target}*");
builder.AppendLine($"**Причина:** {reason}");

var banDuration = TimeSpan.FromMinutes(minutes);

builder.Append($"**Длительность:** ");

if (expires != null)
{
builder.Append($"{banDuration.Days} {NumWord(banDuration.Days, "день", "дня", "дней")}, ");
builder.Append($"{banDuration.Hours} {NumWord(banDuration.Hours, "час", "часа", "часов")}, ");
builder.AppendLine($"{banDuration.Minutes} {NumWord(banDuration.Minutes, "минута", "минуты", "минут")}");

}
else
{
builder.AppendLine($"***Навсегда***");
}

if (expires != null)
{
builder.AppendLine($"**Дата снятия наказания:** {expires}");
}

builder.Append($"**Наказание выдал(-а):** ");

if (player != null)
{
builder.AppendLine($"*{player.Name}*");
}
else
{
builder.AppendLine($"***СИСТЕМА***");
}

return builder.ToString();
}

private string NumWord(int value, params string[] words)
{
value = Math.Abs(value) % 100;
var num = value % 10;

if (value > 10 && value < 20)
{
return words[2];
}

if (value > 1 && value < 5)
{
return words[1];
}

if (num == 1)
{
return words[0];
}

return words[2];
}
}
151 changes: 149 additions & 2 deletions Content.Server/Administration/Commands/DepartmentBanCommand.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Content.Server.Administration.Managers;
using Content.Server.Database;
using Content.Server.Discord;
using Content.Server.Discord.Webhooks;
using Content.Server.GameTicking;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Content.Shared.Roles;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using WebhookPayload = Content.Server.Discord.WebhookPayload;

namespace Content.Server.Administration.Commands;

Expand All @@ -16,7 +25,10 @@ public sealed class DepartmentBanCommand : IConsoleCommand
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly IBanManager _banManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IServerDbManager _dbManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;

private readonly HttpClient _httpClient = new();
public string Command => "departmentban";
public string Description => Loc.GetString("cmd-departmentban-desc");
public string Help => Loc.GetString("cmd-departmentban-help");
Expand All @@ -27,9 +39,13 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args)
string department;
string reason;
uint minutes;
var webhookUrl = _cfg.GetCVar(CCVars.DiscordBansWebhook);
var serverName = _cfg.GetCVar(CCVars.GameHostName);

if (!Enum.TryParse(_cfg.GetCVar(CCVars.DepartmentBanDefaultSeverity), out NoteSeverity severity))
{
Logger.WarningS("admin.department_ban", "Department ban severity could not be parsed from config! Defaulting to medium.");
Logger.WarningS("admin.department_ban",
"Department ban severity could not be parsed from config! Defaulting to medium.");
severity = NoteSeverity.Medium;
}

Expand Down Expand Up @@ -77,6 +93,26 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args)
return;
}

var startRoleBanId = await _dbManager.GetLastServerRoleBanId() + 1;

DateTimeOffset? expires = null;
if (minutes > 0)
{
expires = DateTimeOffset.Now + TimeSpan.FromMinutes(minutes);
}

var gameTicker = _entitySystemManager.GetEntitySystem<GameTicker>();
var round = gameTicker.RunLevel switch
{
GameRunLevel.PreRoundLobby => gameTicker.RoundId == 0
? "pre-round lobby after server restart" // first round after server restart has ID == 0
: $"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."),
};

if (!_protoManager.TryIndex<DepartmentPrototype>(department, out var departmentProto))
{
return;
Expand All @@ -97,7 +133,50 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args)
var now = DateTimeOffset.UtcNow;
foreach (var job in departmentProto.Roles)
{
_banManager.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes, severity, reason, now);
_banManager.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes,
severity, reason, now);
}

if (webhookUrl != null)
{
var roleBanIdsString = "";

if (departmentProto.Roles != null && departmentProto.Roles.Count > 0)
{
int[] roleBanIds;
roleBanIds = new int[departmentProto.Roles.Count];
roleBanIds[0] = startRoleBanId;

for (var i = 1; i < roleBanIds.Length; i++)
{
roleBanIds[i] = roleBanIds[i - 1] + 1;
}

roleBanIdsString = string.Join(", ", roleBanIds);
}


var payload = new WebhookPayload
{
Username = "Это департмент-бан",
AvatarUrl = "",
Embeds = new List<WebhookEmbed>
{
new WebhookEmbed
{
Color = 0xffea00,
Description = GenerateBanDescription(roleBanIdsString, target, shell.Player, minutes, reason,
expires, department),
Footer = new WebhookEmbedFooter
{
Text = $"{serverName} ({round})"
}
}
}
};

await _httpClient.PostAsync($"{webhookUrl}?wait=true",
new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json"));
}
}

Expand Down Expand Up @@ -134,4 +213,72 @@ public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
};
}

private string GenerateBanDescription(string roleBanIdsString, string target, ICommonSession? session, uint minutes, string reason, DateTimeOffset? expires, string department)
{
var builder = new StringBuilder();

builder.AppendLine($"### **Департмент-бан | IDs {roleBanIdsString}**");
builder.AppendLine($"**Нарушитель:** *{target}*");
builder.AppendLine($"**Причина:** {reason}");

var banDuration = TimeSpan.FromMinutes(minutes);

builder.Append($"**Длительность:** ");

if (expires != null)
{
builder.Append($"{banDuration.Days} {NumWord(banDuration.Days, "день", "дня", "дней")}, ");
builder.Append($"{banDuration.Hours} {NumWord(banDuration.Hours, "час", "часа", "часов")}, ");
builder.AppendLine($"{banDuration.Minutes} {NumWord(banDuration.Minutes, "минута", "минуты", "минут")}");

}
else
{
builder.AppendLine($"***Навсегда***");
}

builder.AppendLine($"**Отдел:** {department}");

if (expires != null)
{
builder.AppendLine($"**Дата снятия наказания:** {expires}");
}

builder.Append($"**Наказание выдал(-а):** ");

if (session != null)
{
builder.AppendLine($"*{session.Name}*");
}
else
{
builder.AppendLine($"***СИСТЕМА***");
}

return builder.ToString();
}

private string NumWord(int value, params string[] words)
{
value = Math.Abs(value) % 100;
var num = value % 10;

if (value > 10 && value < 20)
{
return words[2];
}

if (value > 1 && value < 5)
{
return words[1];
}

if (num == 1)
{
return words[0];
}

return words[2];
}

}
Loading

0 comments on commit fa9a488

Please sign in to comment.