refactor(channels): share reset-command normalization utility

This commit is contained in:
William Valentin
2026-02-15 22:22:40 -08:00
parent 05d8abc79d
commit 8b529a18f2
7 changed files with 59 additions and 11 deletions
+4 -3
View File
@@ -17,7 +17,7 @@ import type {
ChannelAdapter,
ChannelStatus,
} from '../types.js';
import { splitMessage } from '../utils.js';
import { normalizeResetCommandText, splitMessage } from '../utils.js';
import type { PairingManager } from '../pairing.js';
/** Configuration for the Discord channel adapter. */
@@ -221,7 +221,8 @@ export class DiscordAdapter implements ChannelAdapter {
} catch { /* ignore typing errors */ }
// Strip bot mention from the message text
const text = message.content.replace(/<@!?\d+>/g, '').trim();
const rawText = message.content.replace(/<@!?\d+>/g, '').trim();
const text = normalizeResetCommandText(rawText);
// ── Extract media attachments ──
const attachments: Attachment[] = [];
@@ -240,7 +241,7 @@ export class DiscordAdapter implements ChannelAdapter {
}
// ── Reset command ──
if (text === '!reset' || text === 'reset') {
if (text === '!reset') {
this.messageHandler({
id: message.id,
channel: 'discord',
+4 -3
View File
@@ -15,7 +15,7 @@ import type {
ChannelAdapter,
ChannelStatus,
} from '../types.js';
import { splitMessage } from '../utils.js';
import { normalizeResetCommandText, splitMessage } from '../utils.js';
import type { PairingManager } from '../pairing.js';
/** Configuration for the Slack channel adapter. */
@@ -344,7 +344,8 @@ export class SlackAdapter implements ChannelAdapter {
const peerId = `${channelId}:${threadTs}`;
// Strip bot mentions: <@U\w+> pattern
let text = (message.text ?? '').replace(/<@U\w+>/g, '').trim();
const rawText = (message.text ?? '').replace(/<@U\w+>/g, '').trim();
const text = normalizeResetCommandText(rawText);
// Resolve display name from Slack user ID
const senderName = message.user
@@ -355,7 +356,7 @@ export class SlackAdapter implements ChannelAdapter {
const attachments = await this.extractMediaAttachments(message.files);
// Detect reset command
if (text === '!reset' || text === 'reset') {
if (text === '!reset') {
this.messageHandler({
id: message.ts ?? '',
channel: 'slack',
+15 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import { splitMessage } from './utils.js';
import { normalizeResetCommandText, splitMessage } from './utils.js';
describe('splitMessage', () => {
it('returns single chunk for empty string', () => {
@@ -84,3 +84,17 @@ describe('splitMessage', () => {
expect(result[1]).toBe('klmnopqrst');
});
});
describe('normalizeResetCommandText', () => {
it('normalizes reset to !reset', () => {
expect(normalizeResetCommandText('reset')).toBe('!reset');
});
it('keeps !reset unchanged', () => {
expect(normalizeResetCommandText('!reset')).toBe('!reset');
});
it('does not change non-command text', () => {
expect(normalizeResetCommandText('hello')).toBe('hello');
});
});
+11
View File
@@ -31,3 +31,14 @@ export function splitMessage(text: string, maxLength: number): string[] {
return chunks;
}
/**
* Normalize reset command variants to a canonical text form.
* Returns '!reset' for recognized variants, otherwise returns the original text.
*/
export function normalizeResetCommandText(text: string): string {
if (text === '!reset' || text === 'reset') {
return '!reset';
}
return text;
}
+4 -2
View File
@@ -17,7 +17,7 @@ import type {
ChannelAdapter,
ChannelStatus,
} from '../types.js';
import { splitMessage } from '../utils.js';
import { normalizeResetCommandText, splitMessage } from '../utils.js';
import type { PairingManager } from '../pairing.js';
/** Configuration for the WhatsApp channel adapter. */
@@ -309,8 +309,10 @@ export class WhatsAppAdapter implements ChannelAdapter {
}
}
text = normalizeResetCommandText(text);
// Detect reset command
if (text === '!reset' || text === 'reset') {
if (text === '!reset') {
this.messageHandler({
id: message.id.id,
channel: 'whatsapp',