@apocaliss92/nodelink-js 0.4.30 → 0.4.32

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/index.d.cts CHANGED
@@ -5623,19 +5623,6 @@ interface EmailPushEvent {
5623
5623
  from: string;
5624
5624
  /** Raw body text excerpt (max 500 chars). */
5625
5625
  bodyExcerpt: string;
5626
- /**
5627
- * First image attachment from the e-mail, when present. The camera
5628
- * sends a JPEG snapshot of the trigger frame on motion when
5629
- * `attachmentType=picture`; consumers can republish it to MQTT image
5630
- * entities or cache it as the camera's `lastPicture` so battery
5631
- * cameras don't have to be woken up to get a fresh thumbnail.
5632
- * Kept in memory only — the bus does not persist it.
5633
- */
5634
- attachment?: {
5635
- contentType: string;
5636
- data: Buffer;
5637
- filename?: string;
5638
- };
5639
5626
  }
5640
5627
  type EventHandler = (event: EmailPushEvent) => void;
5641
5628
  type CameraResolver = (recipient: string) => string | undefined;
@@ -5715,6 +5702,13 @@ declare class ReolinkBaichuanApi {
5715
5702
  * Once closed, the API instance should not be reused.
5716
5703
  */
5717
5704
  private _closed;
5705
+ /**
5706
+ * Off-handle for the auto-bridge between the global email-push bus
5707
+ * and this api's `simpleEventListeners`. Set in the constructor
5708
+ * when `emailPushCameraId` is provided; released in `close()`.
5709
+ * `undefined` means no bridge was requested for this api.
5710
+ */
5711
+ private emailPushAutoBridgeOff;
5718
5712
  /**
5719
5713
  * Socket pool with tag-based allocation strategy.
5720
5714
  * Tags determine which sockets are shared vs dedicated:
@@ -6229,6 +6223,23 @@ declare class ReolinkBaichuanApi {
6229
6223
  * out on TCP, or `true` to opt in on UDP (not recommended).
6230
6224
  */
6231
6225
  enableEventResubscribe?: boolean;
6226
+ /**
6227
+ * When set, the api auto-subscribes to the global email-push bus
6228
+ * and translates each matching delivery (`event.cameraId ===
6229
+ * emailPushCameraId`) into `dispatchSimpleEvent` — so any
6230
+ * consumer registered via `api.onSimpleEvent(...)` receives
6231
+ * native Baichuan push AND SMTP-delivered motion through the
6232
+ * exact same stream, with no second subscription needed. The
6233
+ * bridge survives TCP transient disconnects (it's a JS-level
6234
+ * fan-out, not a network operation) and is released
6235
+ * automatically by `close()`.
6236
+ *
6237
+ * Pair with `emailPushChannel` when the camera lives on a
6238
+ * non-zero channel (NVR children, multi-channel cams).
6239
+ */
6240
+ emailPushCameraId?: string;
6241
+ /** Channel reported on the synthesised event. Default 0. */
6242
+ emailPushChannel?: number;
6232
6243
  });
6233
6244
  /**
6234
6245
  * CGI forward: fetch RTSP URL for a channel via `GetRtspUrl`.
package/dist/index.d.ts CHANGED
@@ -4807,19 +4807,6 @@ export declare interface EmailPushEvent {
4807
4807
  from: string;
4808
4808
  /** Raw body text excerpt (max 500 chars). */
4809
4809
  bodyExcerpt: string;
4810
- /**
4811
- * First image attachment from the e-mail, when present. The camera
4812
- * sends a JPEG snapshot of the trigger frame on motion when
4813
- * `attachmentType=picture`; consumers can republish it to MQTT image
4814
- * entities or cache it as the camera's `lastPicture` so battery
4815
- * cameras don't have to be woken up to get a fresh thumbnail.
4816
- * Kept in memory only — the bus does not persist it.
4817
- */
4818
- attachment?: {
4819
- contentType: string;
4820
- data: Buffer;
4821
- filename?: string;
4822
- };
4823
4810
  }
4824
4811
 
4825
4812
  /**
@@ -6700,6 +6687,13 @@ export declare class ReolinkBaichuanApi {
6700
6687
  * Once closed, the API instance should not be reused.
6701
6688
  */
6702
6689
  private _closed;
