@timmeck/brain-core 2.36.12 → 2.36.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cross-brain/__tests__/borg-sync-engine.test.d.ts +1 -0
- package/dist/cross-brain/__tests__/borg-sync-engine.test.js +240 -0
- package/dist/cross-brain/__tests__/borg-sync-engine.test.js.map +1 -0
- package/dist/cross-brain/borg-sync-engine.d.ts +62 -0
- package/dist/cross-brain/borg-sync-engine.js +215 -0
- package/dist/cross-brain/borg-sync-engine.js.map +1 -0
- package/dist/cross-brain/borg-types.d.ts +37 -0
- package/dist/cross-brain/borg-types.js +9 -0
- package/dist/cross-brain/borg-types.js.map +1 -0
- package/dist/embeddings/engine.js +2 -1
- package/dist/embeddings/engine.js.map +1 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/__tests__/anthropic-provider.test.d.ts +1 -0
- package/dist/llm/__tests__/anthropic-provider.test.js +121 -0
- package/dist/llm/__tests__/anthropic-provider.test.js.map +1 -0
- package/dist/llm/__tests__/llm-service.test.js +181 -40
- package/dist/llm/__tests__/llm-service.test.js.map +1 -1
- package/dist/llm/__tests__/ollama-embedding.test.d.ts +1 -0
- package/dist/llm/__tests__/ollama-embedding.test.js +128 -0
- package/dist/llm/__tests__/ollama-embedding.test.js.map +1 -0
- package/dist/llm/__tests__/ollama-provider.test.d.ts +1 -0
- package/dist/llm/__tests__/ollama-provider.test.js +213 -0
- package/dist/llm/__tests__/ollama-provider.test.js.map +1 -0
- package/dist/llm/__tests__/provider.test.d.ts +1 -0
- package/dist/llm/__tests__/provider.test.js +126 -0
- package/dist/llm/__tests__/provider.test.js.map +1 -0
- package/dist/llm/anthropic-provider.d.ts +41 -0
- package/dist/llm/anthropic-provider.js +86 -0
- package/dist/llm/anthropic-provider.js.map +1 -0
- package/dist/llm/index.d.ts +9 -1
- package/dist/llm/index.js +4 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/llm-service.d.ts +55 -7
- package/dist/llm/llm-service.js +184 -82
- package/dist/llm/llm-service.js.map +1 -1
- package/dist/llm/ollama-embedding.d.ts +46 -0
- package/dist/llm/ollama-embedding.js +93 -0
- package/dist/llm/ollama-embedding.js.map +1 -0
- package/dist/llm/ollama-provider.d.ts +80 -0
- package/dist/llm/ollama-provider.js +178 -0
- package/dist/llm/ollama-provider.js.map +1 -0
- package/dist/llm/provider.d.ts +120 -0
- package/dist/llm/provider.js +104 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/missions/mission-engine.d.ts +4 -0
- package/dist/missions/mission-engine.js +30 -8
- package/dist/missions/mission-engine.js.map +1 -1
- package/dist/notifications/__tests__/notification-service.test.d.ts +1 -0
- package/dist/notifications/__tests__/notification-service.test.js +176 -0
- package/dist/notifications/__tests__/notification-service.test.js.map +1 -0
- package/dist/notifications/discord-provider.d.ts +30 -0
- package/dist/notifications/discord-provider.js +89 -0
- package/dist/notifications/discord-provider.js.map +1 -0
- package/dist/notifications/email-provider.d.ts +41 -0
- package/dist/notifications/email-provider.js +101 -0
- package/dist/notifications/email-provider.js.map +1 -0
- package/dist/notifications/index.d.ts +8 -0
- package/dist/notifications/index.js +5 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/notification-provider.d.ts +75 -0
- package/dist/notifications/notification-provider.js +47 -0
- package/dist/notifications/notification-provider.js.map +1 -0
- package/dist/notifications/notification-service.d.ts +85 -0
- package/dist/notifications/notification-service.js +184 -0
- package/dist/notifications/notification-service.js.map +1 -0
- package/dist/notifications/telegram-provider.d.ts +30 -0
- package/dist/notifications/telegram-provider.js +78 -0
- package/dist/notifications/telegram-provider.js.map +1 -0
- package/dist/plugin/__tests__/plugin-registry.test.d.ts +1 -0
- package/dist/plugin/__tests__/plugin-registry.test.js +166 -0
- package/dist/plugin/__tests__/plugin-registry.test.js.map +1 -0
- package/dist/plugin/plugin-registry.d.ts +38 -0
- package/dist/plugin/plugin-registry.js +185 -0
- package/dist/plugin/plugin-registry.js.map +1 -0
- package/dist/plugin/types.d.ts +59 -0
- package/dist/plugin/types.js +2 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/research/adapters/__tests__/web-adapters.test.d.ts +1 -0
- package/dist/research/adapters/__tests__/web-adapters.test.js +106 -0
- package/dist/research/adapters/__tests__/web-adapters.test.js.map +1 -0
- package/dist/research/adapters/firecrawl-adapter.d.ts +57 -0
- package/dist/research/adapters/firecrawl-adapter.js +137 -0
- package/dist/research/adapters/firecrawl-adapter.js.map +1 -0
- package/dist/research/adapters/index.d.ts +3 -0
- package/dist/research/adapters/index.js +2 -0
- package/dist/research/adapters/index.js.map +1 -1
- package/dist/research/adapters/playwright-adapter.d.ts +54 -0
- package/dist/research/adapters/playwright-adapter.js +130 -0
- package/dist/research/adapters/playwright-adapter.js.map +1 -0
- package/dist/research/research-orchestrator.d.ts +3 -0
- package/dist/research/research-orchestrator.js +19 -1
- package/dist/research/research-orchestrator.js.map +1 -1
- package/dist/techradar/__tests__/techradar-engine.test.d.ts +1 -0
- package/dist/techradar/__tests__/techradar-engine.test.js +246 -0
- package/dist/techradar/__tests__/techradar-engine.test.js.map +1 -0
- package/dist/techradar/daily-digest.d.ts +18 -0
- package/dist/techradar/daily-digest.js +100 -0
- package/dist/techradar/daily-digest.js.map +1 -0
- package/dist/techradar/index.d.ts +5 -0
- package/dist/techradar/index.js +5 -0
- package/dist/techradar/index.js.map +1 -0
- package/dist/techradar/relevance-scorer.d.ts +29 -0
- package/dist/techradar/relevance-scorer.js +139 -0
- package/dist/techradar/relevance-scorer.js.map +1 -0
- package/dist/techradar/repo-watcher.d.ts +24 -0
- package/dist/techradar/repo-watcher.js +87 -0
- package/dist/techradar/repo-watcher.js.map +1 -0
- package/dist/techradar/techradar-engine.d.ts +69 -0
- package/dist/techradar/techradar-engine.js +382 -0
- package/dist/techradar/techradar-engine.js.map +1 -0
- package/dist/techradar/types.d.ts +87 -0
- package/dist/techradar/types.js +5 -0
- package/dist/techradar/types.js.map +1 -0
- package/dist/watchdog/__tests__/watchdog-service.test.d.ts +1 -0
- package/dist/watchdog/__tests__/watchdog-service.test.js +113 -0
- package/dist/watchdog/__tests__/watchdog-service.test.js.map +1 -0
- package/dist/watchdog/watchdog-service.d.ts +60 -0
- package/dist/watchdog/watchdog-service.js +275 -0
- package/dist/watchdog/watchdog-service.js.map +1 -0
- package/dist/watchdog/windows-service.d.ts +39 -0
- package/dist/watchdog/windows-service.js +179 -0
- package/dist/watchdog/windows-service.js.map +1 -0
- package/package.json +20 -2
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Notification Provider — SMTP via nodemailer
|
|
3
|
+
*
|
|
4
|
+
* Einrichten:
|
|
5
|
+
* 1. SMTP Server konfigurieren (Gmail, Outlook, eigener SMTP)
|
|
6
|
+
* Gmail: App-Passwort erstellen unter
|
|
7
|
+
* https://myaccount.google.com/apppasswords
|
|
8
|
+
* 2. In .env:
|
|
9
|
+
* SMTP_HOST=smtp.gmail.com
|
|
10
|
+
* SMTP_PORT=587
|
|
11
|
+
* SMTP_USER=deine@email.com
|
|
12
|
+
* SMTP_PASS=app-password
|
|
13
|
+
* NOTIFICATION_EMAIL_TO=empfaenger@email.com
|
|
14
|
+
* NOTIFICATION_EMAIL_FROM=Brain Ecosystem <brain@example.com> (optional)
|
|
15
|
+
*/
|
|
16
|
+
import type { NotificationProvider, Notification, NotificationResult } from './notification-provider.js';
|
|
17
|
+
export interface EmailProviderConfig {
|
|
18
|
+
smtpHost?: string;
|
|
19
|
+
smtpPort?: number;
|
|
20
|
+
smtpUser?: string;
|
|
21
|
+
smtpPass?: string;
|
|
22
|
+
from?: string;
|
|
23
|
+
to?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class EmailProvider implements NotificationProvider {
|
|
26
|
+
readonly name = "email";
|
|
27
|
+
private readonly smtpHost;
|
|
28
|
+
private readonly smtpPort;
|
|
29
|
+
private readonly smtpUser;
|
|
30
|
+
private readonly smtpPass;
|
|
31
|
+
private readonly from;
|
|
32
|
+
private readonly to;
|
|
33
|
+
private readonly log;
|
|
34
|
+
private transporter;
|
|
35
|
+
private sentCount;
|
|
36
|
+
constructor(config?: EmailProviderConfig);
|
|
37
|
+
isAvailable(): Promise<boolean>;
|
|
38
|
+
send(notification: Notification): Promise<NotificationResult>;
|
|
39
|
+
shutdown(): Promise<void>;
|
|
40
|
+
private getTransporter;
|
|
41
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email Notification Provider — SMTP via nodemailer
|
|
3
|
+
*
|
|
4
|
+
* Einrichten:
|
|
5
|
+
* 1. SMTP Server konfigurieren (Gmail, Outlook, eigener SMTP)
|
|
6
|
+
* Gmail: App-Passwort erstellen unter
|
|
7
|
+
* https://myaccount.google.com/apppasswords
|
|
8
|
+
* 2. In .env:
|
|
9
|
+
* SMTP_HOST=smtp.gmail.com
|
|
10
|
+
* SMTP_PORT=587
|
|
11
|
+
* SMTP_USER=deine@email.com
|
|
12
|
+
* SMTP_PASS=app-password
|
|
13
|
+
* NOTIFICATION_EMAIL_TO=empfaenger@email.com
|
|
14
|
+
* NOTIFICATION_EMAIL_FROM=Brain Ecosystem <brain@example.com> (optional)
|
|
15
|
+
*/
|
|
16
|
+
import { getLogger } from '../utils/logger.js';
|
|
17
|
+
export class EmailProvider {
|
|
18
|
+
name = 'email';
|
|
19
|
+
smtpHost;
|
|
20
|
+
smtpPort;
|
|
21
|
+
smtpUser;
|
|
22
|
+
smtpPass;
|
|
23
|
+
from;
|
|
24
|
+
to;
|
|
25
|
+
log = getLogger();
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
transporter = null;
|
|
28
|
+
sentCount = 0;
|
|
29
|
+
constructor(config = {}) {
|
|
30
|
+
this.smtpHost = config.smtpHost ?? process.env.SMTP_HOST ?? null;
|
|
31
|
+
this.smtpPort = config.smtpPort ?? Number(process.env.SMTP_PORT ?? 587);
|
|
32
|
+
this.smtpUser = config.smtpUser ?? process.env.SMTP_USER ?? null;
|
|
33
|
+
this.smtpPass = config.smtpPass ?? process.env.SMTP_PASS ?? null;
|
|
34
|
+
this.from = config.from ?? process.env.NOTIFICATION_EMAIL_FROM ?? `Brain Ecosystem <${this.smtpUser ?? 'brain@localhost'}>`;
|
|
35
|
+
this.to = config.to ?? process.env.NOTIFICATION_EMAIL_TO ?? null;
|
|
36
|
+
}
|
|
37
|
+
async isAvailable() {
|
|
38
|
+
if (!this.smtpHost || !this.smtpUser || !this.smtpPass || !this.to)
|
|
39
|
+
return false;
|
|
40
|
+
try {
|
|
41
|
+
const transporter = await this.getTransporter();
|
|
42
|
+
await transporter.verify();
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async send(notification) {
|
|
50
|
+
try {
|
|
51
|
+
const transporter = await this.getTransporter();
|
|
52
|
+
const priorityLabel = notification.priority === 'critical' ? '[CRITICAL] ' :
|
|
53
|
+
notification.priority === 'high' ? '[HIGH] ' : '';
|
|
54
|
+
await transporter.sendMail({
|
|
55
|
+
from: this.from,
|
|
56
|
+
to: this.to,
|
|
57
|
+
subject: `${priorityLabel}Brain: ${notification.title}`,
|
|
58
|
+
text: `${notification.title}\n\n${notification.message}\n\nEvent: ${notification.event}\nPriority: ${notification.priority}\nTime: ${new Date(notification.timestamp ?? Date.now()).toISOString()}`,
|
|
59
|
+
html: `
|
|
60
|
+
<h2>${notification.title}</h2>
|
|
61
|
+
<p>${notification.message.replace(/\n/g, '<br>')}</p>
|
|
62
|
+
<hr>
|
|
63
|
+
<small>Event: ${notification.event} | Priority: ${notification.priority} | ${new Date(notification.timestamp ?? Date.now()).toISOString()}</small>
|
|
64
|
+
`,
|
|
65
|
+
});
|
|
66
|
+
this.sentCount++;
|
|
67
|
+
return { provider: this.name, success: true };
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return { provider: this.name, success: false, error: err.message };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async shutdown() {
|
|
74
|
+
if (this.transporter) {
|
|
75
|
+
try {
|
|
76
|
+
this.transporter.close();
|
|
77
|
+
}
|
|
78
|
+
catch { /* best effort */ }
|
|
79
|
+
this.transporter = null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
83
|
+
async getTransporter() {
|
|
84
|
+
if (this.transporter)
|
|
85
|
+
return this.transporter;
|
|
86
|
+
// Dynamic import — nodemailer is optional (variable path avoids TS module resolution)
|
|
87
|
+
const modulePath = 'nodemailer';
|
|
88
|
+
const nodemailer = await import(/* webpackIgnore: true */ modulePath);
|
|
89
|
+
this.transporter = nodemailer.createTransport({
|
|
90
|
+
host: this.smtpHost,
|
|
91
|
+
port: this.smtpPort,
|
|
92
|
+
secure: this.smtpPort === 465,
|
|
93
|
+
auth: {
|
|
94
|
+
user: this.smtpUser,
|
|
95
|
+
pass: this.smtpPass,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
return this.transporter;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=email-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-provider.js","sourceRoot":"","sources":["../../src/notifications/email-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { NotificationService, runNotificationMigration } from './notification-service.js';
|
|
2
|
+
export { DiscordProvider } from './discord-provider.js';
|
|
3
|
+
export { TelegramProvider } from './telegram-provider.js';
|
|
4
|
+
export { EmailProvider } from './email-provider.js';
|
|
5
|
+
export type { NotificationProvider, Notification, NotificationResult, NotificationPriority, NotificationEvent, NotificationProviderStatus, } from './notification-provider.js';
|
|
6
|
+
export type { DiscordProviderConfig } from './discord-provider.js';
|
|
7
|
+
export type { TelegramProviderConfig } from './telegram-provider.js';
|
|
8
|
+
export type { EmailProviderConfig } from './email-provider.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { NotificationService, runNotificationMigration } from './notification-service.js';
|
|
2
|
+
export { DiscordProvider } from './discord-provider.js';
|
|
3
|
+
export { TelegramProvider } from './telegram-provider.js';
|
|
4
|
+
export { EmailProvider } from './email-provider.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notifications/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Provider Interface — Multi-Channel Notifications
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════
|
|
5
|
+
* PROVIDER EINRICHTEN
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* InternalProvider (default):
|
|
9
|
+
* → Speichert Notifications in SQLite. Keine Config nötig.
|
|
10
|
+
*
|
|
11
|
+
* WebhookProvider (bereits vorhanden):
|
|
12
|
+
* → WebhookService für HTTP POST Notifications.
|
|
13
|
+
*
|
|
14
|
+
* Discord (optional):
|
|
15
|
+
* 1. Discord Bot erstellen: https://discord.com/developers/applications
|
|
16
|
+
* → Bot → Add Bot → Token kopieren
|
|
17
|
+
* → OAuth2 → URL Generator → Scope: bot → Permissions: Send Messages
|
|
18
|
+
* → Bot zum Server einladen
|
|
19
|
+
* 2. In .env:
|
|
20
|
+
* DISCORD_BOT_TOKEN=...
|
|
21
|
+
* DISCORD_CHANNEL_ID=... (Rechtsklick auf Channel → Copy Channel ID)
|
|
22
|
+
*
|
|
23
|
+
* Telegram (optional):
|
|
24
|
+
* 1. Bot erstellen: https://t.me/BotFather → /newbot
|
|
25
|
+
* → Token kopieren
|
|
26
|
+
* 2. Chat ID finden: Message an Bot senden, dann
|
|
27
|
+
* https://api.telegram.org/bot<TOKEN>/getUpdates → chat.id
|
|
28
|
+
* 3. In .env:
|
|
29
|
+
* TELEGRAM_BOT_TOKEN=...
|
|
30
|
+
* TELEGRAM_CHAT_ID=...
|
|
31
|
+
*
|
|
32
|
+
* Email (optional):
|
|
33
|
+
* 1. SMTP Server konfigurieren (Gmail, Outlook, eigener SMTP)
|
|
34
|
+
* 2. In .env:
|
|
35
|
+
* SMTP_HOST=smtp.gmail.com
|
|
36
|
+
* SMTP_PORT=587
|
|
37
|
+
* SMTP_USER=deine@email.com
|
|
38
|
+
* SMTP_PASS=app-password (Gmail: App-Passwort erstellen!)
|
|
39
|
+
* NOTIFICATION_EMAIL_TO=empfaenger@email.com
|
|
40
|
+
*
|
|
41
|
+
* Eigenen Provider bauen:
|
|
42
|
+
* Implementiere NotificationProvider, registriere mit
|
|
43
|
+
* notificationService.registerProvider(new MyProvider())
|
|
44
|
+
* ═══════════════════════════════════════════════════════════════
|
|
45
|
+
*/
|
|
46
|
+
export interface Notification {
|
|
47
|
+
event: NotificationEvent;
|
|
48
|
+
title: string;
|
|
49
|
+
message: string;
|
|
50
|
+
priority: NotificationPriority;
|
|
51
|
+
data?: Record<string, unknown>;
|
|
52
|
+
timestamp?: number;
|
|
53
|
+
}
|
|
54
|
+
export type NotificationPriority = 'critical' | 'high' | 'medium' | 'low';
|
|
55
|
+
export type NotificationEvent = 'mission.complete' | 'trade.signal' | 'trade.closed' | 'learning.rule_created' | 'selfmod.proposal' | 'techradar.digest' | 'techradar.opportunity' | 'system.error' | 'system.health' | string;
|
|
56
|
+
export interface NotificationResult {
|
|
57
|
+
provider: string;
|
|
58
|
+
success: boolean;
|
|
59
|
+
error?: string;
|
|
60
|
+
}
|
|
61
|
+
export interface NotificationProvider {
|
|
62
|
+
/** Unique provider name (e.g. 'discord', 'telegram', 'email') */
|
|
63
|
+
readonly name: string;
|
|
64
|
+
/** Check if provider is configured and reachable */
|
|
65
|
+
isAvailable(): Promise<boolean>;
|
|
66
|
+
/** Send a notification */
|
|
67
|
+
send(notification: Notification): Promise<NotificationResult>;
|
|
68
|
+
/** Graceful shutdown */
|
|
69
|
+
shutdown?(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export interface NotificationProviderStatus {
|
|
72
|
+
name: string;
|
|
73
|
+
available: boolean;
|
|
74
|
+
sentCount: number;
|
|
75
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Provider Interface — Multi-Channel Notifications
|
|
3
|
+
*
|
|
4
|
+
* ═══════════════════════════════════════════════════════════════
|
|
5
|
+
* PROVIDER EINRICHTEN
|
|
6
|
+
* ═══════════════════════════════════════════════════════════════
|
|
7
|
+
*
|
|
8
|
+
* InternalProvider (default):
|
|
9
|
+
* → Speichert Notifications in SQLite. Keine Config nötig.
|
|
10
|
+
*
|
|
11
|
+
* WebhookProvider (bereits vorhanden):
|
|
12
|
+
* → WebhookService für HTTP POST Notifications.
|
|
13
|
+
*
|
|
14
|
+
* Discord (optional):
|
|
15
|
+
* 1. Discord Bot erstellen: https://discord.com/developers/applications
|
|
16
|
+
* → Bot → Add Bot → Token kopieren
|
|
17
|
+
* → OAuth2 → URL Generator → Scope: bot → Permissions: Send Messages
|
|
18
|
+
* → Bot zum Server einladen
|
|
19
|
+
* 2. In .env:
|
|
20
|
+
* DISCORD_BOT_TOKEN=...
|
|
21
|
+
* DISCORD_CHANNEL_ID=... (Rechtsklick auf Channel → Copy Channel ID)
|
|
22
|
+
*
|
|
23
|
+
* Telegram (optional):
|
|
24
|
+
* 1. Bot erstellen: https://t.me/BotFather → /newbot
|
|
25
|
+
* → Token kopieren
|
|
26
|
+
* 2. Chat ID finden: Message an Bot senden, dann
|
|
27
|
+
* https://api.telegram.org/bot<TOKEN>/getUpdates → chat.id
|
|
28
|
+
* 3. In .env:
|
|
29
|
+
* TELEGRAM_BOT_TOKEN=...
|
|
30
|
+
* TELEGRAM_CHAT_ID=...
|
|
31
|
+
*
|
|
32
|
+
* Email (optional):
|
|
33
|
+
* 1. SMTP Server konfigurieren (Gmail, Outlook, eigener SMTP)
|
|
34
|
+
* 2. In .env:
|
|
35
|
+
* SMTP_HOST=smtp.gmail.com
|
|
36
|
+
* SMTP_PORT=587
|
|
37
|
+
* SMTP_USER=deine@email.com
|
|
38
|
+
* SMTP_PASS=app-password (Gmail: App-Passwort erstellen!)
|
|
39
|
+
* NOTIFICATION_EMAIL_TO=empfaenger@email.com
|
|
40
|
+
*
|
|
41
|
+
* Eigenen Provider bauen:
|
|
42
|
+
* Implementiere NotificationProvider, registriere mit
|
|
43
|
+
* notificationService.registerProvider(new MyProvider())
|
|
44
|
+
* ═══════════════════════════════════════════════════════════════
|
|
45
|
+
*/
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=notification-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-provider.js","sourceRoot":"","sources":["../../src/notifications/notification-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Service — Aggregiert alle Notification Provider
|
|
3
|
+
*
|
|
4
|
+
* Architektur:
|
|
5
|
+
* NotificationService
|
|
6
|
+
* ├── InternalProvider (SQLite, default — immer da)
|
|
7
|
+
* ├── WebhookProvider (HTTP POST — already exists)
|
|
8
|
+
* ├── DiscordProvider (discord.js, optional)
|
|
9
|
+
* ├── TelegramProvider (grammy, optional)
|
|
10
|
+
* └── EmailProvider (nodemailer SMTP, optional)
|
|
11
|
+
*
|
|
12
|
+
* Event-Routing:
|
|
13
|
+
* Jeder Event-Typ kann an bestimmte Provider geroutet werden.
|
|
14
|
+
* Default: alle Events → alle verfügbaren Provider.
|
|
15
|
+
*
|
|
16
|
+
* Einrichten:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const service = new NotificationService(db);
|
|
19
|
+
* service.registerProvider(new DiscordProvider());
|
|
20
|
+
* service.registerProvider(new TelegramProvider());
|
|
21
|
+
* service.registerProvider(new EmailProvider());
|
|
22
|
+
*
|
|
23
|
+
* // Optional: Event-Routing konfigurieren
|
|
24
|
+
* service.setEventRouting('system.error', ['discord', 'telegram', 'email']);
|
|
25
|
+
* service.setEventRouting('techradar.digest', ['telegram', 'email']);
|
|
26
|
+
* service.setEventRouting('learning.rule_created', ['internal']);
|
|
27
|
+
*
|
|
28
|
+
* await service.notify({
|
|
29
|
+
* event: 'trade.signal',
|
|
30
|
+
* title: 'New Trading Signal',
|
|
31
|
+
* message: 'BTC breakout detected...',
|
|
32
|
+
* priority: 'high',
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import Database from 'better-sqlite3';
|
|
37
|
+
import type { NotificationProvider, Notification, NotificationResult, NotificationProviderStatus } from './notification-provider.js';
|
|
38
|
+
export declare function runNotificationMigration(db: Database.Database): void;
|
|
39
|
+
export declare class NotificationService {
|
|
40
|
+
private providers;
|
|
41
|
+
private eventRouting;
|
|
42
|
+
private readonly db;
|
|
43
|
+
constructor(db: Database.Database);
|
|
44
|
+
/** Register a notification provider */
|
|
45
|
+
registerProvider(provider: NotificationProvider): void;
|
|
46
|
+
/** Remove a provider by name */
|
|
47
|
+
removeProvider(name: string): void;
|
|
48
|
+
/** Get all registered providers */
|
|
49
|
+
getProviders(): NotificationProvider[];
|
|
50
|
+
/**
|
|
51
|
+
* Set event routing: which providers handle which events.
|
|
52
|
+
* If no routing is set, all providers receive all events.
|
|
53
|
+
*/
|
|
54
|
+
setEventRouting(event: string, providerNames: string[]): void;
|
|
55
|
+
/** Get current event routing */
|
|
56
|
+
getEventRouting(): Record<string, string[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Send a notification to all relevant providers.
|
|
59
|
+
* Uses event routing if configured, otherwise sends to all.
|
|
60
|
+
*/
|
|
61
|
+
notify(notification: Notification): Promise<NotificationResult[]>;
|
|
62
|
+
/** Get target providers for an event based on routing config */
|
|
63
|
+
private getTargetProviders;
|
|
64
|
+
/** Log notification to SQLite */
|
|
65
|
+
private logNotification;
|
|
66
|
+
/** Get notification history */
|
|
67
|
+
getHistory(options?: {
|
|
68
|
+
event?: string;
|
|
69
|
+
limit?: number;
|
|
70
|
+
}): Array<{
|
|
71
|
+
id: number;
|
|
72
|
+
event: string;
|
|
73
|
+
title: string;
|
|
74
|
+
message: string;
|
|
75
|
+
priority: string;
|
|
76
|
+
provider: string;
|
|
77
|
+
success: boolean;
|
|
78
|
+
error: string | null;
|
|
79
|
+
created_at: string;
|
|
80
|
+
}>;
|
|
81
|
+
/** Get provider status */
|
|
82
|
+
getProviderStatus(): Promise<NotificationProviderStatus[]>;
|
|
83
|
+
/** Graceful shutdown */
|
|
84
|
+
shutdown(): Promise<void>;
|
|
85
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Service — Aggregiert alle Notification Provider
|
|
3
|
+
*
|
|
4
|
+
* Architektur:
|
|
5
|
+
* NotificationService
|
|
6
|
+
* ├── InternalProvider (SQLite, default — immer da)
|
|
7
|
+
* ├── WebhookProvider (HTTP POST — already exists)
|
|
8
|
+
* ├── DiscordProvider (discord.js, optional)
|
|
9
|
+
* ├── TelegramProvider (grammy, optional)
|
|
10
|
+
* └── EmailProvider (nodemailer SMTP, optional)
|
|
11
|
+
*
|
|
12
|
+
* Event-Routing:
|
|
13
|
+
* Jeder Event-Typ kann an bestimmte Provider geroutet werden.
|
|
14
|
+
* Default: alle Events → alle verfügbaren Provider.
|
|
15
|
+
*
|
|
16
|
+
* Einrichten:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const service = new NotificationService(db);
|
|
19
|
+
* service.registerProvider(new DiscordProvider());
|
|
20
|
+
* service.registerProvider(new TelegramProvider());
|
|
21
|
+
* service.registerProvider(new EmailProvider());
|
|
22
|
+
*
|
|
23
|
+
* // Optional: Event-Routing konfigurieren
|
|
24
|
+
* service.setEventRouting('system.error', ['discord', 'telegram', 'email']);
|
|
25
|
+
* service.setEventRouting('techradar.digest', ['telegram', 'email']);
|
|
26
|
+
* service.setEventRouting('learning.rule_created', ['internal']);
|
|
27
|
+
*
|
|
28
|
+
* await service.notify({
|
|
29
|
+
* event: 'trade.signal',
|
|
30
|
+
* title: 'New Trading Signal',
|
|
31
|
+
* message: 'BTC breakout detected...',
|
|
32
|
+
* priority: 'high',
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import { getLogger } from '../utils/logger.js';
|
|
37
|
+
const log = getLogger();
|
|
38
|
+
// ── Migration ────────────────────────────────────────────
|
|
39
|
+
export function runNotificationMigration(db) {
|
|
40
|
+
db.exec(`
|
|
41
|
+
CREATE TABLE IF NOT EXISTS notification_log (
|
|
42
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43
|
+
event TEXT NOT NULL,
|
|
44
|
+
title TEXT NOT NULL,
|
|
45
|
+
message TEXT NOT NULL,
|
|
46
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
47
|
+
provider TEXT NOT NULL,
|
|
48
|
+
success INTEGER NOT NULL DEFAULT 1,
|
|
49
|
+
error TEXT,
|
|
50
|
+
data_json TEXT,
|
|
51
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_notification_log_event ON notification_log(event);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_notification_log_created ON notification_log(created_at);
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
// ── Service ──────────────────────────────────────────────
|
|
59
|
+
export class NotificationService {
|
|
60
|
+
providers = [];
|
|
61
|
+
eventRouting = new Map(); // event → provider names
|
|
62
|
+
db;
|
|
63
|
+
constructor(db) {
|
|
64
|
+
this.db = db;
|
|
65
|
+
runNotificationMigration(db);
|
|
66
|
+
}
|
|
67
|
+
/** Register a notification provider */
|
|
68
|
+
registerProvider(provider) {
|
|
69
|
+
if (this.providers.some(p => p.name === provider.name))
|
|
70
|
+
return;
|
|
71
|
+
this.providers.push(provider);
|
|
72
|
+
log.debug(`[Notifications] Registered provider: ${provider.name}`);
|
|
73
|
+
}
|
|
74
|
+
/** Remove a provider by name */
|
|
75
|
+
removeProvider(name) {
|
|
76
|
+
this.providers = this.providers.filter(p => p.name !== name);
|
|
77
|
+
}
|
|
78
|
+
/** Get all registered providers */
|
|
79
|
+
getProviders() {
|
|
80
|
+
return [...this.providers];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Set event routing: which providers handle which events.
|
|
84
|
+
* If no routing is set, all providers receive all events.
|
|
85
|
+
*/
|
|
86
|
+
setEventRouting(event, providerNames) {
|
|
87
|
+
this.eventRouting.set(event, providerNames);
|
|
88
|
+
}
|
|
89
|
+
/** Get current event routing */
|
|
90
|
+
getEventRouting() {
|
|
91
|
+
return Object.fromEntries(this.eventRouting);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Send a notification to all relevant providers.
|
|
95
|
+
* Uses event routing if configured, otherwise sends to all.
|
|
96
|
+
*/
|
|
97
|
+
async notify(notification) {
|
|
98
|
+
const results = [];
|
|
99
|
+
notification.timestamp = notification.timestamp ?? Date.now();
|
|
100
|
+
// Determine which providers should receive this event
|
|
101
|
+
const targetProviders = this.getTargetProviders(notification.event);
|
|
102
|
+
for (const provider of targetProviders) {
|
|
103
|
+
try {
|
|
104
|
+
const available = await provider.isAvailable();
|
|
105
|
+
if (!available) {
|
|
106
|
+
const result = { provider: provider.name, success: false, error: 'Provider not available' };
|
|
107
|
+
results.push(result);
|
|
108
|
+
this.logNotification(notification, result);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const result = await provider.send(notification);
|
|
112
|
+
results.push(result);
|
|
113
|
+
this.logNotification(notification, result);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
const result = { provider: provider.name, success: false, error: err.message };
|
|
117
|
+
results.push(result);
|
|
118
|
+
this.logNotification(notification, result);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return results;
|
|
122
|
+
}
|
|
123
|
+
/** Get target providers for an event based on routing config */
|
|
124
|
+
getTargetProviders(event) {
|
|
125
|
+
const routing = this.eventRouting.get(event);
|
|
126
|
+
if (!routing)
|
|
127
|
+
return this.providers; // No routing → all providers
|
|
128
|
+
return this.providers.filter(p => routing.includes(p.name));
|
|
129
|
+
}
|
|
130
|
+
/** Log notification to SQLite */
|
|
131
|
+
logNotification(notification, result) {
|
|
132
|
+
try {
|
|
133
|
+
this.db.prepare(`
|
|
134
|
+
INSERT INTO notification_log (event, title, message, priority, provider, success, error, data_json)
|
|
135
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
136
|
+
`).run(notification.event, notification.title, notification.message, notification.priority, result.provider, result.success ? 1 : 0, result.error ?? null, notification.data ? JSON.stringify(notification.data) : null);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Best effort logging
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Get notification history */
|
|
143
|
+
getHistory(options = {}) {
|
|
144
|
+
let sql = 'SELECT * FROM notification_log';
|
|
145
|
+
const params = [];
|
|
146
|
+
if (options.event) {
|
|
147
|
+
sql += ' WHERE event = ?';
|
|
148
|
+
params.push(options.event);
|
|
149
|
+
}
|
|
150
|
+
sql += ' ORDER BY created_at DESC LIMIT ?';
|
|
151
|
+
params.push(options.limit ?? 50);
|
|
152
|
+
return this.db.prepare(sql).all(...params).map(r => ({
|
|
153
|
+
...r,
|
|
154
|
+
success: r.success === 1,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
/** Get provider status */
|
|
158
|
+
async getProviderStatus() {
|
|
159
|
+
return Promise.all(this.providers.map(async (p) => {
|
|
160
|
+
let available = false;
|
|
161
|
+
try {
|
|
162
|
+
available = await p.isAvailable();
|
|
163
|
+
}
|
|
164
|
+
catch { /* not available */ }
|
|
165
|
+
return {
|
|
166
|
+
name: p.name,
|
|
167
|
+
available,
|
|
168
|
+
sentCount: 0,
|
|
169
|
+
};
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
/** Graceful shutdown */
|
|
173
|
+
async shutdown() {
|
|
174
|
+
for (const provider of this.providers) {
|
|
175
|
+
if (provider.shutdown) {
|
|
176
|
+
try {
|
|
177
|
+
await provider.shutdown();
|
|
178
|
+
}
|
|
179
|
+
catch { /* best effort */ }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=notification-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-service.js","sourceRoot":"","sources":["../../src/notifications/notification-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQ/C,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;AAExB,4DAA4D;AAE5D,MAAM,UAAU,wBAAwB,CAAC,EAAqB;IAC5D,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;GAgBP,CAAC,CAAC;AACL,CAAC;AAED,4DAA4D;AAE5D,MAAM,OAAO,mBAAmB;IACtB,SAAS,GAA2B,EAAE,CAAC;IACvC,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC,CAAC,yBAAyB;IAC5D,EAAE,CAAoB;IAEvC,YAAY,EAAqB;QAC/B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,wBAAwB,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,uCAAuC;IACvC,gBAAgB,CAAC,QAA8B;QAC7C,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QAC/D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9B,GAAG,CAAC,KAAK,CAAC,wCAAwC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,gCAAgC;IAChC,cAAc,CAAC,IAAY;QACzB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,mCAAmC;IACnC,YAAY;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,KAAa,EAAE,aAAuB;QACpD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IAC9C,CAAC;IAED,gCAAgC;IAChC,eAAe;QACb,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,YAA0B;QACrC,MAAM,OAAO,GAAyB,EAAE,CAAC;QACzC,YAAY,CAAC,SAAS,GAAG,YAAY,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAE9D,sDAAsD;QACtD,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAEpE,KAAK,MAAM,QAAQ,IAAI,eAAe,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC/C,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC;oBAC5F,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACrB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;oBAC3C,SAAS;gBACX,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBACjD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAG,GAAa,CAAC,OAAO,EAAE,CAAC;gBAC1F,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACrB,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,gEAAgE;IACxD,kBAAkB,CAAC,KAAa;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,6BAA6B;QAElE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,iCAAiC;IACzB,eAAe,CAAC,YAA0B,EAAE,MAA0B;QAC5E,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;OAGf,CAAC,CAAC,GAAG,CACJ,YAAY,CAAC,KAAK,EAClB,YAAY,CAAC,KAAK,EAClB,YAAY,CAAC,OAAO,EACpB,YAAY,CAAC,QAAQ,EACrB,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACtB,MAAM,CAAC,KAAK,IAAI,IAAI,EACpB,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAC7D,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,UAAU,CAAC,UAA8C,EAAE;QAIzD,IAAI,GAAG,GAAG,gCAAgC,CAAC;QAC3C,MAAM,MAAM,GAAc,EAAE,CAAC;QAE7B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,GAAG,IAAI,kBAAkB,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAED,GAAG,IAAI,mCAAmC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAEjC,OAAQ,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9D,GAAG,CAAC;YACJ,OAAO,EAAE,CAAC,CAAC,OAAO,KAAK,CAAC;SACzB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,0BAA0B;IAC1B,KAAK,CAAC,iBAAiB;QACrB,OAAO,OAAO,CAAC,GAAG,CAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAC,CAAC,EAAC,EAAE;YAC3B,IAAI,SAAS,GAAG,KAAK,CAAC;YACtB,IAAI,CAAC;gBAAC,SAAS,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,CAAC;YACxE,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,SAAS;gBACT,SAAS,EAAE,CAAC;aACb,CAAC;QACJ,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED,wBAAwB;IACxB,KAAK,CAAC,QAAQ;QACZ,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,IAAI,CAAC;oBAAC,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telegram Notification Provider — Bot Messages via grammy
|
|
3
|
+
*
|
|
4
|
+
* Einrichten:
|
|
5
|
+
* 1. Bot erstellen: https://t.me/BotFather → /newbot → Token kopieren
|
|
6
|
+
* 2. Chat ID finden: Nachricht an Bot senden, dann
|
|
7
|
+
* https://api.telegram.org/bot<TOKEN>/getUpdates → chat.id
|
|
8
|
+
* 3. In .env:
|
|
9
|
+
* TELEGRAM_BOT_TOKEN=...
|
|
10
|
+
* TELEGRAM_CHAT_ID=...
|
|
11
|
+
*/
|
|
12
|
+
import type { NotificationProvider, Notification, NotificationResult } from './notification-provider.js';
|
|
13
|
+
export interface TelegramProviderConfig {
|
|
14
|
+
botToken?: string;
|
|
15
|
+
chatId?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class TelegramProvider implements NotificationProvider {
|
|
18
|
+
readonly name = "telegram";
|
|
19
|
+
private readonly botToken;
|
|
20
|
+
private readonly chatId;
|
|
21
|
+
private readonly log;
|
|
22
|
+
private bot;
|
|
23
|
+
private sentCount;
|
|
24
|
+
constructor(config?: TelegramProviderConfig);
|
|
25
|
+
isAvailable(): Promise<boolean>;
|
|
26
|
+
send(notification: Notification): Promise<NotificationResult>;
|
|
27
|
+
shutdown(): Promise<void>;
|
|
28
|
+
private escapeMarkdown;
|
|
29
|
+
private getBot;
|
|
30
|
+
}
|