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

119 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace SharpChat {
public class ChannelsContext {
private readonly Dictionary<string, ChannelInfo> Channels = new();
public ChannelInfo? MainChannel { get; private set; }
public int TotalCount { get; private set; }
public int PublicCount { get; private set; }
public ChannelInfo[] All => Channels.Values.ToArray();
public ChannelInfo? Get(
string? name,
Func<string, string>? sanitise = null
) {
if(string.IsNullOrWhiteSpace(name))
return null;
foreach(ChannelInfo info in Channels.Values) {
string chanName = info.Name;
if(sanitise != null)
chanName = sanitise(chanName);
if(!chanName.Equals(name, StringComparison.InvariantCultureIgnoreCase))
continue;
return info;
}
return null;
}
public ChannelInfo[] GetMany(
string[]? names = null,
Func<string, string>? sanitiseName = null,
int minRank = 0,
bool? isPublic = null
) {
List<ChannelInfo> chans = new();
names ??= Array.Empty<string>();
for(int i = 0; i < names.Length; ++i)
names[i] = names[i].ToLowerInvariant();
foreach(ChannelInfo info in Channels.Values) {
if(info.Rank > minRank)
continue;
if(isPublic != null && info.IsPublic != isPublic)
continue;
if(names?.Length > 0) {
string chanName = info.Name;
if(sanitiseName != null)
chanName = sanitiseName(chanName);
bool match = false;
foreach(string name in names)
if(match = chanName.Equals(name, StringComparison.InvariantCultureIgnoreCase))
break;
if(!match)
continue;
}
chans.Add(info);
}
return chans.ToArray();
}
public void Add(ChannelInfo info, bool forceMain = false) {
if(Channels.ContainsKey(info.Name.ToLowerInvariant()))
throw new ArgumentException("A channel with this name has already been registered.", nameof(info));
if(string.IsNullOrWhiteSpace(info.Name))
throw new ArgumentException("Channel names may not be blank.", nameof(info));
// todo: there should be more restrictions on channel names
Channels.Add(info.Name.ToLowerInvariant(), info);
++TotalCount;
if(info.IsPublic)
++PublicCount;
if(forceMain || MainChannel == null)
MainChannel = info;
}
public void Remove(
ChannelInfo info,
Func<string, string>? sanitiseName = null
) {
Remove(info.Name, sanitiseName);
}
public void Remove(
string? name,
Func<string, string>? sanitise = null
) {
if(string.IsNullOrWhiteSpace(name))
return;
ChannelInfo? info = Get(name, sanitise);
if(info == null)
return;
Channels.Remove(info.Name.ToLowerInvariant());
--TotalCount;
if(info.IsPublic)
--PublicCount;
if(MainChannel == info)
MainChannel = Channels.Values.FirstOrDefault(c => !c.IsPublic);
}
}
}