import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime"; import type { TwitchAccountConfig, TwitchChatMessage } from "./types.js";
/** * Result of checking access control for a Twitch message
*/
export type TwitchAccessControlResult = {
allowed: boolean;
reason?: string;
matchKey?: string;
matchSource?: string;
};
/** * Check if a Twitch message should be allowed based on account configuration * * This function implements the access control logic for incoming Twitch messages, * checking allowlists, role-based restrictions, and mention requirements. * * Priority order: * 1. If `requireMention` is true, message must mention the bot * 2. If `allowFrom` is set, sender must be in the allowlist (by user ID) * 3. If `allowedRoles` is set (and `allowFrom` is not), sender must have at least one role * * Note: `allowFrom` is a hard allowlist. When set, only those user IDs are allowed. * Use `allowedRoles` as an alternative when you don't want to maintain an allowlist. * * Available roles: * - "moderator": Moderators * - "owner": Channel owner/broadcaster * - "vip": VIPs * - "subscriber": Subscribers * - "all": Anyone in the chat
*/
export function checkTwitchAccessControl(params: {
message: TwitchChatMessage;
account: TwitchAccountConfig;
botUsername: string;
}): TwitchAccessControlResult { const { message, account, botUsername } = params;
if (account.requireMention ?? true) { const mentions = extractMentions(message.message); if (!mentions.includes(normalizeLowercaseStringOrEmpty(botUsername))) { return {
allowed: false,
reason: "message does not mention the bot (requireMention is enabled)",
};
}
}
if (account.allowFrom !== undefined) { const allowFrom = account.allowFrom; if (allowFrom.length === 0) { return {
allowed: false,
reason: "sender is not in allowFrom allowlist",
};
} const senderId = message.userId;
if (!senderId) { return {
allowed: false,
reason: "sender user ID not available for allowlist check",
};
}
/** * Check if the sender has any of the allowed roles
*/ function checkSenderRoles(params: { message: TwitchChatMessage; allowedRoles: string[] }): boolean { const { message, allowedRoles } = params; const { isMod, isOwner, isVip, isSub } = message;
for (const role of allowedRoles) { switch (role) { case"moderator": if (isMod) { returntrue;
} break; case"owner": if (isOwner) { returntrue;
} break; case"vip": if (isVip) { returntrue;
} break; case"subscriber": if (isSub) { returntrue;
} break;
}
}
returnfalse;
}
/** * Extract @mentions from a Twitch chat message * * Returns a list of lowercase usernames that were mentioned in the message. * Twitch mentions are in the format @username.
*/
export function extractMentions(message: string): string[] { const mentionRegex = /@(\w+)/g; const mentions: string[] = [];
let match: RegExpExecArray | null;
while ((match = mentionRegex.exec(message)) !== null) { const username = match[1]; if (username) {
mentions.push(normalizeLowercaseStringOrEmpty(username));
}
}
return mentions;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-05-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.