sharp-chat/SharpChatCommon/Users/UsersContext.cs

194 lines
5.6 KiB
C#
Raw Normal View History

using SharpChat.Auth;
namespace SharpChat.Users;
public class UsersContext {
private readonly Dictionary<string, User> Users = [];
private readonly Lock @lock = new();
public bool UserExists(string id) {
lock(@lock)
return Users.ContainsKey(id);
}
public bool UserExists(Func<User, bool> predicate) {
lock(@lock)
return Users.Values.Any(predicate);
}
public User? GetUser(string id) {
lock(@lock)
return Users.TryGetValue(id, out User? user) ? user : null;
}
public User? GetUser(Func<User, bool> predicate) {
lock(@lock)
return Users.Values.FirstOrDefault(predicate);
}
public IEnumerable<User> GetUsers() {
lock(@lock)
return [.. Users.Values];
}
public IEnumerable<User> GetUsers(IEnumerable<string> ids) {
return [.. ids.Select(GetUser).Where(u => u is not null).Cast<User>()];
}
public IEnumerable<User> GetUsers(Func<User, bool> predicate) {
lock(@lock)
return [.. Users.Values.Where(predicate)];
}
public IEnumerable<User> GetUsersWithStatus(UserStatus status) {
return GetUsers(u => u.Status == status);
}
public IEnumerable<User> GetUsersOfMinimumRank(int minRank) {
return GetUsers(u => u.Rank >= minRank);
}
public User CreateOrUpdateUser(AuthResult authResult) {
lock(@lock) {
User? user = GetUser(authResult.UserId);
return user is null ? CreateUserInternal(
authResult.UserId,
authResult.UserName,
authResult.UserColour,
authResult.UserRank,
authResult.UserPermissions
) : UpdateUserInternal(
user,
authResult.UserId,
authResult.UserName,
authResult.UserColour,
authResult.UserRank,
authResult.UserPermissions
).User;
}
}
public User CreateUser(
string id,
string name,
ColourInheritable colour,
int rank,
UserPermissions perms,
string nick = "",
UserStatus status = UserStatus.Online,
string statusText = ""
) {
lock(@lock)
return UserExists(id)
? throw new UserExistsException(nameof(id))
: CreateUserInternal(id, name, colour, rank, perms, nick, status, statusText);
}
private User CreateUserInternal(
string id,
string name,
ColourInheritable colour,
int rank,
UserPermissions perms,
string nick = "",
UserStatus status = UserStatus.Online,
string statusText = ""
) {
User user = new(id, name, colour, rank, perms, nick, status, statusText);
Users.Add(id, user);
return user;
}
public UserDiff UpdateUser(
User user,
string? name = null,
ColourInheritable? colour = null,
int? rank = null,
UserPermissions? perms = null,
string? nick = null,
UserStatus? status = null,
string? statusText = null
) => UpdateUser(user.UserId, name, colour, rank, perms, nick, status, statusText);
public UserDiff UpdateUser(
string id,
string? name = null,
ColourInheritable? colour = null,
int? rank = null,
UserPermissions? perms = null,
string? nick = null,
UserStatus? status = null,
string? statusText = null
) {
lock(@lock)
return UpdateUserInternal(
GetUser(id) ?? throw new UserNotFoundException(nameof(id)),
id, name, colour, rank, perms, nick, status, statusText
);
}
private static UserDiff UpdateUserInternal(
User user,
string id,
string? name = null,
ColourInheritable? colour = null,
int? rank = null,
UserPermissions? perms = null,
string? nick = null,
UserStatus? status = null,
string? statusText = null
) {
StringDiff nameDiff = new(user.UserName, name);
if(nameDiff.Changed)
user.UserName = nameDiff.After;
ValueDiff<ColourInheritable> colourDiff = new(user.Colour, colour);
if(colourDiff.Changed)
user.Colour = colourDiff.After;
ValueDiff<int> rankDiff = new(user.Rank, rank);
if(rankDiff.Changed)
user.Rank = rankDiff.After;
ValueDiff<UserPermissions> permsDiff = new(user.Permissions, perms);
if(permsDiff.Changed)
user.Permissions = permsDiff.After;
StringDiff nickDiff = new(user.NickName, nick);
if(nickDiff.Changed)
user.NickName = nickDiff.After;
ValueDiff<UserStatus> statusDiff = new(user.Status, status);
if(statusDiff.Changed)
user.Status = statusDiff.After;
StringDiff statusTextDiff = new(user.StatusText, statusText);
if(statusTextDiff.Changed)
user.StatusText = statusTextDiff.After;
return new(
user,
id,
nameDiff,
colourDiff,
rankDiff,
permsDiff,
nickDiff,
statusDiff,
statusTextDiff
);
}
public void RemoveUser(User user)
=> RemoveUserInternal(user.UserId, nameof(user));
public void RemoveUser(string id)
=> RemoveUserInternal(id, nameof(id));
private void RemoveUserInternal(string id, string argName) {
lock(@lock)
if(!Users.Remove(id))
throw new UserNotFoundException(argName);
}
}