@photon-ai/advanced-imessage-kit 1.2.1 → 1.3.2

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.ts CHANGED
@@ -24,6 +24,7 @@ interface SendAttachmentOptions {
24
24
  filePath: string;
25
25
  fileName?: string;
26
26
  isAudioMessage?: boolean;
27
+ selectedMessageGuid?: string;
27
28
  }
28
29
  interface Attachment {
29
30
  guid: string;
@@ -148,6 +149,7 @@ type MessageResponse = {
148
149
  partCount?: number | null;
149
150
  payloadData?: NodeJS.Dict<any>[];
150
151
  hasPayloadData?: boolean;
152
+ isPoll?: boolean;
151
153
  wasDeliveredQuietly?: boolean;
152
154
  didNotifyRecipient?: boolean;
153
155
  shareStatus?: number | null;
@@ -326,11 +328,59 @@ interface TypedEventEmitter {
326
328
  removeListener(event: string | symbol, listener: (...args: unknown[]) => void): this;
327
329
  }
328
330
 
331
+ interface CreatePollOptions {
332
+ chatGuid: string;
333
+ title?: string;
334
+ options: string[];
335
+ }
336
+ interface VotePollOptions {
337
+ chatGuid: string;
338
+ pollMessageGuid: string;
339
+ optionIdentifier: string;
340
+ }
341
+ interface AddPollOptionOptions {
342
+ chatGuid: string;
343
+ pollMessageGuid: string;
344
+ optionText: string;
345
+ }
346
+ interface PollOption {
347
+ optionIdentifier: string;
348
+ text: string;
349
+ attributedText: string;
350
+ creatorHandle: string;
351
+ canBeEdited: boolean;
352
+ }
353
+ interface PollVote {
354
+ voteOptionIdentifier: string;
355
+ participantHandle: string;
356
+ serverVoteTime?: number;
357
+ }
358
+ interface PollDefinition {
359
+ version: number;
360
+ item: {
361
+ title: string;
362
+ orderedPollOptions: PollOption[];
363
+ creatorHandle: string;
364
+ };
365
+ }
366
+ interface PollVoteResponse {
367
+ version: number;
368
+ item: {
369
+ votes: PollVote[];
370
+ };
371
+ }
372
+ type PollMessageResponse = MessageResponse;
373
+
329
374
  interface SendStickerOptions {
330
375
  chatGuid: string;
331
376
  filePath: string;
332
377
  fileName?: string;
333
378
  selectedMessageGuid?: string;
379
+ stickerX?: number;
380
+ stickerY?: number;
381
+ stickerScale?: number;
382
+ stickerRotation?: number;
383
+ stickerWidth?: number;
334
384
  }
335
385
 
336
386
  type ValidTapback = "love" | "like" | "dislike" | "laugh" | "emphasize" | "question";
@@ -387,7 +437,6 @@ declare class ChatModule {
387
437
  }): Promise<ChatResponse>;
388
438
  deleteChat(guid: string): Promise<void>;
389
439
  markChatRead(guid: string): Promise<void>;
390
- markChatUnread(guid: string): Promise<void>;
391
440
  leaveChat(guid: string): Promise<void>;
392
441
  addParticipant(chatGuid: string, address: string): Promise<ChatResponse>;
393
442
  removeParticipant(chatGuid: string, address: string): Promise<ChatResponse>;
@@ -528,6 +577,15 @@ declare class MessageModule {
528
577
  }): Promise<MessageResponse[]>;
529
578
  }
530
579
 
