Only notify segment changes when amount has changed
This commit is contained in:
@@ -44,9 +44,16 @@ async function processProjectSegments(projectId: string, projectName?: string):
|
|||||||
`[SEGMENT-COUNT-WORKER] Segment "${segment.name}": +${result.added} entries, -${result.removed} exits, ${result.total} total members`,
|
`[SEGMENT-COUNT-WORKER] Segment "${segment.name}": +${result.added} entries, -${result.removed} exits, ${result.total} total members`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Notify about segment membership update (only for tracked segments)
|
// Notify about segment membership update only if there were actual changes
|
||||||
if (projectName) {
|
if (projectName && (result.added > 0 || result.removed > 0)) {
|
||||||
await NtfyService.notifySegmentMembershipComputed(segment.name, projectName, projectId, result.total);
|
await NtfyService.notifySegmentMembershipComputed(
|
||||||
|
segment.name,
|
||||||
|
projectName,
|
||||||
|
projectId,
|
||||||
|
result.total,
|
||||||
|
result.added,
|
||||||
|
result.removed,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
signale.error(`[SEGMENT-COUNT-WORKER] Failed to compute membership for segment ${segment.id}:`, error);
|
signale.error(`[SEGMENT-COUNT-WORKER] Failed to compute membership for segment ${segment.id}:`, error);
|
||||||
|
|||||||
@@ -43,24 +43,6 @@ export class NtfyService {
|
|||||||
private static ntfyUrl: string | null = null;
|
private static ntfyUrl: string | null = null;
|
||||||
private static isConfigured = false;
|
private static isConfigured = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the ntfy service with the configured URL
|
|
||||||
*/
|
|
||||||
private static initialize(): void {
|
|
||||||
if (this.isConfigured) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ntfyUrl = process.env.NTFY_URL || null;
|
|
||||||
this.isConfigured = true;
|
|
||||||
|
|
||||||
if (!this.ntfyUrl) {
|
|
||||||
signale.warn('[NTFY] NTFY_URL not configured - notifications will be skipped');
|
|
||||||
} else {
|
|
||||||
signale.info(`[NTFY] Initialized with URL: ${this.ntfyUrl}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a notification to ntfy
|
* Send a notification to ntfy
|
||||||
* @param notification - The notification details
|
* @param notification - The notification details
|
||||||
@@ -77,7 +59,7 @@ export class NtfyService {
|
|||||||
try {
|
try {
|
||||||
const headers: Record<string, string> = {
|
const headers: Record<string, string> = {
|
||||||
'Content-Type': 'text/plain',
|
'Content-Type': 'text/plain',
|
||||||
Title: notification.title,
|
'Title': notification.title,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (notification.priority) {
|
if (notification.priority) {
|
||||||
@@ -153,8 +135,6 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Event-specific notification helpers =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about a new project creation
|
* Notify about a new project creation
|
||||||
*/
|
*/
|
||||||
@@ -166,6 +146,8 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Event-specific notification helpers =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about subscription started
|
* Notify about subscription started
|
||||||
*/
|
*/
|
||||||
@@ -216,11 +198,10 @@ export class NtfyService {
|
|||||||
* Notify about payment failure
|
* Notify about payment failure
|
||||||
*/
|
*/
|
||||||
public static async notifyPaymentFailed(projectName: string, projectId: string): Promise<void> {
|
public static async notifyPaymentFailed(projectName: string, projectId: string): Promise<void> {
|
||||||
await this.sendHigh(
|
await this.sendHigh('Payment Failed', `Payment failed for project "${projectName}" (${projectId})`, [
|
||||||
'Payment Failed',
|
NtfyTag.WARNING,
|
||||||
`Payment failed for project "${projectName}" (${projectId})`,
|
NtfyTag.MONEY,
|
||||||
[NtfyTag.WARNING, NtfyTag.MONEY],
|
]);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -251,21 +232,15 @@ export class NtfyService {
|
|||||||
* Notify about project deletion - DEFAULT priority
|
* Notify about project deletion - DEFAULT priority
|
||||||
*/
|
*/
|
||||||
public static async notifyProjectDeleted(projectName: string, projectId: string, userId: string): Promise<void> {
|
public static async notifyProjectDeleted(projectName: string, projectId: string, userId: string): Promise<void> {
|
||||||
await this.sendDefault(
|
await this.sendDefault('Project Deleted', `Project "${projectName}" (${projectId}) was deleted by user ${userId}`, [
|
||||||
'Project Deleted',
|
NtfyTag.WARNING,
|
||||||
`Project "${projectName}" (${projectId}) was deleted by user ${userId}`,
|
]);
|
||||||
[NtfyTag.WARNING],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about security warning (non-critical)
|
* Notify about security warning (non-critical)
|
||||||
*/
|
*/
|
||||||
public static async notifySecurityWarning(
|
public static async notifySecurityWarning(projectName: string, projectId: string, warnings: string[]): Promise<void> {
|
||||||
projectName: string,
|
|
||||||
projectId: string,
|
|
||||||
warnings: string[],
|
|
||||||
): Promise<void> {
|
|
||||||
const warningText = warnings.join(', ');
|
const warningText = warnings.join(', ');
|
||||||
await this.sendDefault(
|
await this.sendDefault(
|
||||||
'Security Warning',
|
'Security Warning',
|
||||||
@@ -338,9 +313,7 @@ export class NtfyService {
|
|||||||
projectCounts.sort((a, b) => b.count - a.count);
|
projectCounts.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
// Build breakdown message
|
// Build breakdown message
|
||||||
const breakdown = projectCounts
|
const breakdown = projectCounts.map(p => ` • ${p.name} (${p.projectId}): ${p.count}`).join('\n');
|
||||||
.map((p) => ` • ${p.name} (${p.projectId}): ${p.count}`)
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
const bounceInfo = bounceType ? ` (${bounceType})` : '';
|
const bounceInfo = bounceType ? ` (${bounceType})` : '';
|
||||||
await this.send({
|
await this.send({
|
||||||
@@ -395,8 +368,6 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Campaign event notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about campaign created (draft) - LOW priority
|
* Notify about campaign created (draft) - LOW priority
|
||||||
*/
|
*/
|
||||||
@@ -413,6 +384,8 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Campaign event notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about campaign scheduled - DEFAULT priority
|
* Notify about campaign scheduled - DEFAULT priority
|
||||||
*/
|
*/
|
||||||
@@ -495,8 +468,6 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Workflow event notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about workflow created - LOW priority
|
* Notify about workflow created - LOW priority
|
||||||
*/
|
*/
|
||||||
@@ -513,6 +484,8 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Workflow event notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about workflow enabled
|
* Notify about workflow enabled
|
||||||
*/
|
*/
|
||||||
@@ -576,8 +549,6 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Domain verification notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about domain added
|
* Notify about domain added
|
||||||
*/
|
*/
|
||||||
@@ -589,6 +560,8 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Domain verification notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about domain verified
|
* Notify about domain verified
|
||||||
*/
|
*/
|
||||||
@@ -626,8 +599,6 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Billing and usage limit notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about billing limit approaching (80% threshold)
|
* Notify about billing limit approaching (80% threshold)
|
||||||
*/
|
*/
|
||||||
@@ -646,6 +617,8 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Billing and usage limit notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about billing limit exceeded - MAX priority (blocks operations)
|
* Notify about billing limit exceeded - MAX priority (blocks operations)
|
||||||
*/
|
*/
|
||||||
@@ -663,16 +636,10 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== API key notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about API keys regenerated
|
* Notify about API keys regenerated
|
||||||
*/
|
*/
|
||||||
public static async notifyApiKeysRegenerated(
|
public static async notifyApiKeysRegenerated(projectName: string, projectId: string, userId: string): Promise<void> {
|
||||||
projectName: string,
|
|
||||||
projectId: string,
|
|
||||||
userId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.sendHigh(
|
await this.sendHigh(
|
||||||
'API Keys Regenerated',
|
'API Keys Regenerated',
|
||||||
`API keys for project "${projectName}" (${projectId}) were regenerated by user ${userId}`,
|
`API keys for project "${projectName}" (${projectId}) were regenerated by user ${userId}`,
|
||||||
@@ -680,7 +647,7 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Contact import notifications =====
|
// ===== API key notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about contact import started - MIN priority (routine, high volume)
|
* Notify about contact import started - MIN priority (routine, high volume)
|
||||||
@@ -699,6 +666,8 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Contact import notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about contact import completed
|
* Notify about contact import completed
|
||||||
*/
|
*/
|
||||||
@@ -734,16 +703,10 @@ export class NtfyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Segment notifications =====
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about segment created - MIN priority
|
* Notify about segment created - MIN priority
|
||||||
*/
|
*/
|
||||||
public static async notifySegmentCreated(
|
public static async notifySegmentCreated(segmentName: string, projectName: string, projectId: string): Promise<void> {
|
||||||
segmentName: string,
|
|
||||||
projectName: string,
|
|
||||||
projectId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.send({
|
await this.send({
|
||||||
title: 'Segment Created',
|
title: 'Segment Created',
|
||||||
message: `Segment "${segmentName}" created in project "${projectName}" (${projectId})`,
|
message: `Segment "${segmentName}" created in project "${projectName}" (${projectId})`,
|
||||||
@@ -752,6 +715,8 @@ export class NtfyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== Segment notifications =====
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify about segment membership computed - LOW priority
|
* Notify about segment membership computed - LOW priority
|
||||||
*/
|
*/
|
||||||
@@ -760,10 +725,23 @@ export class NtfyService {
|
|||||||
projectName: string,
|
projectName: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
memberCount: number,
|
memberCount: number,
|
||||||
|
added?: number,
|
||||||
|
removed?: number,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
let message = `Segment "${segmentName}" in project "${projectName}" (${projectId}) now has ${memberCount} members`;
|
||||||
|
|
||||||
|
if (added !== undefined && removed !== undefined) {
|
||||||
|
const changes: string[] = [];
|
||||||
|
if (added > 0) changes.push(`+${added} added`);
|
||||||
|
if (removed > 0) changes.push(`-${removed} removed`);
|
||||||
|
if (changes.length > 0) {
|
||||||
|
message += ` (${changes.join(', ')})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await this.send({
|
await this.send({
|
||||||
title: 'Segment Membership Updated',
|
title: 'Segment Membership Updated',
|
||||||
message: `Segment "${segmentName}" in project "${projectName}" (${projectId}) now has ${memberCount} members`,
|
message,
|
||||||
priority: NtfyPriority.LOW,
|
priority: NtfyPriority.LOW,
|
||||||
tags: [NtfyTag.CHART],
|
tags: [NtfyTag.CHART],
|
||||||
});
|
});
|
||||||
@@ -772,11 +750,7 @@ export class NtfyService {
|
|||||||
/**
|
/**
|
||||||
* Notify about segment deleted - MIN priority
|
* Notify about segment deleted - MIN priority
|
||||||
*/
|
*/
|
||||||
public static async notifySegmentDeleted(
|
public static async notifySegmentDeleted(segmentName: string, projectName: string, projectId: string): Promise<void> {
|
||||||
segmentName: string,
|
|
||||||
projectName: string,
|
|
||||||
projectId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.send({
|
await this.send({
|
||||||
title: 'Segment Deleted',
|
title: 'Segment Deleted',
|
||||||
message: `Segment "${segmentName}" was deleted from project "${projectName}" (${projectId})`,
|
message: `Segment "${segmentName}" was deleted from project "${projectName}" (${projectId})`,
|
||||||
@@ -784,4 +758,22 @@ export class NtfyService {
|
|||||||
tags: [NtfyTag.INFO],
|
tags: [NtfyTag.INFO],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the ntfy service with the configured URL
|
||||||
|
*/
|
||||||
|
private static initialize(): void {
|
||||||
|
if (this.isConfigured) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ntfyUrl = process.env.NTFY_URL || null;
|
||||||
|
this.isConfigured = true;
|
||||||
|
|
||||||
|
if (!this.ntfyUrl) {
|
||||||
|
signale.warn('[NTFY] NTFY_URL not configured - notifications will be skipped');
|
||||||
|
} else {
|
||||||
|
signale.info(`[NTFY] Initialized with URL: ${this.ntfyUrl}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user