mirror of
https://github.com/Stone-Red-Code/EchoHub.git
synced 2026-09-04 09:06:07 +02:00
- Add IrcGatewayService to handle IRC connections and commands. - Create IrcMessage class for parsing IRC protocol lines. - Implement IrcMessageFormatter for formatting messages as IRC lines. - Define IrcNumericReply constants for IRC numeric replies. - Add IrcOptions class for configuration settings related to IRC. - Create IrcServiceExtensions for adding IRC services to the application. - Refactor ChannelsController to use IChatService for broadcasting messages and channel updates. - Update ChatHub to utilize IChatService for user connection and message handling. - Introduce ChatService to manage chat-related operations and interactions. - Implement SignalRBroadcaster for broadcasting messages to SignalR clients. - Update PresenceTracker to retrieve usernames for connections. - Modify appsettings.example.json to include IRC configuration options. - Update solution file to include the new IRC project.
88 lines
2.4 KiB
C#
88 lines
2.4 KiB
C#
using System.Net.Sockets;
|
|
using System.Text;
|
|
|
|
namespace EchoHub.Server.Irc;
|
|
|
|
/// <summary>
|
|
/// Manages a single IRC client TCP connection.
|
|
/// </summary>
|
|
public sealed class IrcClientConnection : IAsyncDisposable
|
|
{
|
|
private readonly TcpClient _tcpClient;
|
|
private readonly StreamReader _reader;
|
|
private readonly StreamWriter _writer;
|
|
private readonly SemaphoreSlim _writeLock = new(1, 1);
|
|
|
|
// Connection identity
|
|
public string ConnectionId { get; } = $"irc-{Guid.NewGuid()}";
|
|
|
|
// Registration state
|
|
public string? Nickname { get; set; }
|
|
public string? Username { get; set; }
|
|
public string? RealName { get; set; }
|
|
public string? Password { get; set; }
|
|
public Guid? UserId { get; set; }
|
|
public bool IsRegistered { get; set; }
|
|
public bool IsAuthenticated { get; set; }
|
|
public bool IsSasl { get; set; }
|
|
public bool CapNegotiating { get; set; }
|
|
|
|
// Channel state
|
|
public HashSet<string> JoinedChannels { get; } = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
// Away state
|
|
public string? AwayMessage { get; set; }
|
|
|
|
public string Hostmask => $"{Nickname}!{Username ?? Nickname}@echohub";
|
|
|
|
public IrcClientConnection(TcpClient tcpClient, Stream stream)
|
|
{
|
|
_tcpClient = tcpClient;
|
|
_reader = new StreamReader(stream, Encoding.UTF8);
|
|
_writer = new StreamWriter(stream, Encoding.UTF8) { AutoFlush = true, NewLine = "\r\n" };
|
|
}
|
|
|
|
public async Task<string?> ReadLineAsync(CancellationToken ct)
|
|
{
|
|
try
|
|
{
|
|
return await _reader.ReadLineAsync(ct);
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public async Task SendAsync(string line)
|
|
{
|
|
await _writeLock.WaitAsync();
|
|
try
|
|
{
|
|
await _writer.WriteLineAsync(line);
|
|
}
|
|
catch
|
|
{
|
|
// Connection lost — swallow
|
|
}
|
|
finally
|
|
{
|
|
_writeLock.Release();
|
|
}
|
|
}
|
|
|
|
public Task SendNumericAsync(string serverName, string numeric, string target, string text)
|
|
=> SendAsync($":{serverName} {numeric} {target} {text}");
|
|
|
|
public Task SendNumericAsync(string serverName, string numeric, string text)
|
|
=> SendNumericAsync(serverName, numeric, Nickname ?? "*", text);
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
try { _tcpClient.Close(); } catch { }
|
|
_reader.Dispose();
|
|
_writer.Dispose();
|
|
_writeLock.Dispose();
|
|
}
|
|
}
|