580
+ declare class PollModule {
581
+ private readonly http;
582
+ constructor(http: AxiosInstance);
583
+ create(options: CreatePollOptions): Promise<PollMessageResponse>;
584
+ vote(options: VotePollOptions): Promise<PollMessageResponse>;
585
+ unvote(options: VotePollOptions): Promise<PollMessageResponse>;
586
+ addOption(options: AddPollOptionOptions): Promise<PollMessageResponse>;
587
+ }
588
+
531
589
  declare class ScheduledMessageModule {
532
590
  private readonly http;
533
591
  constructor(http: AxiosInstance);
@@ -543,8 +601,6 @@ declare class ServerModule {
543
601
  getServerInfo(): Promise<any>;
544
602
  getMessageStats(): Promise<any>;
545
603
  getServerLogs(count?: number): Promise<string[]>;
546
- getAlerts(): Promise<any[]>;
547
- markAlertAsRead(ids: string[]): Promise<any>;
548
604
  getMediaStatistics(options?: {
549
605
  only?: string[];
550
606
  }): Promise<any>;
@@ -568,10 +624,12 @@ declare class AdvancedIMessageKit extends EventEmitter$1 implements TypedEventEm
568
624
  readonly handles: HandleModule;
569
625
  readonly facetime: FaceTimeModule;
570
626
  readonly icloud: ICloudModule;
627
+ readonly polls: PollModule;
571
628
  readonly scheduledMessages: ScheduledMessageModule;
572
629
  readonly server: ServerModule;
573
630
  private processedMessages;
574
631
  private sendQueue;
632
+ private readyEmitted;
575
633
  private constructor();
576
634
  emit<K extends keyof PhotonEventMap>(event: K, ...args: PhotonEventMap[K] extends undefined ? [] : [PhotonEventMap[K]]): boolean;
577
635
  on<K extends keyof PhotonEventMap>(event: K, listener: PhotonEventMap[K] extends undefined ? () => void : (data: PhotonEventMap[K]) => void): this;
@@ -636,4 +694,19 @@ declare const NEW_FINDMY_LOCATION = "new-findmy-location";
636
694
  declare const setGlobalLogLevel: (level: LogLevel) => void;
637
695
  declare const getLogger: (tag: string) => Logger;
638
696
 
639
- export { AdvancedIMessageKit, type Attachment, type AttachmentResponse, type BackupData, CHAT_READ_STATUS_CHANGED, type Chat, type ChatResponse, type ClientConfig, FT_CALL_STATUS_CHANGED, type FaceTimeStatusData, type FindMyLocationItem, GROUP_ICON_CHANGED, GROUP_ICON_REMOVED, GROUP_NAME_CHANGE, HELLO_WORLD, type Handle, type HandleResponse, IMESSAGE_ALIASES_REMOVED, INCOMING_FACETIME, MESSAGE_SEND_ERROR, MESSAGE_UPDATED, type Message, type MessageData, type MessageResponse, NEW_FINDMY_LOCATION, NEW_MESSAGE, NEW_SERVER, PARTICIPANT_ADDED, PARTICIPANT_LEFT, PARTICIPANT_REMOVED, type PhotonEventMap, type PhotonEventName, SCHEDULED_MESSAGE_CREATED, SCHEDULED_MESSAGE_DELETED, SCHEDULED_MESSAGE_ERROR, SCHEDULED_MESSAGE_SENT, SCHEDULED_MESSAGE_UPDATED, SDK, SERVER_UPDATE, SERVER_UPDATE_DOWNLOADING, SERVER_UPDATE_INSTALLING, SETTINGS_BACKUP_CREATED, SETTINGS_BACKUP_DELETED, SETTINGS_BACKUP_UPDATED, type ScheduledMessageData, type SendAttachmentOptions, type SendMessageOptions, type SendStickerOptions, type ServerMetadataResponse, type ServerUpdateData, THEME_BACKUP_CREATED, THEME_BACKUP_DELETED, THEME_BACKUP_UPDATED, TYPING_INDICATOR, type TypedEventEmitter, type ValidRemoveTapback, type ValidTapback, getLogger, setGlobalLogLevel };
697
+ declare function isPollMessage(message: MessageResponse): boolean;
698
+ declare function isPollVote(message: MessageResponse): boolean;
699
+ interface ParsedPoll {
700
+ title: string;
701
+ creatorHandle: string;
702
+ options: PollOption[];
703
+ }
704
+ interface ParsedPollVote {
705
+ votes: PollVote[];
706
+ }
707
+ declare function parsePollDefinition(message: MessageResponse): ParsedPoll | null;
708
+ declare function parsePollVotes(message: MessageResponse): ParsedPollVote | null;
709
+ declare function getPollSummary(message: MessageResponse): string;
710
+ declare function getPollOneLiner(message: MessageResponse): string;
711
+
712
+ export { type AddPollOptionOptions, AdvancedIMessageKit, type Attachment, type AttachmentResponse, type BackupData, CHAT_READ_STATUS_CHANGED, type Chat, type ChatResponse, type ClientConfig, type CreatePollOptions, FT_CALL_STATUS_CHANGED, type FaceTimeStatusData, type FindMyLocationItem, GROUP_ICON_CHANGED, GROUP_ICON_REMOVED, GROUP_NAME_CHANGE, HELLO_WORLD, type Handle, type HandleResponse, IMESSAGE_ALIASES_REMOVED, INCOMING_FACETIME, MESSAGE_SEND_ERROR, MESSAGE_UPDATED, type Message, type MessageData, type MessageResponse, NEW_FINDMY_LOCATION, NEW_MESSAGE, NEW_SERVER, PARTICIPANT_ADDED, PARTICIPANT_LEFT, PARTICIPANT_REMOVED, type ParsedPoll, type ParsedPollVote, type PhotonEventMap, type PhotonEventName, type PollDefinition, type PollMessageResponse, type PollOption, type PollVote, type PollVoteResponse, SCHEDULED_MESSAGE_CREATED, SCHEDULED_MESSAGE_DELETED, SCHEDULED_MESSAGE_ERROR, SCHEDULED_MESSAGE_SENT, SCHEDULED_MESSAGE_UPDATED, SDK, SERVER_UPDATE, SERVER_UPDATE_DOWNLOADING, SERVER_UPDATE_INSTALLING, SETTINGS_BACKUP_CREATED, SETTINGS_BACKUP_DELETED, SETTINGS_BACKUP_UPDATED, type ScheduledMessageData, type SendAttachmentOptions, type SendMessageOptions, type SendStickerOptions, type ServerMetadataResponse, type ServerUpdateData, THEME_BACKUP_CREATED, THEME_BACKUP_DELETED, THEME_BACKUP_UPDATED, TYPING_INDICATOR, type TypedEventEmitter, type ValidRemoveTapback, type ValidTapback, type VotePollOptions, getLogger, getPollOneLiner, getPollSummary, isPollMessage, isPollVote, parsePollDefinition, parsePollVotes, setGlobalLogLevel };
package/dist/index.js CHANGED
@@ -162,6 +162,9 @@ var AttachmentModule = class {
162
162
  form.append("method", "private-api");
163
163
  }
164
164
  }
165
+ if (options.selectedMessageGuid) {
166
+ form.append("selectedMessageGuid", options.selectedMessageGuid);
167
+ }
165
168
  const response = await this.http.post("/api/v1/message/attachment", form, {
166
169
  headers: form.getHeaders()
167
170
  });
@@ -173,15 +176,23 @@ var AttachmentModule = class {
173
176
  const fileName = options.fileName || path__default.basename(options.filePath);
174
177
  const form = new FormData();
175
178
  form.append("attachment", await readFile(options.filePath), fileName);
176
- const { data } = await this.http.post("/api/v1/attachment/upload", form, {
179
+ form.append("name", fileName);
180
+ form.append("chatGuid", options.chatGuid);
181
+ form.append("isSticker", "true");
182
+ form.append("method", "private-api");
183
+ if (options.selectedMessageGuid) {
184
+ form.append("selectedMessageGuid", options.selectedMessageGuid);
185
+ form.append("partIndex", "0");
186
+ }
187
+ form.append("stickerX", String(options.stickerX ?? 0.5));
188
+ form.append("stickerY", String(options.stickerY ?? 0.5));
189
+ form.append("stickerScale", String(options.stickerScale ?? 0.75));
190
+ form.append("stickerRotation", String(options.stickerRotation ?? 0));
191
+ form.append("stickerWidth", String(options.stickerWidth ?? 300));
192
+ const { data } = await this.http.post("/api/v1/message/attachment", form, {
177
193
  headers: form.getHeaders()
178
194
  });
179
- const response = await this.http.post("/api/v1/message/multipart", {
180
- chatGuid: options.chatGuid,
181
- selectedMessageGuid: options.selectedMessageGuid,
182
- parts: [{ partIndex: 0, attachment: data.data.path, name: fileName }]
183
- });
184
- return response.data.data;
195
+ return data.data;
185
196
  });
186
197
  }
187
198
  };
