Files
ai-code-app/etc/servers/work-server/src/services/plan-notification-service.ts

117 lines
2.9 KiB
TypeScript

import { sendNotifications } from './notification-service.js';
import type { AppConfigSnapshot } from './app-config-service.js';
import { getPlanItemById } from './plan-service.js';
function buildPlanNotificationTargetUrl(planId: number, workId: string | null | undefined) {
const targetUrl = new URL('https://sm-home.cloud/');
targetUrl.searchParams.set('topMenu', 'plans');
targetUrl.searchParams.set('planId', String(planId));
if (workId?.trim()) {
targetUrl.searchParams.set('workId', workId.trim());
}
return targetUrl.toString();
}
export function shouldNotifyPlanEventType(
automation: AppConfigSnapshot['automation'] | undefined,
eventType: string,
) {
if (eventType === 'work-started') {
return automation?.notifyOnAutomationStart ?? true;
}
if (eventType === 'work-progress') {
return automation?.notifyOnAutomationProgress ?? true;
}
if (
eventType === 'work-completed' ||
eventType === 'work-noop-complete' ||
eventType === 'development-completed' ||
eventType === 'plan-completed'
) {
return automation?.notifyOnAutomationCompletion ?? true;
}
if (eventType === 'release-merged') {
return automation?.notifyOnAutomationRelease ?? true;
}
if (eventType === 'main-merged') {
return automation?.notifyOnAutomationMain ?? true;
}
if (
eventType === 'branch-failed' ||
eventType === 'work-failed' ||
eventType === 'release-failed' ||
eventType === 'main-failed'
) {
return automation?.notifyOnAutomationFailure ?? true;
}
if (eventType === 'plan-restarted') {
return automation?.notifyOnAutomationRestart ?? true;
}
if (eventType === 'issue-resolved') {
return automation?.notifyOnAutomationIssueResolved ?? true;
}
return true;
}
export async function shouldSendPlanNotification(eventType: string) {
void eventType;
return true;
}
export function buildPlanNotificationData(planId: number, workId: string | null | undefined, eventType: string) {
return {
category: 'automation',
planId: String(planId),
workId: String(workId ?? ''),
eventType,
notificationScope: 'automation',
targetUrl: buildPlanNotificationTargetUrl(planId, workId),
notificationKey: `plan:${planId}`,
};
}
export async function notifyPlanEvent(
planId: number,
title: string,
body: string,
eventType: string,
) {
if (!(await shouldSendPlanNotification(eventType))) {
return {
ok: true,
skipped: true,
reason: '앱 설정에서 이 알림 항목이 꺼져 있습니다.',
};
}
const item = await getPlanItemById(planId);
if (!item) {
return {
ok: false,
skipped: true,
reason: '작업 항목을 찾을 수 없습니다.',
};
}
return sendNotifications({
title,
body,
threadId: `plan-${planId}`,
data: buildPlanNotificationData(planId, String(item.workId), eventType),
}, {
disableWebPush: Boolean(item.suppressWebPush),
});
}