From 4bb1fee99593e393c91166b3e8c8e41346643e78 Mon Sep 17 00:00:00 2001 From: discountry Date: Mon, 12 Jan 2026 12:23:24 +0800 Subject: [PATCH] Refactor Telegram notification handling in MakerPointsEngine - Introduced a dedicated `notify` method to streamline notification sending and improve logging for Telegram notifications. - Added a new environment variable check for enabling debug logging of Telegram notifications. - Enhanced logging to include detailed information about notification attempts, including masked sensitive data for security. - Updated various notification calls to utilize the new `notify` method, ensuring consistent logging and functionality. --- src/strategy/maker-points-engine.ts | 61 +++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/src/strategy/maker-points-engine.ts b/src/strategy/maker-points-engine.ts index 1f18307..0c07cee 100644 --- a/src/strategy/maker-points-engine.ts +++ b/src/strategy/maker-points-engine.ts @@ -84,6 +84,7 @@ type MakerPointsListener = (snapshot: MakerPointsSnapshot) => void; const EPS = 1e-5; const INSUFFICIENT_BALANCE_COOLDOWN_MS = 15_000; const STOP_LOSS_COOLDOWN_MS = 10_000; +const TELEGRAM_LOG_PREFIX = "[Telegram]"; export class MakerPointsEngine { private accountSnapshot: AsterAccountSnapshot | null = null; @@ -102,6 +103,7 @@ export class MakerPointsEngine { private readonly rateLimit: RateLimitController; private readonly binanceDepth: BinanceDepthTracker; private readonly notifier: NotificationSender; + private readonly telegramDebugLog: boolean; private priceTick: number = 0.1; private qtyStep: number = 0.001; @@ -155,6 +157,8 @@ export class MakerPointsEngine { this.tradeLog.push(type, detail) ); this.notifier = createTelegramNotifier(); + this.telegramDebugLog = isTruthyEnv(process.env.TELEGRAM_DEBUG_LOG); + this.tradeLog.push("info", formatTelegramConfigLog(this.notifier.isEnabled())); this.priceTick = Math.max(1e-9, this.config.priceTick); this.qtyStep = Math.max(1e-9, this.config.qtyStep); this.binanceDepth = new BinanceDepthTracker(resolveBinanceSymbol(this.config.symbol), { @@ -645,7 +649,7 @@ export class MakerPointsEngine { "stop", `触发止损: 未实现亏损 ${position.unrealizedProfit.toFixed(4)} USDT` ); - this.notifier.send({ + this.notify({ type: "stop_loss", level: "error", symbol: this.config.symbol, @@ -802,6 +806,13 @@ export class MakerPointsEngine { return getMidOrLast(this.depthSnapshot, this.tickerSnapshot); } + private notify(notification: TradeNotification): void { + if (this.telegramDebugLog) { + this.tradeLog.push("info", formatTelegramSendLog(notification, this.notifier.isEnabled())); + } + this.notifier.send(notification); + } + private logReadinessBlockers(): void { if (!this.feedStatus.account && !this.readinessLogged.account) { this.tradeLog.push("info", t("log.maker.waitAccount")); @@ -887,7 +898,7 @@ export class MakerPointsEngine { const reference = this.getReferencePrice() ?? 0; if (prevSide === "FLAT" && currentSide !== "FLAT") { - this.notifier.send({ + this.notify({ type: "position_opened", level: "info", symbol: this.config.symbol, @@ -902,7 +913,7 @@ export class MakerPointsEngine { } else if (currentSide === "FLAT" && prevSide !== "FLAT") { const pnl = position.unrealizedProfit; const closeType = this.tokenExpiredCloseOnlyMode ? "Token过期平仓" : "平仓"; - this.notifier.send({ + this.notify({ type: "position_closed", level: "success", symbol: this.config.symbol, @@ -917,7 +928,7 @@ export class MakerPointsEngine { } else if (currentSide === prevSide && absChange > EPS) { const isIncrease = Math.abs(currentAmt) > Math.abs(prevAmt); if (isIncrease) { - this.notifier.send({ + this.notify({ type: "order_filled", level: "info", symbol: this.config.symbol, @@ -930,7 +941,7 @@ export class MakerPointsEngine { }, }); } else { - this.notifier.send({ + this.notify({ type: "order_filled", level: "info", symbol: this.config.symbol, @@ -944,7 +955,7 @@ export class MakerPointsEngine { }); } } else if (currentSide !== prevSide && currentSide !== "FLAT" && prevSide !== "FLAT") { - this.notifier.send({ + this.notify({ type: "position_opened", level: "info", symbol: this.config.symbol, @@ -995,7 +1006,7 @@ export class MakerPointsEngine { } if (!this.tokenExpiryNotified) { - this.notifier.send({ + this.notify({ type: "token_expired", level: "warn", symbol: this.config.symbol, @@ -1047,6 +1058,42 @@ export class MakerPointsEngine { } } +function isTruthyEnv(value: string | undefined): boolean { + if (!value) return false; + const normalized = value.trim().toLowerCase(); + return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on"; +} + +function maskSecret(value: string | undefined, revealStart = 4, revealEnd = 4): string { + if (!value) return "missing"; + const trimmed = value.trim(); + if (!trimmed) return "missing"; + if (trimmed.length <= revealStart + revealEnd + 2) { + return `${trimmed.slice(0, 1)}...${trimmed.slice(-1)}(len=${trimmed.length})`; + } + return `${trimmed.slice(0, revealStart)}...${trimmed.slice(-revealEnd)}(len=${trimmed.length})`; +} + +function maskChatId(value: string | undefined): string { + if (!value) return "missing"; + const trimmed = value.trim(); + if (!trimmed) return "missing"; + if (trimmed.length <= 4) return `***${trimmed}`; + return `***${trimmed.slice(-4)}`; +} + +function formatTelegramConfigLog(enabled: boolean): string { + const botToken = maskSecret(process.env.TELEGRAM_BOT_TOKEN); + const chatId = maskChatId(process.env.TELEGRAM_CHAT_ID); + const accountLabel = process.env.TELEGRAM_ACCOUNT_LABEL ?? "none"; + return `${TELEGRAM_LOG_PREFIX} 配置: ${enabled ? "启用" : "未启用"} botToken=${botToken} chatId=${chatId} label=${accountLabel}`; +} + +function formatTelegramSendLog(notification: TradeNotification, enabled: boolean): string { + const chatId = maskChatId(process.env.TELEGRAM_CHAT_ID); + return `${TELEGRAM_LOG_PREFIX} 发送尝试: enabled=${enabled} type=${notification.type} level=${notification.level} title=${notification.title} symbol=${notification.symbol} chatId=${chatId}`; +} + function resolveBinanceSymbol(symbol: string): string { const parts = parseSymbolParts(symbol); const base = (parts.base ?? symbol).replace(/[^a-zA-Z0-9]/g, "").toUpperCase();