riff/IRCBot.cs

122 lines
3.2 KiB
C#

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<string>? Channels;
public List<Action<PRIVMSG>> Listeners = new();
private List<CommandRunner> CommandRunners = new();
private List<PollRunner> 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<PRIVMSG>)[] commands)
{
foreach ((string, Action<PRIVMSG>) 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<PRIVMSG>[] listeners)
{
foreach (Action<PRIVMSG> 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<PRIVMSG> listener in Listeners)
listener(privmsg);
foreach (CommandRunner command in CommandRunners)
if (command.Run(privmsg))
break;
break;
}
}
}
}