feat: add :nick command and /me action messages

- :nick/:name <name>: change username in-session with full validation,
  thread-safe update under write lock, and system broadcast
- /me <action>: IRC-style action messages displayed as "* user action"
- Updated help text (EN/ZH) and manpage with new commands

Closes #38
This commit is contained in:
m1ngsama 2026-04-19 18:34:02 +08:00
parent 450f1828fd
commit e2990000e6
3 changed files with 53 additions and 2 deletions

View file

@ -1147,6 +1147,7 @@ static void execute_command(client_t *client) {
" Available Commands\n" " Available Commands\n"
"========================================\n" "========================================\n"
"list, users, who - Show online users\n" "list, users, who - Show online users\n"
"nick/name <name> - Change nickname\n"
"msg/w <user> <text> - Whisper to user\n" "msg/w <user> <text> - Whisper to user\n"
"help, commands - Show this help\n" "help, commands - Show this help\n"
"clear, cls - Clear command output\n" "clear, cls - Clear command output\n"
@ -1201,6 +1202,40 @@ static void execute_command(client_t *client) {
} }
} }
} else if (strncmp(cmd, "nick ", 5) == 0 || strncmp(cmd, "name ", 5) == 0) {
char *new_name = cmd + 5;
while (*new_name == ' ') new_name++;
if (new_name[0] == '\0') {
buffer_appendf(output, sizeof(output), &pos,
"Usage: nick <new_username>\n");
} else if (!is_valid_username(new_name)) {
buffer_appendf(output, sizeof(output), &pos,
"Invalid username\n");
} else {
char validated_name[MAX_USERNAME_LEN];
snprintf(validated_name, sizeof(validated_name), "%s", new_name);
if (utf8_strlen(validated_name) > 20) {
utf8_truncate(validated_name, 20);
}
char old_name[MAX_USERNAME_LEN];
pthread_rwlock_wrlock(&g_room->lock);
snprintf(old_name, sizeof(old_name), "%s", client->username);
snprintf(client->username, MAX_USERNAME_LEN, "%s", validated_name);
pthread_rwlock_unlock(&g_room->lock);
message_t nick_msg = { .timestamp = time(NULL) };
snprintf(nick_msg.username, MAX_USERNAME_LEN, "系统");
snprintf(nick_msg.content, MAX_MESSAGE_LEN,
"%s 更名为 %s", old_name, client->username);
room_broadcast(g_room, &nick_msg);
message_save(&nick_msg);
buffer_appendf(output, sizeof(output), &pos,
"Nickname changed: %s -> %s\n", old_name, client->username);
}
} else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0 || } else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0 ||
strcmp(cmd, "exit") == 0) { strcmp(cmd, "exit") == 0) {
client->connected = false; client->connected = false;
@ -1296,8 +1331,18 @@ static bool handle_key(client_t *client, unsigned char key, char *input) {
message_t msg = { message_t msg = {
.timestamp = time(NULL), .timestamp = time(NULL),
}; };
if (strncmp(input, "/me ", 4) == 0 && input[4] != '\0') {
msg.username[0] = '*';
msg.username[1] = '\0';
int n = snprintf(msg.content, sizeof(msg.content), "%s %s",
client->username, input + 4);
if (n >= (int)sizeof(msg.content)) {
msg.content[sizeof(msg.content) - 1] = '\0';
}
} else {
snprintf(msg.username, sizeof(msg.username), "%s", client->username); snprintf(msg.username, sizeof(msg.username), "%s", client->username);
snprintf(msg.content, sizeof(msg.content), "%s", input); snprintf(msg.content, sizeof(msg.content), "%s", input);
}
room_broadcast(g_room, &msg); room_broadcast(g_room, &msg);
message_save(&msg); message_save(&msg);
input[0] = '\0'; input[0] = '\0';

View file

@ -301,6 +301,8 @@ const char* tui_get_help_text(help_lang_t lang) {
"\n" "\n"
"AVAILABLE COMMANDS:\n" "AVAILABLE COMMANDS:\n"
" list, users, who - Show online users\n" " list, users, who - Show online users\n"
" nick/name <name> - Change nickname\n"
" msg/w <user> <text> - Whisper to user\n"
" help, commands - Show available commands\n" " help, commands - Show available commands\n"
" clear, cls - Clear command output\n" " clear, cls - Clear command output\n"
"\n" "\n"
@ -347,6 +349,8 @@ const char* tui_get_help_text(help_lang_t lang) {
"\n" "\n"
"可用命令:\n" "可用命令:\n"
" list, users, who - 显示在线用户\n" " list, users, who - 显示在线用户\n"
" nick/name <名字> - 更改昵称\n"
" msg/w <用户> <文本> - 私聊\n"
" help, commands - 显示可用命令\n" " help, commands - 显示可用命令\n"
" clear, cls - 清空命令输出\n" " clear, cls - 清空命令输出\n"
"\n" "\n"

2
tnt.1
View file

@ -97,6 +97,8 @@ Ctrl+C Disconnect
.TS .TS
l l. l l.
:list Show online users :list Show online users
:nick \fIname\fR Change nickname
:name \fIname\fR Alias for :nick
:msg \fIuser text\fR Send private whisper :msg \fIuser text\fR Send private whisper
:w \fIuser text\fR Short alias for :msg :w \fIuser text\fR Short alias for :msg
:help Show available commands :help Show available commands