HEH HEH YEAH ILIGHT HAHAHAHA WAHHH episode 2
This commit is contained in:
parent
a8f5c00e37
commit
626951ad10
37 changed files with 61 additions and 47 deletions
.editorconfigSharpChat.sln
SharpChat
C2SPacketHandlers
ChatCommand.csChatContext.csCommands
AFKCommand.csActionCommand.csBanListCommand.csBroadcastCommand.csCreateChannelCommand.csDeleteChannelCommand.csDeleteMessageCommand.csJoinChannelCommand.csKickBanCommand.csNickCommand.csPardonAddressCommand.csPardonUserCommand.csPasswordChannelCommand.csRankChannelCommand.csRemoteAddressCommand.csShutdownRestartCommand.csWhisperCommand.csWhoCommand.cs
Config
EventStorage
Events
Misuzu
Program.csSockChatServer.cs
13
.editorconfig
Normal file
13
.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.cs]
|
||||
|
||||
# IDE1006: Naming Styles
|
||||
dotnet_diagnostic.IDE1006.severity = none
|
|
@ -7,6 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpChat", "SharpChat\Shar
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DF7A7073-A67A-4D93-92C6-F9D0F95E2359}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.gitattributes = .gitattributes
|
||||
.gitignore = .gitignore
|
||||
LICENSE = LICENSE
|
||||
|
|
|
@ -11,13 +11,13 @@ namespace SharpChat.C2SPacketHandlers {
|
|||
) : C2SPacketHandler {
|
||||
private readonly CachedValue<int> MaxMessageLength = maxMsgLength ?? throw new ArgumentNullException(nameof(maxMsgLength));
|
||||
|
||||
private List<IChatCommand> Commands { get; } = [];
|
||||
private List<ChatCommand> Commands { get; } = [];
|
||||
|
||||
public void AddCommand(IChatCommand command) {
|
||||
public void AddCommand(ChatCommand command) {
|
||||
Commands.Add(command ?? throw new ArgumentNullException(nameof(command)));
|
||||
}
|
||||
|
||||
public void AddCommands(IEnumerable<IChatCommand> commands) {
|
||||
public void AddCommands(IEnumerable<ChatCommand> commands) {
|
||||
Commands.AddRange(commands ?? throw new ArgumentNullException(nameof(commands)));
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ namespace SharpChat.C2SPacketHandlers {
|
|||
|
||||
if(messageText.StartsWith('/')) {
|
||||
ChatCommandContext context = new(messageText, ctx.Chat, user, ctx.Connection, channel);
|
||||
foreach(IChatCommand cmd in Commands)
|
||||
foreach(ChatCommand cmd in Commands)
|
||||
if(cmd.IsMatch(context)) {
|
||||
cmd.Dispatch(context);
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
namespace SharpChat {
|
||||
public interface IChatCommand {
|
||||
public interface ChatCommand {
|
||||
bool IsMatch(ChatCommandContext ctx);
|
||||
void Dispatch(ChatCommandContext ctx);
|
||||
}
|
|
@ -16,17 +16,17 @@ namespace SharpChat {
|
|||
public HashSet<ChatChannel> Channels { get; } = [];
|
||||
public HashSet<ChatConnection> Connections { get; } = [];
|
||||
public HashSet<ChatUser> Users { get; } = [];
|
||||
public IEventStorage Events { get; }
|
||||
public EventStorage.EventStorage Events { get; }
|
||||
public HashSet<ChannelUserAssoc> ChannelUsers { get; } = [];
|
||||
public Dictionary<long, RateLimiter> UserRateLimiters { get; } = [];
|
||||
public Dictionary<long, ChatChannel> UserLastChannel { get; } = [];
|
||||
|
||||
public ChatContext(IEventStorage evtStore) {
|
||||
public ChatContext(EventStorage.EventStorage evtStore) {
|
||||
Events = evtStore ?? throw new ArgumentNullException(nameof(evtStore));
|
||||
RandomSnowflake = new(SnowflakeGenerator);
|
||||
}
|
||||
|
||||
public void DispatchEvent(IChatEvent eventInfo) {
|
||||
public void DispatchEvent(ChatEvent eventInfo) {
|
||||
if(eventInfo is MessageCreateEvent mce) {
|
||||
if(mce.IsBroadcast) {
|
||||
Send(new CommandResponseS2CPacket(RandomSnowflake.Next(), LCR.BROADCAST, false, mce.MessageText));
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class AFKCommand : IChatCommand {
|
||||
public class AFKCommand : ChatCommand {
|
||||
private const string DEFAULT = "AFK";
|
||||
public const int MAX_GRAPHEMES = 5;
|
||||
public const int MAX_BYTES = MAX_GRAPHEMES * 10;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.Events;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class ActionCommand : IChatCommand {
|
||||
public class ActionCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("action")
|
||||
|| ctx.NameEquals("me");
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class BanListCommand(MisuzuClient msz) : IChatCommand {
|
||||
public class BanListCommand(MisuzuClient msz) : ChatCommand {
|
||||
private readonly MisuzuClient Misuzu = msz ?? throw new ArgumentNullException(nameof(msz));
|
||||
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class BroadcastCommand : IChatCommand {
|
||||
public class BroadcastCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("say")
|
||||
|| ctx.NameEquals("broadcast");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class CreateChannelCommand : IChatCommand {
|
||||
public class CreateChannelCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("create");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class DeleteChannelCommand : IChatCommand {
|
||||
public class DeleteChannelCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("delchan") || (
|
||||
ctx.NameEquals("delete")
|
||||
|
|
|
@ -3,7 +3,7 @@ using SharpChat.S2CPackets;
|
|||
|
||||
namespace SharpChat.Commands
|
||||
{
|
||||
public class DeleteMessageCommand : IChatCommand {
|
||||
public class DeleteMessageCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("delmsg") || (
|
||||
ctx.NameEquals("delete")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class JoinChannelCommand : IChatCommand {
|
||||
public class JoinChannelCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("join");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class KickBanCommand(MisuzuClient msz) : IChatCommand {
|
||||
public class KickBanCommand(MisuzuClient msz) : ChatCommand {
|
||||
private readonly MisuzuClient Misuzu = msz ?? throw new ArgumentNullException(nameof(msz));
|
||||
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Globalization;
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class NickCommand : IChatCommand {
|
||||
public class NickCommand : ChatCommand {
|
||||
private const int MAX_GRAPHEMES = 16;
|
||||
private const int MAX_BYTES = MAX_GRAPHEMES * 10;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ using SharpChat.S2CPackets;
|
|||
using System.Net;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class PardonAddressCommand(MisuzuClient msz) : IChatCommand {
|
||||
public class PardonAddressCommand(MisuzuClient msz) : ChatCommand {
|
||||
private readonly MisuzuClient Misuzu = msz ?? throw new ArgumentNullException(nameof(msz));
|
||||
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class PardonUserCommand(MisuzuClient msz) : IChatCommand {
|
||||
public class PardonUserCommand(MisuzuClient msz) : ChatCommand {
|
||||
private readonly MisuzuClient Misuzu = msz ?? throw new ArgumentNullException(nameof(msz));
|
||||
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class PasswordChannelCommand : IChatCommand {
|
||||
public class PasswordChannelCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("pwd")
|
||||
|| ctx.NameEquals("password");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class RankChannelCommand : IChatCommand {
|
||||
public class RankChannelCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("rank")
|
||||
|| ctx.NameEquals("privilege")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Net;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class RemoteAddressCommand : IChatCommand {
|
||||
public class RemoteAddressCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("ip")
|
||||
|| ctx.NameEquals("whois");
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class ShutdownRestartCommand(ManualResetEvent waitHandle, Func<bool> shutdownCheck) : IChatCommand {
|
||||
public class ShutdownRestartCommand(ManualResetEvent waitHandle, Func<bool> shutdownCheck) : ChatCommand {
|
||||
private readonly ManualResetEvent WaitHandle = waitHandle ?? throw new ArgumentNullException(nameof(waitHandle));
|
||||
private readonly Func<bool> ShutdownCheck = shutdownCheck ?? throw new ArgumentNullException(nameof(shutdownCheck));
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using SharpChat.S2CPackets;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class WhisperCommand : IChatCommand {
|
||||
public class WhisperCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("whisper")
|
||||
|| ctx.NameEquals("msg");
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.Commands {
|
||||
public class WhoCommand : IChatCommand {
|
||||
public class WhoCommand : ChatCommand {
|
||||
public bool IsMatch(ChatCommandContext ctx) {
|
||||
return ctx.NameEquals("who");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace SharpChat.Config {
|
||||
public class CachedValue<T>(IConfig config, string name, TimeSpan lifetime, T? fallback) {
|
||||
private IConfig Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
public class CachedValue<T>(Config config, string name, TimeSpan lifetime, T? fallback) {
|
||||
private Config Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
private string Name { get; } = name ?? throw new ArgumentNullException(nameof(name));
|
||||
private object ConfigAccess { get; } = new();
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
namespace SharpChat.Config {
|
||||
public interface IConfig : IDisposable {
|
||||
public interface Config : IDisposable {
|
||||
/// <summary>
|
||||
/// Creates a proxy object that forces all names to start with the given prefix.
|
||||
/// </summary>
|
||||
IConfig ScopeTo(string prefix);
|
||||
Config ScopeTo(string prefix);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a raw (string) value from the config.
|
|
@ -1,6 +1,6 @@
|
|||
namespace SharpChat.Config {
|
||||
public class ScopedConfig(IConfig config, string prefix) : IConfig {
|
||||
private IConfig Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
public class ScopedConfig(Config config, string prefix) : Config {
|
||||
private Config Config { get; } = config ?? throw new ArgumentNullException(nameof(config));
|
||||
private string Prefix { get; } = prefix ?? throw new ArgumentNullException(nameof(prefix));
|
||||
|
||||
private string GetName(string name) {
|
||||
|
@ -19,7 +19,7 @@
|
|||
return Config.SafeReadValue(GetName(name), fallback);
|
||||
}
|
||||
|
||||
public IConfig ScopeTo(string prefix) {
|
||||
public Config ScopeTo(string prefix) {
|
||||
return Config.ScopeTo(GetName(prefix));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Text;
|
||||
|
||||
namespace SharpChat.Config {
|
||||
public class StreamConfig : IConfig {
|
||||
public class StreamConfig : Config {
|
||||
private Stream Stream { get; }
|
||||
private StreamReader StreamReader { get; }
|
||||
private Mutex Lock { get; }
|
||||
|
@ -82,7 +82,7 @@ namespace SharpChat.Config {
|
|||
}
|
||||
}
|
||||
|
||||
public IConfig ScopeTo(string prefix) {
|
||||
public Config ScopeTo(string prefix) {
|
||||
if(string.IsNullOrWhiteSpace(prefix))
|
||||
throw new ArgumentException("Prefix must exist.", nameof(prefix));
|
||||
if(prefix[^1] != ':')
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
namespace SharpChat.EventStorage {
|
||||
public interface IEventStorage {
|
||||
public interface EventStorage {
|
||||
void AddEvent(
|
||||
long id,
|
||||
string type,
|
|
@ -3,7 +3,7 @@ using System.Text;
|
|||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public partial class MariaDBEventStorage(string connString) : IEventStorage {
|
||||
public partial class MariaDBEventStorage(string connString) : EventStorage {
|
||||
private string ConnectionString { get; } = connString ?? throw new ArgumentNullException(nameof(connString));
|
||||
|
||||
public void AddEvent(
|
||||
|
|
|
@ -3,7 +3,7 @@ using SharpChat.Config;
|
|||
|
||||
namespace SharpChat.EventStorage {
|
||||
public partial class MariaDBEventStorage {
|
||||
public static string BuildConnString(IConfig config) {
|
||||
public static string BuildConnString(Config.Config config) {
|
||||
return BuildConnString(
|
||||
config.ReadValue("host", "localhost"),
|
||||
config.ReadValue("user", string.Empty),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace SharpChat.EventStorage {
|
||||
public class VirtualEventStorage : IEventStorage {
|
||||
public class VirtualEventStorage : EventStorage {
|
||||
private readonly Dictionary<long, StoredEventInfo> Events = [];
|
||||
|
||||
public void AddEvent(
|
||||
|
|
3
SharpChat/Events/ChatEvent.cs
Normal file
3
SharpChat/Events/ChatEvent.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace SharpChat.Events {
|
||||
public interface ChatEvent {}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
namespace SharpChat.Events {
|
||||
public interface IChatEvent {}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
bool isPrivate,
|
||||
bool isAction,
|
||||
bool isBroadcast
|
||||
) : IChatEvent {
|
||||
) : ChatEvent {
|
||||
public long MessageId { get; } = msgId;
|
||||
public string ChannelName { get; } = channelName;
|
||||
public long SenderId { get; } = senderId;
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace SharpChat.Misuzu {
|
|||
private CachedValue<string> BaseURL { get; }
|
||||
private CachedValue<string> SecretKey { get; }
|
||||
|
||||
public MisuzuClient(HttpClient httpClient, IConfig config) {
|
||||
public MisuzuClient(HttpClient httpClient, Config.Config config) {
|
||||
ArgumentNullException.ThrowIfNull(config);
|
||||
HttpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace SharpChat {
|
|||
|
||||
if(hasCancelled) return;
|
||||
|
||||
IEventStorage evtStore;
|
||||
EventStorage.EventStorage evtStore;
|
||||
if(string.IsNullOrWhiteSpace(config.SafeReadValue("mariadb:host", string.Empty))) {
|
||||
evtStore = new VirtualEventStorage();
|
||||
} else {
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace SharpChat {
|
|||
|
||||
private ChatChannel DefaultChannel { get; set; }
|
||||
|
||||
public SockChatServer(HttpClient httpClient, MisuzuClient msz, IEventStorage evtStore, IConfig config) {
|
||||
public SockChatServer(HttpClient httpClient, MisuzuClient msz, EventStorage.EventStorage evtStore, Config.Config config) {
|
||||
Logger.Write("Initialising Sock Chat server...");
|
||||
|
||||
HttpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
|
||||
|
@ -51,7 +51,7 @@ namespace SharpChat {
|
|||
string[]? channelNames = config.ReadValue("channels", DEFAULT_CHANNELS);
|
||||
if(channelNames is not null)
|
||||
foreach(string channelName in channelNames) {
|
||||
IConfig channelCfg = config.ScopeTo($"channels:{channelName}");
|
||||
Config.Config channelCfg = config.ScopeTo($"channels:{channelName}");
|
||||
|
||||
string name = channelCfg.SafeReadValue("name", string.Empty)!;
|
||||
if(string.IsNullOrWhiteSpace(name))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue