feat: aplicar codeId y monoespacio en listados, ayudas y mensajes

Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>
pull/1/head
borja 2 months ago
parent 60ed92970b
commit fe5a8d29cb

@ -170,7 +170,7 @@ export class CommandService {
' · Tomar: tomar, claim',
' · Soltar: soltar, unassign',
'- Preferencias:',
' · /t configurar daily|weekly|off (hora por defecto 08:30; semanal: lunes 08:30)',
' · `/t configurar daily|weekly|off` (hora por defecto 08:30; semanal: lunes 08:30)',
'- Notas:',
' · En grupos, el bot responde por DM al autor (no publica en el grupo).',
' · Si creas en grupo y no mencionas a nadie → “sin responsable”; en DM → se asigna al creador.',
@ -184,12 +184,12 @@ export class CommandService {
}
const help = [
'Guía rápida:',
'- Crear: /t n Descripción mañana @Ana',
'- Ver grupo: /t ver grupo',
'- Ver mis: /t ver mis',
'- Ver todos: /t ver todos',
'- Completar: /t x 123',
'- Configurar recordatorios: /t configurar daily|weekly|off'
'- Crear: `/t n Descripción mañana @Ana`',
'- Ver grupo: `/t ver grupo`',
'- Ver mis: `/t ver mis`',
'- Ver todos: `/t ver todos`',
'- Completar: `/t x 123`',
'- Configurar recordatorios: `/t configurar daily|weekly|off`'
].join('\n');
return [{
recipient: context.sender,
@ -217,7 +217,7 @@ export class CommandService {
if (!isGroupId(context.groupId)) {
return [{
recipient: context.sender,
message: 'Este comando se usa en grupos. Prueba: /t ver mis'
message: 'Este comando se usa en grupos. Prueba: `/t ver mis`'
}];
}
if (!GroupSyncService.isGroupActive(context.groupId)) {
@ -239,7 +239,7 @@ export class CommandService {
const rendered = items.map((t) => {
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
});
const total = TaskService.countGroupUnassigned(context.groupId);
@ -288,7 +288,7 @@ export class CommandService {
: `${t.assignees!.length > 1 ? '👥' : '👤'} ${names.join(', ')}`;
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${owner}`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${owner}`;
}));
sections.push(...rendered);
}
@ -313,7 +313,7 @@ export class CommandService {
const renderedUnassigned = unassigned.map((t) => {
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
});
sections.push(...renderedUnassigned);
@ -341,7 +341,7 @@ export class CommandService {
const renderedUnassigned = unassigned.map((t) => {
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${ICONS.unassigned} sin responsable`;
});
sections.push(...renderedUnassigned);
@ -353,7 +353,7 @@ export class CommandService {
}
} else {
// Si no hay snapshot fresca de membresía, mantenemos una nota instructiva mínima
sections.push(' Para ver tareas sin responsable de un grupo, usa “/t ver sin” desde ese grupo.');
sections.push(' Para ver tareas sin responsable de un grupo, usa `/t ver sin` desde ese grupo.');
}
}
@ -368,7 +368,7 @@ export class CommandService {
if (!isGroupId(context.groupId)) {
return [{
recipient: context.sender,
message: 'Este comando se usa en grupos. Prueba: /t ver mis'
message: 'Este comando se usa en grupos. Prueba: `/t ver mis`'
}];
}
if (!GroupSyncService.isGroupActive(context.groupId)) {
@ -407,7 +407,7 @@ export class CommandService {
: `${t.assignees!.length > 1 ? '👥' : '👤'} ${names.join(', ')}`;
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${owner}`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${owner}`;
}));
const total = TaskService.countGroupPending(context.groupId);
@ -458,7 +458,7 @@ export class CommandService {
: `${t.assignees!.length > 1 ? '👥' : '👤'} ${names.join(', ')}`;
const isOverdue = t.due_date ? t.due_date < todayYMD : false;
const datePart = t.due_date ? `${isOverdue ? `${ICONS.warn} ` : ''}${ICONS.date} ${formatDDMM(t.due_date)}` : '';
return `- ${t.id}) _${t.description || '(sin descripción)'}_${datePart}${owner}`;
return `- ${codeId(t.id)} _${t.description || '(sin descripción)'}_${datePart}${owner}`;
}));
sections.push(...rendered);
}
@ -480,7 +480,7 @@ export class CommandService {
if (!id || Number.isNaN(id)) {
return [{
recipient: context.sender,
message: ' Uso: /t x 26'
message: ' Uso: `/t x 26`'
}];
}
@ -518,7 +518,7 @@ export class CommandService {
const due = res.task?.due_date ? `${ICONS.date} ${formatDDMM(res.task?.due_date)}` : '';
return [{
recipient: context.sender,
message: `${ICONS.complete} ${id} completada — _${res.task?.description || '(sin descripción)'}_${due}`
message: `${ICONS.complete} ${codeId(id)} completada — _${res.task?.description || '(sin descripción)'}_${due}`
}];
}
@ -529,7 +529,7 @@ export class CommandService {
if (!id || Number.isNaN(id)) {
return [{
recipient: context.sender,
message: ' Uso: /t tomar 26'
message: ' Uso: `/t tomar 26`'
}];
}
@ -588,7 +588,7 @@ export class CommandService {
if (!id || Number.isNaN(id)) {
return [{
recipient: context.sender,
message: ' Uso: /t soltar 26'
message: ' Uso: `/t soltar 26`'
}];
}
@ -669,7 +669,7 @@ export class CommandService {
if (!freq) {
return [{
recipient: context.sender,
message: 'Uso: /t configurar daily|weekly|off'
message: 'Uso: `/t configurar daily|weekly|off`'
}];
}
const ensured = ensureUserExists(context.sender, this.dbInstance);
@ -809,7 +809,8 @@ export class CommandService {
`${description || '(sin descripción)'}`,
formatDDMM(dueDate) ? `${ICONS.date} ${formatDDMM(dueDate)}` : null,
groupName ? `Grupo: ${groupName}` : null,
italic(`Acciones: Completar → /t x ${taskId} · Soltar → /t soltar ${taskId}`)
`- Completar: \`/t x ${taskId}\``,
`- Soltar: \`/t soltar ${taskId}\``
].filter(Boolean).join('\n'),
mentions: [creatorJid]
});

@ -47,7 +47,7 @@ describe('CommandService - /t tomar y /t soltar', () => {
const res = await CommandService.handle(ctx('111', '/t tomar'));
expect(res).toHaveLength(1);
expect(res[0].recipient).toBe('111');
expect(res[0].message).toContain('Uso: /t tomar 26');
expect(res[0].message).toContain('Uso: `/t tomar 26`');
});
it('tomar: not_found', async () => {
@ -78,7 +78,7 @@ describe('CommandService - /t tomar y /t soltar', () => {
it('soltar: uso inválido (sin id)', async () => {
const res = await CommandService.handle(ctx('111', '/t soltar'));
expect(res[0].message).toContain('Uso: /t soltar 26');
expect(res[0].message).toContain('Uso: `/t soltar 26`');
});
it('soltar: not_found', async () => {

@ -73,7 +73,7 @@ describe('CommandService - configurar recordatorios', () => {
it('configurar con opción inválida devuelve uso correcto y no escribe en DB', async () => {
const res = await runCmd('/t configurar foo');
expect(res).toHaveLength(1);
expect(res[0].message).toContain('Uso: /t configurar daily|weekly|off');
expect(res[0].message).toContain('Uso: `/t configurar daily|weekly|off`');
const pref = getPref();
expect(pref).toBeNull();

@ -93,8 +93,8 @@ test('listar “mis” por defecto en DM con /t ver', async () => {
const msg = responses[0].message;
expect(msg).toContain('Test Group');
expect(msg).toContain('Group 2');
expect(msg).toMatch(/- \d+\) _G1 Task_/);
expect(msg).toMatch(/- \d+\) _G2 Task_/);
expect(msg).toMatch(/- `\d{4}` _G1 Task_/);
expect(msg).toMatch(/- `\d{4}` _G2 Task_/);
});
test('completar tarea: camino feliz, ya completada y no encontrada', async () => {
@ -122,7 +122,7 @@ test('completar tarea: camino feliz, ya completada y no encontrada', async () =>
});
expect(responses.length).toBe(1);
expect(responses[0].recipient).toBe('1234567890');
expect(responses[0].message).toContain(`${taskId} completada`);
expect(responses[0].message).toMatch(/^✅ `\d{4}` completada/);
// 2) Ya completada
responses = await CommandService.handle({

Loading…
Cancel
Save