Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/events/mineflayer/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ function splitRightCarrotInFirstWord(words: string[]): string[] {
* from the message and collapse spaces.
*/
function removePlayerFromMsg(fullMsg: string, player: string): string {
// allow optional spaces, optional < and >, optional trailing colon
const pattern = new RegExp(`\\s*<?\\s*${player}\\s*>?\\s*:?\\s*`, "g");
return fullMsg.replace(pattern, " ").trim().replace(/\s+/g, " ");
// allow optional clan tag inside <>, optional trailing colon
const bracketPattern = new RegExp(`\\s*<\\s*[^>]*\\b${player}\\b\\s*>\\s*:?\\s*`, "g");
const plainPattern = new RegExp(`\\s*<?\\s*${player}\\s*>?\\s*:?\\s*`, "g");
return fullMsg
.replace(bracketPattern, " ")
.replace(plainPattern, " ")
.trim()
.replace(/\s+/g, " ");
}

/**
Expand Down
18 changes: 17 additions & 1 deletion src/events/mineflayer/messagestr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,22 @@ export default {
}

// Fallback for simpler chat formats (e.g., <username> message)
if (!username) {
const clanMatch = rawMessage.match(/^<([^>]+)>\s*(.+)$/);
if (clanMatch) {
const inside = clanMatch[1].trim();
const msgContent = clanMatch[2];
const parts = inside.split(/\s+/);
const nameToken = parts[parts.length - 1];
const possibleUsername = parseUsername(nameToken, Bot.bot);
if (Bot.bot.players[possibleUsername]) {
username = possibleUsername;
uuid = Bot.bot.players[username].uuid;
message = msgContent.trim();
}
}
}

if (!username) {
const chatDividers = ["»", ">>", ">", ":"];
for (const divider of chatDividers) {
Expand Down Expand Up @@ -257,4 +273,4 @@ export default {
}
}
},
};
};
21 changes: 14 additions & 7 deletions src/structure/mineflayer/utils/parseUsername.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import type { Bot } from "mineflayer";

export default function parseUsername(name: string, bot: Bot): string {
let cleanedName = name.trim();
// If a clan/prefix is present, take the last token (usernames have no spaces)
if (cleanedName.includes(" ")) {
const parts = cleanedName.split(/\s+/);
cleanedName = parts[parts.length - 1];
}

// remove everything except word chars, underscores, numbers
name = name.replace(/[^_\w\d]/g, '');
cleanedName = cleanedName.replace(/[^_\w\d]/g, '');

// remove leading "<" if present
if (name.startsWith("<")) {
name = name.slice(1);
if (cleanedName.startsWith("<")) {
cleanedName = cleanedName.slice(1);
}
Comment on lines +15 to 17
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check for a leading "<" character will never match because the previous line (line 12) already removes all non-word characters, underscores, and numbers. The regex [^_\w\d] removes all special characters including "<", so by the time this check runs, any "<" character would already be removed. This check should either be moved before line 12, or removed entirely if it's no longer needed.

Copilot uses AI. Check for mistakes.

// if exact match, return early
if (bot.players[name] && name === bot.players[name].displayName.toString()) {
return name;
if (bot.players[cleanedName] && cleanedName === bot.players[cleanedName].displayName.toString()) {
return cleanedName;
}

// try to resolve real username
Expand All @@ -25,11 +32,11 @@ export default function parseUsername(name: string, bot: Bot): string {
}

// strict equality check, not includes
if (name === displayName || name === user) {
if (cleanedName === displayName || cleanedName === user) {
return user;
}
}

// fallback
return name;
return cleanedName;
}
Loading