283 lines
10 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|