no commit messages on my christian minecraft server

This commit is contained in:
nebula 2025-07-02 06:19:06 +00:00
parent 493c290e9b
commit 12668dff43
4 changed files with 116 additions and 22 deletions

View File

@ -1,7 +1,7 @@
using System.Data;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Channels;
using System.Text.Json;
namespace riff;
@ -11,23 +11,33 @@ public abstract class IRCBot
public int Port;
public string Nick;
public string RealName;
public List<string> Channels = new();
public List<string> JoinedChannels = new();
public List<string> PermanentChannels;
public List<string> UserChannels;
public string UserChannelStoragePath;
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)
public IRCBot(string host, int port, string nick, string realname, List<string> permanentChannels)
{
Host = host;
Port = port;
Nick = nick;
RealName = realname;
PermanentChannels = permanentChannels;
UserChannelStoragePath = $"data/{Nick}_user_channels.json";
UserChannels = LoadUserChannels();
Client = new TcpClient(Host, Port);
Stream = Client.GetStream();
SendLine($"NICK {Nick}");
SendLine($"USER {Nick} 0 * :{RealName}");
foreach (string channel in PermanentChannels)
JoinChannel(channel);
foreach (string channel in UserChannels)
JoinChannel(channel);
}
public void HookCommands((string, Action<PRIVMSG>)[] commands)
@ -69,10 +79,10 @@ public abstract class IRCBot
public void JoinChannel(string channel)
{
SendLine($"JOIN {channel}");
Channels.Add(channel);
JoinedChannels.Add(channel);
}
public void JoinChannels(string[] channels)
public void JoinChannels(List<string> channels)
{
foreach (string channel in channels)
JoinChannel(channel);
@ -81,13 +91,52 @@ public abstract class IRCBot
public void PartChannel(string channel)
{
SendLine($"PART {channel}");
Channels.Remove(channel);
JoinedChannels.Remove(channel);
}
public List<string> LoadUserChannels()
{
List<string> channels;
try
{
using (FileStream stream = File.OpenRead(UserChannelStoragePath))
{
channels = JsonSerializer.Deserialize<List<string>>(stream)!;
if (channels == null)
throw new NoNullAllowedException();
return channels;
}
}
catch (FileNotFoundException)
{
channels = [];
return channels;
}
}
public void AddUserChannel(string channel)
{
UserChannels.Add(channel);
JoinChannel(channel);
WriteUserChannels();
}
public void RemoveUserChannel(string channel)
{
UserChannels.Remove(channel);
PartChannel(channel);
WriteUserChannels();
}
public void WriteUserChannels()
{
File.WriteAllText(UserChannelStoragePath, JsonSerializer.Serialize(UserChannels));
}
public void MainLoop()
{
foreach (PollRunner runner in PollRunners)
runner.Run();
runner.Start();
using var reader = new StreamReader(Stream, Encoding.UTF8);
while (true)
{
@ -97,15 +146,25 @@ public abstract class IRCBot
Console.WriteLine($"{Nick} disconnected");
break;
}
Console.WriteLine(line);
IRCMessage msg = new(line);
switch (msg.Command)
{
case "PING":
if (msg.Arguments == null)
if (msg.Arguments.Count == 0)
SendLine("PONG");
else
SendLine("PONG " + msg.Arguments[0]);
break;
case "INVITE":
AddUserChannel(msg.Arguments[1]);
break;
case "KICK":
string channel = msg.Arguments[0];
UserChannels.Remove(channel);
JoinedChannels.Remove(channel);
WriteUserChannels();
break;
case "PRIVMSG":
PRIVMSG privmsg = new(msg);
foreach (Action<PRIVMSG> listener in Listeners)

View File

@ -4,7 +4,15 @@ class Program
{
static void Main(string[] args)
{
var cube = new Cube("localhost", 6667, "mysterious_cube", "~nebula https://git.tilde.town/nebula/riff");
List<string> mysteriousCubeChannels = [
"#testbot",
];
var cube = new MysteriousCube(
"localhost",
6667,
"mysterious_cube",
"~nebula https://git.tilde.town/nebula/riff",
mysteriousCubeChannels);
new Thread(new ThreadStart(cube.MainLoop)).Start();
}
}

View File

@ -6,7 +6,7 @@ public class IRCMessage
{
public string? Source;
public string Command;
public List<string>? Arguments;
public List<string> Arguments;
public IRCMessage(string line)
{
@ -31,7 +31,7 @@ public class IRCMessage
args.Add(arg);
}
Command = args[0];
Arguments = args.Count > 1 ? args[1..] : null;
Arguments = args.Count > 1 ? args[1..] : new List<string>();
}
}
@ -43,7 +43,7 @@ public class PRIVMSG
public PRIVMSG(IRCMessage message)
{
if (message.Source == null || message.Arguments == null)
if (message.Source == null)
throw new NoNullAllowedException();
Nick = message.Source.Substring(0, message.Source.IndexOf("!"));
Body = message.Arguments[1].Trim();
@ -91,7 +91,7 @@ public class PollRunner
Callback = callback;
}
public async void Run()
public async void Start()
{
while (true)
{

View File

@ -2,31 +2,34 @@ using System.Data;
using System.Text.Json;
using riff;
public class Cube : IRCBot
public class MysteriousCube : IRCBot
{
private HttpClient RequestClient = new();
private const string AllTriviaQuestionsPath = "data/TriviaQuestions.json";
private const string UnaskedTriviaQuestionsPath = "data/UnaskedTriviaQuestions.json";
private TriviaQuestion[] AllTriviaQuestions;
private List<TriviaQuestion> UnaskedTriviaQuestions;
private bool ListeningForAnswer = false;
private TriviaQuestion? CurrentQuestion = null;
private Random Rand = new();
public Cube(string host, int port, string nick, string realname) : base(host, port, nick, realname)
public MysteriousCube(string host, int port, string nick, string realname, List<string> permanentChannels)
: base(host, port, nick, realname, permanentChannels)
{
AllTriviaQuestions = LoadAllQuestions();
UnaskedTriviaQuestions = LoadUnaskedQuestions();
string[] channels = [
"#testbot",
];
(string, Action<PRIVMSG>)[] commands = [
("echo", Echo),
("trivia", PostQuestion)
];
Action<PRIVMSG>[] listeners = [
AnswerListener
];
HookCommands(commands);
JoinChannels(channels);
HookListeners(listeners);
}
private void Echo(PRIVMSG privmsg)
@ -37,7 +40,31 @@ public class Cube : IRCBot
private void PostQuestion(PRIVMSG privmsg)
{
var question = GetQuestion();
SendPrivmsg(privmsg.Sender, question.Question);
CurrentQuestion = question;
ListeningForAnswer = true;
SendPrivmsg(privmsg.Sender, $"Answer 'true' or 'false': {question.Question}");
}
private void AnswerListener(PRIVMSG privmsg)
{
if (!ListeningForAnswer || CurrentQuestion == null)
return;
string line = privmsg.Body.ToLower().Trim();
bool? answer = null;
if (line.StartsWith("true"))
answer = true;
else if (line.StartsWith("false"))
answer = false;
else
return;
ListeningForAnswer = false;
string response;
if (answer == CurrentQuestion.Answer)
response = $"{privmsg.Nick} is correct!";
else
response = $"{privmsg.Nick} is wrong!";
CurrentQuestion = null;
SendPrivmsg(privmsg.Sender, response);
}
private TriviaQuestion GetQuestion()