sharp-chat/SharpChatCommon/ChannelsUsersContext.cs
2024-05-29 20:51:41 +00:00

283 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace SharpChat {
public class ChannelsUsersContext {
private readonly Dictionary<string, HashSet<long>> ChannelUsers = new();
private readonly Dictionary<long, HashSet<string>> UserChannels = new();
private readonly Dictionary<long, string> UserLastChannel = new();
public string GetUserLastChannel(long userId) {
return UserLastChannel.ContainsKey(userId)
? UserLastChannel[userId]
: string.Empty;
}
public string GetUserLastChannel(UserInfo userInfo) {
return GetUserLastChannel(userInfo.UserId);
}
public void SetUserLastChannel(long userId, string channelName) {
channelName = channelName.ToLowerInvariant();
if(UserLastChannel.ContainsKey(userId))
UserLastChannel[userId] = channelName;
else
UserLastChannel.Add(userId, channelName);
}
public void SetUserLastChannel(UserInfo userInfo, ChannelInfo channelInfo) {
SetUserLastChannel(userInfo.UserId, channelInfo.Name);
}
public void DeleteUserLastChannel(long userId) {
if(UserLastChannel.ContainsKey(userId))
UserLastChannel.Remove(userId);
}
public void DeleteUserLastChannel(UserInfo userInfo) {
DeleteUserLastChannel(userInfo.UserId);
}
public bool IsUserLastChannel(long userId, string channelName) {
return !string.IsNullOrWhiteSpace(channelName)
&& GetUserLastChannel(userId).Equals(channelName, StringComparison.InvariantCultureIgnoreCase);
}
public bool IsUserLastChannel(UserInfo userInfo, ChannelInfo channelInfo) {
return IsUserLastChannel(userInfo.UserId, channelInfo.Name);
}
public string[] GetUserChannelNames(long userId) {
if(!UserChannels.ContainsKey(userId))
return Array.Empty<string>();
return UserChannels[userId].ToArray();
}
public string[] GetUserChannelNames(UserInfo userInfo) {
return GetUserChannelNames(userInfo.UserId);
}
public long[] GetChannelUserIds(string channelName) {
channelName = channelName.ToLowerInvariant();
if(!ChannelUsers.ContainsKey(channelName))
return Array.Empty<long>();
return ChannelUsers[channelName].ToArray();
}
public long[] GetChannelUserIds(string channelName, Func<string, string> sanitise) {
foreach(KeyValuePair<string, HashSet<long>> kvp in ChannelUsers)
if(sanitise(kvp.Key).Equals(channelName, StringComparison.InvariantCultureIgnoreCase))
return kvp.Value.ToArray();
return Array.Empty<long>();
}
public long[] GetChannelUserIds(ChannelInfo channelInfo) {
return GetChannelUserIds(channelInfo.Name);
}
public void Join(string channelName, long userId) {
channelName = channelName.ToLowerInvariant();
if(ChannelUsers.ContainsKey(channelName))
ChannelUsers[channelName].Add(userId);
else
ChannelUsers.Add(channelName, new HashSet<long> { userId });
if(UserChannels.ContainsKey(userId))
UserChannels[userId].Add(channelName);
else
UserChannels.Add(userId, new HashSet<string> { channelName });
SetUserLastChannel(userId, channelName);
}
public void Join(ChannelInfo channelInfo, UserInfo userInfo) {
Join(channelInfo.Name, userInfo.UserId);
}
public void Leave(string channelName, long userId) {
channelName = channelName.ToLowerInvariant();
if(ChannelUsers.ContainsKey(channelName)) {
if(ChannelUsers[channelName].Count < 2)
ChannelUsers.Remove(channelName);
else
ChannelUsers[channelName].Remove(userId);
}
if(UserChannels.ContainsKey(userId)) {
if(UserChannels[userId].Count < 2)
UserChannels.Remove(userId);
else
UserChannels[userId].Remove(channelName);
}
if(IsUserLastChannel(userId, channelName))
DeleteUserLastChannel(userId);
}
public void Leave(ChannelInfo channelInfo, UserInfo userInfo) {
Leave(channelInfo.Name, userInfo.UserId);
}
public bool Has(string channelName, long userId) {
channelName = channelName.ToLowerInvariant();
return ChannelUsers.ContainsKey(channelName)
&& ChannelUsers[channelName].Contains(userId);
}
public bool Has(ChannelInfo channelInfo, UserInfo userInfo) {
return Has(channelInfo.Name, userInfo.UserId);
}
public long[] FilterUsers(string channelName, long[] userIds) {
if(userIds.Length < 1)
return userIds;
channelName = channelName.ToLowerInvariant();
if(!ChannelUsers.ContainsKey(channelName))
return Array.Empty<long>();
List<long> filtered = new();
HashSet<long> channelUserIds = ChannelUsers[channelName];
foreach(long userId in userIds)
if(channelUserIds.Contains(userId))
filtered.Add(userId);
return filtered.ToArray();
}
public UserInfo[] FilterUsers(ChannelInfo channelInfo, UserInfo[] userInfos) {
if(userInfos.Length < 1)
return userInfos;
long[] filteredIds = FilterUsers(channelInfo.Name, userInfos.Select(u => u.UserId).ToArray());
if(filteredIds.Length < 1)
return Array.Empty<UserInfo>();
return userInfos.Where(u => filteredIds.Contains(u.UserId)).ToArray();
}
public bool HasUsers(string channelName, long[] userIds) {
return FilterUsers(channelName, userIds).SequenceEqual(userIds);
}
public bool HasUsers(ChannelInfo channelInfo, UserInfo[] userInfos) {
return HasUsers(channelInfo.Name, userInfos.Select(u => u.UserId).ToArray());
}
public string[] FilterChannels(long userId, string[] channelNames) {
if(channelNames.Length < 1)
return channelNames;
if(!UserChannels.ContainsKey(userId))
return Array.Empty<string>();
List<string> filtered = new();
HashSet<string> userChannelNames = UserChannels[userId];
foreach(string channelName in userChannelNames)
if(userChannelNames.Contains(channelName))
filtered.Add(channelName);
return filtered.ToArray();
}
public ChannelInfo[] FilterChannels(UserInfo userInfo, ChannelInfo[] channelInfos) {
if(channelInfos.Length < 1)
return channelInfos;
string[] filteredNames = FilterChannels(userInfo.UserId, channelInfos.Select(c => c.Name).ToArray());
if(filteredNames.Length < 1)
return Array.Empty<ChannelInfo>();
return channelInfos.Where(c => filteredNames.Contains(c.Name.ToLowerInvariant())).ToArray();
}
public bool HasChannels(long userId, string[] channelNames) {
if(!UserChannels.ContainsKey(userId))
return false;
HashSet<string> userChannelNames = UserChannels[userId];
foreach(string channelName in channelNames)
if(!userChannelNames.Contains(channelName.ToLowerInvariant()))
return false;
return true;
}
public bool HasChannels(UserInfo userInfo, ChannelInfo[] channelInfos) {
return HasChannels(userInfo.UserId, channelInfos.Select(c => c.Name).ToArray());
}
public void DeleteUser(long userId) {
if(!UserChannels.ContainsKey(userId))
return;
HashSet<string> channelNames = UserChannels[userId];
UserChannels.Remove(userId);
DeleteUserLastChannel(userId);
foreach(string channelName in channelNames) {
if(!ChannelUsers.ContainsKey(channelName))
continue;
ChannelUsers[channelName].Remove(userId);
}
}
public void DeleteUser(UserInfo userInfo) {
DeleteUser(userInfo.UserId);
}
public void DeleteChannel(string channelName) {
channelName = channelName.ToLowerInvariant();
if(!ChannelUsers.ContainsKey(channelName))
return;
HashSet<long> userIds = ChannelUsers[channelName];
ChannelUsers.Remove(channelName);
foreach(long userId in userIds) {
if(!UserChannels.ContainsKey(userId))
continue;
UserChannels[userId].Remove(channelName);
if(IsUserLastChannel(userId, channelName))
DeleteUserLastChannel(userId);
}
}
public void DeleteChannel(ChannelInfo channelInfo) {
DeleteChannel(channelInfo.Name);
}
public void RenameChannel(ChannelInfo channelInfo, string newName) {
RenameChannel(channelInfo.Name, newName);
}
public void RenameChannel(string prevName, string newName) {
newName = newName.ToLowerInvariant();
if(ChannelUsers.ContainsKey(newName))
throw new ArgumentException("A channel with that name is already registered!", nameof(newName));
prevName = prevName.ToLowerInvariant();
if(ChannelUsers.ContainsKey(prevName)) {
ChannelUsers.Add(newName, ChannelUsers[prevName]);
ChannelUsers.Remove(prevName);
}
foreach(KeyValuePair<long, string> kvp in UserLastChannel)
if(kvp.Value.Equals(prevName, StringComparison.InvariantCultureIgnoreCase))
UserLastChannel[kvp.Key] = newName;
foreach(HashSet<string> userChans in UserChannels.Values)
if(userChans.Contains(prevName)) {
userChans.Add(newName);
userChans.Remove(prevName);
}
}
}
}