···
console.error("IRC error:", error);
250
+
// Handle IRC /me actions
251
+
ircClient.addListener("action", async (nick: string, to: string, text: string) => {
252
+
// Ignore messages from our own bot
253
+
const botNickPattern = new RegExp(`^${process.env.IRC_NICK}\\d*$`);
254
+
if (botNickPattern.test(nick)) return;
255
+
if (nick === "****") return;
257
+
// Find Slack channel mapping for this IRC channel
258
+
const mapping = channelMappings.getByIrcChannel(to);
259
+
if (!mapping) return;
261
+
// Check if this IRC nick is mapped to a Slack user
262
+
const userMapping = userMappings.getByIrcNick(nick);
264
+
let iconUrl: string;
266
+
iconUrl = `https://cachet.dunkirk.sh/users/${userMapping.slack_user_id}/r`;
268
+
iconUrl = getAvatarForNick(nick);
271
+
// Parse IRC formatting and mentions
272
+
let messageText = parseIRCFormatting(text);
274
+
// Find all @mentions and nick: mentions in the IRC message
275
+
const atMentionPattern = /@(\w+)/g;
276
+
const nickMentionPattern = /(\w+):/g;
278
+
const atMentions = Array.from(messageText.matchAll(atMentionPattern));
279
+
const nickMentions = Array.from(messageText.matchAll(nickMentionPattern));
281
+
for (const match of atMentions) {
282
+
const mentionedNick = match[1] as string;
283
+
const mentionedUserMapping = userMappings.getByIrcNick(mentionedNick);
284
+
if (mentionedUserMapping) {
285
+
messageText = messageText.replace(
287
+
`<@${mentionedUserMapping.slack_user_id}>`,
292
+
for (const match of nickMentions) {
293
+
const mentionedNick = match[1] as string;
294
+
const mentionedUserMapping = userMappings.getByIrcNick(mentionedNick);
295
+
if (mentionedUserMapping) {
296
+
messageText = messageText.replace(
298
+
`<@${mentionedUserMapping.slack_user_id}>:`,
303
+
// Format as action message with context block
304
+
const actionText = `${nick} ${messageText}`;
306
+
await slackClient.chat.postMessage({
307
+
token: process.env.SLACK_BOT_TOKEN,
308
+
channel: mapping.slack_channel_id,
316
+
image_url: iconUrl,
328
+
console.log(`IRC → Slack (action): ${actionText}`);
slackApp.event("message", async ({ payload, context }) => {
// Ignore bot messages and threaded messages