2bcfb9f6f4
Tests / frontend-test (pull_request) Failing after 28s
Иначе сообщение из одного файла приходило письмом с пустым текстом. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
3.9 KiB
TypeScript
84 lines
3.9 KiB
TypeScript
import { IChatParticipant, extractMentionedEmails } from './chatMentions';
|
|
|
|
/**
|
|
* Тело запроса к потоку оповещения о сообщении в чате (FLOW_CHAT_NOTIFY_URL).
|
|
* Контракт потока: все поля — строки, кроме mentionedEmails; никого не
|
|
* отметили — пустой массив, а не null и не пропущенное поле.
|
|
*/
|
|
export interface IChatNotifyBody {
|
|
initiatorEmail: string;
|
|
mentionedEmails: string[];
|
|
authorName: string;
|
|
messageText: string;
|
|
RequestUniqueCode: string;
|
|
requestUrl: string;
|
|
requestTitle: string;
|
|
}
|
|
|
|
export interface IChatNotifyInput {
|
|
/** Инициатор заявки (автор строки списка данных). */
|
|
initiatorEmail: string;
|
|
/** Кого можно было отметить — по ним ищутся «@ФИО» в тексте. */
|
|
participants: IChatParticipant[];
|
|
authorName: string;
|
|
authorEmail: string;
|
|
messageText: string;
|
|
/** Имена приложенных файлов, как их выбрал пользователь (без складского префикса). */
|
|
fileNames?: string[];
|
|
requestCode: string;
|
|
requestUrl: string;
|
|
requestTitle: string;
|
|
/** Режим проверки (свойство веб-части chatSelfNotify): письма и о своих сообщениях. */
|
|
selfNotify: boolean;
|
|
}
|
|
|
|
const sameEmail = (a: string, b: string): boolean => a.toLowerCase() === b.toLowerCase();
|
|
|
|
/**
|
|
* Текст для письма: сообщение и строка о файлах. Без неё сообщение из одного
|
|
* файла пришло бы письмом с пустым текстом. Сами файлы в письмо не кладём —
|
|
* они в библиотеке, открываются по ссылке на заявку.
|
|
*/
|
|
function letterText(text: string, fileNames: string[]): string {
|
|
if (fileNames.length === 0) return text;
|
|
const files = `Прикреплены файлы: ${fileNames.join(', ')}`;
|
|
return text ? `${text}\n\n${files}` : files;
|
|
}
|
|
|
|
/**
|
|
* Собрать тело запроса к потоку или undefined, если писать некому.
|
|
*
|
|
* Поток шлёт инициатору письмо ВСЕГДА, когда его нет среди отмеченных. Значит,
|
|
* когда пишет сам инициатор (а режим проверки выключен), письмо «новое сообщение
|
|
* по вашей заявке» ушло бы ему же. Отключить его в контракте потока нечем,
|
|
* поэтому:
|
|
* — никого не отметил → поток не вызываем вовсе;
|
|
* — кого-то отметил → в initiatorEmail кладём первого отмеченного: по
|
|
* контракту отмеченный инициатор получает только «Вас упомянули», и
|
|
* лишнего письма никому не уходит.
|
|
*/
|
|
export function buildChatNotifyBody(input: IChatNotifyInput): IChatNotifyBody | undefined {
|
|
const mentioned = extractMentionedEmails(input.messageText, input.participants).filter(
|
|
(email) => input.selfNotify || !sameEmail(email, input.authorEmail)
|
|
);
|
|
|
|
let initiatorEmail = input.initiatorEmail;
|
|
const authorIsInitiator =
|
|
!!initiatorEmail && !!input.authorEmail && sameEmail(initiatorEmail, input.authorEmail);
|
|
if (authorIsInitiator && !input.selfNotify) {
|
|
if (mentioned.length === 0) return undefined;
|
|
initiatorEmail = mentioned[0];
|
|
}
|
|
if (!initiatorEmail && mentioned.length === 0) return undefined;
|
|
|
|
return {
|
|
initiatorEmail,
|
|
mentionedEmails: mentioned,
|
|
authorName: input.authorName,
|
|
messageText: letterText(input.messageText, input.fileNames || []),
|
|
RequestUniqueCode: input.requestCode,
|
|
requestUrl: input.requestUrl,
|
|
requestTitle: input.requestTitle
|
|
};
|
|
}
|