@@ -198,35 +209,32 @@ var ChatModule = class {
198
209
  return response.data.data;
199
210
  }
200
211
  async getChat(guid, options) {
201
- const response = await this.http.get(`/api/v1/chat/${guid}`, {
212
+ const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(guid)}`, {
202
213
  params: options?.with ? { with: options.with.join(",") } : {}
203
214
  });
204
215
  return response.data.data;
205
216
  }
206
217
  async updateChat(guid, options) {
207
- const response = await this.http.put(`/api/v1/chat/${guid}`, options);
218
+ const response = await this.http.put(`/api/v1/chat/${encodeURIComponent(guid)}`, options);
208
219
  return response.data.data;
209
220
  }
210
221
  async deleteChat(guid) {
211
- await this.http.delete(`/api/v1/chat/${guid}`);
222
+ await this.http.delete(`/api/v1/chat/${encodeURIComponent(guid)}`);
212
223
  }
213
224
  async markChatRead(guid) {
214
- await this.http.post(`/api/v1/chat/${guid}/read`);
215
- }
216
- async markChatUnread(guid) {
217
- await this.http.post(`/api/v1/chat/${guid}/unread`);
225
+ await this.http.post(`/api/v1/chat/${encodeURIComponent(guid)}/read`);
218
226
  }
219
227
  async leaveChat(guid) {
220
- await this.http.post(`/api/v1/chat/${guid}/leave`);
228
+ await this.http.post(`/api/v1/chat/${encodeURIComponent(guid)}/leave`);
221
229
  }
222
230
  async addParticipant(chatGuid, address) {
223
- const response = await this.http.post(`/api/v1/chat/${chatGuid}/participant`, {
231
+ const response = await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/participant`, {
224
232
  address
225
233
  });
226
234
  return response.data.data;
227
235
  }
