diff --git a/package-lock.json b/package-lock.json index fda9533..d865c9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@nestjs/platform-express": "11.1.28", "@nestjs/schedule": "^6.1.3", "@remnawave/hashed-set": "^0.0.4", - "@remnawave/node-plugins": "0.6.0", + "@remnawave/node-plugins": "0.6.2", "@remnawave/xtls-sdk": "0.16.0", "@remnawave/xtls-sdk-nestjs": "0.6.1", "compression": "^1.8.1", @@ -2545,9 +2545,9 @@ "license": "AGPL-3.0-only" }, "node_modules/@remnawave/node-plugins": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@remnawave/node-plugins/-/node-plugins-0.6.0.tgz", - "integrity": "sha512-q82oHyZxqw0OdbTyC6fDs6s+Wbky9HzVL36T/nDyRA4BKdboOuOH58tET0YiO12M1kQFXqiMsEci0ZEB1ONKmQ==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@remnawave/node-plugins/-/node-plugins-0.6.2.tgz", + "integrity": "sha512-M5r50NVA94Lh7uWx16+PjCV34OxdKDieVmfrCS97qynk9sQm+VvHkS5wIDfsDSKxIB05y0HyT/N1cS3WxR/uEA==", "license": "AGPL-3.0-only", "dependencies": { "zod": "4.4.3" diff --git a/package.json b/package.json index 6001e23..e309288 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@nestjs/platform-express": "11.1.28", "@nestjs/schedule": "^6.1.3", "@remnawave/hashed-set": "^0.0.4", - "@remnawave/node-plugins": "0.6.0", + "@remnawave/node-plugins": "0.6.2", "@remnawave/xtls-sdk": "0.16.0", "@remnawave/xtls-sdk-nestjs": "0.6.1", "compression": "^1.8.1", diff --git a/src/modules/_plugin/events/xray-webhook/xray-webhook.handler.ts b/src/modules/_plugin/events/xray-webhook/xray-webhook.handler.ts index 1eaea88..44d1ade 100644 --- a/src/modules/_plugin/events/xray-webhook/xray-webhook.handler.ts +++ b/src/modules/_plugin/events/xray-webhook/xray-webhook.handler.ts @@ -11,6 +11,7 @@ import { PluginStateService } from '../../services/plugin-state.service'; import { XrayWebhookEvent } from './xray-webhook.event'; const SOURCE_REGEX = /^(?:(?:tcp|udp):)?(?:\[(.+?)\]|(.+?))(?::(\d+))?$/; +const WEBHOOK_TIMEOUT_MS = 5_000; @EventsHandler(XrayWebhookEvent) export class XrayWebhookHandler implements IEventHandler { @@ -75,6 +76,12 @@ export class XrayWebhookHandler implements IEventHandler { }; this.pluginState.torrentBlocker.addReport(report); + + const webhookUrl = this.pluginState.torrentBlocker.getWebhookUrl(); + + if (webhookUrl) { + this.sendWebhook(webhookUrl, report); + } } catch (error) { this.logger.error(`Error in Event XrayWebhookHandler: ${error}`); } finally { @@ -92,4 +99,15 @@ export class XrayWebhookHandler implements IEventHandler { return candidate; } + + private sendWebhook(url: string, report: TorrentBlockerReportModel): void { + fetch(url, { + method: 'POST', + headers: { 'content-type': 'application/json' }, + body: JSON.stringify(report), + signal: AbortSignal.timeout(WEBHOOK_TIMEOUT_MS), + }) + .then((response) => response.body?.cancel()) + .catch(() => void 0); + } } diff --git a/src/modules/_plugin/plugin.service.ts b/src/modules/_plugin/plugin.service.ts index 9b03f49..0289773 100644 --- a/src/modules/_plugin/plugin.service.ts +++ b/src/modules/_plugin/plugin.service.ts @@ -209,6 +209,7 @@ export class PluginService { this.state.torrentBlocker.setIgnoredIps(ips); this.state.torrentBlocker.setIgnoredUsers(users); this.state.torrentBlocker.configure(blockDuration); + this.state.torrentBlocker.setWebhookUrl(pluginData.torrentBlocker.webhookUrl); this.state.torrentBlocker.setIncludeRuleTags(pluginData.torrentBlocker.includeRuleTags); this.logger.log( diff --git a/src/modules/_plugin/services/states/torrent-blocker.state.ts b/src/modules/_plugin/services/states/torrent-blocker.state.ts index d46d7be..b96e072 100644 --- a/src/modules/_plugin/services/states/torrent-blocker.state.ts +++ b/src/modules/_plugin/services/states/torrent-blocker.state.ts @@ -7,6 +7,7 @@ export class TorrentBlockerState { private ignoredIps = new Set(); private ignoredUsers = new Set(); private includeRuleTags = new Set(); + private webhookUrl: string | null = null; private reports: TorrentBlockerReportModel[] = []; get isEnabled(): boolean { @@ -30,6 +31,14 @@ export class TorrentBlockerState { this.ignoredUsers = new Set(users); } + setWebhookUrl(url: string | undefined | null): void { + this.webhookUrl = url ?? null; + } + + getWebhookUrl(): string | null { + return this.webhookUrl; + } + isIpIgnored(ip: string): boolean { return this.ignoredIps.has(ip) || DEFAULT_IGNORED_IPS.has(ip); }