Better notes and bans (#14228)

Co-authored-by: Chief-Engineer <119664036+Chief-Engineer@users.noreply.github.com>
This commit is contained in:
Riggle
2023-07-21 13:38:52 +02:00
committed by GitHub
parent c6cb6ad928
commit 579913b617
84 changed files with 9820 additions and 886 deletions

View File

@@ -2,144 +2,141 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Content.Server.Administration.Managers;
using Content.Server.Administration.Notes;
using Content.Server.Database;
using Content.Server.GameTicking;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Content.Shared.Players.PlayTimeTracking;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
namespace Content.Server.Administration.Commands
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Ban)]
public sealed class BanCommand : LocalizedCommands
{
[AdminCommand(AdminFlags.Ban)]
public sealed class BanCommand : LocalizedCommands
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly IBanManager _bans = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!;
public override string Command => "ban";
public override async void Execute(IConsoleShell shell, string argStr, string[] args)
{
[Dependency] private readonly IConfigurationManager _cfg = default!;
public override string Command => "ban";
public override async void Execute(IConsoleShell shell, string argStr, string[] args)
string target;
string reason;
uint minutes;
if (!Enum.TryParse(_cfg.GetCVar(CCVars.ServerBanDefaultSeverity), out NoteSeverity severity))
{
var player = shell.Player as IPlayerSession;
var plyMgr = IoCManager.Resolve<IPlayerManager>();
var locator = IoCManager.Resolve<IPlayerLocator>();
var dbMan = IoCManager.Resolve<IServerDbManager>();
string target;
string reason;
uint minutes;
switch (args.Length)
{
case 2:
target = args[0];
reason = args[1];
minutes = 0;
break;
case 3:
target = args[0];
reason = args[1];
if (!uint.TryParse(args[2], out minutes))
{
shell.WriteLine($"{args[2]} is not a valid amount of minutes.\n{Help}");
return;
}
break;
default:
shell.WriteLine($"Invalid amount of arguments.{Help}");
return;
}
var located = await locator.LookupIdByNameOrIdAsync(target);
if (located == null)
{
shell.WriteError(LocalizationManager.GetString("cmd-ban-player"));
return;
}
var targetUid = located.UserId;
var targetHWid = located.LastHWId;
var targetAddr = located.LastAddress;
if (player != null && player.UserId == targetUid)
{
shell.WriteLine(LocalizationManager.GetString("cmd-ban-self"));
return;
}
DateTimeOffset? expires = null;
if (minutes > 0)
{
expires = DateTimeOffset.Now + TimeSpan.FromMinutes(minutes);
}
(IPAddress, int)? addrRange = null;
if (targetAddr != null)
{
if (targetAddr.IsIPv4MappedToIPv6)
targetAddr = targetAddr.MapToIPv4();
// Ban /64 for IPv4, /32 for IPv4.
var cidr = targetAddr.AddressFamily == AddressFamily.InterNetworkV6 ? 64 : 32;
addrRange = (targetAddr, cidr);
}
var banDef = new ServerBanDef(
null,
targetUid,
addrRange,
targetHWid,
DateTimeOffset.Now,
expires,
reason,
player?.UserId,
null);
await dbMan.AddServerBanAsync(banDef);
var response = new StringBuilder($"Banned {target} with reason \"{reason}\"");
response.Append(expires == null ? " permanently." : $" until {expires}");
shell.WriteLine(response.ToString());
if (plyMgr.TryGetSessionById(targetUid, out var targetPlayer))
{
var message = banDef.FormatBanMessage(_cfg, LocalizationManager);
targetPlayer.ConnectedClient.Disconnect(message);
}
Logger.WarningS("admin.server_ban", "Server ban severity could not be parsed from config! Defaulting to high.");
severity = NoteSeverity.High;
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
switch (args.Length)
{
if (args.Length == 1)
{
var playerMgr = IoCManager.Resolve<IPlayerManager>();
var options = playerMgr.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray();
return CompletionResult.FromHintOptions(options, LocalizationManager.GetString("cmd-ban-hint"));
}
case 2:
target = args[0];
reason = args[1];
minutes = 0;
break;
case 3:
target = args[0];
reason = args[1];
if (args.Length == 2)
return CompletionResult.FromHint(LocalizationManager.GetString("cmd-ban-hint-reason"));
if (args.Length == 3)
{
var durations = new CompletionOption[]
if (!uint.TryParse(args[2], out minutes))
{
new("0", LocalizationManager.GetString("cmd-ban-hint-duration-1")),
new("1440", LocalizationManager.GetString("cmd-ban-hint-duration-2")),
new("4320", LocalizationManager.GetString("cmd-ban-hint-duration-3")),
new("10080", LocalizationManager.GetString("cmd-ban-hint-duration-4")),
new("20160", LocalizationManager.GetString("cmd-ban-hint-duration-5")),
new("43800", LocalizationManager.GetString("cmd-ban-hint-duration-6")),
};
shell.WriteLine(Loc.GetString("cmd-ban-invalid-minutes", ("minutes", args[2])));
shell.WriteLine(Help);
return;
}
return CompletionResult.FromHintOptions(durations, LocalizationManager.GetString("cmd-ban-hint-duration"));
}
break;
case 4:
target = args[0];
reason = args[1];
return CompletionResult.Empty;
if (!uint.TryParse(args[2], out minutes))
{
shell.WriteLine(Loc.GetString("cmd-ban-invalid-minutes", ("minutes", args[2])));
shell.WriteLine(Help);
return;
}
if (!Enum.TryParse(args[3], ignoreCase: true, out severity))
{
shell.WriteLine(Loc.GetString("cmd-ban-invalid-severity", ("severity", args[3])));
shell.WriteLine(Help);
return;
}
break;
default:
shell.WriteLine(Loc.GetString("cmd-ban-invalid-arguments"));
shell.WriteLine(Help);
return;
}
var located = await _locator.LookupIdByNameOrIdAsync(target);
var player = shell.Player as IPlayerSession;
if (located == null)
{
shell.WriteError(Loc.GetString("cmd-ban-player"));
return;
}
var targetUid = located.UserId;
var targetHWid = located.LastHWId;
_bans.CreateServerBan(targetUid, target, player?.UserId, null, targetHWid, minutes, severity, reason);
}
public override CompletionResult GetCompletion(IConsoleShell shell, string[] args)
{
if (args.Length == 1)
{
var options = _playerManager.ServerSessions.Select(c => c.Name).OrderBy(c => c).ToArray();
return CompletionResult.FromHintOptions(options, LocalizationManager.GetString("cmd-ban-hint"));
}
if (args.Length == 2)
return CompletionResult.FromHint(LocalizationManager.GetString("cmd-ban-hint-reason"));
if (args.Length == 3)
{
var durations = new CompletionOption[]
{
new("0", LocalizationManager.GetString("cmd-ban-hint-duration-1")),
new("1440", LocalizationManager.GetString("cmd-ban-hint-duration-2")),
new("4320", LocalizationManager.GetString("cmd-ban-hint-duration-3")),
new("10080", LocalizationManager.GetString("cmd-ban-hint-duration-4")),
new("20160", LocalizationManager.GetString("cmd-ban-hint-duration-5")),
new("43800", LocalizationManager.GetString("cmd-ban-hint-duration-6")),
};
return CompletionResult.FromHintOptions(durations, LocalizationManager.GetString("cmd-ban-hint-duration"));
}
if (args.Length == 4)
{
var severities = new CompletionOption[]
{
new("none", Loc.GetString("admin-note-editor-severity-none")),
new("minor", Loc.GetString("admin-note-editor-severity-low")),
new("medium", Loc.GetString("admin-note-editor-severity-medium")),
new("high", Loc.GetString("admin-note-editor-severity-high")),
};
return CompletionResult.FromHintOptions(severities, Loc.GetString("cmd-ban-hint-severity"));
}
return CompletionResult.Empty;
}
}

