@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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Advanced iMessage Kit
6
6
 
7
- > Powerful TypeScript iMessage SDK with real-time message processing
7
+ > A powerful TypeScript SDK for iMessage with real-time messaging support
8
8
 
9
9
  </div>
10
10
 
@@ -12,18 +12,38 @@
12
12
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
13
13
  [![Discord](https://img.shields.io/badge/Discord-Join-5865F2.svg?logo=discord&logoColor=white)](https://discord.gg/RSJUUHTV)
14
14
 
15
- Advanced iMessage Kit is a comprehensive iMessage SDK for **reading**, **sending**, and **automating** iMessage conversations on macOS. Designed for building **AI agents**, **automation tools**, and **chat applications**.
15
+ Advanced iMessage Kit is a full-featured iMessage SDK for **reading**, **sending**, and **automating** iMessage conversations on macOS. Perfect for building **AI agents**, **automation tools**, and **chat applications**.
16
+
17
+ ---
16
18
 
17
19
  ## Features
18
20
 
19
- - **Type Safe** — Complete TypeScript support with full type definitions
20
- - **Real-time Communication** WebSocket-based event system for instant message updates
21
- - **Complete API** — Send text, attachments, reactions, edit messages, and more
22
- - **Group Management** Create groups, manage members, and set group icons
23
- - **Rich Attachments** — Send images, files, voice messages, stickers, and contact cards
24
- - **Advanced Querying** Powerful message filtering and search capabilities
25
- - **Analytics** Track message counts, delivery status, and chat statistics
26
- - **Event-driven** — Listen for new messages, typing indicators, and status changes
21
+ | Feature | Method | Example |
22
+ | ---------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------- |
23
+ | [Send Messages](#send-messages) | `messages.sendMessage()` | [message-send.ts](./examples/message-send.ts) |
24
+ | [Reply to Messages](#send-messages) | `messages.sendMessage()` | [message-reply.ts](./examples/message-reply.ts) |
25
+ | [Message Effects](#send-messages) | `messages.sendMessage()` | [message-effects.ts](./examples/message-effects.ts) |
26
+ | [Unsend Messages](#unsend-messages) | `messages.unsendMessage()` | [message-unsend.ts](./examples/message-unsend.ts) |
27
+ | [Send Tapbacks](#send-tapbacks) | `messages.sendReaction()` | [message-reaction.ts](./examples/message-reaction.ts) |
28
+ | [Query Messages](#query-messages) | `messages.getMessages()` | [message-search.ts](./examples/message-search.ts) |
29
+ | [Send Attachments](#send-attachments) | `attachments.sendAttachment()` | [message-attachment.ts](./examples/message-attachment.ts) |
30
+ | [Send Audio Messages](#send-audio-messages) | `attachments.sendAttachment()` | [message-audio.ts](./examples/message-audio.ts) |
31
+ | [Send Stickers](#send-stickers) | `attachments.sendSticker()` | [message-reply-sticker.ts](./examples/message-reply-sticker.ts) |
32
+ | [Download Attachments](#download-attachments) | `attachments.downloadAttachment()` | [attachment-download.ts](./examples/attachment-download.ts) |
33
+ | [Get Chats](#get-chats) | `chats.getChats()` | [chat-fetch.ts](./examples/chat-fetch.ts) |
34
+ | [Manage Group Chats](#manage-group-chats) | `chats.addParticipant()` | [chat-group.ts](./examples/chat-group.ts) |
35
+ | [Typing Indicators](#typing-indicators) | `chats.startTyping()` | [message-typing.ts](./examples/message-typing.ts) |
36
+ | [Get Contacts](#get-contacts) | `contacts.getContacts()` | [contact-list.ts](./examples/contact-list.ts) |
37
+ | [Check iMessage Availability](#check-service-availability) | `handles.getHandleAvailability()` | [service-check.ts](./examples/service-check.ts) |
38
+ | [Server Info](#get-server-info) | `server.getServerInfo()` | [server-info.ts](./examples/server-info.ts) |
39
+ | [Message Statistics](#message-statistics) | `server.getMessageStats()` | [message-stats.ts](./examples/message-stats.ts) |
40
+ | [Create Polls](#create-polls) | `polls.create()` | [poll-create.ts](./examples/poll-create.ts) |
41
+ | [Add Poll Options](#add-poll-options) | `polls.addOption()` | [poll-add-option.ts](./examples/poll-add-option.ts) |
42
+ | [Find My Friends](#find-my-friends) _(WIP)_ | `icloud.getFindMyFriends()` | [findmy-friends.ts](./examples/findmy-friends.ts) |
43
+ | [Real-time Events](#real-time-events) | `sdk.on()` | [listen-simple.ts](./examples/listen-simple.ts) |
44
+ | [Auto Reply](#real-time-events) | `sdk.on()` | [auto-reply-hey.ts](./examples/auto-reply-hey.ts) |
45
+
46
+ ---
27
47
 
28
48
  ## Quick Start
29
49
 
@@ -41,158 +61,266 @@ bun add @photon-ai/advanced-imessage-kit
41
61
  import { SDK } from "@photon-ai/advanced-imessage-kit";
42
62
 
43
63
  const sdk = SDK({
44
- serverUrl: "{your-subdomain}.imsgd.photon.codes", // Your subdomain is the unique link address assigned to you
64
+ serverUrl: "http://localhost:1234",
45
65
  });
46
66
 
47
- // Connect to the server
48
67
  await sdk.connect();
49
68
 
50
- // Listen for new messages
51
69
  sdk.on("new-message", (message) => {
52
70
  console.log("New message:", message.text);
53
71
  });
54
72
 
55
- // Send a message
56
73
  await sdk.messages.sendMessage({
57
- chatGuid: "any;-;+1234567890",
74
+ chatGuid: "iMessage;-;+1234567890",
58
75
  message: "Hello World!",
59
76
  });
60
77
 
61
- // Disconnect when done
62
78
  await sdk.close();
63
79
  ```
64
80
 
65
- ## Core API
66
-
67
- ### Initialization & Connection
81
+ ### Configuration
68
82
 
69
83
  ```typescript
70
- import { SDK } from "@photon-ai/advanced-imessage-kit";
84
+ interface ClientConfig {
85
+ serverUrl?: string; // Server URL, defaults to "http://localhost:1234"
86
+ apiKey?: string; // API key (if server requires authentication)
87
+ logLevel?: "debug" | "info" | "warn" | "error"; // Log level, defaults to "info"
88
+ }
89
+ ```
71
90
 
72
- const sdk = SDK({
73
- serverUrl: "{your-subdomain}.imsgd.photon.codes", // Your subdomain is the unique link address assigned to you
74
- logLevel: "info", // Log level: 'debug' | 'info' | 'warn' | 'error'
75
- });
91
+ ---
76
92
 
77
- // Connect to server
78
- await sdk.connect();
93
+ ## Core Concepts
79
94
 
80
- // Check connection status
81
- sdk.on("ready", () => {
82
- console.log("SDK is ready!");
83
- });
95
+ ### chatGuid Format
96
+
97
+ `chatGuid` is the unique identifier for a conversation. The format is `service;-;address`:
98
+
99
+ - **iMessage DM**: `iMessage;-;+1234567890` or `iMessage;-;email@example.com`
100
+ - **SMS DM**: `SMS;-;+1234567890`
101
+ - **Group chat**: `iMessage;+;chat123456789`
102
+ - **Auto-detect**: `any;-;+1234567890` (SDK automatically detects the service type)
103
+
104
+ ### How to Get IDs
84
105
 
85
- // Graceful disconnect
86
- await sdk.close();
87
106
  ```
107
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
108
+ │ Phone / Email │────▶│ Build chatGuid │────▶│ Send Message │
109
+ │ +1234567890 │ │ any;-;+123... │ │ sendMessage() │
110
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
88
111
 
89
- ### Connection Management
112
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
113
+ │ getChats() │────▶│ Get chat.guid │────▶│ Use for other │
114
+ │ List chats │ │ │ │ operations │
115
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
90
116
 
91
- ```typescript
92
- // Message deduplication (prevents duplicate processing)
93
- sdk.clearProcessedMessages(1000); // Clear old processed message records
94
- const count = sdk.getProcessedMessageCount(); // Get processed message count
117
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
118
+ │ sendMessage() │────▶│ Get message.guid│────▶│ edit/unsend │
119
+ │ Send message │ │ │ │ sendReaction │
120
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
95
121
  ```
96
122
 
97
- ## Message Operations
123
+ ---
124
+
125
+ ## Messages
98
126
 
99
- ### Sending Messages
127
+ > Examples: [message-send.ts](./examples/message-send.ts) | [message-unsend.ts](./examples/message-unsend.ts) | [message-reaction.ts](./examples/message-reaction.ts) | [message-search.ts](./examples/message-search.ts)
128
+
129
+ ### Send Messages
100
130
 
101
131
  ```typescript
102
- // Send text message
132
+ // Send a text message
103
133
  const message = await sdk.messages.sendMessage({
104
- chatGuid: "any;-;+1234567890",
105
- message: "Hello World!",
134
+ chatGuid: "iMessage;-;+1234567890",
135
+ message: "Hello!",
106
136
  });
107
137
 
108
- // Send message with options
138
+ // With subject and effect
109
139
  await sdk.messages.sendMessage({
110
- chatGuid: "any;-;+1234567890",
111
- message: "Important message",
112
- subject: "Subject line",
140
+ chatGuid: "iMessage;-;+1234567890",
141
+ message: "Happy Birthday!",
142
+ subject: "Wishes",
113
143
  effectId: "com.apple.messages.effect.CKConfettiEffect",
114
144
  });
115
145
 
116
- // Reply to message
146
+ // Reply to a message
117
147
  await sdk.messages.sendMessage({
118
- chatGuid: "any;-;+1234567890",
148
+ chatGuid: "iMessage;-;+1234567890",
119
149
  message: "This is a reply",
120
150
  selectedMessageGuid: "original-message-guid",
121
151
  });
122
152
  ```
123
153
 
124
- ### Message Querying
154
+ **Message Effects**:
155
+
156
+ | Effect | effectId |
157
+ | ------------- | ------------------------------------------------- |
158
+ | Confetti | `com.apple.messages.effect.CKConfettiEffect` |
159
+ | Fireworks | `com.apple.messages.effect.CKFireworksEffect` |
160
+ | Balloons | `com.apple.messages.effect.CKBalloonEffect` |
161
+ | Hearts | `com.apple.messages.effect.CKHeartEffect` |
162
+ | Lasers | `com.apple.messages.effect.CKHappyBirthdayEffect` |
163
+ | Shooting Star | `com.apple.messages.effect.CKShootingStarEffect` |
164
+ | Sparkles | `com.apple.messages.effect.CKSparklesEffect` |
165
+ | Echo | `com.apple.messages.effect.CKEchoEffect` |
166
+ | Spotlight | `com.apple.messages.effect.CKSpotlightEffect` |
167
+ | Gentle | `com.apple.MobileSMS.expressivesend.gentle` |
168
+ | Loud | `com.apple.MobileSMS.expressivesend.loud` |
169
+ | Slam | `com.apple.MobileSMS.expressivesend.impact` |
170
+ | Invisible Ink | `com.apple.MobileSMS.expressivesend.invisibleink` |
171
+
172
+ > Example: [message-effects.ts](./examples/message-effects.ts)
173
+
174
+ ### Query Messages
125
175
 
126
176
  ```typescript
127
- // Get messages with filters
177
+ // Get a single message
178
+ const message = await sdk.messages.getMessage("message-guid");
179
+
180
+ // Query messages
128
181
  const messages = await sdk.messages.getMessages({
129
- chatGuid: "any;-;+1234567890",
182
+ chatGuid: "iMessage;-;+1234567890",
130
183
  limit: 50,
131
184
  offset: 0,
185
+ sort: "DESC", // DESC = newest first, ASC = oldest first
186
+ before: Date.now(),
187
+ after: Date.now() - 86400000, // Last 24 hours
132
188
  });
133
189
 
134
- // Get message counts
135
- const totalCount = await sdk.messages.getMessageCount({
136
- chatGuid: "any;-;+1234567890",
137
- after: 1640995200000, // Timestamp
138
- before: 1641081600000, // Timestamp
190
+ // Search messages
191
+ const results = await sdk.messages.searchMessages({
192
+ query: "keyword",
193
+ chatGuid: "iMessage;-;+1234567890", // Optional
194
+ limit: 20,
139
195
  });
140
196
 
141
- const sentCount = await sdk.messages.getSentMessageCount();
197
+ // Get counts
198
+ const total = await sdk.messages.getMessageCount();
199
+ const sent = await sdk.messages.getSentMessageCount();
200
+ const updated = await sdk.messages.getUpdatedMessageCount();
142
201
  ```
143
202
 
144
- ### Message Actions
203
+ ### Unsend Messages
145
204
 
146
205
  ```typescript
147
- // Edit message
148
- await sdk.messages.editMessage({
149
- messageGuid: "message-guid",
150
- editedMessage: "Updated text",
151
- backwardsCompatibilityMessage: "Updated text",
206
+ await sdk.messages.unsendMessage({
207
+ messageGuid: "message-guid-to-unsend",
208
+ partIndex: 0, // Optional
152
209
  });
210
+ ```
211
+
212
+ > Example: [message-unsend.ts](./examples/message-unsend.ts)
213
+
214
+ ### Send Tapbacks
153
215
 
154
- // Add reaction
216
+ ```typescript
155
217
  await sdk.messages.sendReaction({
156
- chatGuid: "any;-;+1234567890",
157
- messageGuid: "message-guid",
158
- reaction: "love", // Options: love, like, dislike, laugh, emphasize, question, -love, -like, etc.
159
- partIndex: 0, // Optional: defaults to 0
218
+ chatGuid: "iMessage;-;+1234567890",
219
+ messageGuid: "target-message-guid",
220
+ reaction: "love", // love, like, dislike, laugh, emphasize, question
221
+ partIndex: 0, // Optional
160
222
  });
161
223
 
162
- // Unsend message
163
- await sdk.messages.unsendMessage({
164
- messageGuid: "message-guid",
224
+ // Remove a Tapback (prefix with -)
225
+ await sdk.messages.sendReaction({
226
+ chatGuid: "iMessage;-;+1234567890",
227
+ messageGuid: "target-message-guid",
228
+ reaction: "-love", // -love, -like, -dislike, -laugh, -emphasize, -question
165
229
  });
166
230
  ```
167
231
 
168
- ## Chat Management
232
+ > Example: [message-reaction.ts](./examples/message-reaction.ts)
233
+
234
+ ### Other Message Operations
235
+
236
+ ```typescript
237
+ // Trigger message notification
238
+ await sdk.messages.notifyMessage("message-guid");
239
+
240
+ // Get embedded media
241
+ const media = await sdk.messages.getEmbeddedMedia("message-guid");
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Chats
247
+
248
+ > Examples: [chat-fetch.ts](./examples/chat-fetch.ts) | [chat-group.ts](./examples/chat-group.ts) | [message-typing.ts](./examples/message-typing.ts)
169
249
 
170
- ### Chat Operations
250
+ ### Get Chats
171
251
 
172
252
  ```typescript
173
- // Get all chats
174
- const chats = await sdk.chats.getChats();
253
+ const chats = await sdk.chats.getChats({
254
+ withLastMessage: true, // Include last message
255
+ withArchived: false, // Include archived chats
256
+ offset: 0,
257
+ limit: 50,
258
+ });
175
259
 
176
- // Get specific chat
260
+ // Get chat count
261
+ const count = await sdk.chats.getChatCount();
262
+ ```
263
+
264
+ ### Get Single Chat
265
+
266
+ ```typescript
177
267
  const chat = await sdk.chats.getChat("chat-guid", {
178
268
  with: ["participants", "lastMessage"],
179
269
  });
270
+ ```
271
+
272
+ ### Create Chat
180
273
 
181
- // Create new chat
274
+ ```typescript
182
275
  const newChat = await sdk.chats.createChat({
183
276
  addresses: ["+1234567890", "+0987654321"],
184
- message: "Hello everyone!",
185
- service: "iMessage", // 'iMessage' or 'SMS'
186
- method: "private-api", // 'apple-script' or 'private-api'
277
+ message: "Hello everyone!", // Optional initial message
278
+ service: "iMessage", // "iMessage" or "SMS"
279
+ method: "private-api", // "apple-script" or "private-api"
280
+ });
281
+ ```
282
+
283
+ ### Chat Status
284
+
285
+ ```typescript
286
+ // Mark as read/unread
287
+ await sdk.chats.markChatRead("chat-guid");
288
+ await sdk.chats.markChatUnread("chat-guid");
289
+
290
+ // Delete chat
291
+ await sdk.chats.deleteChat("chat-guid");
292
+ ```
293
+
294
+ ### Typing Indicators
295
+
296
+ ```typescript
297
+ // Show "typing..."
298
+ await sdk.chats.startTyping("chat-guid");
299
+
300
+ // Stop showing
301
+ await sdk.chats.stopTyping("chat-guid");
302
+ ```
303
+
304
+ > Example: [message-typing.ts](./examples/message-typing.ts)
305
+
306
+ ### Get Chat Messages
307
+
308
+ ```typescript
309
+ const messages = await sdk.chats.getChatMessages("chat-guid", {
310
+ limit: 100,
311
+ offset: 0,
312
+ sort: "DESC",
313
+ before: Date.now(),
314
+ after: Date.now() - 86400000,
187
315
  });
188
316
  ```
189
317
 
190
- ### Group Management
318
+ ### Manage Group Chats
191
319
 
192
320
  ```typescript
193
- // Update group name
321
+ // Rename group
194
322
  await sdk.chats.updateChat("chat-guid", {
195
- displayName: "My Group Chat",
323
+ displayName: "New Group Name",
196
324
  });
197
325
 
198
326
  // Add participant
@@ -205,7 +333,7 @@ await sdk.chats.removeParticipant("chat-guid", "+1234567890");
205
333
  await sdk.chats.leaveChat("chat-guid");
206
334
  ```
207
335
 
208
- ### Group Icons
336
+ ### Group Icon
209
337
 
210
338
  ```typescript
211
339
  // Set group icon
@@ -218,699 +346,553 @@ const iconBuffer = await sdk.chats.getGroupIcon("chat-guid");
218
346
  await sdk.chats.removeGroupIcon("chat-guid");
219
347
  ```
220
348
 
221
- ### Chat Status
222
-
223
- ```typescript
224
- // Mark as read/unread
225
- await sdk.chats.markChatRead("chat-guid");
226
- await sdk.chats.markChatUnread("chat-guid");
349
+ > Example: [chat-group.ts](./examples/chat-group.ts)
227
350
 
228
- // Typing indicators
229
- await sdk.chats.startTyping("chat-guid");
230
- await sdk.chats.stopTyping("chat-guid");
351
+ ---
231
352
 
232
- // Get chat messages
233
- const messages = await sdk.chats.getChatMessages("chat-guid", {
234
- limit: 100,
235
- offset: 0,
236
- sort: "DESC",
237
- });
238
- ```
353
+ ## Attachments
239
354
 
240
- ## Attachments & Media
355
+ > Examples: [message-attachment.ts](./examples/message-attachment.ts) | [message-audio.ts](./examples/message-audio.ts) | [message-reply-sticker.ts](./examples/message-reply-sticker.ts) | [attachment-download.ts](./examples/attachment-download.ts)
241
356
 
242
- ### Sending Attachments
357
+ ### Send Attachments
243
358
 
244
359
  ```typescript
245
- // Send file attachment
246
360
  const message = await sdk.attachments.sendAttachment({
247
- chatGuid: "any;-;+1234567890",
361
+ chatGuid: "iMessage;-;+1234567890",
248
362
  filePath: "/path/to/file.jpg",
249
363
  fileName: "custom-name.jpg", // Optional
250
364
  });
251
-
252
- // Send sticker
253
- await sdk.attachments.sendSticker({
254
- chatGuid: "any;-;+1234567890",
255
- filePath: "/path/to/sticker.png",
256
- selectedMessageGuid: "message-to-reply-to", // Optional
257
- });
258
365
  ```
259
366
 
260
- ### Voice Messages
261
-
262
- Voice messages differ from regular audio attachments. Ensure the audio file path exists and use common formats like `.m4a` or `.mp3`. In the example script, you can also supply the path via the `AUDIO_FILE_PATH` environment variable.
367
+ ### Send Audio Messages
263
368
 
264
369
  ```typescript
265
- // Send voice message
266
370
  const message = await sdk.attachments.sendAttachment({
267
- chatGuid: "any;-;+1234567890",
268
- filePath: "/path/to/audio.mp3",
371
+ chatGuid: "iMessage;-;+1234567890",
372
+ filePath: "/path/to/audio.m4a",
269
373
  isAudioMessage: true,
270
374
  });
271
-
272
- // Detect and handle incoming audio messages
273
- sdk.on("new-message", async (msg) => {
274
- if (msg.isAudioMessage) {
275
- const att = msg.attachments?.[0];
276
- if (att) {
277
- // Download original audio attachment
278
- const audioBuffer = await sdk.attachments.downloadAttachment(att.guid, {
279
- original: true,
280
- });
281
- // Save or process audioBuffer
282
- }
283
- }
284
- });
285
375
  ```
286
376
 
287
- ### Attachment Info
377
+ > Example: [message-audio.ts](./examples/message-audio.ts)
288
378
 
289
- ```typescript
290
- // Get attachment details
291
- const attachment = await sdk.attachments.getAttachment("attachment-guid");
379
+ ### Send Stickers
292
380
 
293
- // Get attachment count
294
- const count = await sdk.attachments.getAttachmentCount();
381
+ ```typescript
382
+ await sdk.attachments.sendSticker({
383
+ chatGuid: "iMessage;-;+1234567890",
384
+ filePath: "/path/to/sticker.png",
385
+ selectedMessageGuid: "message-to-stick-on", // Optional
386
+ });
295
387
  ```
296
388
 
297
- ## Contacts & Handles
389
+ > Example: [message-reply-sticker.ts](./examples/message-reply-sticker.ts)
298
390
 
299
- ### Contact Management
391
+ ### Get Attachment Info
300
392
 
301
393
  ```typescript
302
- // Get all contacts
303
- const contacts = await sdk.contacts.getContacts();
304
-
305
- // Get contact card
306
- const contactCard = await sdk.contacts.getContactCard("+1234567890");
307
-
308
- // Share contact card
309
- await sdk.contacts.shareContactCard("chat-guid");
394
+ // Get attachment details
395
+ const attachment = await sdk.attachments.getAttachment("attachment-guid");
310
396
 
311
- // Check if should share contact
312
- const shouldShare = await sdk.contacts.shouldShareContact("chat-guid");
397
+ // Get total count
398
+ const count = await sdk.attachments.getAttachmentCount();
313
399
  ```
314
400
 
315
- ### Handle Operations
401
+ ### Download Attachments
316
402
 
317
403
  ```typescript
318
- // Query handles
319
- const result = await sdk.handles.queryHandles({
320
- address: "+1234567890",
321
- with: ["chats"],
322
- limit: 50,
404
+ // Download attachment
405
+ const buffer = await sdk.attachments.downloadAttachment("attachment-guid", {
406
+ original: true, // Download original file
407
+ force: false, // Force re-download
408
+ width: 800, // Image width (for thumbnails)
409
+ height: 600, // Image height
410
+ quality: 80, // Image quality
323
411
  });
324
412
 
325
- // Get handle availability
326
- const isAvailable = await sdk.handles.getHandleAvailability(
327
- "handle-guid",
328
- "imessage"
413
+ // Download Live Photo video
414
+ const liveBuffer = await sdk.attachments.downloadAttachmentLive(
415
+ "attachment-guid"
329
416
  );
330
417
 
331
- // Get focus status
332
- const focusStatus = await sdk.handles.getHandleFocusStatus("handle-guid");
418
+ // Get blurhash (for placeholders)
419
+ const blurhash = await sdk.attachments.getAttachmentBlurhash("attachment-guid");
333
420
  ```
334
421
 
335
- ## Real-time Events
422
+ > Example: [attachment-download.ts](./examples/attachment-download.ts)
336
423
 
337
- The SDK emits various events for real-time updates. All events can be listened to using the `on()` method.
424
+ ---
338
425
 
339
- ### Core Events
426
+ ## Contacts
340
427
 
341
- #### `ready`
428
+ > Example: [contact-list.ts](./examples/contact-list.ts)
342
429
 
343
- Emitted when the SDK is fully connected and ready to use.
430
+ ### Get Contacts
344
431
 
345
432
  ```typescript
346
- sdk.on("ready", () => {
347
- console.log("SDK connected and ready");
348
- });
433
+ const contacts = await sdk.contacts.getContacts();
349
434
  ```
350
435
 
351
- #### `connect`
352
-
353
- Emitted when Socket.IO connection is established.
436
+ ### Get Contact Card
354
437
 
355
438
  ```typescript
356
- sdk.on("connect", () => {
357
- console.log("Socket.IO connected");
358
- });
439
+ // Get by phone or email
440
+ const card = await sdk.contacts.getContactCard("+1234567890");
359
441
  ```
360
442
 
361
- #### `disconnect`
443
+ ---
362
444
 
363
- Emitted when Socket.IO connection is lost.
445
+ ## Handles
364
446
 
365
- ```typescript
366
- sdk.on("disconnect", () => {
367
- console.log("Socket.IO disconnected");
368
- });
369
- ```
447
+ > Examples: [service-check.ts](./examples/service-check.ts) | [handle-query.ts](./examples/handle-query.ts)
370
448
 
371
- #### `error`
449
+ A Handle represents a messaging address (phone number or email).
372
450
 
373
- Emitted when an error occurs.
451
+ ### Query Handles
374
452
 
375
453
  ```typescript
376
- sdk.on("error", (error) => {
377
- console.error("SDK error:", error);
454
+ // Query handles
455
+ const result = await sdk.handles.queryHandles({
456
+ address: "+1234567890", // Optional, filter by address
457
+ with: ["chats"], // Optional, include related chats
458
+ offset: 0,
459
+ limit: 50,
378
460
  });
379
- ```
380
461
 
381
- ### Message Events
382
-
383
- #### `new-message`
384
-
385
- Emitted when a new message is received or sent.
462
+ // Get single handle
463
+ const handle = await sdk.handles.getHandle("handle-guid");
386
464
 
387
- ```typescript
388
- sdk.on("new-message", (message) => {
389
- console.log("New message received:", message.text);
390
- console.log("From:", message.handle?.address);
391
- console.log("GUID:", message.guid);
392
- });
465
+ // Get total count
466
+ const count = await sdk.handles.getHandleCount();
393
467
  ```
394
468
 
395
- #### `updated-message` / `message-updated`
469
+ ### Check Service Availability
396
470
 
397
- Emitted when a message status changes (delivered, read, etc.).
471
+ Check if a phone/email supports iMessage or FaceTime:
398
472
 
399
473
  ```typescript
400
- sdk.on("updated-message", (message) => {
401
- const status = message.dateRead
402
- ? "read"
403
- : message.dateDelivered
404
- ? "delivered"
405
- : "sent";
406
- console.log(`Message ${message.guid} is now ${status}`);
407
- });
474
+ // First parameter is the address (phone or email), not handle guid
475
+ const hasIMessage = await sdk.handles.getHandleAvailability(
476
+ "+1234567890",
477
+ "imessage"
478
+ );
479
+ const hasFaceTime = await sdk.handles.getHandleAvailability(
480
+ "+1234567890",
481
+ "facetime"
482
+ );
483
+
484
+ // Choose service based on availability
485
+ const chatGuid = hasIMessage ? `iMessage;-;+1234567890` : `SMS;-;+1234567890`;
408
486
  ```
409
487
 
410
- #### `message-send-error`
488
+ > Example: [service-check.ts](./examples/service-check.ts)
411
489
 
412
- Emitted when sending a message fails.
490
+ ### Get Focus Status
413
491
 
414
492
  ```typescript
415
- sdk.on("message-send-error", (data) => {
416
- console.error("Failed to send message:", data);
417
- });
493
+ const focusStatus = await sdk.handles.getHandleFocusStatus("handle-guid");
418
494
  ```
419
495
 
420
- ### Chat Events
496
+ ---
497
+
498
+ ## Server
421
499
 
422
- #### `chat-read-status-changed`
500
+ > Examples: [message-stats.ts](./examples/message-stats.ts) | [server-info.ts](./examples/server-info.ts)
423
501
 
424
- Emitted when a chat is marked as read or unread.
502
+ ### Get Server Info
425
503
 
426
504
  ```typescript
427
- sdk.on("chat-read-status-changed", ({ chatGuid, read }) => {
428
- console.log(`Chat ${chatGuid} marked as ${read ? "read" : "unread"}`);
429
- });
505
+ const info = await sdk.server.getServerInfo();
506
+ // {
507
+ // os_version: "14.0",
508
+ // server_version: "1.0.0",
509
+ // private_api: true,
510
+ // helper_connected: true,
511
+ // detected_icloud: "user@icloud.com",
512
+ // ...
513
+ // }
430
514
  ```
431
515
 
432
- ### Group Chat Events
516
+ ### Message Statistics
433
517
 
434
- #### `group-name-change`
518
+ ```typescript
519
+ const stats = await sdk.server.getMessageStats();
520
+ // {
521
+ // total: 12345,
522
+ // sent: 5000,
523
+ // received: 7345,
524
+ // last24h: 50,
525
+ // last7d: 300,
526
+ // last30d: 1000,
527
+ // }
528
+ ```
435
529
 
436
- Emitted when a group chat name is changed.
530
+ ### Media Statistics
437
531
 
438
532
  ```typescript
439
- sdk.on("group-name-change", (data) => {
440
- console.log(`Group renamed to: ${data.message.groupTitle}`);
441
- });
442
- ```
533
+ // All media stats
534
+ const mediaStats = await sdk.server.getMediaStatistics();
443
535
 
444
- #### `participant-added`
536
+ // Per-chat media stats
537
+ const chatMediaStats = await sdk.server.getMediaStatisticsByChat();
538
+ ```
445
539
 
446
- Emitted when someone is added to a group chat.
540
+ ### Server Logs
447
541
 
448
542
  ```typescript
449
- sdk.on("participant-added", (data) => {
450
- console.log(`Participant added to ${data.chat.displayName}`);
451
- });
543
+ const logs = await sdk.server.getServerLogs(100); // Get last 100 logs
452
544
  ```
453
545
 
454
- #### `participant-removed`
455
-
456
- Emitted when someone is removed from a group chat.
546
+ ### Alert Management
457
547
 
458
548
  ```typescript
459
- sdk.on("participant-removed", (data) => {
460
- console.log(`Participant removed from ${data.chat.displayName}`);
461
- });
549
+ // Get alerts
550
+ const alerts = await sdk.server.getAlerts();
551
+
552
+ // Mark alerts as read
553
+ await sdk.server.markAlertAsRead(["alert-id-1", "alert-id-2"]);
462
554
  ```
463
555
 
464
- #### `participant-left`
556
+ > Example: [server-info.ts](./examples/server-info.ts)
465
557
 
466
- Emitted when someone leaves a group chat.
558
+ ---
467
559
 
468
- ```typescript
469
- sdk.on("participant-left", (data) => {
470
- console.log(`Participant left ${data.chat.displayName}`);
471
- });
472
- ```
560
+ ## Polls
473
561
 
474
- #### `group-icon-changed`
562
+ > Examples: [poll-create.ts](./examples/poll-create.ts) | [poll-add-option.ts](./examples/poll-add-option.ts)
475
563
 
476
- Emitted when a group chat icon is changed.
564
+ ### Create Polls
477
565
 
478
566
  ```typescript
479
- sdk.on("group-icon-changed", (data) => {
480
- console.log("Group icon changed");
567
+ const pollMessage = await sdk.polls.create({
568
+ chatGuid: "iMessage;-;+1234567890",
569
+ title: "What should we do?", // Optional
570
+ options: ["Option A", "Option B", "Option C"],
481
571
  });
572
+
573
+ console.log("Poll GUID:", pollMessage.guid);
482
574
  ```
483
575
 
484
- #### `group-icon-removed`
576
+ > Example: [poll-create.ts](./examples/poll-create.ts)
485
577
 
486
- Emitted when a group chat icon is removed.
578
+ ### Add Poll Options
487
579
 
488
580
  ```typescript
489
- sdk.on("group-icon-removed", (data) => {
490
- console.log("Group icon removed");
581
+ await sdk.polls.addOption({
582
+ chatGuid: "iMessage;-;+1234567890",
583
+ pollMessageGuid: "poll-message-guid",
584
+ optionText: "New Option D",
491
585
  });
492
586
  ```
493
587
 
494
- ### Private API Events
588
+ > Example: [poll-add-option.ts](./examples/poll-add-option.ts)
495
589
 
496
- #### `typing-indicator`
590
+ ### Parse Poll Messages
497
591
 
498
- Emitted when someone is typing. Requires Private API.
592
+ Use the `poll-utils` helper functions to parse and display poll messages:
499
593
 
500
594
  ```typescript
501
- sdk.on("typing-indicator", (data) => {
502
- console.log("Typing status changed:", data);
503
- });
504
- ```
505
-
506
- #### `ft-call-status-changed`
595
+ import {
596
+ isPollMessage,
597
+ isPollVote,
598
+ parsePollDefinition,
599
+ parsePollVotes,
600
+ getPollSummary,
601
+ getOptionTextById,
602
+ } from "@photon-ai/advanced-imessage-kit/lib/poll-utils";
507
603
 
508
- Emitted when FaceTime call status changes.
604
+ sdk.on("new-message", (message) => {
605
+ if (isPollMessage(message)) {
606
+ if (isPollVote(message)) {
607
+ // Parse vote data
608
+ const voteData = parsePollVotes(message);
609
+ console.log("Votes:", voteData?.votes);
610
+
611
+ // Get option text for each vote
612
+ voteData?.votes.forEach((vote) => {
613
+ const optionText = getOptionTextById(vote.voteOptionIdentifier);
614
+ console.log(`${vote.participantHandle} voted for "${optionText}"`);
615
+ });
616
+ } else {
617
+ // Parse poll definition
618
+ const pollData = parsePollDefinition(message);
619
+ console.log("Poll title:", pollData?.title);
620
+ console.log("Options:", pollData?.options);
621
+ }
509
622
 
510
- ```typescript
511
- sdk.on("ft-call-status-changed", ({ callUuid, status }) => {
512
- console.log(`FaceTime call ${callUuid}: ${status}`);
623
+ // Or get a formatted summary
624
+ console.log(getPollSummary(message));
625
+ }
513
626
  });
514
627
  ```
515
628
 
516
- ### Find My Events
629
+ **Note**: Poll definitions are automatically cached when received. When a vote arrives, the SDK looks up the corresponding option text from the cache. If you receive a vote for a poll that was created before the SDK started, the option text won't be available and will show the UUID instead.
630
+
631
+ ---
632
+
633
+ ## iCloud _(Work in Progress)_
517
634
 
518
- #### `new-findmy-location`
635
+ > Example: [findmy-friends.ts](./examples/findmy-friends.ts)
519
636
 
520
- Emitted when a Find My friend's location updates.
637
+ ### Find My Friends
521
638
 
522
639
  ```typescript
523
- sdk.on("new-findmy-location", ({ name, friendId, location }) => {
524
- console.log(`${name} location: ${location.latitude}, ${location.longitude}`);
525
- });
640
+ // Get friends' locations
641
+ const friends = await sdk.icloud.getFindMyFriends();
642
+
643
+ // Refresh location data
644
+ await sdk.icloud.refreshFindMyFriends();
526
645
  ```
527
646
 
528
- ### Scheduled Message Events
647
+ > Example: [findmy-friends.ts](./examples/findmy-friends.ts)
529
648
 
530
- #### `scheduled-message-sent`
649
+ ---
531
650
 
532
- Emitted when a scheduled message is sent.
651
+ ## Real-time Events
533
652
 
534
- ```typescript
535
- sdk.on("scheduled-message-sent", (data) => {
536
- console.log("Scheduled message sent:", data);
537
- });
538
- ```
653
+ > Examples: [listen-simple.ts](./examples/listen-simple.ts) | [listen-advanced.ts](./examples/listen-advanced.ts) | [auto-reply-hey.ts](./examples/auto-reply-hey.ts)
539
654
 
540
- #### `scheduled-message-error`
655
+ The SDK receives real-time events from the server via Socket.IO.
541
656
 
542
- Emitted when a scheduled message fails.
657
+ ### Connection Events
543
658
 
544
659
  ```typescript
545
- sdk.on("scheduled-message-error", (data) => {
546
- console.error("Scheduled message error:", data);
660
+ sdk.on("ready", () => {
661
+ console.log("SDK connected and ready");
547
662
  });
548
- ```
549
-
550
- #### `scheduled-message-created`
551
663
 
552
- Emitted when a scheduled message is created.
664
+ sdk.on("disconnect", () => {
665
+ console.log("Disconnected");
666
+ });
553
667
 
554
- ```typescript
555
- sdk.on("scheduled-message-created", (data) => {
556
- console.log("Scheduled message created:", data);
668
+ sdk.on("error", (error) => {
669
+ console.error("Error:", error);
557
670
  });
558
671
  ```
559
672
 
560
- #### `scheduled-message-updated`
561
-
562
- Emitted when a scheduled message is updated.
673
+ ### Message Events
563
674
 
564
675
  ```typescript
565
- sdk.on("scheduled-message-updated", (data) => {
566
- console.log("Scheduled message updated:", data);
676
+ // New message
677
+ sdk.on("new-message", (message) => {
678
+ console.log("New message:", message.text);
679
+ console.log("From:", message.handle?.address);
680
+ console.log("From me:", message.isFromMe);
567
681
  });
568
- ```
569
-
570
- #### `scheduled-message-deleted`
571
682
 
572
- Emitted when a scheduled message is deleted.
683
+ // Message status update (delivered, read, etc.)
684
+ sdk.on("updated-message", (message) => {
685
+ if (message.dateRead) console.log("Message read");
686
+ else if (message.dateDelivered) console.log("Message delivered");
687
+ });
573
688
 
574
- ```typescript
575
- sdk.on("scheduled-message-deleted", (data) => {
576
- console.log("Scheduled message deleted:", data);
689
+ // Send failed
690
+ sdk.on("message-send-error", (data) => {
691
+ console.error("Send failed:", data);
577
692
  });
578
693
  ```
579
694
 
580
- ### Event Management
695
+ ### Chat Events
581
696
 
582
697
  ```typescript
583
- // Remove event listeners
584
- sdk.off("new-message", messageHandler);
585
-
586
- // Remove all listeners for an event
587
- sdk.removeAllListeners("new-message");
698
+ // Chat read status changed
699
+ sdk.on("chat-read-status-changed", ({ chatGuid, read }) => {
700
+ console.log(`Chat ${chatGuid} marked as ${read ? "read" : "unread"}`);
701
+ });
588
702
  ```
589
703
 
590
- ## Advanced Features
591
-
592
- ### FaceTime Integration
704
+ ### Typing Indicators
593
705
 
594
706
  ```typescript
595
- // Create FaceTime link
596
- const link = await sdk.facetime.createFaceTimeLink();
597
- console.log("FaceTime link:", link);
598
-
599
- // Listen for FaceTime status changes
600
- sdk.on("ft-call-status-changed", (data) => {
601
- console.log("FaceTime status:", data.status);
707
+ sdk.on("typing-indicator", ({ display, guid }) => {
708
+ console.log(`${guid} ${display ? "is typing" : "stopped typing"}`);
602
709
  });
603
710
  ```
604
711
 
605
- ### iCloud Services
712
+ ### Group Events
606
713
 
607
714
  ```typescript
608
- // Get Find My Friends
609
- const friends = await sdk.icloud.getFindMyFriends();
610
-
611
- // Refresh data
612
- await sdk.icloud.refreshFindMyFriends();
613
- ```
715
+ sdk.on("group-name-change", (message) => {
716
+ console.log("Group renamed to:", message.groupTitle);
717
+ });
614
718
 
615
- ### Scheduled Messages
719
+ sdk.on("participant-added", (message) => {
720
+ console.log("Someone joined the group");
721
+ });
616
722
 
617
- ```typescript
618
- // Create scheduled message
619
- const scheduled = await sdk.scheduledMessages.createScheduledMessage({
620
- chatGuid: "any;-;+1234567890",
621
- message: "This message was scheduled!",
622
- scheduledFor: new Date(Date.now() + 60000), // 1 minute from now
623
- schedule: { type: "once" },
723
+ sdk.on("participant-removed", (message) => {
724
+ console.log("Someone was removed from the group");
624
725
  });
625
726
 
626
- // Get all scheduled messages
627
- const allScheduled = await sdk.scheduledMessages.getScheduledMessages();
727
+ sdk.on("participant-left", (message) => {
728
+ console.log("Someone left the group");
729
+ });
628
730
 
629
- // Update scheduled message
630
- await sdk.scheduledMessages.updateScheduledMessage("schedule-id", {
631
- message: "Updated message",
731
+ sdk.on("group-icon-changed", (message) => {
732
+ console.log("Group icon changed");
632
733
  });
633
734
 
634
- // Delete scheduled message
635
- await sdk.scheduledMessages.deleteScheduledMessage("schedule-id");
735
+ sdk.on("group-icon-removed", (message) => {
736
+ console.log("Group icon removed");
737
+ });
636
738
  ```
637
739
 
638
- ### Server Information
740
+ ### Find My Friends Events _(WIP)_
639
741
 
640
742
  ```typescript
641
- // Get server info
642
- const serverInfo = await sdk.server.getServerInfo();
643
-
644
- // Get message statistics
645
- const stats = await sdk.server.getMessageStats();
646
-
647
- // Get server logs
648
- const logs = await sdk.server.getServerLogs(100);
649
-
650
- // Get alerts
651
- const alerts = await sdk.server.getAlerts();
652
-
653
- // Mark alerts as read
654
- await sdk.server.markAlertAsRead(["alert-id-1", "alert-id-2"]);
743
+ sdk.on("new-findmy-location", (location) => {
744
+ console.log(`${location.handle} location updated:`, location.coordinates);
745
+ });
655
746
  ```
656
747
 
657
- ## Error Handling
748
+ ### Remove Event Listeners
658
749
 
659
750
  ```typescript
660
- try {
661
- await sdk.messages.sendMessage({
662
- chatGuid: "invalid-guid",
663
- message: "Test",
664
- });
665
- } catch (error) {
666
- if (error.response?.status === 404) {
667
- console.error("Chat not found");
668
- } else {
669
- console.error("Send failed:", error.message);
670
- }
671
- }
672
- ```
751
+ const handler = (message) => console.log(message);
752
+ sdk.on("new-message", handler);
673
753
 
674
- ## Configuration Options
754
+ // Remove specific listener
755
+ sdk.off("new-message", handler);
675
756
 
676
- ```typescript
677
- interface ClientConfig {
678
- serverUrl?: string; // Your subdomain: '{your-subdomain}.imsgd.photon.codes'
679
- apiKey?: string; // Optional API key for authenticated backends
680
- logLevel?: "debug" | "info" | "warn" | "error"; // Default: 'info'
681
- }
757
+ // Remove all listeners
758
+ sdk.removeAllListeners("new-message");
682
759
  ```
683
760
 
761
+ ---
762
+
684
763
  ## Best Practices
685
764
 
686
765
  ### Resource Management
687
766
 
688
767
  ```typescript
689
- // Always disconnect when done
768
+ // Graceful shutdown
690
769
  process.on("SIGINT", async () => {
691
770
  await sdk.close();
692
771
  process.exit(0);
693
772
  });
694
773
  ```
695
774
 
696
- ### Event Handling
697
-
698
- ```typescript
699
- // Use specific event handlers
700
- sdk.on("new-message", handleNewMessage);
701
- sdk.on("error", handleError);
702
-
703
- // Remove listeners when needed
704
- sdk.off("new-message", handleNewMessage);
705
- ```
775
+ ### Message Deduplication
706
776
 
707
- ### Performance Optimization
777
+ The SDK includes built-in message deduplication to prevent processing duplicates during network instability:
708
778
 
709
779
  ```typescript
710
- // Use pagination for large queries
711
- const messages = await sdk.messages.getMessages({
712
- chatGuid: "any;-;+1234567890",
713
- limit: 100,
714
- offset: 0,
715
- });
716
-
717
- // Clear processed message records (prevents memory leaks)
780
+ // Clear processed messages (prevent memory leaks)
718
781
  sdk.clearProcessedMessages(1000);
719
782
 
720
783
  // Get processed message count
721
- const processedCount = sdk.getProcessedMessageCount();
722
- ```
723
-
724
- ## Examples
725
-
726
- The SDK includes comprehensive examples in the `examples/` directory. All examples can be run using Bun:
727
-
728
- ### Basic Examples
729
-
730
- #### `demo-basic.ts` - Listen for Messages
731
-
732
- Simple message listener demonstrating event handling.
733
-
734
- ```bash
735
- bun run examples/demo-basic.ts
784
+ const count = sdk.getProcessedMessageCount();
736
785
  ```
737
786
 
738
- #### `message-send.ts` - Send a Message
787
+ ### Error Handling
739
788
 
740
- Send a text message to a contact or chat.
741
-
742
- ```bash
743
- CHAT_GUID="+1234567890" bun run examples/message-send.ts
744
- ```
745
-
746
- #### `message-attachment.ts` - Send Files
747
-
748
- Send images, videos, or other files as attachments.
749
-
750
- ```bash
751
- CHAT_GUID="+1234567890" bun run examples/message-attachment.ts
752
- ```
753
-
754
- #### `message-audio.ts` - Send Voice Messages
755
-
756
- Send voice messages (audio attachments with special handling).
757
-
758
- ```bash
759
- CHAT_GUID="+1234567890" AUDIO_FILE_PATH="/path/to/audio.m4a" bun run examples/message-audio.ts
760
- ```
761
-
762
- ### Advanced Examples
763
-
764
- #### `message-reaction.ts` - Reactions (Tapbacks)
765
-
766
- Add and remove reactions to messages.
767
-
768
- ```bash
769
- CHAT_GUID="chat-guid" MESSAGE_GUID="message-guid" bun run examples/message-reaction.ts
770
- ```
771
-
772
- #### `message-edit.ts` - Edit Messages
773
-
774
- Edit a sent message. Requires macOS Ventura (13.0) or newer and Private API.
775
-
776
- ```bash
777
- CHAT_GUID="chat-guid" bun run examples/message-edit.ts
778
- ```
779
-
780
- #### `message-unsend.ts` - Unsend Messages
781
-
782
- Unsend a message within 2 minutes of sending. Requires macOS Ventura (13.0) or newer and Private API.
783
-
784
- ```bash
785
- CHAT_GUID="chat-guid" bun run examples/message-unsend.ts
786
- ```
787
-
788
- #### `message-typing.ts` - Typing Indicators
789
-
790
- Start and stop typing indicators in a chat. Requires Private API.
791
-
792
- ```bash
793
- CHAT_GUID="chat-guid" bun run examples/message-typing.ts
794
- ```
795
-
796
- #### `message-contact-card.ts` - Share Contact Cards
797
-
798
- Share contact cards in chats. Requires macOS Big Sur (11.0) or newer and Private API.
799
-
800
- ```bash
801
- CHAT_GUID="chat-guid" CONTACT_ADDRESS="email-or-phone" bun run examples/message-contact-card.ts
802
- ```
803
-
804
- #### `message-reply-sticker.ts` - Send Stickers
805
-
806
- Send stickers and multipart messages. Requires Private API.
807
-
808
- ```bash
809
- CHAT_GUID="chat-guid" STICKER_PATH="path/to/image.jpg" bun run examples/message-reply-sticker.ts
810
- ```
811
-
812
- #### `message-effects.ts` - Message Effects
813
-
814
- Send messages with visual effects (confetti, fireworks, balloons, etc.). Requires Private API.
815
-
816
- ```bash
817
- CHAT_GUID="chat-guid" bun run examples/message-effects.ts
818
- ```
819
-
820
- #### `message-reply.ts` - Reply to Messages
821
-
822
- Reply to a specific message in a chat.
823
-
824
- ```bash
825
- CHAT_GUID="chat-guid" MESSAGE_GUID="message-guid" bun run examples/message-reply.ts
826
- ```
827
-
828
- #### `chat-fetch.ts` - Fetch Chats
829
-
830
- Retrieve and filter chats from the database.
831
-
832
- ```bash
833
- bun run examples/chat-fetch.ts
834
- ```
835
-
836
- #### `chat-group.ts` - Group Chat Management
837
-
838
- List and monitor group chats, track membership changes.
839
-
840
- ```bash
841
- bun run examples/chat-group.ts
789
+ ```typescript
790
+ try {
791
+ await sdk.messages.sendMessage({
792
+ chatGuid: "invalid-guid",
793
+ message: "test",
794
+ });
795
+ } catch (error) {
796
+ if (error.response?.status === 404) {
797
+ console.error("Chat not found");
798
+ } else {
799
+ console.error("Send failed:", error.message);
800
+ }
801
+ }
842
802
  ```
843
803
 
844
- #### `message-search.ts` - Search Messages
804
+ ### Auto-create Chats
845
805
 
846
- Search through message history with filtering options.
806
+ When sending to a contact you've never messaged before, the SDK automatically creates the chat:
847
807
 
848
- ```bash
849
- bun run examples/message-search.ts
808
+ ```typescript
809
+ // Works even without existing chat history
810
+ await sdk.messages.sendMessage({
811
+ chatGuid: "any;-;+1234567890",
812
+ message: "Hi, this is John",
813
+ });
814
+ // SDK detects the chat doesn't exist, creates it, then sends
850
815
  ```
851
816
 
852
- #### `message-stats.ts` - Message Statistics
853
-
854
- View message statistics, chat activity, and analytics.
855
-
856
- ```bash
857
- bun run examples/message-stats.ts
858
- ```
817
+ ---
859
818
 
860
- #### `message-scheduled.ts` - Schedule Messages
819
+ ## Examples
861
820
 
862
- Schedule one-time and recurring messages.
821
+ Run any example with Bun:
863
822
 
864
823
  ```bash
865
- CHAT_GUID="+1234567890" bun run examples/message-scheduled.ts
824
+ bun run examples/<filename>.ts
866
825
  ```
867
826
 
868
- #### `facetime-link.ts` - FaceTime Links
827
+ ### Getting Started
869
828
 
870
- Create FaceTime links programmatically. Requires macOS Monterey (12.0) or newer and Private API.
829
+ | File | Description |
830
+ | --------------------------------------------------------- | -------------------------------------- |
831
+ | [listen-simple.ts](./examples/listen-simple.ts) | Listen with formatted output |
832
+ | [listen-advanced.ts](./examples/listen-advanced.ts) | Listen with full JSON and startup info |
833
+ | [message-send.ts](./examples/message-send.ts) | Send text messages |
834
+ | [message-attachment.ts](./examples/message-attachment.ts) | Send attachments |
835
+ | [message-audio.ts](./examples/message-audio.ts) | Send audio messages |
871
836
 
872
- ```bash
873
- bun run examples/facetime-link.ts
874
- ```
837
+ ### Message Operations
875
838
 
876
- #### `findmy-friends.ts` - Find My Integration
839
+ | File | Description |
840
+ | ----------------------------------------------------- | ----------------- |
841
+ | [message-reply.ts](./examples/message-reply.ts) | Reply to messages |
842
+ | [message-unsend.ts](./examples/message-unsend.ts) | Unsend messages |
843
+ | [message-reaction.ts](./examples/message-reaction.ts) | Send Tapbacks |
844
+ | [message-effects.ts](./examples/message-effects.ts) | Message effects |
845
+ | [message-search.ts](./examples/message-search.ts) | Search messages |
877
846
 
878
- Track friends via Find My network.
847
+ ### Chats & Groups
879
848
 
880
- ```bash
881
- bun run examples/findmy-friends.ts
882
- ```
849
+ | File | Description |
850
+ | ------------------------------------------------- | ----------------- |
851
+ | [chat-fetch.ts](./examples/chat-fetch.ts) | Get chat list |
852
+ | [chat-group.ts](./examples/chat-group.ts) | Manage groups |
853
+ | [message-typing.ts](./examples/message-typing.ts) | Typing indicators |
883
854
 
884
- #### `contact-list.ts` - Contact Access
855
+ ### Contacts & Services
885
856
 
886
- Access and search macOS Contacts database.
857
+ | File | Description |
858
+ | --------------------------------------------------------------- | ----------------------------- |
859
+ | [contact-list.ts](./examples/contact-list.ts) | Get contacts |
860
+ | [service-check.ts](./examples/service-check.ts) | Check iMessage availability |
861
+ | [message-service-check.ts](./examples/message-service-check.ts) | Monitor message service types |
887
862
 
888
- ```bash
889
- bun run examples/contact-list.ts
890
- ```
863
+ ### Attachments & Media
891
864
 
892
- #### `demo-advanced.ts` - Advanced Features
865
+ | File | Description |
866
+ | --------------------------------------------------------------- | -------------------- |
867
+ | [attachment-download.ts](./examples/attachment-download.ts) | Download attachments |
868
+ | [message-reply-sticker.ts](./examples/message-reply-sticker.ts) | Send stickers |
893
869
 
894
- Demonstrates permissions checking, chat retrieval, and event monitoring.
870
+ ### Polls
895
871
 
896
- ```bash
897
- bun run examples/demo-advanced.ts
898
- ```
872
+ | File | Description |
873
+ | --------------------------------------------------- | ---------------- |
874
+ | [poll-create.ts](./examples/poll-create.ts) | Create polls |
875
+ | [poll-add-option.ts](./examples/poll-add-option.ts) | Add poll options |
899
876
 
900
- #### `auto-reply-hey.ts` - Auto-Reply Example
877
+ ### Server & Advanced
901
878
 
902
- Automatic reply example that responds to incoming messages.
879
+ | File | Description |
880
+ | ------------------------------------------------- | ----------------------- |
881
+ | [server-info.ts](./examples/server-info.ts) | Server info and logs |
882
+ | [message-stats.ts](./examples/message-stats.ts) | Message statistics |
883
+ | [findmy-friends.ts](./examples/findmy-friends.ts) | Find My Friends _(WIP)_ |
884
+ | [auto-reply-hey.ts](./examples/auto-reply-hey.ts) | Auto reply bot |
903
885
 
904
- ```bash
905
- bun run examples/auto-reply-hey.ts
906
- ```
886
+ ---
907
887
 
908
888
  ## LLMs
909
889
 
910
- You can download the `llms.txt` helper file for language models here:
890
+ Download `llms.txt` for language model context:
911
891
 
912
892
  - [Download llms.txt](./llms.txt)
913
893
 
894
+ ---
895
+
914
896
  ## License
915
897
 
916
898
  MIT License