228
236
  async removeParticipant(chatGuid, address) {
229
- const response = await this.http.delete(`/api/v1/chat/${chatGuid}/participant`, {
237
+ const response = await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/participant`, {
230
238
  data: { address }
231
239
  });
232
240
  return response.data.data;
@@ -239,7 +247,7 @@ var ChatModule = class {
239
247
  if (options?.before !== void 0) params.before = options.before;
240
248
  if (options?.after !== void 0) params.after = options.after;
241
249
  if (options?.with) params.with = options.with.join(",");
242
- const response = await this.http.get(`/api/v1/chat/${chatGuid}/message`, {
250
+ const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/message`, {
243
251
  params
244
252
  });
245
253
  return response.data.data;
@@ -249,15 +257,15 @@ var ChatModule = class {
249
257
  const fileName = path__default.basename(filePath);
250
258
  const form = new FormData();
251
259
  form.append("icon", fileBuffer, fileName);
252
- await this.http.post(`/api/v1/chat/${chatGuid}/icon`, form, {
260
+ await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`, form, {
253
261
  headers: form.getHeaders()
254
262
  });
255
263
  }
256
264
  async removeGroupIcon(chatGuid) {
257
- await this.http.delete(`/api/v1/chat/${chatGuid}/icon`);
265
+ await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`);
258
266
  }
259
267
  async getGroupIcon(chatGuid) {
260
- const response = await this.http.get(`/api/v1/chat/${chatGuid}/icon`, {
268
+ const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`, {
261
269
  responseType: "arraybuffer"
262
270
  });
263
271
  return Buffer.from(response.data);
@@ -269,10 +277,10 @@ var ChatModule = class {
269
277
  return response.data.data;
270
278
  }
271
279
  async startTyping(chatGuid) {
272
- await this.http.post(`/api/v1/chat/${chatGuid}/typing`);
280
+ await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`);
273
281
  }
274
282
  async stopTyping(chatGuid) {
275
- await this.http.delete(`/api/v1/chat/${chatGuid}/typing`);
283
+ await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`);
276
284
  }
277
285
  };
278
286
 
@@ -292,10 +300,10 @@ var ContactModule = class {
292
300
  return response.data.data;
293
301
  }
294
302
  async shareContactCard(chatGuid) {
295
- await this.http.post(`/api/v1/chat/${chatGuid}/share/contact`);
303
+ await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/share/contact`);
296
304
  }
297
305
  async shouldShareContact(chatGuid) {
298
- const response = await this.http.get(`/api/v1/chat/${chatGuid}/share/contact/status`);
306
+ const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/share/contact/status`);
299
307
  return response.data.data;
300
308
  }
301
309
  };
@@ -509,6 +517,51 @@ var MessageModule = class {
509
517
  }
510
518
  };
511
519
 
520
+ // modules/poll.ts
521
+ var PollModule = class {
522
+ constructor(http) {
523
+ this.http = http;
524
+ }
525
+ async create(options) {
526
+ if (options.options.length < 2) {
527
+ throw new Error("Poll must have at least 2 options");
528
+ }
529
+ const { data } = await this.http.post("/api/v1/poll/create", {
530
+ chatGuid: options.chatGuid,
531
+ title: options.title ?? "",
532
+ options: options.options
533
+ });
534
+ return data.data;
535
+ }
536
+ async vote(options) {
537
+ const { data } = await this.http.post("/api/v1/poll/vote", {
538
+ chatGuid: options.chatGuid,
539
+ pollMessageGuid: options.pollMessageGuid,
540
+ optionIdentifier: options.optionIdentifier
541
+ });
542
+ return data.data;
543
+ }
544
+ async unvote(options) {
545
+ const { data } = await this.http.post("/api/v1/poll/unvote", {
546
+ chatGuid: options.chatGuid,
547
+ pollMessageGuid: options.pollMessageGuid,
548
+ optionIdentifier: options.optionIdentifier
549
+ });
550
+ return data.data;
551
+ }
552
+ async addOption(options) {
553
+ if (!options.optionText || options.optionText.trim().length === 0) {
554
+ throw new Error("Option text cannot be empty");
555
+ }
556
+ const { data } = await this.http.post("/api/v1/poll/option", {
557
+ chatGuid: options.chatGuid,
558
+ pollMessageGuid: options.pollMessageGuid,
559
+ optionText: options.optionText
560
+ });
561
+ return data.data;
562
+ }
563
+ };
564
+
512
565
  // modules/scheduled.ts
513
566
  var ScheduledMessageModule = class {
514
567
  constructor(http) {
@@ -550,14 +603,6 @@ var ServerModule = class {
550
603
  });
551
604
  return response.data.data;
552
605
  }
553
- async getAlerts() {
554
- const response = await this.http.get("/api/v1/server/alert");
555
- return response.data.data;
556
- }
557
- async markAlertAsRead(ids) {
558
- const response = await this.http.post("/api/v1/server/alert/read", { ids });
559
- return response.data.data;
560
- }
561
606
  async getMediaStatistics(options) {
562
607
  const params = {};
563
608
  if (options?.only) params.only = options.only.join(",");
@@ -592,6 +637,7 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
592
637
  __publicField(this, "handles");
593
638
  __publicField(this, "facetime");
594
639
  __publicField(this, "icloud");
640
+ __publicField(this, "polls");
595
641
  __publicField(this, "scheduledMessages");
596
642
  __publicField(this, "server");
597
643
  // Message deduplication feature
@@ -605,6 +651,11 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
605
651
  // Purpose: Ensure all outgoing messages (text, attachments, stickers, etc.) from
606
652
  // a single user/SDK instance are sent in strict order, preventing race conditions.
607
653
  __publicField(this, "sendQueue", Promise.resolve());
654
+ // Flag to track if 'ready' event has been emitted
655
+ //
656
+ // Purpose: Prevent duplicate 'ready' events when both legacy mode (no API key)
657
+ // and auth-ok events occur, which would cause user callbacks to fire twice.
658
+ __publicField(this, "readyEmitted", false);
608
659
  this.config = {
609
660
  serverUrl: "http://localhost:1234",
610
661
  logLevel: "info",
@@ -647,6 +698,7 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
647
698
  this.handles = new HandleModule(this.http);
648
699
  this.facetime = new FaceTimeModule(this.http);
649
700
  this.icloud = new ICloudModule(this.http);
701
+ this.polls = new PollModule(this.http);
650
702
  this.scheduledMessages = new ScheduledMessageModule(this.http);
651
703
  this.server = new ServerModule(this.http);
652
704
  }
@@ -715,11 +767,15 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
715
767
  }
716
768
  this.socket.on("disconnect", () => {
717
769
  this.logger.info("Disconnected from iMessage server");
770
+ this.readyEmitted = false;
718
771
  this.emit("disconnect");
719
772
  });
720
773
  this.socket.on("auth-ok", () => {
721
774
  this.logger.info("Authentication successful");
722
- this.emit("ready");
775
+ if (!this.readyEmitted) {
776
+ this.readyEmitted = true;
777
+ this.emit("ready");
778
+ }
723
779
  });
724
780
  this.socket.on("auth-error", (error) => {
725
781
  this.logger.error(`Authentication failed: ${error.message} ${error.reason ? `(${error.reason})` : ""}`);
@@ -733,7 +789,10 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
733
789
  this.logger.info("Connected to iMessage server, waiting for authentication...");
734
790
  if (!this.config.apiKey) {
735
791
  this.logger.info("No API key provided, skipping authentication (legacy server mode)");
736
- this.emit("ready");
792
+ if (!this.readyEmitted) {
793
+ this.readyEmitted = true;
794
+ this.emit("ready");
795
+ }
737
796
  }
738
797
  });
739
798
  if (!this.socket.connected) {
@@ -817,6 +876,144 @@ var IMESSAGE_ALIASES_REMOVED = "imessage-aliases-removed";
817
876
  var FT_CALL_STATUS_CHANGED = "ft-call-status-changed";
818
877
  var NEW_FINDMY_LOCATION = "new-findmy-location";
819
878
 
820
- export { AdvancedIMessageKit, CHAT_READ_STATUS_CHANGED, FT_CALL_STATUS_CHANGED, GROUP_ICON_CHANGED, GROUP_ICON_REMOVED, GROUP_NAME_CHANGE, HELLO_WORLD, IMESSAGE_ALIASES_REMOVED, INCOMING_FACETIME, MESSAGE_SEND_ERROR, MESSAGE_UPDATED, NEW_FINDMY_LOCATION, NEW_MESSAGE, NEW_SERVER, PARTICIPANT_ADDED, PARTICIPANT_LEFT, PARTICIPANT_REMOVED, SCHEDULED_MESSAGE_CREATED, SCHEDULED_MESSAGE_DELETED, SCHEDULED_MESSAGE_ERROR, SCHEDULED_MESSAGE_SENT, SCHEDULED_MESSAGE_UPDATED, SDK, SERVER_UPDATE, SERVER_UPDATE_DOWNLOADING, SERVER_UPDATE_INSTALLING, SETTINGS_BACKUP_CREATED, SETTINGS_BACKUP_DELETED, SETTINGS_BACKUP_UPDATED, THEME_BACKUP_CREATED, THEME_BACKUP_DELETED, THEME_BACKUP_UPDATED, TYPING_INDICATOR, getLogger, setGlobalLogLevel };
879
+ // lib/poll-utils.ts
880
+ var POLL_BALLOON_BUNDLE_ID = "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.messages.Polls";
881
+ var pollCache = /* @__PURE__ */ new Map();
882
+ function cachePoll(messageGuid, poll) {
883
+ pollCache.set(messageGuid, poll);
884
+ }
885
+ function getOptionTextById(optionId) {
886
+ for (const poll of pollCache.values()) {
887
+ const option = poll.options.find((o) => o.optionIdentifier === optionId);
888
+ if (option) return option.text;
889
+ }
890
+ return null;
891
+ }
892
+ function isPollMessage(message) {
893
+ return message.balloonBundleId === POLL_BALLOON_BUNDLE_ID;
894
+ }
895
+ function isPollVote(message) {
896
+ return isPollMessage(message) && message.associatedMessageType === "4000";
897
+ }
898
+ function extractDataUrl(payloadData) {
899
+ if (!payloadData || payloadData.length === 0) return null;
900
+ const payload = payloadData[0];
901
+ if (!payload) return null;
902
+ if (payload.URL && typeof payload.URL === "string") {
903
+ return payload.URL;
904
+ }
905
+ const objects = payload.$objects;
906
+ if (Array.isArray(objects)) {
907
+ for (const obj of objects) {
908
+ if (typeof obj === "object" && obj !== null) {
909
+ if (obj["NS.relative"] && typeof obj["NS.relative"] === "object") {
910
+ const relativeObj = objects[obj["NS.relative"].UID];
911
+ if (typeof relativeObj === "string" && relativeObj.startsWith("data:,")) {
912
+ return relativeObj;
913
+ }
914
+ }
915
+ if (typeof obj === "string" && obj.startsWith("data:,")) {
916
+ return obj;
917
+ }
918
+ }
919
+ }
920
+ }
921
+ return null;
922
+ }
923
+ function parseDataUrl(dataUrl) {
924
+ try {
925
+ const prefix = "data:,";
926
+ if (!dataUrl.startsWith(prefix)) return null;
927
+ let data = dataUrl.slice(prefix.length);
928
+ const queryIndex = data.indexOf("?");
929
+ if (queryIndex !== -1) {
930
+ data = data.slice(0, queryIndex);
931
+ }
932
+ data = decodeURIComponent(data);
933
+ try {
934
+ return JSON.parse(data);
935
+ } catch {
936
+ const decoded = Buffer.from(data, "base64").toString("utf-8");
937
+ return JSON.parse(decoded);
938
+ }
939
+ } catch {
940
+ return null;
941
+ }
942
+ }
943
+ function parsePollDefinition(message) {
944
+ if (!isPollMessage(message)) return null;
945
+ if (isPollVote(message)) return null;
946
+ const dataUrl = extractDataUrl(message.payloadData);
947
+ if (!dataUrl) return null;
948
+ const data = parseDataUrl(dataUrl);
949
+ if (!data || !data.item) return null;
950
+ const parsed = {
951
+ title: data.item.title || "",
952
+ creatorHandle: data.item.creatorHandle || "",
953
+ options: data.item.orderedPollOptions || []
954
+ };
955
+ if (message.guid) {
956
+ cachePoll(message.guid, parsed);
957
+ }
958
+ return parsed;
959
+ }
960
+ function parsePollVotes(message) {
961
+ if (!isPollMessage(message)) return null;
962
+ if (!isPollVote(message)) return null;
963
+ const dataUrl = extractDataUrl(message.payloadData);
964
+ if (!dataUrl) return null;
965
+ const data = parseDataUrl(dataUrl);
966
+ if (!data || !data.item) return null;
967
+ return {
968
+ votes: data.item.votes || []
969
+ };
970
+ }
971
+ function getPollSummary(message) {
972
+ if (!isPollMessage(message)) {
973
+ return message.text || "(no text)";
974
+ }
975
+ if (isPollVote(message)) {
976
+ const voteData = parsePollVotes(message);
977
+ if (voteData && voteData.votes.length > 0) {
978
+ const votes = voteData.votes.map((v) => {
979
+ const optionText = getOptionTextById(v.voteOptionIdentifier);
980
+ const optionDisplay = optionText ? `"${optionText}"` : `option ${v.voteOptionIdentifier}`;
981
+ return `${v.participantHandle || "Someone"} voted ${optionDisplay}`;
982
+ }).join(", ");
983
+ return `[Poll Vote] ${votes}`;
984
+ }
985
+ return "[Poll Vote]";
986
+ }
987
+ const pollData = parsePollDefinition(message);
988
+ if (pollData) {
989
+ const title = pollData.title ? `"${pollData.title}"` : "(untitled poll)";
990
+ const optionsList = pollData.options.map((opt, i) => ` ${i + 1}. ${opt.text}`).join("\n");
991
+ return `[Poll] ${title}
992
+ ${optionsList}`;
993
+ }
994
+ return "[Poll] (unable to parse)";
995
+ }
996
+ function getPollOneLiner(message) {
997
+ if (!isPollMessage(message)) {
998
+ return message.text || "(no text)";
999
+ }
1000
+ if (isPollVote(message)) {
1001
+ const voteData = parsePollVotes(message);
1002
+ if (voteData && voteData.votes.length > 0) {
1003
+ return `[Poll Vote] ${voteData.votes.length} vote(s)`;
1004
+ }
1005
+ return "[Poll Vote]";
1006
+ }
1007
+ const pollData = parsePollDefinition(message);
1008
+ if (pollData) {
1009
+ const title = pollData.title || "Poll";
1010
+ const optionsPreview = pollData.options.slice(0, 2).map((o) => o.text).join(", ");
1011
+ const moreOptions = pollData.options.length > 2 ? `, +${pollData.options.length - 2} more` : "";
1012
+ return `[${title}] ${optionsPreview}${moreOptions}`;
1013
+ }
1014
+ return "[Poll]";
1015
+ }
1016
+
1017
+ export { AdvancedIMessageKit, CHAT_READ_STATUS_CHANGED, FT_CALL_STATUS_CHANGED, GROUP_ICON_CHANGED, GROUP_ICON_REMOVED, GROUP_NAME_CHANGE, HELLO_WORLD, IMESSAGE_ALIASES_REMOVED, INCOMING_FACETIME, MESSAGE_SEND_ERROR, MESSAGE_UPDATED, NEW_FINDMY_LOCATION, NEW_MESSAGE, NEW_SERVER, PARTICIPANT_ADDED, PARTICIPANT_LEFT, PARTICIPANT_REMOVED, SCHEDULED_MESSAGE_CREATED, SCHEDULED_MESSAGE_DELETED, SCHEDULED_MESSAGE_ERROR, SCHEDULED_MESSAGE_SENT, SCHEDULED_MESSAGE_UPDATED, SDK, SERVER_UPDATE, SERVER_UPDATE_DOWNLOADING, SERVER_UPDATE_INSTALLING, SETTINGS_BACKUP_CREATED, SETTINGS_BACKUP_DELETED, SETTINGS_BACKUP_UPDATED, THEME_BACKUP_CREATED, THEME_BACKUP_DELETED, THEME_BACKUP_UPDATED, TYPING_INDICATOR, getLogger, getPollOneLiner, getPollSummary, isPollMessage, isPollVote, parsePollDefinition, parsePollVotes, setGlobalLogLevel };
821
1018
  //# sourceMappingURL=index.js.map
822
1019
  //# sourceMappingURL=index.js.map