using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Channels; namespace riff; public abstract class IRCBot { public string Host; public int Port; public string Nick; public string RealName; public List? Channels; public List> Listeners = new(); private List CommandRunners = new(); private List PollRunners = new(); private TcpClient Client; private NetworkStream Stream; public IRCBot(string host, int port, string nick, string realname) { Host = host; Port = port; Nick = nick; RealName = realname; Client = new TcpClient(Host, Port); Stream = Client.GetStream(); SendLine($"NICK {Nick}"); SendLine($"USER {Nick} 0 * :{RealName}"); } public void HookCommands((string, Action)[] commands) { foreach ((string, Action) command in commands) { CommandRunners.Add(new CommandRunner(command.Item1, command.Item2)); } } public void HookPollRunners((int, Action)[] runners) { foreach ((int, Action) runner in runners) { PollRunners.Add(new PollRunner(runner.Item1, runner.Item2)); } } public void HookListeners(Action[] listeners) { foreach (Action listener in listeners) { Listeners.Add(listener); } } private void SendLine(string line) { Byte[] bytes = Encoding.UTF8.GetBytes(line + "\r\n"); Stream.Write(bytes, 0, bytes.Length); } public void SendPrivmsg(string channel, string message) { if (message != string.Empty) SendLine($"PRIVMSG {channel} :{message}"); } public void JoinChannel(string channel) { SendLine($"JOIN {channel}"); } public void JoinChannels(string[] channels) { foreach (string channel in channels) JoinChannel(channel); } public void PartChannel(string channel) { SendLine($"PART {channel}"); } public void MainLoop() { foreach (PollRunner runner in PollRunners) { runner.Run(); } using var reader = new StreamReader(Stream, Encoding.UTF8); while (true) { string? line = reader.ReadLine(); if (line == null) { Console.WriteLine($"{Nick} disconnected"); break; } IRCMessage msg = new(line); switch (msg.Command) { case "PING": if (msg.Arguments == null) SendLine("PONG"); else SendLine("PONG " + msg.Arguments[0]); break; case "PRIVMSG": PRIVMSG privmsg = new(msg); foreach (Action listener in Listeners) listener(privmsg); foreach (CommandRunner command in CommandRunners) if (command.Run(privmsg)) break; break; } } } }