@photon-ai/advanced-imessage-kit 1.10.1 → 1.11.1

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/README.md CHANGED
@@ -18,37 +18,39 @@ Advanced iMessage Kit is a full-featured iMessage SDK for **reading**, **sending
18
18
 
19
19
  ## Features
20
20
 
21
- | Feature | Description | Method | Example |
22
- | ---------------------------------------------------------- | --------------------------------------------- | ---------------------------------- | --------------------------------------------------------------- |
23
- | [Send Messages](#send-messages) | Send text messages to any contact | `messages.sendMessage()` | [message-send.ts](./examples/message-send.ts) |
24
- | [Reply to Messages](#send-messages) | Reply inline to a specific message | `messages.sendMessage()` | [message-reply.ts](./examples/message-reply.ts) |
25
- | [Message Effects](#send-messages) | Send with effects (confetti, fireworks, etc.) | `messages.sendMessage()` | [message-effects.ts](./examples/message-effects.ts) |
21
+ | Feature | Description | Method | Example |
22
+ | ---------------------------------------------------------- | --------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------- |
23
+ | [Send Messages](#send-messages) | Send text messages to any contact | `messages.sendMessage()` | [message-send.ts](./examples/message-send.ts) |
24
+ | [Reply to Messages](#send-messages) | Reply inline to a specific message | `messages.sendMessage()` | [message-reply.ts](./examples/message-reply.ts) |
25
+ | [Message Effects](#send-messages) | Send with effects (confetti, fireworks, etc.) | `messages.sendMessage()` | [message-effects.ts](./examples/message-effects.ts) |
26
26
  | [Schedule Messages](#scheduled-messages) | Send once or on a recurring schedule | `scheduledMessages.createScheduledMessage()` | [scheduled-message-once.ts](./examples/scheduled-message-once.ts) |
27
- | [Unsend Messages](#unsend-messages) | Retract a sent message | `messages.unsendMessage()` | [message-unsend.ts](./examples/message-unsend.ts) |
28
- | [Edit Messages](#edit-messages) | Edit a sent message | `messages.editMessage()` | [message-edit.ts](./examples/message-edit.ts) |
29
- | [Send Tapbacks](#send-tapbacks) | React with ❤️ 👍 👎 😂 ‼️ ❓ | `messages.sendReaction()` | [message-reaction.ts](./examples/message-reaction.ts) |
30
- | [Query Messages](#query-messages) | Search and filter message history | `messages.getMessages()` | [message-search.ts](./examples/message-search.ts) |
31
- | [Message History](#get-chat-messages) | View messages, reactions, polls, stickers | `chats.getChatMessages()` | [message-history.ts](./examples/message-history.ts) |
32
- | [Send Attachments](#send-attachments) | Send images, files, documents | `attachments.sendAttachment()` | [message-attachment.ts](./examples/message-attachment.ts) |
33
- | [Send Audio Messages](#send-audio-messages) | Send voice messages | `attachments.sendAttachment()` | [message-audio.ts](./examples/message-audio.ts) |
34
- | [Send Stickers](#send-stickers) | Send sticker as standalone message | `attachments.sendSticker()` | [message-sticker.ts](./examples/message-sticker.ts) |
35
- | [Reply Stickers](#send-stickers) | Attach sticker to a message bubble | `attachments.sendSticker()` | [message-reply-sticker.ts](./examples/message-reply-sticker.ts) |
36
- | [Download Attachments](#download-attachments) | Download received files and media | `attachments.downloadAttachment()` | [attachment-download.ts](./examples/attachment-download.ts) |
37
- | [Get Chats](#get-chats) | List all conversations | `chats.getChats()` | [chat-fetch.ts](./examples/chat-fetch.ts) |
38
- | [Get Chat Participants](#get-chat-participants) | View group chat participants | `chats.getChat()` | [chat-participants.ts](./examples/chat-participants.ts) |
39
- | [Manage Group Chats](#manage-group-chats) | Add/remove members, rename groups | `chats.addParticipant()` | [chat-group.ts](./examples/chat-group.ts) |
40
- | [Typing Indicators](#typing-indicators) | Show "typing..." status | `chats.startTyping()` | [message-typing.ts](./examples/message-typing.ts) |
41
- | [Get Contacts](#get-contacts) | Fetch device contacts | `contacts.getContacts()` | [contact-list.ts](./examples/contact-list.ts) |
42
- | [Share Contact Card](#share-contact-card) | Share your contact info in chat | `contacts.shareContactCard()` | [message-contact-card.ts](./examples/message-contact-card.ts) |
43
- | [Check iMessage Availability](#check-service-availability) | Verify if contact uses iMessage | `handles.getHandleAvailability()` | [service-check.ts](./examples/service-check.ts) |
44
- | [Server Info](#get-server-info) | Get server status and config | `server.getServerInfo()` | [server-info.ts](./examples/server-info.ts) |
45
- | [Message Statistics](#message-statistics) | Get message counts and analytics | `server.getMessageStats()` | [message-stats.ts](./examples/message-stats.ts) |
46
- | [Create Polls](#create-polls) | Create interactive polls in chat | `polls.create()` | [poll-create.ts](./examples/poll-create.ts) |
47
- | [Vote on Polls](#vote-on-polls) | Vote or unvote on poll options | `polls.vote()` | [poll-vote.ts](./examples/poll-vote.ts) |
48
- | [Add Poll Options](#add-poll-options) | Add options to existing polls | `polls.addOption()` | [poll-add-option.ts](./examples/poll-add-option.ts) |
49
- | [Find My Friends](#find-my-friends) | Get friends' locations | `icloud.refreshFindMyFriends()` | [findmy-friends.ts](./examples/findmy-friends.ts) |
50
- | [Real-time Events](#real-time-events) | Listen for new messages, typing, etc. | `sdk.on()` | [listen-simple.ts](./examples/listen-simple.ts) |
51
- | [Auto Reply](#real-time-events) | Build automated reply bots | `sdk.on()` | [auto-reply-hey.ts](./examples/auto-reply-hey.ts) |
27
+ | [Unsend Messages](#unsend-messages) | Retract a sent message | `messages.unsendMessage()` | [message-unsend.ts](./examples/message-unsend.ts) |
28
+ | [Edit Messages](#edit-messages) | Edit a sent message | `messages.editMessage()` | [message-edit.ts](./examples/message-edit.ts) |
29
+ | [Send Tapbacks](#send-tapbacks) | React with ❤️ 👍 👎 😂 ‼️ ❓ | `messages.sendReaction()` | [message-reaction.ts](./examples/message-reaction.ts) |
30
+ | [Query Messages](#query-messages) | Search and filter message history | `messages.getMessages()` | [message-search.ts](./examples/message-search.ts) |
31
+ | [Message History](#get-chat-messages) | View messages, reactions, polls, stickers | `chats.getChatMessages()` | [message-history.ts](./examples/message-history.ts) |
32
+ | [Send Attachments](#send-attachments) | Send images, files, documents | `attachments.sendAttachment()` | [message-attachment.ts](./examples/message-attachment.ts) |
33
+ | [Send Audio Messages](#send-audio-messages) | Send voice messages | `attachments.sendAttachment()` | [message-audio.ts](./examples/message-audio.ts) |
34
+ | [Send Stickers](#send-stickers) | Send sticker as standalone message | `attachments.sendSticker()` | [message-sticker.ts](./examples/message-sticker.ts) |
35
+ | [Reply Stickers](#send-stickers) | Attach sticker to a message bubble | `attachments.sendSticker()` | [message-reply-sticker.ts](./examples/message-reply-sticker.ts) |
36
+ | [Download Attachments](#download-attachments) | Download received files and media | `attachments.downloadAttachment()` | [attachment-download.ts](./examples/attachment-download.ts) |
37
+ | [Get Chats](#get-chats) | List all conversations | `chats.getChats()` | [chat-fetch.ts](./examples/chat-fetch.ts) |
38
+ | [Get Chat Participants](#get-chat-participants) | View group chat participants | `chats.getChat()` | [chat-participants.ts](./examples/chat-participants.ts) |
39
+ | [Manage Group Chats](#manage-group-chats) | Add/remove members, rename groups | `chats.addParticipant()` | [chat-group.ts](./examples/chat-group.ts) |
40
+ | [Typing Indicators](#typing-indicators) | Show "typing..." status | `chats.startTyping()` | [message-typing.ts](./examples/message-typing.ts) |
41
+ | [Get Contacts](#get-contacts) | Fetch device contacts | `contacts.getContacts()` | [contact-list.ts](./examples/contact-list.ts) |
42
+ | [Share Contact Card](#share-contact-card) | Share your contact info in chat | `contacts.shareContactCard()` | [message-contact-card.ts](./examples/message-contact-card.ts) |
43
+ | [Check iMessage Availability](#check-service-availability) | Verify if contact uses iMessage | `handles.getHandleAvailability()` | [service-check.ts](./examples/service-check.ts) |
44
+ | [Server Info](#get-server-info) | Get server status and config | `server.getServerInfo()` | [server-info.ts](./examples/server-info.ts) |
45
+ | [Message Statistics](#message-statistics) | Get message counts and analytics | `server.getMessageStats()` | [message-stats.ts](./examples/message-stats.ts) |
46
+ | [Create Polls](#create-polls) | Create interactive polls in chat | `polls.create()` | [poll-create.ts](./examples/poll-create.ts) |
47
+ | [Vote on Polls](#vote-on-polls) | Vote or unvote on poll options | `polls.vote()` | [poll-vote.ts](./examples/poll-vote.ts) |
48
+ | [Add Poll Options](#add-poll-options) | Add options to existing polls | `polls.addOption()` | [poll-add-option.ts](./examples/poll-add-option.ts) |
49
+ | [Find My Friends](#find-my-friends) | Get friends' locations | `icloud.refreshFindMyFriends()` | [findmy-friends.ts](./examples/findmy-friends.ts) |
50
+ | [Set Chat Background](#chat-background) | Set custom background image for chat | `chats.setBackground()` | [background-set.ts](./examples/background-set.ts) |
51
+ | [Remove Chat Background](#chat-background) | Remove background from chat | `chats.removeBackground()` | [background-remove.ts](./examples/background-remove.ts) |
52
+ | [Real-time Events](#real-time-events) | Listen for new messages, typing, etc. | `sdk.on()` | [listen-simple.ts](./examples/listen-simple.ts) |
53
+ | [Auto Reply](#real-time-events) | Build automated reply bots | `sdk.on()` | [auto-reply-hey.ts](./examples/auto-reply-hey.ts) |
52
54
 
53
55
  ---
54
56
 
@@ -314,16 +316,19 @@ const daily = await sdk.scheduledMessages.createScheduledMessage({
314
316
  ```typescript
315
317
  const scheduledMessages = await sdk.scheduledMessages.getScheduledMessages();
316
318
 
317
- const updated = await sdk.scheduledMessages.updateScheduledMessage("scheduled-id", {
318
- type: "send-message",
319
- payload: {
320
- chatGuid: "any;-;+1234567890",
321
- message: "Updated message!",
322
- method: "apple-script",
323
- },
324
- scheduledFor: Date.now() + 10 * 60 * 1000,
325
- schedule: { type: "once" },
326
- });
319
+ const updated = await sdk.scheduledMessages.updateScheduledMessage(
320
+ "scheduled-id",
321
+ {
322
+ type: "send-message",
323
+ payload: {
324
+ chatGuid: "any;-;+1234567890",
325
+ message: "Updated message!",
326
+ method: "apple-script",
327
+ },
328
+ scheduledFor: Date.now() + 10 * 60 * 1000,
329
+ schedule: { type: "once" },
330
+ }
331
+ );
327
332
 
328
333
  await sdk.scheduledMessages.deleteScheduledMessage("scheduled-id");
329
334
  ```
@@ -332,7 +337,7 @@ await sdk.scheduledMessages.deleteScheduledMessage("scheduled-id");
332
337
 
333
338
  ## Chats
334
339
 
335
- > Examples: [chat-fetch.ts](./examples/chat-fetch.ts) | [chat-group.ts](./examples/chat-group.ts) | [message-typing.ts](./examples/message-typing.ts)
340
+ > Examples: [chat-fetch.ts](./examples/chat-fetch.ts) | [chat-group.ts](./examples/chat-group.ts) | [message-typing.ts](./examples/message-typing.ts) | [background-set.ts](./examples/background-set.ts) | [background-remove.ts](./examples/background-remove.ts)
336
341
 
337
342
  ### Get Chats
338
343
 
@@ -466,6 +471,30 @@ await sdk.chats.removeGroupIcon("chat-guid");
466
471
 
467
472
  > Example: [chat-group.ts](./examples/chat-group.ts)
468
473
 
474
+ ### Chat Background
475
+
476
+ Set, get, or remove custom background images for individual chats:
477
+
478
+ ```typescript
479
+ // Get current background info
480
+ const bgInfo = await sdk.chats.getBackground("chat-guid");
481
+ console.log(`Has background: ${bgInfo.hasBackground}`);
482
+ if (bgInfo.hasBackground) {
483
+ console.log(`Background ID: ${bgInfo.backgroundId}`);
484
+ console.log(`Image URL: ${bgInfo.imageUrl}`);
485
+ }
486
+
487
+ // Set a background image
488
+ await sdk.chats.setBackground("chat-guid", {
489
+ filePath: "/path/to/image.png",
490
+ });
491
+
492
+ // Remove background
493
+ await sdk.chats.removeBackground("chat-guid");
494
+ ```
495
+
496
+ > Examples: [background-set.ts](./examples/background-set.ts) | [background-remove.ts](./examples/background-remove.ts)
497
+
469
498
  ---
470
499
 
471
500
  ## Attachments
@@ -1049,6 +1078,8 @@ bun run examples/<filename>.ts
1049
1078
  | [chat-participants.ts](./examples/chat-participants.ts) | Get group participants |
1050
1079
  | [chat-group.ts](./examples/chat-group.ts) | Manage groups |
1051
1080
  | [message-typing.ts](./examples/message-typing.ts) | Typing indicators |
1081
+ | [background-set.ts](./examples/background-set.ts) | Set chat background |
1082
+ | [background-remove.ts](./examples/background-remove.ts) | Remove chat background |
1052
1083
 
1053
1084
  ### Contacts & Services
1054
1085
 
package/dist/index.cjs CHANGED
@@ -779,6 +779,12 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
779
779
  // Purpose: Prevent duplicate 'ready' events when both legacy mode (no API key)
780
780
  // and auth-ok events occur, which would cause user callbacks to fire twice.
781
781
  __publicField(this, "readyEmitted", false);
782
+ // Flag to track if socket event listeners have been attached
783
+ //
784
+ // Purpose: Prevent duplicate event listeners when connect() is called multiple times
785
+ // or after close(). Without this, each connect() call would add new listeners,
786
+ // causing events to fire multiple times.
787
+ __publicField(this, "listenersAttached", false);
782
788
  this.config = {
783
789
  serverUrl: "http://localhost:1234",
784
790
  logLevel: "info",
@@ -810,8 +816,18 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
810
816
  // Only WebSocket - polling disabled to prevent message duplication
811
817
  timeout: 1e4,
812
818
  // 10 second timeout to avoid overly frequent reconnections
813
- forceNew: true
819
+ forceNew: true,
814
820
  // Force new connection to avoid connection state pollution
821
+ reconnection: true,
822
+ // Enable auto-reconnection (default, but explicit for clarity)
823
+ reconnectionAttempts: Number.POSITIVE_INFINITY,
824
+ // Never give up
825
+ reconnectionDelay: 100,
826
+ // Start with 100ms delay (fast initial reconnect)
827
+ reconnectionDelayMax: 2e3,
828
+ // Max 2 seconds between attempts
829
+ randomizationFactor: 0.1
830
+ // Low randomization for more consistent reconnect timing
815
831
  });
816
832
  const enqueueSend = this.enqueueSend.bind(this);
817
833
  this.attachments = new AttachmentModule(this.http, enqueueSend);
@@ -851,6 +867,17 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
851
867
  return super.removeListener(event, listener);
852
868
  }
853
869
  async connect() {
870
+ if (!this.listenersAttached) {
871
+ this.listenersAttached = true;
872
+ this.attachSocketListeners();
873
+ }
874
+ if (this.socket.connected) {
875
+ this.logger.info("Already connected to iMessage server");
876
+ return;
877
+ }
878
+ this.socket.connect();
879
+ }
880
+ attachSocketListeners() {
854
881
  const serverEvents = [
855
882
  "new-message",
856
883
  "message-updated",
@@ -888,10 +915,26 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
888
915
  }
889
916
  });
890
917
  }
891
- this.socket.on("disconnect", () => {
892
- this.logger.info("Disconnected from iMessage server");
918
+ this.socket.on("disconnect", (reason) => {
919
+ this.logger.info(`Disconnected from iMessage server (reason: ${reason})`);
893
920
  this.readyEmitted = false;
894
921
  this.emit("disconnect");
922
+ if (reason === "io server disconnect") {
923
+ this.logger.info("Server disconnected, manually triggering reconnect...");
924
+ this.socket.connect();
925
+ }
926
+ });
927
+ this.socket.io.on("reconnect_attempt", (attempt) => {
928
+ this.logger.info(`Reconnection attempt #${attempt}...`);
929
+ });
930
+ this.socket.io.on("reconnect", (attempt) => {
931
+ this.logger.info(`Reconnected successfully after ${attempt} attempt(s)`);
932
+ });
933
+ this.socket.io.on("reconnect_error", (error) => {
934
+ this.logger.warn(`Reconnection error: ${error.message}`);
935
+ });
936
+ this.socket.io.on("reconnect_failed", () => {
937
+ this.logger.error("All reconnection attempts failed");
895
938
  });
896
939
  this.socket.on("auth-ok", () => {
897
940
  this.logger.info("Authentication successful");
@@ -904,11 +947,7 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
904
947
  this.logger.error(`Authentication failed: ${error.message} ${error.reason ? `(${error.reason})` : ""}`);
905
948
  this.emit("error", new Error(`Authentication failed: ${error.message}`));
906
949
  });
907
- if (this.socket.connected) {
908
- this.logger.info("Already connected to iMessage server");
909
- return;
910
- }
911
- this.socket.once("connect", () => {
950
+ this.socket.on("connect", () => {
912
951
  this.logger.info("Connected to iMessage server, waiting for authentication...");
913
952
  if (!this.config.apiKey) {
914
953
  this.logger.info("No API key provided, skipping authentication (legacy server mode)");
@@ -918,9 +957,9 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter.Event
918
957
  }
919
958
  }
920
959
  });
921
- if (!this.socket.connected) {
922
- this.socket.connect();
923
- }
960
+ this.socket.on("connect_error", (error) => {
961
+ this.logger.warn(`Connection error: ${error.message}`);
962
+ });
924
963
  }
925
964
  async close() {
926
965
  this.socket.disconnect();