View File

@@ -0,0 +1,52 @@
using Content.Shared.Administration;
using Robust.Shared.Console;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Content.Server.EUI;
using Robust.Server.Player;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Ban)]
public sealed class BanPanelCommand : LocalizedCommands
{
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly EuiManager _euis = default!;
public override string Command => "banpanel";
public override async void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (shell.Player is not IPlayerSession player)
{
shell.WriteError(Loc.GetString("cmd-banpanel-server"));
return;
}
switch (args.Length)
{
case 0:
_euis.OpenEui(new BanPanelEui(), player);
break;
case 1:
var located = await _locator.LookupIdByNameOrIdAsync(args[0]);
if (located is null)
{
shell.WriteError(Loc.GetString("cmd-banpanel-player-err"));
return;
}
var ui = new BanPanelEui();
_euis.OpenEui(ui, player);
ui.ChangePlayer(located.UserId, located.Username, located.LastAddress, located.LastHWId);
break;
default:
shell.WriteLine(Loc.GetString("cmd-ban-invalid-arguments"));
shell.WriteLine(Help);
return;
}
}
}

View File

@@ -1,6 +1,9 @@
using Content.Server.Administration.Managers;
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.Prototypes;
@@ -9,9 +12,10 @@ namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Ban)]
public sealed class DepartmentBanCommand : IConsoleCommand
{
[Dependency] private readonly IPlayerLocator _locater = default!;
[Dependency] private readonly IPrototypeManager _protoManager = default!;
[Dependency] private readonly RoleBanManager _bans = default!;
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly IBanManager _banManager = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
public string Command => "departmentban";
public string Description => Loc.GetString("cmd-departmentban-desc");
@@ -23,6 +27,11 @@ public sealed class DepartmentBanCommand : IConsoleCommand
string department;
string reason;
uint minutes;
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.");
severity = NoteSeverity.Medium;
}
switch (args.Length)
{
@@ -43,6 +52,24 @@ public sealed class DepartmentBanCommand : IConsoleCommand
return;
}
break;
case 5:
target = args[0];
department = args[1];
reason = args[2];
if (!uint.TryParse(args[3], out minutes))
{
shell.WriteError(Loc.GetString("cmd-roleban-minutes-parse", ("time", args[3]), ("help", Help)));
return;
}
if (!Enum.TryParse(args[4], ignoreCase: true, out severity))
{
shell.WriteLine(Loc.GetString("cmd-roleban-severity-parse", ("severity", args[4]), ("help", Help)));
return;
}
break;
default:
shell.WriteError(Loc.GetString("cmd-roleban-arg-count"));
@@ -55,20 +82,25 @@ public sealed class DepartmentBanCommand : IConsoleCommand
return;
}
var located = await _locater.LookupIdByNameOrIdAsync(target);
var located = await _locator.LookupIdByNameOrIdAsync(target);
if (located == null)
{
shell.WriteError(Loc.GetString("cmd-roleban-name-parse"));
return;
}
var targetUid = located.UserId;
var targetHWid = located.LastHWId;
// If you are trying to remove the following variable, please don't. It's there because the note system groups role bans by time, reason and banning admin.
// Without it the note list will get needlessly cluttered.
var now = DateTimeOffset.UtcNow;
foreach (var job in departmentProto.Roles)
{
_bans.CreateJobBan(shell, located, job, reason, minutes);
_banManager.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes, severity, reason, now);
}
_bans.SendRoleBans(located);
_banManager.SendRoleBans(located.UserId);
}
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
@@ -83,6 +115,14 @@ public sealed class DepartmentBanCommand : IConsoleCommand
new("43800", Loc.GetString("cmd-roleban-hint-duration-6")),
};
var severities = new CompletionOption[]
{
new("none", Loc.GetString("admin-note-editor-severity-none")),
new("minor", Loc.GetString("admin-note-editor-severity-low")),
new("medium", Loc.GetString("admin-note-editor-severity-medium")),
new("high", Loc.GetString("admin-note-editor-severity-high")),
};
return args.Length switch
{
1 => CompletionResult.FromHintOptions(CompletionHelper.SessionNames(),
@@ -91,6 +131,7 @@ public sealed class DepartmentBanCommand : IConsoleCommand
Loc.GetString("cmd-roleban-hint-2")),
3 => CompletionResult.FromHint(Loc.GetString("cmd-roleban-hint-3")),
4 => CompletionResult.FromHintOptions(durOpts, Loc.GetString("cmd-roleban-hint-4")),
5 => CompletionResult.FromHintOptions(severities, Loc.GetString("cmd-roleban-hint-5")),
_ => CompletionResult.Empty
};
}

