feat(reminders): получатели в отложенных/входящих, приватные сообщения чата, календарь, бейдж уведомлений
This commit is contained in:
@@ -444,7 +444,9 @@ export class NotificationService {
|
||||
formId: data.formId.toString(),
|
||||
isChat: isChatNotification ? 'true' : 'false',
|
||||
...(data.messageId ? { messageId: data.messageId.toString() } : {}),
|
||||
type: 'chat',
|
||||
// Чатовые уведомления сохраняем с type 'chat' (SW-обработчики кнопок «Ответить»/«Прочитано»),
|
||||
// остальные — с реальным типом, чтобы не глушились suppression-логикой активного чата
|
||||
type: isChatNotification ? 'chat' : (data.type || 'notification'),
|
||||
}
|
||||
: undefined;
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@ export interface SendTaskMessageParams {
|
||||
botId?: number | null; // сообщение от бота: authorId=null, botId, messageType='bot'
|
||||
organizationId: number;
|
||||
message: string;
|
||||
messageType?: string; // 'comment' (default), 'bot', 'system', ...
|
||||
messageType?: string; // 'comment' (default), 'bot', 'system', 'status_change', 'reminder', ...
|
||||
replyToMessageId?: number | null;
|
||||
mentionedUserIds?: number[] | null;
|
||||
mentionedBotIds?: number[] | null;
|
||||
attachments?: MessageAttachment[] | null;
|
||||
bodyAuthorId?: number | null; // authorId из тела запроса (null — признак бот/системного сообщения)
|
||||
isBotToken?: boolean; // запрос аутентифицирован bot-service JWT
|
||||
visibleToUserIds?: number[] | null; // приватность: только перечисленные пользователи видят сообщение (NULL — все участники чата)
|
||||
}
|
||||
|
||||
// Создаёт сообщение задачи со всеми side-эффектами:
|
||||
@@ -47,10 +48,10 @@ export interface SendTaskMessageParams {
|
||||
export async function sendTaskMessage(params: SendTaskMessageParams): Promise<TaskMessage> {
|
||||
const { task, user, organizationId } = params;
|
||||
const botId = params.botId ?? null;
|
||||
// Системные сообщения ('system', 'status_change') могут быть без автора —
|
||||
// их пишут автоматизации (ctx.tasks.sendMessage), автор в чате — «Система»
|
||||
// Системные сообщения ('system', 'status_change', 'reminder') могут быть без автора —
|
||||
// их пишут автоматизации (ctx.tasks.sendMessage, напоминания), автор в чате — «Система»
|
||||
const isAuthorlessSystem = !user && !botId &&
|
||||
(params.messageType === 'system' || params.messageType === 'status_change');
|
||||
(params.messageType === 'system' || params.messageType === 'status_change' || params.messageType === 'reminder');
|
||||
if (!user && !botId && !isAuthorlessSystem) {
|
||||
throw new SendTaskMessageError('Не указан автор сообщения (user или botId)', 500);
|
||||
}
|
||||
@@ -105,6 +106,9 @@ export async function sendTaskMessage(params: SendTaskMessageParams): Promise<Ta
|
||||
messageType,
|
||||
mentionedUserIds: mentionedUserIds.length > 0 ? mentionedUserIds : null,
|
||||
attachments: params.attachments?.length ? params.attachments : null,
|
||||
visibleToUserIds: params.visibleToUserIds && params.visibleToUserIds.length > 0
|
||||
? [...new Set(params.visibleToUserIds)]
|
||||
: null,
|
||||
};
|
||||
|
||||
const createdMessage = await storage.createTaskMessage(messageData, organizationId);
|
||||
@@ -232,12 +236,30 @@ export async function sendTaskMessage(params: SendTaskMessageParams): Promise<Ta
|
||||
}
|
||||
}
|
||||
|
||||
eventBus.publishEvent({
|
||||
type: 'message_created',
|
||||
data: { taskId: taskId, message: createdMessage },
|
||||
organizationId,
|
||||
taskId: taskId
|
||||
});
|
||||
// Приватные сообщения (visible_to_user_ids): SSE-событие получают только
|
||||
// разрешённые пользователи (перечисленные + автор). Остальные участники чата
|
||||
// событие не получают и сообщение не увидят ни в реальном времени, ни при загрузке
|
||||
// (фильтр в storage.getTaskMessages по viewerUserId).
|
||||
const visibleTo = messageData.visibleToUserIds;
|
||||
if (visibleTo && visibleTo.length > 0) {
|
||||
const allowed = new Set<number>(visibleTo);
|
||||
if (user?.id) allowed.add(user.id);
|
||||
for (const uid of allowed) {
|
||||
eventBus.publishEvent({
|
||||
type: 'message_created',
|
||||
data: { taskId: taskId, message: createdMessage },
|
||||
organizationId,
|
||||
userId: uid,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
eventBus.publishEvent({
|
||||
type: 'message_created',
|
||||
data: { taskId: taskId, message: createdMessage },
|
||||
organizationId,
|
||||
taskId: taskId
|
||||
});
|
||||
}
|
||||
|
||||
// Уведомления и исходящие вебхуки — только для сообщений от пользователя
|
||||
// (для bot-сообщений — как в POST /api/bot/message: без notificationService).
|
||||
|
||||
Reference in New Issue
Block a user