sharp-chat/SharpChat/Commands/NickCommand.cs

64 lines
2.6 KiB
C#
Raw Normal View History

using SharpChat.S2CPackets;
using System.Globalization;
using System.Text;
namespace SharpChat.Commands {
public class NickCommand : ChatCommand {
private const int MAX_GRAPHEMES = 16;
private const int MAX_BYTES = MAX_GRAPHEMES * 10;
public bool IsMatch(ChatCommandContext ctx) {
return ctx.NameEquals("nick");
}
public void Dispatch(ChatCommandContext ctx) {
long msgId = ctx.Chat.RandomSnowflake.Next();
bool setOthersNick = ctx.User.Can(ChatUserPermissions.SetOthersNickname);
if(!setOthersNick && !ctx.User.Can(ChatUserPermissions.SetOwnNickname)) {
ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.COMMAND_NOT_ALLOWED, true, $"/{ctx.Name}"));
return;
}
2025-04-25 18:18:13 +00:00
ChatUser? targetUser = null;
int offset = 0;
if(setOthersNick && long.TryParse(ctx.Args.FirstOrDefault(), out long targetUserId) && targetUserId > 0) {
2023-02-19 23:27:08 +01:00
targetUser = ctx.Chat.Users.FirstOrDefault(u => u.UserId == targetUserId);
++offset;
}
targetUser ??= ctx.User;
if(ctx.Args.Length < offset) {
ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.COMMAND_FORMAT_ERROR));
return;
}
string nickStr = string.Join('_', ctx.Args.Skip(offset))
.Replace("\n", string.Empty).Replace("\r", string.Empty)
.Replace("\f", string.Empty).Replace("\t", string.Empty)
.Replace(' ', '_').Trim();
if(nickStr == targetUser.UserName)
nickStr = string.Empty;
else if(string.IsNullOrEmpty(nickStr))
nickStr = string.Empty;
else {
2025-04-25 15:49:46 +00:00
StringInfo nsi = new(nickStr);
if(Encoding.UTF8.GetByteCount(nickStr) > MAX_BYTES
|| nsi.LengthInTextElements > MAX_GRAPHEMES)
2025-04-14 22:27:36 +00:00
nickStr = nsi.SubstringByTextElements(0, Math.Min(nsi.LengthInTextElements, MAX_GRAPHEMES)).Trim();
}
2023-02-19 23:27:08 +01:00
if(!string.IsNullOrWhiteSpace(nickStr) && ctx.Chat.Users.Any(u => u.NameEquals(nickStr))) {
ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.NAME_IN_USE, true, nickStr));
2023-02-19 23:27:08 +01:00
return;
}
2025-04-25 18:18:13 +00:00
string? previousName = targetUser.UserId == ctx.User.UserId ? (targetUser.NickName ?? targetUser.UserName) : null;
ctx.Chat.UpdateUser(targetUser, nickName: nickStr, silent: previousName == null);
}
}
}