View File

@@ -0,0 +1,38 @@
using Content.Server.Administration.Notes;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
namespace Content.Server.Administration.Commands;
[AnyCommand]
public sealed class OpenUserVisibleNotesCommand : IConsoleCommand
{
[Dependency] private readonly IConfigurationManager _configuration = default!;
[Dependency] private readonly IAdminNotesManager _notes = default!;
public const string CommandName = "adminremarks";
public string Command => CommandName;
public string Description => Loc.GetString("admin-remarks-command-description");
public string Help => $"Usage: {Command}";
public async void Execute(IConsoleShell shell, string argStr, string[] args)
{
if (!_configuration.GetCVar(CCVars.SeeOwnNotes))
{
shell.WriteError(Loc.GetString("admin-remarks-command-error"));
return;
}
if (shell.Player is not IPlayerSession player)
{
shell.WriteError("This does not work from the server console.");
return;
}
await _notes.OpenUserNotesEui(player);
}
}

View File

@@ -1,19 +1,20 @@
using System.Linq;
using System.Linq;
using System.Text;
using Content.Server.Administration.Managers;
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Database;
using Content.Shared.Roles;
using Robust.Server.Player;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
using Robust.Shared.Prototypes;
using Serilog;
namespace Content.Server.Administration.Commands;
[AdminCommand(AdminFlags.Ban)]
public sealed class RoleBanCommand : IConsoleCommand
{
[Dependency] private readonly IPlayerLocator _locator = default!;
[Dependency] private readonly RoleBanManager _bans = default!;
[Dependency] private readonly IBanManager _bans = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
public string Command => "roleban";
public string Description => Loc.GetString("cmd-roleban-desc");
@@ -25,6 +26,11 @@ public sealed class RoleBanCommand : IConsoleCommand
string job;
string reason;
uint minutes;
if (!Enum.TryParse(_cfg.GetCVar(CCVars.RoleBanDefaultSeverity), out NoteSeverity severity))
{
Logger.WarningS("admin.role_ban", "Role ban severity could not be parsed from config! Defaulting to medium.");
severity = NoteSeverity.Medium;
}
switch (args.Length)
{
@@ -45,6 +51,24 @@ public sealed class RoleBanCommand : IConsoleCommand
return;
}
break;
case 5:
target = args[0];
job = args[1];
reason = args[2];
if (!uint.TryParse(args[3], out minutes))
{
shell.WriteError(Loc.GetString("cmd-roleban-minutes-parse", ("time", args[3]), ("help", Help)));
return;
}
if (!Enum.TryParse(args[4], ignoreCase: true, out severity))
{
shell.WriteLine(Loc.GetString("cmd-roleban-severity-parse", ("severity", args[4]), ("help", Help)));
return;
}
break;
default:
shell.WriteError(Loc.GetString("cmd-roleban-arg-count"));
@@ -53,15 +77,17 @@ public sealed class RoleBanCommand : IConsoleCommand
}
var located = await _locator.LookupIdByNameOrIdAsync(target);
if (located == null)
{
shell.WriteError(Loc.GetString("cmd-roleban-name-parse"));
return;
}
_bans.CreateJobBan(shell, located, job, reason, minutes);
_bans.SendRoleBans(located);
var targetUid = located.UserId;
var targetHWid = located.LastHWId;
_bans.CreateRoleBan(targetUid, located.Username, shell.Player?.UserId, null, targetHWid, job, minutes, severity, reason, DateTimeOffset.UtcNow);
_bans.SendRoleBans(located.UserId);
}
public CompletionResult GetCompletion(IConsoleShell shell, string[] args)
@@ -76,6 +102,14 @@ public sealed class RoleBanCommand : IConsoleCommand
new("43800", Loc.GetString("cmd-roleban-hint-duration-6")),
};
var severities = new CompletionOption[]
{
new("none", Loc.GetString("admin-note-editor-severity-none")),
new("minor", Loc.GetString("admin-note-editor-severity-low")),
new("medium", Loc.GetString("admin-note-editor-severity-medium")),
new("high", Loc.GetString("admin-note-editor-severity-high")),
};
return args.Length switch
{
1 => CompletionResult.FromHintOptions(CompletionHelper.SessionNames(),
@@ -84,6 +118,7 @@ public sealed class RoleBanCommand : IConsoleCommand
Loc.GetString("cmd-roleban-hint-2")),
3 => CompletionResult.FromHint(Loc.GetString("cmd-roleban-hint-3")),
4 => CompletionResult.FromHintOptions(durOpts, Loc.GetString("cmd-roleban-hint-4")),
5 => CompletionResult.FromHintOptions(severities, Loc.GetString("cmd-roleban-hint-5")),
_ => CompletionResult.Empty
};
}