6690
+ /**
6691
+ * Off-handle for the auto-bridge between the global email-push bus
6692
+ * and this api's `simpleEventListeners`. Set in the constructor
6693
+ * when `emailPushCameraId` is provided; released in `close()`.
6694
+ * `undefined` means no bridge was requested for this api.
6695
+ */
6696
+ private emailPushAutoBridgeOff;
6703
6697
  /**
6704
6698
  * Socket pool with tag-based allocation strategy.
6705
6699
  * Tags determine which sockets are shared vs dedicated:
@@ -7214,6 +7208,23 @@ export declare class ReolinkBaichuanApi {
7214
7208
  * out on TCP, or `true` to opt in on UDP (not recommended).
7215
7209
  */
7216
7210
  enableEventResubscribe?: boolean;
7211
+ /**
7212
+ * When set, the api auto-subscribes to the global email-push bus
7213
+ * and translates each matching delivery (`event.cameraId ===
7214
+ * emailPushCameraId`) into `dispatchSimpleEvent` — so any
7215
+ * consumer registered via `api.onSimpleEvent(...)` receives
7216
+ * native Baichuan push AND SMTP-delivered motion through the
7217
+ * exact same stream, with no second subscription needed. The
7218
+ * bridge survives TCP transient disconnects (it's a JS-level
7219
+ * fan-out, not a network operation) and is released
7220
+ * automatically by `close()`.
7221
+ *
7222
+ * Pair with `emailPushChannel` when the camera lives on a
7223
+ * non-zero channel (NVR children, multi-channel cams).
7224
+ */
7225
+ emailPushCameraId?: string;
7226
+ /** Channel reported on the synthesised event. Default 0. */
7227
+ emailPushChannel?: number;
7217
7228
  });
7218
7229
  /**
7219
7230
  * CGI forward: fetch RTSP URL for a channel via `GetRtspUrl`.
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  setEmailPushCameraResolver,
66
66
  setGlobalLogger,
67
67
  xmlIndicatesFloodlight
68
- } from "./chunk-AZZKLRJV.js";
68
+ } from "./chunk-5Z7NVPV6.js";
69
69
  import {
70
70
  ReolinkCgiApi,
71
71
  ReolinkHttpClient,
@@ -8340,8 +8340,10 @@ function createEmailPushServer(params) {
8340
8340
  let server;
8341
8341
  let status = buildInitialStatus(config);
8342
8342
  function parseRecipient(rcpt) {
8343
- const [local, domain] = rcpt.toLowerCase().split("@");
8344
- if (!local || !domain) return void 0;
8343
+ const at = rcpt.lastIndexOf("@");
8344
+ if (at <= 0 || at === rcpt.length - 1) return void 0;
8345
+ const local = rcpt.slice(0, at);
8346
+ const domain = rcpt.slice(at + 1).toLowerCase();
8345
8347
  return { local, domain };
8346
8348
  }
8347
8349
  function resolveCameraIdFromRecipient(rcpt) {
@@ -8364,9 +8366,6 @@ function createEmailPushServer(params) {
8364
8366
  return;
8365
8367
  }
8366
8368
  const receivedAtMs = Date.now();
8367
- const imageAttachment = (parsed.attachments ?? []).find(
8368
- (a) => a && typeof a.contentType === "string" && a.contentType.toLowerCase().startsWith("image/") && Buffer.isBuffer(a.content)
8369
- );
8370
8369
  const event = {
8371
8370
  cameraId,
8372
8371
  recipient,
@@ -8374,18 +8373,11 @@ function createEmailPushServer(params) {
8374
8373
  receivedAtMs,
8375
8374
  subject: parsed.subject ?? "",
8376
8375
  from: typeof parsed.from === "object" && parsed.from !== null && "text" in parsed.from ? String(parsed.from.text) : "",
8377
- bodyExcerpt: (parsed.text ?? "").slice(0, 500),
8378
- ...imageAttachment ? {
8379
- attachment: {
8380
- contentType: imageAttachment.contentType,
8381
- data: imageAttachment.content,
8382
- ...imageAttachment.filename ? { filename: imageAttachment.filename } : {}
8383
- }
8384
- } : {}
8376
+ bodyExcerpt: (parsed.text ?? "").slice(0, 500)
8385
8377
  };
8386
8378
  status.messagesAccepted++;
8387
8379
  log.info(
8388
- `Email push for camera=${cameraId} type=${event.inferredType} attachment=${event.attachment ? `${event.attachment.contentType} ${event.attachment.data.length}B` : "none"} subject="${event.subject.slice(0, 80)}"`
8380
+ `Email push for camera=${cameraId} type=${event.inferredType} subject="${event.subject.slice(0, 80)}"`
8389
8381
  );
8390
8382
  emitEmailPushEvent(event);
8391
8383
  }