Whisper 0.1.0: private messages between players
/pm (/w) with names, #userid, SteamIDs, @me, @aim, @random, @randomt and @randomct, /r to reply, and /block, /blocklist, /unblock. Lines use CS2-Tags' rank prefixes and colours: >[[M] Kalus -> me] message. Gagged players can't send; blocks stop everyone but staff. Messages are kept in CS2-SimpleAdmin's database while History is on (css_whisper_history).
This commit is contained in:
commit
c414e8a770
12 changed files with 1547 additions and 0 deletions
97
Tags.cs
Normal file
97
Tags.cs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Modules.Admin;
|
||||
using CounterStrikeSharp.API.Modules.Utils;
|
||||
|
||||
namespace Whisper;
|
||||
|
||||
// Reads CS2-Tags' tags.json so private messages show the same rank prefix and colours as chat, and
|
||||
// picks a player's tag the way CS2-Tags does: their SteamID64 first, then the first "#group" or
|
||||
// "@permission" key they match in file order, then "everyone". Reread when the file changes.
|
||||
public sealed class Tags(string path, Action<string> warn)
|
||||
{
|
||||
public sealed record Tag(string Prefix, string NickColor, string MessageColor);
|
||||
|
||||
private List<KeyValuePair<string, Tag>> _tags = [];
|
||||
private DateTime _loadedWrite;
|
||||
|
||||
public Tag? Find(CCSPlayerController player)
|
||||
{
|
||||
Refresh();
|
||||
if (player.IsBot || player.IsHLTV || player.AuthorizedSteamID == null)
|
||||
return null;
|
||||
|
||||
var steamid = player.AuthorizedSteamID.SteamId64.ToString();
|
||||
foreach (var (key, tag) in _tags)
|
||||
if (key == steamid)
|
||||
return tag;
|
||||
foreach (var (key, tag) in _tags)
|
||||
{
|
||||
if (key.StartsWith('#') && AdminManager.PlayerInGroup(player, key)) return tag;
|
||||
if (key.StartsWith('@') && AdminManager.PlayerHasPermissions(player, key)) return tag;
|
||||
}
|
||||
foreach (var (key, tag) in _tags)
|
||||
if (key == "everyone")
|
||||
return tag;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Refresh()
|
||||
{
|
||||
DateTime written;
|
||||
try
|
||||
{
|
||||
written = File.GetLastWriteTimeUtc(path);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// GetLastWriteTimeUtc gives 1601 for a missing file.
|
||||
if (written == _loadedWrite || written.Year < 1700)
|
||||
{
|
||||
if (written.Year < 1700 && _tags.Count > 0)
|
||||
_tags = [];
|
||||
_loadedWrite = written;
|
||||
return;
|
||||
}
|
||||
_loadedWrite = written;
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(File.ReadAllText(path),
|
||||
new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
|
||||
var tags = new List<KeyValuePair<string, Tag>>();
|
||||
if (doc.RootElement.TryGetProperty("tags", out var section))
|
||||
foreach (var entry in section.EnumerateObject())
|
||||
tags.Add(new(entry.Name, new Tag(Str(entry.Value, "prefix"), Str(entry.Value, "nick_color"), Str(entry.Value, "message_color"))));
|
||||
_tags = tags;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Keep the tags from before, as CS2-Tags does with a broken file.
|
||||
warn($"Couldn't read {path}: {ex.Message}; keeping the previous tags");
|
||||
}
|
||||
}
|
||||
|
||||
private static string Str(JsonElement e, string name) =>
|
||||
e.TryGetProperty(name, out var v) && v.ValueKind == JsonValueKind.String ? v.GetString() ?? "" : "";
|
||||
|
||||
public static string TeamColor(int team) => team switch
|
||||
{
|
||||
(int)CsTeam.Terrorist => ChatColors.Gold.ToString(),
|
||||
(int)CsTeam.CounterTerrorist => ChatColors.Blue.ToString(),
|
||||
_ => "",
|
||||
};
|
||||
|
||||
// Colour tags in config strings only, never in names or messages: {Red}, {Default}, {TEAMCOLOR}.
|
||||
public static string Colors(string text, int team = 0)
|
||||
{
|
||||
if (!text.Contains('{'))
|
||||
return text;
|
||||
foreach (var field in typeof(ChatColors).GetFields(BindingFlags.Public | BindingFlags.Static))
|
||||
if (field.FieldType == typeof(char))
|
||||
text = text.Replace($"{{{field.Name}}}", field.GetValue(null)!.ToString(), StringComparison.OrdinalIgnoreCase);
|
||||
return text.Replace("{TEAMCOLOR}", TeamColor(team), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue