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

View File

@ -4,7 +4,15 @@ class Program
{ {
static void Main(string[] args) 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(); new Thread(new ThreadStart(cube.MainLoop)).Start();
} }
} }

View File

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

View File

@ -2,31 +2,34 @@ using System.Data;
using System.Text.Json; using System.Text.Json;
using riff; using riff;
public class Cube : IRCBot public class MysteriousCube : IRCBot
{ {
private HttpClient RequestClient = new(); private HttpClient RequestClient = new();
private const string AllTriviaQuestionsPath = "data/TriviaQuestions.json"; private const string AllTriviaQuestionsPath = "data/TriviaQuestions.json";
private const string UnaskedTriviaQuestionsPath = "data/UnaskedTriviaQuestions.json"; private const string UnaskedTriviaQuestionsPath = "data/UnaskedTriviaQuestions.json";
private TriviaQuestion[] AllTriviaQuestions; private TriviaQuestion[] AllTriviaQuestions;
private List<TriviaQuestion> UnaskedTriviaQuestions; private List<TriviaQuestion> UnaskedTriviaQuestions;
private bool ListeningForAnswer = false;
private TriviaQuestion? CurrentQuestion = null;
private Random Rand = new(); 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(); AllTriviaQuestions = LoadAllQuestions();
UnaskedTriviaQuestions = LoadUnaskedQuestions(); UnaskedTriviaQuestions = LoadUnaskedQuestions();
string[] channels = [
"#testbot",
];
(string, Action<PRIVMSG>)[] commands = [ (string, Action<PRIVMSG>)[] commands = [
("echo", Echo), ("echo", Echo),
("trivia", PostQuestion) ("trivia", PostQuestion)
]; ];
Action<PRIVMSG>[] listeners = [
AnswerListener
];
HookCommands(commands); HookCommands(commands);
JoinChannels(channels); HookListeners(listeners);
} }
private void Echo(PRIVMSG privmsg) private void Echo(PRIVMSG privmsg)
@ -37,7 +40,31 @@ public class Cube : IRCBot
private void PostQuestion(PRIVMSG privmsg) private void PostQuestion(PRIVMSG privmsg)
{ {
var question = GetQuestion(); 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() private TriviaQuestion GetQuestion()