@photon-ai/advanced-imessage-kit 1.2.0 → 1.3.0
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 +536 -554
- package/dist/index.cjs +291 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -4
- package/dist/index.d.ts +76 -4
- package/dist/index.js +286 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -148,6 +148,7 @@ type MessageResponse = {
|
|
|
148
148
|
partCount?: number | null;
|
|
149
149
|
payloadData?: NodeJS.Dict<any>[];
|
|
150
150
|
hasPayloadData?: boolean;
|
|
151
|
+
isPoll?: boolean;
|
|
151
152
|
wasDeliveredQuietly?: boolean;
|
|
152
153
|
didNotifyRecipient?: boolean;
|
|
153
154
|
shareStatus?: number | null;
|
|
@@ -326,11 +327,59 @@ interface TypedEventEmitter {
|
|
|
326
327
|
removeListener(event: string | symbol, listener: (...args: unknown[]) => void): this;
|
|
327
328
|
}
|
|
328
329
|
|
|
330
|
+
interface CreatePollOptions {
|
|
331
|
+
chatGuid: string;
|
|
332
|
+
title?: string;
|
|
333
|
+
options: string[];
|
|
334
|
+
}
|
|
335
|
+
interface VotePollOptions {
|
|
336
|
+
chatGuid: string;
|
|
337
|
+
pollMessageGuid: string;
|
|
338
|
+
optionIdentifier: string;
|
|
339
|
+
}
|
|
340
|
+
interface AddPollOptionOptions {
|
|
341
|
+
chatGuid: string;
|
|
342
|
+
pollMessageGuid: string;
|
|
343
|
+
optionText: string;
|
|
344
|
+
}
|
|
345
|
+
interface PollOption {
|
|
346
|
+
optionIdentifier: string;
|
|
347
|
+
text: string;
|
|
348
|
+
attributedText: string;
|
|
349
|
+
creatorHandle: string;
|
|
350
|
+
canBeEdited: boolean;
|
|
351
|
+
}
|
|
352
|
+
interface PollVote {
|
|
353
|
+
voteOptionIdentifier: string;
|
|
354
|
+
participantHandle: string;
|
|
355
|
+
serverVoteTime?: number;
|
|
356
|
+
}
|
|
357
|
+
interface PollDefinition {
|
|
358
|
+
version: number;
|
|
359
|
+
item: {
|
|
360
|
+
title: string;
|
|
361
|
+
orderedPollOptions: PollOption[];
|
|
362
|
+
creatorHandle: string;
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
interface PollVoteResponse {
|
|
366
|
+
version: number;
|
|
367
|
+
item: {
|
|
368
|
+
votes: PollVote[];
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
type PollMessageResponse = MessageResponse;
|
|
372
|
+
|
|
329
373
|
interface SendStickerOptions {
|
|
330
374
|
chatGuid: string;
|
|
331
375
|
filePath: string;
|
|
332
376
|
fileName?: string;
|
|
333
377
|
selectedMessageGuid?: string;
|
|
378
|
+
stickerX?: number;
|
|
379
|
+
stickerY?: number;
|
|
380
|
+
stickerScale?: number;
|
|
381
|
+
stickerRotation?: number;
|
|
382
|
+
stickerWidth?: number;
|
|
334
383
|
}
|
|
335
384
|
|
|
336
385
|
type ValidTapback = "love" | "like" | "dislike" | "laugh" | "emphasize" | "question";
|
|
@@ -387,7 +436,6 @@ declare class ChatModule {
|
|
|
387
436
|
}): Promise<ChatResponse>;
|
|
388
437
|
deleteChat(guid: string): Promise<void>;
|
|
389
438
|
markChatRead(guid: string): Promise<void>;
|
|
390
|
-
markChatUnread(guid: string): Promise<void>;
|
|
391
439
|
leaveChat(guid: string): Promise<void>;
|
|
392
440
|
addParticipant(chatGuid: string, address: string): Promise<ChatResponse>;
|
|
393
441
|
removeParticipant(chatGuid: string, address: string): Promise<ChatResponse>;
|
|
@@ -528,6 +576,15 @@ declare class MessageModule {
|
|
|
528
576
|
}): Promise<MessageResponse[]>;
|
|
529
577
|
}
|
|
530
578
|
|
|
579
|
+
declare class PollModule {
|
|
580
|
+
private readonly http;
|
|
581
|
+
constructor(http: AxiosInstance);
|
|
582
|
+
create(options: CreatePollOptions): Promise<PollMessageResponse>;
|
|
583
|
+
vote(options: VotePollOptions): Promise<PollMessageResponse>;
|
|
584
|
+
unvote(options: VotePollOptions): Promise<PollMessageResponse>;
|
|
585
|
+
addOption(options: AddPollOptionOptions): Promise<PollMessageResponse>;
|
|
586
|
+
}
|
|
587
|
+
|
|
531
588
|
declare class ScheduledMessageModule {
|
|
532
589
|
private readonly http;
|
|
533
590
|
constructor(http: AxiosInstance);
|
|
@@ -543,8 +600,6 @@ declare class ServerModule {
|
|
|
543
600
|
getServerInfo(): Promise<any>;
|
|
544
601
|
getMessageStats(): Promise<any>;
|
|
545
602
|
getServerLogs(count?: number): Promise<string[]>;
|
|
546
|
-
getAlerts(): Promise<any[]>;
|
|
547
|
-
markAlertAsRead(ids: string[]): Promise<any>;
|
|
548
603
|
getMediaStatistics(options?: {
|
|
549
604
|
only?: string[];
|
|
550
605
|
}): Promise<any>;
|
|
@@ -568,10 +623,12 @@ declare class AdvancedIMessageKit extends EventEmitter$1 implements TypedEventEm
|
|
|
568
623
|
readonly handles: HandleModule;
|
|
569
624
|
readonly facetime: FaceTimeModule;
|
|
570
625
|
readonly icloud: ICloudModule;
|
|
626
|
+
readonly polls: PollModule;
|
|
571
627
|
readonly scheduledMessages: ScheduledMessageModule;
|
|
572
628
|
readonly server: ServerModule;
|
|
573
629
|
private processedMessages;
|
|
574
630
|
private sendQueue;
|
|
631
|
+
private readyEmitted;
|
|
575
632
|
private constructor();
|
|
576
633
|
emit<K extends keyof PhotonEventMap>(event: K, ...args: PhotonEventMap[K] extends undefined ? [] : [PhotonEventMap[K]]): boolean;
|
|
577
634
|
on<K extends keyof PhotonEventMap>(event: K, listener: PhotonEventMap[K] extends undefined ? () => void : (data: PhotonEventMap[K]) => void): this;
|
|
@@ -636,4 +693,19 @@ declare const NEW_FINDMY_LOCATION = "new-findmy-location";
|
|
|
636
693
|
declare const setGlobalLogLevel: (level: LogLevel) => void;
|
|
637
694
|
declare const getLogger: (tag: string) => Logger;
|
|
638
695
|
|
|
639
|
-
|
|
696
|
+
declare function isPollMessage(message: MessageResponse): boolean;
|
|
697
|
+
declare function isPollVote(message: MessageResponse): boolean;
|
|
698
|
+
interface ParsedPoll {
|
|
699
|
+
title: string;
|
|
700
|
+
creatorHandle: string;
|
|
701
|
+
options: PollOption[];
|
|
702
|
+
}
|
|
703
|
+
interface ParsedPollVote {
|
|
704
|
+
votes: PollVote[];
|
|
705
|
+
}
|
|
706
|
+
declare function parsePollDefinition(message: MessageResponse): ParsedPoll | null;
|
|
707
|
+
declare function parsePollVotes(message: MessageResponse): ParsedPollVote | null;
|
|
708
|
+
declare function getPollSummary(message: MessageResponse): string;
|
|
709
|
+
declare function getPollOneLiner(message: MessageResponse): string;
|
|
710
|
+
|
|
711
|
+
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
|
@@ -173,15 +173,23 @@ var AttachmentModule = class {
|
|
|
173
173
|
const fileName = options.fileName || path__default.basename(options.filePath);
|
|
174
174
|
const form = new FormData();
|
|
175
175
|
form.append("attachment", await readFile(options.filePath), fileName);
|
|
176
|
-
|
|
176
|
+
form.append("name", fileName);
|
|
177
|
+
form.append("chatGuid", options.chatGuid);
|
|
178
|
+
form.append("isSticker", "true");
|
|
179
|
+
form.append("method", "private-api");
|
|
180
|
+
if (options.selectedMessageGuid) {
|
|
181
|
+
form.append("selectedMessageGuid", options.selectedMessageGuid);
|
|
182
|
+
form.append("partIndex", "0");
|
|
183
|
+
}
|
|
184
|
+
form.append("stickerX", String(options.stickerX ?? 0.5));
|
|
185
|
+
form.append("stickerY", String(options.stickerY ?? 0.5));
|
|
186
|
+
form.append("stickerScale", String(options.stickerScale ?? 0.75));
|
|
187
|
+
form.append("stickerRotation", String(options.stickerRotation ?? 0));
|
|
188
|
+
form.append("stickerWidth", String(options.stickerWidth ?? 300));
|
|
189
|
+
const { data } = await this.http.post("/api/v1/message/attachment", form, {
|
|
177
190
|
headers: form.getHeaders()
|
|
178
191
|
});
|
|
179
|
-
|
|
180
|
-
chatGuid: options.chatGuid,
|
|
181
|
-
selectedMessageGuid: options.selectedMessageGuid,
|
|
182
|
-
parts: [{ partIndex: 0, attachment: data.data.path, name: fileName }]
|
|
183
|
-
});
|
|
184
|
-
return response.data.data;
|
|
192
|
+
return data.data;
|
|
185
193
|
});
|
|
186
194
|
}
|
|
187
195
|
};
|
|
@@ -198,35 +206,32 @@ var ChatModule = class {
|
|
|
198
206
|
return response.data.data;
|
|
199
207
|
}
|
|
200
208
|
async getChat(guid, options) {
|
|
201
|
-
const response = await this.http.get(`/api/v1/chat/${guid}`, {
|
|
209
|
+
const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(guid)}`, {
|
|
202
210
|
params: options?.with ? { with: options.with.join(",") } : {}
|
|
203
211
|
});
|
|
204
212
|
return response.data.data;
|
|
205
213
|
}
|
|
206
214
|
async updateChat(guid, options) {
|
|
207
|
-
const response = await this.http.put(`/api/v1/chat/${guid}`, options);
|
|
215
|
+
const response = await this.http.put(`/api/v1/chat/${encodeURIComponent(guid)}`, options);
|
|
208
216
|
return response.data.data;
|
|
209
217
|
}
|
|
210
218
|
async deleteChat(guid) {
|
|
211
|
-
await this.http.delete(`/api/v1/chat/${guid}`);
|
|
219
|
+
await this.http.delete(`/api/v1/chat/${encodeURIComponent(guid)}`);
|
|
212
220
|
}
|
|
213
221
|
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`);
|
|
222
|
+
await this.http.post(`/api/v1/chat/${encodeURIComponent(guid)}/read`);
|
|
218
223
|
}
|
|
219
224
|
async leaveChat(guid) {
|
|
220
|
-
await this.http.post(`/api/v1/chat/${guid}/leave`);
|
|
225
|
+
await this.http.post(`/api/v1/chat/${encodeURIComponent(guid)}/leave`);
|
|
221
226
|
}
|
|
222
227
|
async addParticipant(chatGuid, address) {
|
|
223
|
-
const response = await this.http.post(`/api/v1/chat/${chatGuid}/participant`, {
|
|
228
|
+
const response = await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/participant`, {
|
|
224
229
|
address
|
|
225
230
|
});
|
|
226
231
|
return response.data.data;
|
|
227
232
|
}
|
|
228
233
|
async removeParticipant(chatGuid, address) {
|
|
229
|
-
const response = await this.http.delete(`/api/v1/chat/${chatGuid}/participant`, {
|
|
234
|
+
const response = await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/participant`, {
|
|
230
235
|
data: { address }
|
|
231
236
|
});
|
|
232
237
|
return response.data.data;
|
|
@@ -239,7 +244,7 @@ var ChatModule = class {
|
|
|
239
244
|
if (options?.before !== void 0) params.before = options.before;
|
|
240
245
|
if (options?.after !== void 0) params.after = options.after;
|
|
241
246
|
if (options?.with) params.with = options.with.join(",");
|
|
242
|
-
const response = await this.http.get(`/api/v1/chat/${chatGuid}/message`, {
|
|
247
|
+
const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/message`, {
|
|
243
248
|
params
|
|
244
249
|
});
|
|
245
250
|
return response.data.data;
|
|
@@ -249,15 +254,15 @@ var ChatModule = class {
|
|
|
249
254
|
const fileName = path__default.basename(filePath);
|
|
250
255
|
const form = new FormData();
|
|
251
256
|
form.append("icon", fileBuffer, fileName);
|
|
252
|
-
await this.http.post(`/api/v1/chat/${chatGuid}/icon`, form, {
|
|
257
|
+
await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`, form, {
|
|
253
258
|
headers: form.getHeaders()
|
|
254
259
|
});
|
|
255
260
|
}
|
|
256
261
|
async removeGroupIcon(chatGuid) {
|
|
257
|
-
await this.http.delete(`/api/v1/chat/${chatGuid}/icon`);
|
|
262
|
+
await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`);
|
|
258
263
|
}
|
|
259
264
|
async getGroupIcon(chatGuid) {
|
|
260
|
-
const response = await this.http.get(`/api/v1/chat/${chatGuid}/icon`, {
|
|
265
|
+
const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/icon`, {
|
|
261
266
|
responseType: "arraybuffer"
|
|
262
267
|
});
|
|
263
268
|
return Buffer.from(response.data);
|
|
@@ -269,10 +274,10 @@ var ChatModule = class {
|
|
|
269
274
|
return response.data.data;
|
|
270
275
|
}
|
|
271
276
|
async startTyping(chatGuid) {
|
|
272
|
-
await this.http.post(`/api/v1/chat/${chatGuid}/typing`);
|
|
277
|
+
await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`);
|
|
273
278
|
}
|
|
274
279
|
async stopTyping(chatGuid) {
|
|
275
|
-
await this.http.delete(`/api/v1/chat/${chatGuid}/typing`);
|
|
280
|
+
await this.http.delete(`/api/v1/chat/${encodeURIComponent(chatGuid)}/typing`);
|
|
276
281
|
}
|
|
277
282
|
};
|
|
278
283
|
|
|
@@ -292,10 +297,10 @@ var ContactModule = class {
|
|
|
292
297
|
return response.data.data;
|
|
293
298
|
}
|
|
294
299
|
async shareContactCard(chatGuid) {
|
|
295
|
-
await this.http.post(`/api/v1/chat/${chatGuid}/share/contact`);
|
|
300
|
+
await this.http.post(`/api/v1/chat/${encodeURIComponent(chatGuid)}/share/contact`);
|
|
296
301
|
}
|
|
297
302
|
async shouldShareContact(chatGuid) {
|
|
298
|
-
const response = await this.http.get(`/api/v1/chat/${chatGuid}/share/contact/status`);
|
|
303
|
+
const response = await this.http.get(`/api/v1/chat/${encodeURIComponent(chatGuid)}/share/contact/status`);
|
|
299
304
|
return response.data.data;
|
|
300
305
|
}
|
|
301
306
|
};
|
|
@@ -361,6 +366,40 @@ var ICloudModule = class {
|
|
|
361
366
|
await this.http.post("/api/v1/icloud/findmy/friends/refresh");
|
|
362
367
|
}
|
|
363
368
|
};
|
|
369
|
+
|
|
370
|
+
// lib/auto-create-chat.ts
|
|
371
|
+
function isChatNotExistError(error) {
|
|
372
|
+
const axiosError = error;
|
|
373
|
+
const errorMsg = axiosError?.response?.data?.error?.message || axiosError?.response?.data?.message || "";
|
|
374
|
+
const lowerMsg = errorMsg.toLowerCase();
|
|
375
|
+
return lowerMsg.includes("chat does not exist") || lowerMsg.includes("chat not found");
|
|
376
|
+
}
|
|
377
|
+
function extractAddress(chatGuid) {
|
|
378
|
+
const parts = chatGuid.split(";-;");
|
|
379
|
+
if (parts.length !== 2 || !parts[1]) {
|
|
380
|
+
return void 0;
|
|
381
|
+
}
|
|
382
|
+
return parts[1];
|
|
383
|
+
}
|
|
384
|
+
async function createChatWithMessage(options) {
|
|
385
|
+
const { http, address, message, tempGuid, subject, effectId } = options;
|
|
386
|
+
try {
|
|
387
|
+
const response = await http.post("/api/v1/chat/new", {
|
|
388
|
+
addresses: [address],
|
|
389
|
+
message,
|
|
390
|
+
tempGuid,
|
|
391
|
+
subject,
|
|
392
|
+
effectId
|
|
393
|
+
});
|
|
394
|
+
return response.data.data?.guid;
|
|
395
|
+
} catch (error) {
|
|
396
|
+
throw new Error(
|
|
397
|
+
`Failed to create chat with address "${address}": ${error instanceof Error ? error.message : String(error)}`
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// modules/message.ts
|
|
364
403
|
var MessageModule = class {
|
|
365
404
|
constructor(http, enqueueSend = (task) => task()) {
|
|
366
405
|
this.http = http;
|
|
@@ -368,12 +407,25 @@ var MessageModule = class {
|
|
|
368
407
|
}
|
|
369
408
|
async sendMessage(options) {
|
|
370
409
|
return this.enqueueSend(async () => {
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
410
|
+
const tempGuid = options.tempGuid || randomUUID();
|
|
411
|
+
const payload = { ...options, tempGuid };
|
|
412
|
+
try {
|
|
413
|
+
const response = await this.http.post("/api/v1/message/text", payload);
|
|
414
|
+
return response.data.data;
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (!isChatNotExistError(error)) throw error;
|
|
417
|
+
const address = extractAddress(options.chatGuid);
|
|
418
|
+
if (!address) throw error;
|
|
419
|
+
await createChatWithMessage({
|
|
420
|
+
http: this.http,
|
|
421
|
+
address,
|
|
422
|
+
message: options.message,
|
|
423
|
+
tempGuid,
|
|
424
|
+
subject: options.subject,
|
|
425
|
+
effectId: options.effectId
|
|
426
|
+
});
|
|
427
|
+
return { guid: tempGuid, text: options.message, dateCreated: Date.now() };
|
|
428
|
+
}
|
|
377
429
|
});
|
|
378
430
|
}
|
|
379
431
|
async getMessage(guid, options) {
|
|
@@ -462,6 +514,51 @@ var MessageModule = class {
|
|
|
462
514
|
}
|
|
463
515
|
};
|
|
464
516
|
|
|
517
|
+
// modules/poll.ts
|
|
518
|
+
var PollModule = class {
|
|
519
|
+
constructor(http) {
|
|
520
|
+
this.http = http;
|
|
521
|
+
}
|
|
522
|
+
async create(options) {
|
|
523
|
+
if (options.options.length < 2) {
|
|
524
|
+
throw new Error("Poll must have at least 2 options");
|
|
525
|
+
}
|
|
526
|
+
const { data } = await this.http.post("/api/v1/poll/create", {
|
|
527
|
+
chatGuid: options.chatGuid,
|
|
528
|
+
title: options.title ?? "",
|
|
529
|
+
options: options.options
|
|
530
|
+
});
|
|
531
|
+
return data.data;
|
|
532
|
+
}
|
|
533
|
+
async vote(options) {
|
|
534
|
+
const { data } = await this.http.post("/api/v1/poll/vote", {
|
|
535
|
+
chatGuid: options.chatGuid,
|
|
536
|
+
pollMessageGuid: options.pollMessageGuid,
|
|
537
|
+
optionIdentifier: options.optionIdentifier
|
|
538
|
+
});
|
|
539
|
+
return data.data;
|
|
540
|
+
}
|
|
541
|
+
async unvote(options) {
|
|
542
|
+
const { data } = await this.http.post("/api/v1/poll/unvote", {
|
|
543
|
+
chatGuid: options.chatGuid,
|
|
544
|
+
pollMessageGuid: options.pollMessageGuid,
|
|
545
|
+
optionIdentifier: options.optionIdentifier
|
|
546
|
+
});
|
|
547
|
+
return data.data;
|
|
548
|
+
}
|
|
549
|
+
async addOption(options) {
|
|
550
|
+
if (!options.optionText || options.optionText.trim().length === 0) {
|
|
551
|
+
throw new Error("Option text cannot be empty");
|
|
552
|
+
}
|
|
553
|
+
const { data } = await this.http.post("/api/v1/poll/option", {
|
|
554
|
+
chatGuid: options.chatGuid,
|
|
555
|
+
pollMessageGuid: options.pollMessageGuid,
|
|
556
|
+
optionText: options.optionText
|
|
557
|
+
});
|
|
558
|
+
return data.data;
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
|
|
465
562
|
// modules/scheduled.ts
|
|
466
563
|
var ScheduledMessageModule = class {
|
|
467
564
|
constructor(http) {
|
|
@@ -503,14 +600,6 @@ var ServerModule = class {
|
|
|
503
600
|
});
|
|
504
601
|
return response.data.data;
|
|
505
602
|
}
|
|
506
|
-
async getAlerts() {
|
|
507
|
-
const response = await this.http.get("/api/v1/server/alert");
|
|
508
|
-
return response.data.data;
|
|
509
|
-
}
|
|
510
|
-
async markAlertAsRead(ids) {
|
|
511
|
-
const response = await this.http.post("/api/v1/server/alert/read", { ids });
|
|
512
|
-
return response.data.data;
|
|
513
|
-
}
|
|
514
603
|
async getMediaStatistics(options) {
|
|
515
604
|
const params = {};
|
|
516
605
|
if (options?.only) params.only = options.only.join(",");
|
|
@@ -545,6 +634,7 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
|
|
|
545
634
|
__publicField(this, "handles");
|
|
546
635
|
__publicField(this, "facetime");
|
|
547
636
|
__publicField(this, "icloud");
|
|
637
|
+
__publicField(this, "polls");
|
|
548
638
|
__publicField(this, "scheduledMessages");
|
|
549
639
|
__publicField(this, "server");
|
|
550
640
|
// Message deduplication feature
|
|
@@ -558,6 +648,11 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
|
|
|
558
648
|
// Purpose: Ensure all outgoing messages (text, attachments, stickers, etc.) from
|
|
559
649
|
// a single user/SDK instance are sent in strict order, preventing race conditions.
|
|
560
650
|
__publicField(this, "sendQueue", Promise.resolve());
|
|
651
|
+
// Flag to track if 'ready' event has been emitted
|
|
652
|
+
//
|
|
653
|
+
// Purpose: Prevent duplicate 'ready' events when both legacy mode (no API key)
|
|
654
|
+
// and auth-ok events occur, which would cause user callbacks to fire twice.
|
|
655
|
+
__publicField(this, "readyEmitted", false);
|
|
561
656
|
this.config = {
|
|
562
657
|
serverUrl: "http://localhost:1234",
|
|
563
658
|
logLevel: "info",
|
|
@@ -600,6 +695,7 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
|
|
|
600
695
|
this.handles = new HandleModule(this.http);
|
|
601
696
|
this.facetime = new FaceTimeModule(this.http);
|
|
602
697
|
this.icloud = new ICloudModule(this.http);
|
|
698
|
+
this.polls = new PollModule(this.http);
|
|
603
699
|
this.scheduledMessages = new ScheduledMessageModule(this.http);
|
|
604
700
|
this.server = new ServerModule(this.http);
|
|
605
701
|
}
|
|
@@ -668,11 +764,15 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
|
|
|
668
764
|
}
|
|
669
765
|
this.socket.on("disconnect", () => {
|
|
670
766
|
this.logger.info("Disconnected from iMessage server");
|
|
767
|
+
this.readyEmitted = false;
|
|
671
768
|
this.emit("disconnect");
|
|
672
769
|
});
|
|
673
770
|
this.socket.on("auth-ok", () => {
|
|
674
771
|
this.logger.info("Authentication successful");
|
|
675
|
-
this.
|
|
772
|
+
if (!this.readyEmitted) {
|
|
773
|
+
this.readyEmitted = true;
|
|
774
|
+
this.emit("ready");
|
|
775
|
+
}
|
|
676
776
|
});
|
|
677
777
|
this.socket.on("auth-error", (error) => {
|
|
678
778
|
this.logger.error(`Authentication failed: ${error.message} ${error.reason ? `(${error.reason})` : ""}`);
|
|
@@ -684,6 +784,13 @@ var _AdvancedIMessageKit = class _AdvancedIMessageKit extends EventEmitter {
|
|
|
684
784
|
}
|
|
685
785
|
this.socket.once("connect", () => {
|
|
686
786
|
this.logger.info("Connected to iMessage server, waiting for authentication...");
|
|
787
|
+
if (!this.config.apiKey) {
|
|
788
|
+
this.logger.info("No API key provided, skipping authentication (legacy server mode)");
|
|
789
|
+
if (!this.readyEmitted) {
|
|
790
|
+
this.readyEmitted = true;
|
|
791
|
+
this.emit("ready");
|
|
792
|
+
}
|
|
793
|
+
}
|
|
687
794
|
});
|
|
688
795
|
if (!this.socket.connected) {
|
|
689
796
|
this.socket.connect();
|
|
@@ -766,6 +873,144 @@ var IMESSAGE_ALIASES_REMOVED = "imessage-aliases-removed";
|
|
|
766
873
|
var FT_CALL_STATUS_CHANGED = "ft-call-status-changed";
|
|
767
874
|
var NEW_FINDMY_LOCATION = "new-findmy-location";
|
|
768
875
|
|
|
769
|
-
|
|
876
|
+
// lib/poll-utils.ts
|
|
877
|
+
var POLL_BALLOON_BUNDLE_ID = "com.apple.messages.MSMessageExtensionBalloonPlugin:0000000000:com.apple.messages.Polls";
|
|
878
|
+
var pollCache = /* @__PURE__ */ new Map();
|
|
879
|
+
function cachePoll(messageGuid, poll) {
|
|
880
|
+
pollCache.set(messageGuid, poll);
|
|
881
|
+
}
|
|
882
|
+
function getOptionTextById(optionId) {
|
|
883
|
+
for (const poll of pollCache.values()) {
|
|
884
|
+
const option = poll.options.find((o) => o.optionIdentifier === optionId);
|
|
885
|
+
if (option) return option.text;
|
|
886
|
+
}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
function isPollMessage(message) {
|
|
890
|
+
return message.balloonBundleId === POLL_BALLOON_BUNDLE_ID;
|
|
891
|
+
}
|
|
892
|
+
function isPollVote(message) {
|
|
893
|
+
return isPollMessage(message) && message.associatedMessageType === "4000";
|
|
894
|
+
}
|
|
895
|
+
function extractDataUrl(payloadData) {
|
|
896
|
+
if (!payloadData || payloadData.length === 0) return null;
|
|
897
|
+
const payload = payloadData[0];
|
|
898
|
+
if (!payload) return null;
|
|
899
|
+
if (payload.URL && typeof payload.URL === "string") {
|
|
900
|
+
return payload.URL;
|
|
901
|
+
}
|
|
902
|
+
const objects = payload.$objects;
|
|
903
|
+
if (Array.isArray(objects)) {
|
|
904
|
+
for (const obj of objects) {
|
|
905
|
+
if (typeof obj === "object" && obj !== null) {
|
|
906
|
+
if (obj["NS.relative"] && typeof obj["NS.relative"] === "object") {
|
|
907
|
+
const relativeObj = objects[obj["NS.relative"].UID];
|
|
908
|
+
if (typeof relativeObj === "string" && relativeObj.startsWith("data:,")) {
|
|
909
|
+
return relativeObj;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
if (typeof obj === "string" && obj.startsWith("data:,")) {
|
|
913
|
+
return obj;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return null;
|
|
919
|
+
}
|
|
920
|
+
function parseDataUrl(dataUrl) {
|
|
921
|
+
try {
|
|
922
|
+
const prefix = "data:,";
|
|
923
|
+
if (!dataUrl.startsWith(prefix)) return null;
|
|
924
|
+
let data = dataUrl.slice(prefix.length);
|
|
925
|
+
const queryIndex = data.indexOf("?");
|
|
926
|
+
if (queryIndex !== -1) {
|
|
927
|
+
data = data.slice(0, queryIndex);
|
|
928
|
+
}
|
|
929
|
+
data = decodeURIComponent(data);
|
|
930
|
+
try {
|
|
931
|
+
return JSON.parse(data);
|
|
932
|
+
} catch {
|
|
933
|
+
const decoded = Buffer.from(data, "base64").toString("utf-8");
|
|
934
|
+
return JSON.parse(decoded);
|
|
935
|
+
}
|
|
936
|
+
} catch {
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
function parsePollDefinition(message) {
|
|
941
|
+
if (!isPollMessage(message)) return null;
|
|
942
|
+
if (isPollVote(message)) return null;
|
|
943
|
+
const dataUrl = extractDataUrl(message.payloadData);
|
|
944
|
+
if (!dataUrl) return null;
|
|
945
|
+
const data = parseDataUrl(dataUrl);
|
|
946
|
+
if (!data || !data.item) return null;
|
|
947
|
+
const parsed = {
|
|
948
|
+
title: data.item.title || "",
|
|
949
|
+
creatorHandle: data.item.creatorHandle || "",
|
|
950
|
+
options: data.item.orderedPollOptions || []
|
|
951
|
+
};
|
|
952
|
+
if (message.guid) {
|
|
953
|
+
cachePoll(message.guid, parsed);
|
|
954
|
+
}
|
|
955
|
+
return parsed;
|
|
956
|
+
}
|
|
957
|
+
function parsePollVotes(message) {
|
|
958
|
+
if (!isPollMessage(message)) return null;
|
|
959
|
+
if (!isPollVote(message)) return null;
|
|
960
|
+
const dataUrl = extractDataUrl(message.payloadData);
|
|
961
|
+
if (!dataUrl) return null;
|
|
962
|
+
const data = parseDataUrl(dataUrl);
|
|
963
|
+
if (!data || !data.item) return null;
|
|
964
|
+
return {
|
|
965
|
+
votes: data.item.votes || []
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function getPollSummary(message) {
|
|
969
|
+
if (!isPollMessage(message)) {
|
|
970
|
+
return message.text || "(no text)";
|
|
971
|
+
}
|
|
972
|
+
if (isPollVote(message)) {
|
|
973
|
+
const voteData = parsePollVotes(message);
|
|
974
|
+
if (voteData && voteData.votes.length > 0) {
|
|
975
|
+
const votes = voteData.votes.map((v) => {
|
|
976
|
+
const optionText = getOptionTextById(v.voteOptionIdentifier);
|
|
977
|
+
const optionDisplay = optionText ? `"${optionText}"` : `option ${v.voteOptionIdentifier}`;
|
|
978
|
+
return `${v.participantHandle || "Someone"} voted ${optionDisplay}`;
|
|
979
|
+
}).join(", ");
|
|
980
|
+
return `[Poll Vote] ${votes}`;
|
|
981
|
+
}
|
|
982
|
+
return "[Poll Vote]";
|
|
983
|
+
}
|
|
984
|
+
const pollData = parsePollDefinition(message);
|
|
985
|
+
if (pollData) {
|
|
986
|
+
const title = pollData.title ? `"${pollData.title}"` : "(untitled poll)";
|
|
987
|
+
const optionsList = pollData.options.map((opt, i) => ` ${i + 1}. ${opt.text}`).join("\n");
|
|
988
|
+
return `[Poll] ${title}
|
|
989
|
+
${optionsList}`;
|
|
990
|
+
}
|
|
991
|
+
return "[Poll] (unable to parse)";
|
|
992
|
+
}
|
|
993
|
+
function getPollOneLiner(message) {
|
|
994
|
+
if (!isPollMessage(message)) {
|
|
995
|
+
return message.text || "(no text)";
|
|
996
|
+
}
|
|
997
|
+
if (isPollVote(message)) {
|
|
998
|
+
const voteData = parsePollVotes(message);
|
|
999
|
+
if (voteData && voteData.votes.length > 0) {
|
|
1000
|
+
return `[Poll Vote] ${voteData.votes.length} vote(s)`;
|
|
1001
|
+
}
|
|
1002
|
+
return "[Poll Vote]";
|
|
1003
|
+
}
|
|
1004
|
+
const pollData = parsePollDefinition(message);
|
|
1005
|
+
if (pollData) {
|
|
1006
|
+
const title = pollData.title || "Poll";
|
|
1007
|
+
const optionsPreview = pollData.options.slice(0, 2).map((o) => o.text).join(", ");
|
|
1008
|
+
const moreOptions = pollData.options.length > 2 ? `, +${pollData.options.length - 2} more` : "";
|
|
1009
|
+
return `[${title}] ${optionsPreview}${moreOptions}`;
|
|
1010
|
+
}
|
|
1011
|
+
return "[Poll]";
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
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 };
|
|
770
1015
|
//# sourceMappingURL=index.js.map
|
|
771
1016
|
//# sourceMappingURL=index.js.map
|