Split status elements out of UserInfo and made user update event based.
This commit is contained in:
parent
2eae48325a
commit
86effa0452
18 changed files with 343 additions and 144 deletions
|
@ -1,4 +1,5 @@
|
|||
using System.Linq;
|
||||
using SharpChat.Events;
|
||||
using System.Linq;
|
||||
|
||||
namespace SharpChat.SockChat.Commands {
|
||||
public class UserAFKCommand : ISockChatClientCommand {
|
||||
|
@ -19,10 +20,10 @@ namespace SharpChat.SockChat.Commands {
|
|||
statusText = statusText[..MAX_LENGTH].Trim();
|
||||
}
|
||||
|
||||
ctx.Chat.UpdateUser(
|
||||
ctx.Chat.Events.Dispatch(
|
||||
"user:status",
|
||||
ctx.User,
|
||||
status: UserStatus.Away,
|
||||
statusText: statusText
|
||||
new UserStatusUpdateEventData(UserStatus.Away, statusText)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using SharpChat.SockChat.PacketsS2C;
|
||||
using SharpChat.Events;
|
||||
using SharpChat.SockChat.PacketsS2C;
|
||||
using System.Linq;
|
||||
|
||||
namespace SharpChat.SockChat.Commands {
|
||||
|
@ -39,16 +40,22 @@ namespace SharpChat.SockChat.Commands {
|
|||
nickStr = string.Empty;
|
||||
else if(nickStr.Length > 15)
|
||||
nickStr = nickStr[..15];
|
||||
else if(string.IsNullOrEmpty(nickStr))
|
||||
nickStr = string.Empty;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(nickStr) && ctx.Chat.Users.Get(name: nickStr, nameTarget: UsersContext.NameTarget.UserAndNickName) != null) {
|
||||
if(string.IsNullOrWhiteSpace(nickStr))
|
||||
nickStr = string.Empty;
|
||||
else if(ctx.Chat.Users.Get(name: nickStr, nameTarget: UsersContext.NameTarget.UserAndNickName) != null) {
|
||||
ctx.Chat.SendTo(ctx.User, new UserNameInUseErrorS2CPacket(nickStr));
|
||||
return;
|
||||
}
|
||||
|
||||
string? previousName = targetUser == ctx.User ? (targetUser.NickName ?? targetUser.UserName) : null;
|
||||
ctx.Chat.UpdateUser(targetUser, nickName: nickStr, silent: previousName == null);
|
||||
ctx.Chat.Events.Dispatch(
|
||||
"user:update",
|
||||
targetUser,
|
||||
new UserUpdateEventData(
|
||||
nickName: nickStr,
|
||||
notify: targetUser.UserId == ctx.User.UserId
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace SharpChat.SockChat.Commands {
|
|||
|
||||
if(string.IsNullOrEmpty(channelName)) {
|
||||
ctx.Chat.SendTo(ctx.User, new WhoServerResponseS2CPacket(
|
||||
ctx.Chat.Users.All.Select(u => SockChatUtility.GetUserNameWithStatus(u)).ToArray(),
|
||||
ctx.Chat.Users.All.Select(u => SockChatUtility.GetUserName(u, ctx.Chat.UserStatuses.Get(u))).ToArray(),
|
||||
SockChatUtility.GetUserName(ctx.User)
|
||||
));
|
||||
return;
|
||||
|
@ -32,8 +32,8 @@ namespace SharpChat.SockChat.Commands {
|
|||
|
||||
ctx.Chat.SendTo(ctx.User, new WhoChannelResponseS2CPacket(
|
||||
channel.Name,
|
||||
ctx.Chat.GetChannelUsers(channel).Select(user => SockChatUtility.GetUserNameWithStatus(user)).ToArray(),
|
||||
SockChatUtility.GetUserNameWithStatus(ctx.User)
|
||||
ctx.Chat.GetChannelUsers(channel).Select(user => SockChatUtility.GetUserName(user, ctx.Chat.UserStatuses.Get(user))).ToArray(),
|
||||
SockChatUtility.GetUserName(ctx.User, ctx.Chat.UserStatuses.Get(ctx.User))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using SharpChat.Config;
|
||||
using SharpChat.Events;
|
||||
using SharpChat.Misuzu;
|
||||
using SharpChat.SockChat.PacketsS2C;
|
||||
using System;
|
||||
|
@ -121,7 +122,7 @@ namespace SharpChat.SockChat.PacketsC2S {
|
|||
try {
|
||||
UserInfo? user = ctx.Chat.Users.Get(fai.UserId);
|
||||
|
||||
if(user == null)
|
||||
if(user == null) {
|
||||
user = new UserInfo(
|
||||
fai.UserId,
|
||||
fai.UserName ?? string.Empty,
|
||||
|
@ -130,15 +131,26 @@ namespace SharpChat.SockChat.PacketsC2S {
|
|||
fai.Permissions,
|
||||
isSuper: fai.IsSuper
|
||||
);
|
||||
else
|
||||
ctx.Chat.UpdateUser(
|
||||
user,
|
||||
userName: fai.UserName,
|
||||
colour: fai.Colour,
|
||||
rank: fai.Rank,
|
||||
perms: fai.Permissions,
|
||||
isSuper: fai.IsSuper
|
||||
);
|
||||
} else {
|
||||
string? updName = !user.UserName.Equals(fai.UserName) ? fai.UserName : null;
|
||||
int? updColour = (updColour = fai.Colour.ToMisuzu()) != user.Colour.ToMisuzu() ? updColour : null;
|
||||
int? updRank = user.Rank != fai.Rank ? fai.Rank : null;
|
||||
UserPermissions? updPerms = user.Permissions != fai.Permissions ? fai.Permissions : null;
|
||||
bool? updSuper = user.IsSuper != fai.IsSuper ? fai.IsSuper : null;
|
||||
|
||||
if(updName != null || updColour != null || updRank != null || updPerms != null || updSuper != null)
|
||||
ctx.Chat.Events.Dispatch(
|
||||
"user:update",
|
||||
user,
|
||||
new UserUpdateEventData(
|
||||
name: updName,
|
||||
colour: updColour,
|
||||
rank: updRank,
|
||||
perms: updPerms,
|
||||
isSuper: updSuper
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Enforce a maximum amount of connections per user
|
||||
if(ctx.Chat.Connections.GetCountForUser(user) >= MaxConnections) {
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace SharpChat.SockChat.PacketsC2S {
|
|||
List<(string, string)> bumpList = new();
|
||||
|
||||
foreach(UserInfo userInfo in ctx.Chat.Users.All) {
|
||||
if(userInfo.Status != UserStatus.Online)
|
||||
if(ctx.Chat.UserStatuses.GetStatus(userInfo) != UserStatus.Online)
|
||||
continue;
|
||||
|
||||
string[] remoteAddrs = ctx.Chat.Connections.GetUserRemoteAddresses(userInfo);
|
||||
|
|
|
@ -49,8 +49,12 @@ namespace SharpChat.SockChat.PacketsC2S {
|
|||
if(channelInfo == null)
|
||||
return;
|
||||
|
||||
if(user.Status != UserStatus.Online)
|
||||
ctx.Chat.UpdateUser(user, status: UserStatus.Online);
|
||||
if(ctx.Chat.UserStatuses.GetStatus(user) != UserStatus.Online)
|
||||
ctx.Chat.Events.Dispatch(
|
||||
"user:status",
|
||||
user,
|
||||
new UserStatusUpdateEventData(UserStatus.Online)
|
||||
);
|
||||
|
||||
int maxMsgLength = MaxMessageLength;
|
||||
if(messageText.Length > maxMsgLength)
|
||||
|
|
32
SharpChat.SockChat/PacketsS2C/UserNickChangeLogS2CPacket.cs
Normal file
32
SharpChat.SockChat/PacketsS2C/UserNickChangeLogS2CPacket.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
|
||||
namespace SharpChat.SockChat.PacketsS2C {
|
||||
public class UserNickChangeLogS2CPacket : ISockChatS2CPacket {
|
||||
private readonly long MessageId;
|
||||
private readonly DateTimeOffset TimeStamp;
|
||||
private readonly string PrevName;
|
||||
private readonly string NewName;
|
||||
|
||||
public UserNickChangeLogS2CPacket(
|
||||
long messageId,
|
||||
DateTimeOffset timeStamp,
|
||||
string prevName,
|
||||
string newName
|
||||
) {
|
||||
MessageId = messageId;
|
||||
TimeStamp = timeStamp;
|
||||
PrevName = prevName;
|
||||
NewName = newName;
|
||||
}
|
||||
|
||||
public string Pack() {
|
||||
return string.Format(
|
||||
"7\t1\t{0}\t-1\tChatBot\tinherit\t\t0\fnick\f{1}\f{2}\t{3}\t0\t10010",
|
||||
TimeStamp.ToUnixTimeSeconds(),
|
||||
PrevName,
|
||||
NewName,
|
||||
MessageId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,21 @@
|
|||
using System;
|
||||
|
||||
namespace SharpChat.SockChat.PacketsS2C {
|
||||
public class UserUpdateNotificationS2CPacket : ISockChatS2CPacket {
|
||||
public class UserNickChangeS2CPacket : ISockChatS2CPacket {
|
||||
private readonly long MessageId;
|
||||
private readonly DateTimeOffset TimeStamp;
|
||||
private readonly string PreviousName;
|
||||
private readonly string PrevName;
|
||||
private readonly string NewName;
|
||||
|
||||
public UserUpdateNotificationS2CPacket(string previousName, string newName) {
|
||||
MessageId = SharpId.Next();
|
||||
TimeStamp = DateTimeOffset.UtcNow;
|
||||
PreviousName = previousName;
|
||||
public UserNickChangeS2CPacket(
|
||||
long messageId,
|
||||
DateTimeOffset timeStamp,
|
||||
string prevName,
|
||||
string newName
|
||||
) {
|
||||
MessageId = messageId;
|
||||
TimeStamp = timeStamp;
|
||||
PrevName = prevName;
|
||||
NewName = newName;
|
||||
}
|
||||
|
||||
|
@ -18,7 +23,7 @@ namespace SharpChat.SockChat.PacketsS2C {
|
|||
return string.Format(
|
||||
"2\t{0}\t-1\t0\fnick\f{1}\f{2}\t{3}\t10010",
|
||||
TimeStamp.ToUnixTimeSeconds(),
|
||||
PreviousName,
|
||||
PrevName,
|
||||
NewName,
|
||||
MessageId
|
||||
);
|
|
@ -11,11 +11,12 @@ namespace SharpChat {
|
|||
public class SockChatContext : IChatEventHandler {
|
||||
public readonly SemaphoreSlim ContextAccess = new(1, 1);
|
||||
|
||||
public ChannelsContext Channels { get; } = new();
|
||||
public ConnectionsContext Connections { get; } = new();
|
||||
public UsersContext Users { get; } = new();
|
||||
public IEventStorage EventStorage { get; }
|
||||
public ChatEventDispatcher Events { get; } = new();
|
||||
public ConnectionsContext Connections { get; } = new();
|
||||
public ChannelsContext Channels { get; } = new();
|
||||
public UsersContext Users { get; } = new();
|
||||
public UserStatusContext UserStatuses { get; } = new();
|
||||
public ChannelsUsersContext ChannelsUsers { get; } = new();
|
||||
public Dictionary<long, RateLimiter> UserRateLimiters { get; } = new();
|
||||
|
||||
|
@ -28,6 +29,7 @@ namespace SharpChat {
|
|||
public void HandleEvent(ChatEventInfo info) {
|
||||
// user status should be stored outside of the UserInfo class so we don't need to do this:
|
||||
UserInfo? userInfo = Users.Get(info.SenderId);
|
||||
UserStatusInfo userStatusInfo = UserStatuses.Get(info.SenderId);
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(info.ChannelName))
|
||||
ChannelsUsers.SetUserLastChannel(info.SenderId, info.ChannelName);
|
||||
|
@ -40,7 +42,7 @@ namespace SharpChat {
|
|||
info.Id,
|
||||
info.Created,
|
||||
info.SenderId,
|
||||
userInfo == null ? SockChatUtility.GetUserName(info) : SockChatUtility.GetUserNameWithStatus(userInfo),
|
||||
SockChatUtility.GetUserName(info, userStatusInfo),
|
||||
info.SenderColour,
|
||||
info.SenderRank,
|
||||
info.SenderPerms
|
||||
|
@ -49,7 +51,8 @@ namespace SharpChat {
|
|||
|
||||
case "user:disconnect":
|
||||
if(userInfo != null)
|
||||
UpdateUser(userInfo, status: UserStatus.Offline);
|
||||
Events.Dispatch("user:status", userInfo, new UserStatusUpdateEventData(UserStatus.Offline));
|
||||
UserStatuses.Clear(info.SenderId);
|
||||
Users.Remove(info.SenderId);
|
||||
|
||||
ChannelInfo[] channels = Channels.GetMany(ChannelsUsers.GetUserChannelNames(info.SenderId));
|
||||
|
@ -60,7 +63,7 @@ namespace SharpChat {
|
|||
info.Id,
|
||||
info.Created,
|
||||
info.SenderId,
|
||||
userInfo == null ? SockChatUtility.GetUserName(info) : SockChatUtility.GetUserNameWithStatus(userInfo),
|
||||
SockChatUtility.GetUserName(info, userStatusInfo),
|
||||
info.Data is UserDisconnectEventData userDisconnect ? userDisconnect.Reason : UserDisconnectReason.Leave
|
||||
);
|
||||
|
||||
|
@ -73,6 +76,86 @@ namespace SharpChat {
|
|||
}
|
||||
break;
|
||||
|
||||
case "user:status":
|
||||
if(info.Data is not UserStatusUpdateEventData userStatusUpdate)
|
||||
break;
|
||||
|
||||
if(userStatusInfo.Status == userStatusUpdate.Status
|
||||
&& userStatusInfo.Text.Equals(userStatusUpdate.Text))
|
||||
break;
|
||||
|
||||
userStatusInfo = UserStatuses.Set(
|
||||
info.SenderId,
|
||||
userStatusUpdate.Status,
|
||||
userStatusUpdate.Text ?? string.Empty
|
||||
);
|
||||
|
||||
SendToUserChannels(info.SenderId, new UserUpdateS2CPacket(
|
||||
info.SenderId,
|
||||
SockChatUtility.GetUserName(info, userStatusInfo),
|
||||
info.SenderColour,
|
||||
info.SenderRank,
|
||||
info.SenderPerms
|
||||
));
|
||||
break;
|
||||
|
||||
case "user:update":
|
||||
if(info.Data is not UserUpdateEventData userUpdate || userInfo is null)
|
||||
break;
|
||||
|
||||
bool uuHasChanged = false;
|
||||
string? uuPrevName = null;
|
||||
|
||||
if(userUpdate.Name != null && !userUpdate.Name.Equals(userInfo.UserName)) {
|
||||
userInfo.UserName = userUpdate.Name;
|
||||
uuHasChanged = true;
|
||||
}
|
||||
|
||||
if(userUpdate.NickName != null && !userUpdate.NickName.Equals(userInfo.NickName)) {
|
||||
if(userUpdate.Notify)
|
||||
uuPrevName = string.IsNullOrWhiteSpace(userInfo.NickName) ? userInfo.UserName : userInfo.NickName;
|
||||
|
||||
userInfo.NickName = userUpdate.NickName;
|
||||
uuHasChanged = true;
|
||||
}
|
||||
|
||||
if(userUpdate.Colour.HasValue && userUpdate.Colour != userInfo.Colour.ToMisuzu()) {
|
||||
userInfo.Colour = Colour.FromMisuzu(userUpdate.Colour.Value);
|
||||
uuHasChanged = true;
|
||||
}
|
||||
|
||||
if(userUpdate.Rank != null && userUpdate.Rank != userInfo.Rank) {
|
||||
userInfo.Rank = userUpdate.Rank.Value;
|
||||
uuHasChanged = true;
|
||||
}
|
||||
|
||||
if(userUpdate.Perms.HasValue && userUpdate.Perms != userInfo.Permissions) {
|
||||
userInfo.Permissions = userUpdate.Perms.Value;
|
||||
uuHasChanged = true;
|
||||
}
|
||||
|
||||
if(userUpdate.IsSuper.HasValue && userUpdate.IsSuper != userInfo.IsSuper)
|
||||
userInfo.IsSuper = userUpdate.IsSuper.Value;
|
||||
|
||||
if(uuHasChanged) {
|
||||
if(uuPrevName != null)
|
||||
SendToUserChannels(info.SenderId, new UserNickChangeS2CPacket(
|
||||
info.Id,
|
||||
info.Created,
|
||||
string.IsNullOrWhiteSpace(info.SenderNickName) ? uuPrevName : $"~{info.SenderNickName}",
|
||||
SockChatUtility.GetUserName(userInfo, userStatusInfo)
|
||||
));
|
||||
|
||||
SendToUserChannels(info.SenderId, new UserUpdateS2CPacket(
|
||||
userInfo.UserId,
|
||||
SockChatUtility.GetUserName(userInfo, userStatusInfo),
|
||||
userInfo.Colour,
|
||||
userInfo.Rank,
|
||||
userInfo.Permissions
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "user:kickban":
|
||||
if(info.Data is not UserKickBanEventData userBaka)
|
||||
break;
|
||||
|
@ -108,7 +191,7 @@ namespace SharpChat {
|
|||
case "chan:join":
|
||||
SendTo(info.ChannelName, new UserChannelJoinS2CPacket(
|
||||
info.SenderId,
|
||||
userInfo == null ? SockChatUtility.GetUserName(info) : SockChatUtility.GetUserNameWithStatus(userInfo),
|
||||
SockChatUtility.GetUserName(info, userStatusInfo),
|
||||
info.SenderColour,
|
||||
info.SenderRank,
|
||||
info.SenderPerms
|
||||
|
@ -219,86 +302,10 @@ namespace SharpChat {
|
|||
}
|
||||
}
|
||||
|
||||
public ChannelInfo[] GetUserChannels(UserInfo user) {
|
||||
return Channels.GetMany(ChannelsUsers.GetUserChannelNames(user));
|
||||
}
|
||||
|
||||
public UserInfo[] GetChannelUsers(ChannelInfo channel) {
|
||||
return Users.GetMany(ChannelsUsers.GetChannelUserIds(channel));
|
||||
}
|
||||
|
||||
public void UpdateUser(
|
||||
UserInfo user,
|
||||
string? userName = null,
|
||||
string? nickName = null,
|
||||
Colour? colour = null,
|
||||
UserStatus? status = null,
|
||||
string? statusText = null,
|
||||
int? rank = null,
|
||||
UserPermissions? perms = null,
|
||||
bool? isSuper = null,
|
||||
bool silent = false
|
||||
) {
|
||||
bool hasChanged = false;
|
||||
string? previousName = null;
|
||||
|
||||
if(userName != null && !user.UserName.Equals(userName)) {
|
||||
user.UserName = userName;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(nickName != null && !user.NickName.Equals(nickName)) {
|
||||
if(!silent)
|
||||
previousName = string.IsNullOrWhiteSpace(user.NickName) ? user.UserName : user.NickName;
|
||||
|
||||
user.NickName = nickName;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(colour.HasValue && !user.Colour.Equals(colour.Value)) {
|
||||
user.Colour = colour.Value;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(status.HasValue && user.Status != status.Value) {
|
||||
user.Status = status.Value;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(statusText != null && !user.StatusText.Equals(statusText)) {
|
||||
user.StatusText = statusText;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(rank != null && user.Rank != rank) {
|
||||
user.Rank = (int)rank;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(perms.HasValue && user.Permissions != perms) {
|
||||
user.Permissions = perms.Value;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(isSuper.HasValue && user.IsSuper != isSuper) {
|
||||
user.IsSuper = isSuper.Value;
|
||||
hasChanged = true;
|
||||
}
|
||||
|
||||
if(hasChanged) {
|
||||
if(previousName != null)
|
||||
SendToUserChannels(user, new UserUpdateNotificationS2CPacket(previousName, SockChatUtility.GetUserNameWithStatus(user)));
|
||||
|
||||
SendToUserChannels(user, new UserUpdateS2CPacket(
|
||||
user.UserId,
|
||||
SockChatUtility.GetUserNameWithStatus(user),
|
||||
user.Colour,
|
||||
user.Rank,
|
||||
user.Permissions
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleChannelEventLog(string channelName, Action<ISockChatS2CPacket> handler) {
|
||||
foreach(ChatEventInfo info in EventStorage.GetChannelEventLog(channelName)) {
|
||||
switch(info.Type) {
|
||||
|
@ -339,6 +346,16 @@ namespace SharpChat {
|
|||
));
|
||||
break;
|
||||
|
||||
case "user:update":
|
||||
if(info.Data is UserUpdateEventData userUpdate && userUpdate.Notify)
|
||||
handler(new UserNickChangeLogS2CPacket(
|
||||
info.Id,
|
||||
info.Created,
|
||||
info.SenderNickName == null ? info.SenderName : $"~{info.SenderNickName}",
|
||||
userUpdate.NickName == null ? info.SenderName : $"~{userUpdate.NickName}"
|
||||
));
|
||||
break;
|
||||
|
||||
case "chan:join":
|
||||
handler(new UserChannelJoinLogS2CPacket(
|
||||
info.Id,
|
||||
|
@ -362,9 +379,11 @@ namespace SharpChat {
|
|||
if(!ChannelsUsers.Has(chan, user))
|
||||
Events.Dispatch("user:connect", chan, user);
|
||||
|
||||
UserStatusInfo statusInfo = UserStatuses.Get(user);
|
||||
|
||||
conn.Send(new AuthSuccessS2CPacket(
|
||||
user.UserId,
|
||||
SockChatUtility.GetUserNameWithStatus(user),
|
||||
SockChatUtility.GetUserName(user, statusInfo),
|
||||
user.Colour,
|
||||
user.Rank,
|
||||
user.Permissions,
|
||||
|
@ -374,7 +393,7 @@ namespace SharpChat {
|
|||
conn.Send(new UsersPopulateS2CPacket(GetChannelUsers(chan).Except(new[] { user }).Select(
|
||||
user => new UsersPopulateS2CPacket.ListEntry(
|
||||
user.UserId,
|
||||
SockChatUtility.GetUserNameWithStatus(user),
|
||||
SockChatUtility.GetUserName(user, statusInfo),
|
||||
user.Colour,
|
||||
user.Rank,
|
||||
user.Permissions,
|
||||
|
@ -430,7 +449,7 @@ namespace SharpChat {
|
|||
SendTo(user, new UsersPopulateS2CPacket(GetChannelUsers(chan).Except(new[] { user }).Select(
|
||||
user => new UsersPopulateS2CPacket.ListEntry(
|
||||
user.UserId,
|
||||
SockChatUtility.GetUserNameWithStatus(user),
|
||||
SockChatUtility.GetUserName(user, UserStatuses.Get(user)),
|
||||
user.Colour,
|
||||
user.Rank,
|
||||
user.Permissions,
|
||||
|
@ -494,7 +513,11 @@ namespace SharpChat {
|
|||
}
|
||||
|
||||
public void SendToUserChannels(UserInfo user, ISockChatS2CPacket packet) {
|
||||
ChannelInfo[] chans = GetUserChannels(user);
|
||||
SendToUserChannels(user.UserId, packet);
|
||||
}
|
||||
|
||||
public void SendToUserChannels(long userId, ISockChatS2CPacket packet) {
|
||||
ChannelInfo[] chans = Channels.GetMany(ChannelsUsers.GetUserChannelNames(userId));
|
||||
string data = packet.Pack();
|
||||
foreach(ChannelInfo chan in chans)
|
||||
SendTo(chan, data);
|
||||
|
|
|
@ -21,25 +21,30 @@ namespace SharpChat.SockChat {
|
|||
return name.Length < 1 || ChannelName.IsMatch(name);
|
||||
}
|
||||
|
||||
public static string GetUserName(UserInfo info) {
|
||||
return string.IsNullOrWhiteSpace(info.NickName) ? info.UserName : $"~{info.NickName}";
|
||||
}
|
||||
public static string GetUserName(UserInfo info, UserStatusInfo? statusInfo = null) {
|
||||
string name = string.IsNullOrWhiteSpace(info.NickName) ? info.UserName : $"~{info.NickName}";
|
||||
|
||||
public static string GetUserNameWithStatus(UserInfo info) {
|
||||
string name = GetUserName(info);
|
||||
|
||||
if(info.Status == UserStatus.Away)
|
||||
if(statusInfo?.Status == UserStatus.Away)
|
||||
name = string.Format(
|
||||
"<{0}>_{1}",
|
||||
info.StatusText[..Math.Min(info.StatusText.Length, 5)].ToUpperInvariant(),
|
||||
statusInfo.Text[..Math.Min(statusInfo.Text.Length, 5)].ToUpperInvariant(),
|
||||
name
|
||||
);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static string GetUserName(ChatEventInfo info) {
|
||||
return string.IsNullOrWhiteSpace(info.SenderNickName) ? info.SenderName : $"~{info.SenderNickName}";
|
||||
public static string GetUserName(ChatEventInfo info, UserStatusInfo? statusInfo = null) {
|
||||
string name = string.IsNullOrWhiteSpace(info.SenderNickName) ? info.SenderName : $"~{info.SenderNickName}";
|
||||
|
||||
if(statusInfo?.Status == UserStatus.Away)
|
||||
name = string.Format(
|
||||
"<{0}>_{1}",
|
||||
statusInfo.Text[..Math.Min(statusInfo.Text.Length, 5)].ToUpperInvariant(),
|
||||
name
|
||||
);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static (string, UsersContext.NameTarget) ExplodeUserName(string name) {
|
||||
|
|
|
@ -3,7 +3,6 @@ using SharpChat.Events;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
|
@ -91,7 +90,7 @@ namespace SharpChat.EventStorage {
|
|||
reader.GetInt64("event_id"),
|
||||
eventType,
|
||||
DateTimeOffset.FromUnixTimeSeconds(reader.GetInt32("event_created")),
|
||||
reader.GetString("event_channel"),
|
||||
reader.IsDBNull(reader.GetOrdinal("event_channel")) ? string.Empty : reader.GetString("event_channel"),
|
||||
reader.IsDBNull(reader.GetOrdinal("event_sender")) ? -1 : reader.GetInt64("event_sender"),
|
||||
reader.IsDBNull(reader.GetOrdinal("event_sender_name")) ? string.Empty : reader.GetString("event_sender_name"),
|
||||
reader.IsDBNull(reader.GetOrdinal("event_sender_colour")) ? Colour.None : Colour.FromMisuzu(reader.GetInt32("event_sender_colour")),
|
||||
|
|
17
SharpChatCommon/Events/UserStatusUpdateEventData.cs
Normal file
17
SharpChatCommon/Events/UserStatusUpdateEventData.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharpChat.Events {
|
||||
[ChatEventDataFor("user:status")]
|
||||
public class UserStatusUpdateEventData : ChatEventData {
|
||||
[JsonPropertyName("status")]
|
||||
public UserStatus Status { get; }
|
||||
|
||||
[JsonPropertyName("text")]
|
||||
public string? Text { get; }
|
||||
|
||||
public UserStatusUpdateEventData(UserStatus status, string? text = null) {
|
||||
Status = status;
|
||||
Text = string.IsNullOrWhiteSpace(text) ? null : text;
|
||||
}
|
||||
}
|
||||
}
|
45
SharpChatCommon/Events/UserUpdateEventData.cs
Normal file
45
SharpChatCommon/Events/UserUpdateEventData.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SharpChat.Events {
|
||||
[ChatEventDataFor("user:update")]
|
||||
public class UserUpdateEventData : ChatEventData {
|
||||
[JsonPropertyName("notify")]
|
||||
public bool Notify { get; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; }
|
||||
|
||||
[JsonPropertyName("colour")]
|
||||
public int? Colour { get; }
|
||||
|
||||
[JsonPropertyName("rank")]
|
||||
public int? Rank { get; }
|
||||
|
||||
[JsonPropertyName("perms")]
|
||||
public UserPermissions? Perms { get; }
|
||||
|
||||
[JsonPropertyName("nick")]
|
||||
public string? NickName { get; }
|
||||
|
||||
[JsonPropertyName("super")]
|
||||
public bool? IsSuper { get; }
|
||||
|
||||
public UserUpdateEventData(
|
||||
string? name = null,
|
||||
int? colour = null,
|
||||
int? rank = null,
|
||||
UserPermissions? perms = null,
|
||||
string? nickName = null,
|
||||
bool? isSuper = null,
|
||||
bool notify = false
|
||||
) {
|
||||
Notify = notify;
|
||||
Name = name;
|
||||
Colour = colour;
|
||||
Rank = rank;
|
||||
Perms = perms;
|
||||
NickName = nickName;
|
||||
IsSuper = isSuper;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,8 +11,6 @@
|
|||
public UserPermissions Permissions { get; set; }
|
||||
public bool IsSuper { get; set; }
|
||||
public string NickName { get; set; }
|
||||
public UserStatus Status { get; set; }
|
||||
public string StatusText { get; set; }
|
||||
|
||||
public UserInfo(
|
||||
long userId,
|
||||
|
@ -21,8 +19,6 @@
|
|||
int rank,
|
||||
UserPermissions perms,
|
||||
string? nickName = null,
|
||||
UserStatus status = UserStatus.Online,
|
||||
string? statusText = null,
|
||||
bool isSuper = false
|
||||
) {
|
||||
UserId = userId;
|
||||
|
@ -31,8 +27,6 @@
|
|||
Rank = rank;
|
||||
Permissions = perms;
|
||||
NickName = nickName ?? string.Empty;
|
||||
Status = status;
|
||||
StatusText = statusText ?? string.Empty;
|
||||
IsSuper = isSuper;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
namespace SharpChat {
|
||||
public enum UserStatus {
|
||||
Online,
|
||||
Away,
|
||||
Offline,
|
||||
public enum UserStatus : int {
|
||||
Unknown = 0,
|
||||
Online = 1,
|
||||
Away = 2,
|
||||
Offline = 3,
|
||||
}
|
||||
}
|
||||
|
|
39
SharpChatCommon/UserStatusContext.cs
Normal file
39
SharpChatCommon/UserStatusContext.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace SharpChat {
|
||||
public class UserStatusContext {
|
||||
private readonly Dictionary<long, UserStatusInfo> Statuses = new();
|
||||
|
||||
public UserStatusInfo Get(long userId) {
|
||||
return Statuses.ContainsKey(userId)
|
||||
? Statuses[userId]
|
||||
: UserStatusInfo.EmptyInstance;
|
||||
}
|
||||
|
||||
public UserStatusInfo Get(UserInfo userInfo) {
|
||||
return Get(userInfo.UserId);
|
||||
}
|
||||
|
||||
public UserStatus GetStatus(long userId) {
|
||||
return Get(userId).Status;
|
||||
}
|
||||
|
||||
public UserStatus GetStatus(UserInfo userInfo) {
|
||||
return Get(userInfo.UserId).Status;
|
||||
}
|
||||
|
||||
public UserStatusInfo Set(long userId, UserStatus status, string text) {
|
||||
UserStatusInfo statusInfo = new(status, text);
|
||||
if(Statuses.ContainsKey(userId))
|
||||
Statuses[userId] = statusInfo;
|
||||
else
|
||||
Statuses.Add(userId, statusInfo);
|
||||
|
||||
return statusInfo;
|
||||
}
|
||||
|
||||
public void Clear(long userId) {
|
||||
Statuses.Remove(userId);
|
||||
}
|
||||
}
|
||||
}
|
16
SharpChatCommon/UserStatusInfo.cs
Normal file
16
SharpChatCommon/UserStatusInfo.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace SharpChat {
|
||||
public class UserStatusInfo {
|
||||
public UserStatus Status { get; }
|
||||
public string Text { get; }
|
||||
|
||||
public UserStatusInfo(
|
||||
UserStatus status,
|
||||
string text
|
||||
) {
|
||||
Status = status;
|
||||
Text = text;
|
||||
}
|
||||
|
||||
public static readonly UserStatusInfo EmptyInstance = new(UserStatus.Unknown, string.Empty);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using SharpChat.SockChat;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue