fix: make admin command parsing more robust

There was a bug in how we parsed admin commands, apparently we never
tested if we could parse `!backlog X` or unknown admin commands.

This commit also make updates to the backlog command construction to
make sure that we don't try to access messages in the backlog that
don't exist.
This commit is contained in:
Jacob Jonsson 2026-03-11 00:48:02 +01:00
parent d237ba9e8a
commit 4e11cc9ea1
Signed by: Jassob
GPG key ID: 7E30B9B047F7202E
4 changed files with 100 additions and 40 deletions

View file

@ -55,18 +55,22 @@ pub const AdminCommand = union(enum) {
if (command.consume_str("status")) |_| {
return .status;
}
if (command.consume_str("join").?.consume_char(' ')) |join| {
if (join.rest[0] != '#') {
return .{ .err = .{ .message = "channels must start with \"#\"" } };
if (command.consume_str("join")) |join| {
if (join.consume_space()) |channel| {
if (channel.rest[0] != '#') {
return .{ .err = .{ .message = "channels must start with \"#\"" } };
}
return .{ .join = .{ .channel = join.rest } };
}
return .{ .join = .{ .channel = join.rest } };
}
if (command.consume_str("backlog")) |backlog| {
const history = std.fmt.parseInt(u16, backlog.rest, 10) catch |err| {
std.debug.print("failed to parse int ('{s}') with error: {}\n", .{ backlog.rest, err });
return null;
};
return .{ .backlog = .{ .history = history } };
if (backlog.consume_space()) |history| {
const historyOffset = std.fmt.parseInt(u16, history.rest, 10) catch |err| {
std.debug.print("failed to parse int ('{s}') with error: {}\n", .{ history.rest, err });
return null;
};
return .{ .backlog = .{ .history = historyOffset } };
}
}
std.log.debug("unknown command: \"{s}\"", .{command.rest});
}
@ -104,3 +108,16 @@ test "parse admin commands" {
cmd,
);
}
test "parse backlog admin commands" {
const cmd = AdminCommand.parse("!backlog 1") orelse unreachable;
try std.testing.expectEqual(
AdminCommand{ .backlog = .{ .history = 1 } },
cmd,
);
}
test "parse unknown admin commands" {
const cmd = AdminCommand.parse("!history 1");
try std.testing.expectEqual(null, cmd);
}