@elizaos/plugin-imessage 2.0.0-beta.1 → 2.0.11-beta.7
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/LICENSE +21 -0
- package/README.md +13 -18
- package/auto-enable.ts +1 -1
- package/package.json +21 -4
- package/dist/accounts.d.ts +0 -135
- package/dist/accounts.d.ts.map +0 -1
- package/dist/accounts.js +0 -209
- package/dist/accounts.js.map +0 -1
- package/dist/api/bluebubbles-routes.d.ts +0 -10
- package/dist/api/bluebubbles-routes.d.ts.map +0 -1
- package/dist/api/bluebubbles-routes.js +0 -132
- package/dist/api/bluebubbles-routes.js.map +0 -1
- package/dist/api/imessage-routes.d.ts +0 -80
- package/dist/api/imessage-routes.d.ts.map +0 -1
- package/dist/api/imessage-routes.js +0 -230
- package/dist/api/imessage-routes.js.map +0 -1
- package/dist/chatdb-reader.d.ts +0 -240
- package/dist/chatdb-reader.d.ts.map +0 -1
- package/dist/chatdb-reader.js +0 -647
- package/dist/chatdb-reader.js.map +0 -1
- package/dist/config.d.ts +0 -60
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -8
- package/dist/config.js.map +0 -1
- package/dist/connector-account-provider.d.ts +0 -18
- package/dist/connector-account-provider.d.ts.map +0 -1
- package/dist/connector-account-provider.js +0 -83
- package/dist/connector-account-provider.js.map +0 -1
- package/dist/contacts-reader.d.ts +0 -147
- package/dist/contacts-reader.d.ts.map +0 -1
- package/dist/contacts-reader.js +0 -481
- package/dist/contacts-reader.js.map +0 -1
- package/dist/index.d.ts +0 -23
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -78
- package/dist/index.js.map +0 -1
- package/dist/providers/index.d.ts +0 -4
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -5
- package/dist/providers/index.js.map +0 -1
- package/dist/rpc.d.ts +0 -206
- package/dist/rpc.d.ts.map +0 -1
- package/dist/rpc.js +0 -393
- package/dist/rpc.js.map +0 -1
- package/dist/service.d.ts +0 -266
- package/dist/service.d.ts.map +0 -1
- package/dist/service.js +0 -1694
- package/dist/service.js.map +0 -1
- package/dist/setup-routes.d.ts +0 -38
- package/dist/setup-routes.d.ts.map +0 -1
- package/dist/setup-routes.js +0 -322
- package/dist/setup-routes.js.map +0 -1
- package/dist/types.d.ts +0 -192
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -138
- package/dist/types.js.map +0 -1
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
const BLUEBUBBLES_SERVICE_NAME = "bluebubbles";
|
|
2
|
-
const DEFAULT_WEBHOOK_PATH = "/webhooks/bluebubbles";
|
|
3
|
-
const MAX_BODY_BYTES = 1_048_576;
|
|
4
|
-
function resolveService(state) {
|
|
5
|
-
if (!state.runtime) {
|
|
6
|
-
return null;
|
|
7
|
-
}
|
|
8
|
-
const raw = state.runtime.getService(BLUEBUBBLES_SERVICE_NAME);
|
|
9
|
-
return raw ?? null;
|
|
10
|
-
}
|
|
11
|
-
export function resolveBlueBubblesWebhookPath(state) {
|
|
12
|
-
const service = resolveService(state);
|
|
13
|
-
const configuredPath = service?.getWebhookPath();
|
|
14
|
-
if (typeof configuredPath === "string" && configuredPath.trim().length > 0) {
|
|
15
|
-
return configuredPath.trim();
|
|
16
|
-
}
|
|
17
|
-
return DEFAULT_WEBHOOK_PATH;
|
|
18
|
-
}
|
|
19
|
-
export async function handleBlueBubblesRoute(req, res, pathname, method, state, helpers) {
|
|
20
|
-
const webhookPath = resolveBlueBubblesWebhookPath(state);
|
|
21
|
-
const isWebhookPath = pathname === webhookPath;
|
|
22
|
-
const isApiPath = pathname.startsWith("/api/bluebubbles");
|
|
23
|
-
if (!isWebhookPath && !isApiPath) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
if (method === "GET" && pathname === "/api/bluebubbles/status") {
|
|
27
|
-
const service = resolveService(state);
|
|
28
|
-
if (!service) {
|
|
29
|
-
helpers.json(res, {
|
|
30
|
-
available: false,
|
|
31
|
-
connected: false,
|
|
32
|
-
webhookPath,
|
|
33
|
-
reason: "bluebubbles service not registered",
|
|
34
|
-
});
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
helpers.json(res, {
|
|
38
|
-
available: true,
|
|
39
|
-
connected: service.isConnected(),
|
|
40
|
-
webhookPath,
|
|
41
|
-
});
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
if (method === "GET" && pathname === "/api/bluebubbles/chats") {
|
|
45
|
-
const service = resolveService(state);
|
|
46
|
-
if (!service) {
|
|
47
|
-
helpers.error(res, "bluebubbles service not registered", 503);
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
const client = service.getClient();
|
|
51
|
-
if (!client) {
|
|
52
|
-
helpers.error(res, "bluebubbles client not available", 503);
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
const url = new URL(req.url ?? pathname, "http://localhost");
|
|
56
|
-
const limit = Math.min(Math.max(1, Number.parseInt(url.searchParams.get("limit") ?? "100", 10) || 100), 500);
|
|
57
|
-
const offset = Math.max(0, Number.parseInt(url.searchParams.get("offset") ?? "0", 10) || 0);
|
|
58
|
-
try {
|
|
59
|
-
const chats = await client.listChats(limit, offset);
|
|
60
|
-
helpers.json(res, { chats, count: chats.length, limit, offset });
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
helpers.error(res, `failed to read bluebubbles chats: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
64
|
-
}
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
if (method === "GET" && pathname === "/api/bluebubbles/messages") {
|
|
68
|
-
const service = resolveService(state);
|
|
69
|
-
if (!service) {
|
|
70
|
-
helpers.error(res, "bluebubbles service not registered", 503);
|
|
71
|
-
return true;
|
|
72
|
-
}
|
|
73
|
-
const client = service.getClient();
|
|
74
|
-
if (!client) {
|
|
75
|
-
helpers.error(res, "bluebubbles client not available", 503);
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
const url = new URL(req.url ?? pathname, "http://localhost");
|
|
79
|
-
const chatGuid = (url.searchParams.get("chatGuid") ?? "").trim();
|
|
80
|
-
if (!chatGuid) {
|
|
81
|
-
helpers.error(res, "chatGuid query parameter is required", 400);
|
|
82
|
-
return true;
|
|
83
|
-
}
|
|
84
|
-
const limit = Math.min(Math.max(1, Number.parseInt(url.searchParams.get("limit") ?? "50", 10) || 50), 500);
|
|
85
|
-
const offset = Math.max(0, Number.parseInt(url.searchParams.get("offset") ?? "0", 10) || 0);
|
|
86
|
-
try {
|
|
87
|
-
const messages = await client.getMessages(chatGuid, limit, offset);
|
|
88
|
-
helpers.json(res, {
|
|
89
|
-
chatGuid,
|
|
90
|
-
messages,
|
|
91
|
-
count: messages.length,
|
|
92
|
-
limit,
|
|
93
|
-
offset,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
helpers.error(res, `failed to read bluebubbles messages: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
98
|
-
}
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
if (method === "POST" && isWebhookPath) {
|
|
102
|
-
const service = resolveService(state);
|
|
103
|
-
if (!service) {
|
|
104
|
-
helpers.error(res, "bluebubbles service not registered", 503);
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
const payload = await helpers.readJsonBody(req, res, {
|
|
108
|
-
maxBytes: MAX_BODY_BYTES,
|
|
109
|
-
});
|
|
110
|
-
if (!payload) {
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
if (typeof payload.type !== "string" ||
|
|
114
|
-
!payload.type.trim() ||
|
|
115
|
-
typeof payload.data !== "object" ||
|
|
116
|
-
payload.data === null ||
|
|
117
|
-
Array.isArray(payload.data)) {
|
|
118
|
-
helpers.error(res, "invalid BlueBubbles webhook payload", 400);
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
await service.handleWebhook(payload);
|
|
123
|
-
helpers.json(res, { ok: true });
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
helpers.error(res, `failed to handle bluebubbles webhook: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
127
|
-
}
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
return false;
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=bluebubbles-routes.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bluebubbles-routes.js","sourceRoot":"","sources":["../../src/api/bluebubbles-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* iMessage connector HTTP routes.
|
|
3
|
-
*
|
|
4
|
-
* Exposes the @elizaos/plugin-imessage service state through Eliza's
|
|
5
|
-
* HTTP API so downstream UI layers (the dashboard, a future CLI, third-
|
|
6
|
-
* party integrations) can read and write against the macOS Messages.app
|
|
7
|
-
* world without each client having to go straight to chat.db or to
|
|
8
|
-
* AppleScript.
|
|
9
|
-
*
|
|
10
|
-
* Routes served (all under `/api/imessage`):
|
|
11
|
-
*
|
|
12
|
-
* GET /api/imessage/status service health + cursor + counts
|
|
13
|
-
* GET /api/imessage/messages recent messages from chat.db
|
|
14
|
-
* GET /api/imessage/chats list of chats (DMs + groups)
|
|
15
|
-
* GET /api/imessage/contacts every contact with full detail
|
|
16
|
-
* POST /api/imessage/contacts create a new contact
|
|
17
|
-
* PATCH /api/imessage/contacts/:id update an existing contact
|
|
18
|
-
* DELETE /api/imessage/contacts/:id delete a contact
|
|
19
|
-
*
|
|
20
|
-
* Each handler pulls the IMessageService instance off the runtime via
|
|
21
|
-
* `runtime.getService("imessage")` and calls the public methods added
|
|
22
|
-
* in the plugin's patched branch. If the service isn't registered (the
|
|
23
|
-
* plugin isn't enabled, Eliza booted before it was loaded, etc.) we
|
|
24
|
-
* return 503 with a structured reason so the UI can render an
|
|
25
|
-
* informative empty state.
|
|
26
|
-
*
|
|
27
|
-
* Write endpoints (POST/PATCH/DELETE on contacts) touch the real macOS
|
|
28
|
-
* Contacts.app and will trigger a one-time TCC permission prompt the
|
|
29
|
-
* first time they fire. That prompt targets whichever process ran the
|
|
30
|
-
* osascript child; in Eliza's case that's `bun`/`node`. Once granted
|
|
31
|
-
* the permission is persistent across restarts.
|
|
32
|
-
*/
|
|
33
|
-
import type http from "node:http";
|
|
34
|
-
/**
|
|
35
|
-
* Minimal structural copy of the agent's RouteHelpers / RouteRequestMeta
|
|
36
|
-
* surface, inlined here so this file can live inside @elizaos/plugin-imessage
|
|
37
|
-
* without taking a build-time dependency on @elizaos/agent.
|
|
38
|
-
*/
|
|
39
|
-
export interface ReadJsonBodyOptions {
|
|
40
|
-
maxBytes?: number;
|
|
41
|
-
requireObject?: boolean;
|
|
42
|
-
readErrorStatus?: number;
|
|
43
|
-
nonObjectStatus?: number;
|
|
44
|
-
parseErrorStatus?: number;
|
|
45
|
-
readErrorMessage?: string;
|
|
46
|
-
nonObjectMessage?: string;
|
|
47
|
-
parseErrorMessage?: string;
|
|
48
|
-
}
|
|
49
|
-
export interface RouteRequestMeta {
|
|
50
|
-
req: http.IncomingMessage;
|
|
51
|
-
res: http.ServerResponse;
|
|
52
|
-
method: string;
|
|
53
|
-
pathname: string;
|
|
54
|
-
}
|
|
55
|
-
export interface RouteHelpers {
|
|
56
|
-
json: (res: http.ServerResponse, data: unknown, status?: number) => void;
|
|
57
|
-
error: (res: http.ServerResponse, message: string, status?: number) => void;
|
|
58
|
-
readJsonBody: <T extends object>(req: http.IncomingMessage, res: http.ServerResponse, options?: ReadJsonBodyOptions) => Promise<T | null>;
|
|
59
|
-
}
|
|
60
|
-
export interface IMessageRouteState {
|
|
61
|
-
/**
|
|
62
|
-
* The running AgentRuntime (or a test stub). Typed loosely as
|
|
63
|
-
* `unknown` so this route file doesn't re-declare core's stricter
|
|
64
|
-
* generic getService signature — we narrow the result inside
|
|
65
|
-
* resolveService via an unknown cast. Optional so route files
|
|
66
|
-
* tolerate the boot window where the runtime hasn't finished
|
|
67
|
-
* registering services yet.
|
|
68
|
-
*/
|
|
69
|
-
runtime?: {
|
|
70
|
-
getService(type: string): unknown;
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Route handler entry point. Returns `true` when a route matched and
|
|
75
|
-
* the response has been written; returns `false` so the caller can
|
|
76
|
-
* continue to other route handlers (mirrors the handleWhatsAppRoute /
|
|
77
|
-
* handleWalletRoute pattern used elsewhere in this codebase).
|
|
78
|
-
*/
|
|
79
|
-
export declare function handleIMessageRoute(req: http.IncomingMessage, res: http.ServerResponse, pathname: string, method: string, state: IMessageRouteState, helpers: RouteHelpers): Promise<boolean>;
|
|
80
|
-
//# sourceMappingURL=imessage-routes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"imessage-routes.d.ts","sourceRoot":"","sources":["../../src/api/imessage-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC;IAC1B,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,YAAY,EAAE,CAAC,CAAC,SAAS,MAAM,EAC7B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,OAAO,CAAC,EAAE,mBAAmB,KAC1B,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;CACxB;AA2ED,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;KACnC,CAAC;CACH;AAyBD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,OAAO,CAAC,CA0NlB"}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* iMessage connector HTTP routes.
|
|
3
|
-
*
|
|
4
|
-
* Exposes the @elizaos/plugin-imessage service state through Eliza's
|
|
5
|
-
* HTTP API so downstream UI layers (the dashboard, a future CLI, third-
|
|
6
|
-
* party integrations) can read and write against the macOS Messages.app
|
|
7
|
-
* world without each client having to go straight to chat.db or to
|
|
8
|
-
* AppleScript.
|
|
9
|
-
*
|
|
10
|
-
* Routes served (all under `/api/imessage`):
|
|
11
|
-
*
|
|
12
|
-
* GET /api/imessage/status service health + cursor + counts
|
|
13
|
-
* GET /api/imessage/messages recent messages from chat.db
|
|
14
|
-
* GET /api/imessage/chats list of chats (DMs + groups)
|
|
15
|
-
* GET /api/imessage/contacts every contact with full detail
|
|
16
|
-
* POST /api/imessage/contacts create a new contact
|
|
17
|
-
* PATCH /api/imessage/contacts/:id update an existing contact
|
|
18
|
-
* DELETE /api/imessage/contacts/:id delete a contact
|
|
19
|
-
*
|
|
20
|
-
* Each handler pulls the IMessageService instance off the runtime via
|
|
21
|
-
* `runtime.getService("imessage")` and calls the public methods added
|
|
22
|
-
* in the plugin's patched branch. If the service isn't registered (the
|
|
23
|
-
* plugin isn't enabled, Eliza booted before it was loaded, etc.) we
|
|
24
|
-
* return 503 with a structured reason so the UI can render an
|
|
25
|
-
* informative empty state.
|
|
26
|
-
*
|
|
27
|
-
* Write endpoints (POST/PATCH/DELETE on contacts) touch the real macOS
|
|
28
|
-
* Contacts.app and will trigger a one-time TCC permission prompt the
|
|
29
|
-
* first time they fire. That prompt targets whichever process ran the
|
|
30
|
-
* osascript child; in Eliza's case that's `bun`/`node`. Once granted
|
|
31
|
-
* the permission is persistent across restarts.
|
|
32
|
-
*/
|
|
33
|
-
const IMESSAGE_SERVICE_NAME = "imessage";
|
|
34
|
-
const MAX_BODY_BYTES = 256 * 1024; // Contacts payloads are tiny; cap aggressively.
|
|
35
|
-
function resolveService(state) {
|
|
36
|
-
if (!state.runtime)
|
|
37
|
-
return null;
|
|
38
|
-
const raw = state.runtime.getService(IMESSAGE_SERVICE_NAME);
|
|
39
|
-
return raw ?? null;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Extract the `:id` segment from a contact path like
|
|
43
|
-
* `/api/imessage/contacts/ABCD-EFGH-...`. Returns null if the path
|
|
44
|
-
* doesn't match. The id is URL-decoded since Contacts.app ids are
|
|
45
|
-
* GUID-style and safe, but callers could URL-encode for paranoia.
|
|
46
|
-
*/
|
|
47
|
-
function parseContactId(pathname) {
|
|
48
|
-
const prefix = "/api/imessage/contacts/";
|
|
49
|
-
if (!pathname.startsWith(prefix))
|
|
50
|
-
return null;
|
|
51
|
-
const rest = pathname.slice(prefix.length);
|
|
52
|
-
if (!rest)
|
|
53
|
-
return null;
|
|
54
|
-
return decodeURIComponent(rest);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Route handler entry point. Returns `true` when a route matched and
|
|
58
|
-
* the response has been written; returns `false` so the caller can
|
|
59
|
-
* continue to other route handlers (mirrors the handleWhatsAppRoute /
|
|
60
|
-
* handleWalletRoute pattern used elsewhere in this codebase).
|
|
61
|
-
*/
|
|
62
|
-
export async function handleIMessageRoute(req, res, pathname, method, state, helpers) {
|
|
63
|
-
if (!pathname.startsWith("/api/imessage"))
|
|
64
|
-
return false;
|
|
65
|
-
const meta = { req, res, method, pathname };
|
|
66
|
-
// ── GET /api/imessage/status ──────────────────────────────────────
|
|
67
|
-
if (method === "GET" && pathname === "/api/imessage/status") {
|
|
68
|
-
const service = resolveService(state);
|
|
69
|
-
if (!service) {
|
|
70
|
-
helpers.json(res, {
|
|
71
|
-
available: false,
|
|
72
|
-
reason: "imessage service not registered",
|
|
73
|
-
});
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
helpers.json(res, {
|
|
77
|
-
available: true,
|
|
78
|
-
connected: service.isConnected(),
|
|
79
|
-
...(service.getStatus?.() ?? {}),
|
|
80
|
-
});
|
|
81
|
-
return true;
|
|
82
|
-
}
|
|
83
|
-
// ── GET /api/imessage/messages?limit=N ────────────────────────────
|
|
84
|
-
if (method === "GET" && pathname === "/api/imessage/messages") {
|
|
85
|
-
const service = resolveService(state);
|
|
86
|
-
if (!service) {
|
|
87
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
const url = new URL(req.url ?? pathname, "http://localhost");
|
|
91
|
-
const limitParam = url.searchParams.get("limit");
|
|
92
|
-
const limit = Math.min(Math.max(1, Number.parseInt(limitParam ?? "50", 10) || 50), 500);
|
|
93
|
-
try {
|
|
94
|
-
const messages = await service.getRecentMessages(limit);
|
|
95
|
-
helpers.json(res, { messages, count: messages.length });
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
helpers.error(res, `failed to read messages: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
99
|
-
}
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
// ── GET /api/imessage/chats ───────────────────────────────────────
|
|
103
|
-
if (method === "GET" && pathname === "/api/imessage/chats") {
|
|
104
|
-
const service = resolveService(state);
|
|
105
|
-
if (!service) {
|
|
106
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
try {
|
|
110
|
-
const chats = await service.getChats();
|
|
111
|
-
helpers.json(res, { chats, count: chats.length });
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
helpers.error(res, `failed to read chats: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
115
|
-
}
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
// ── GET /api/imessage/contacts ────────────────────────────────────
|
|
119
|
-
if (method === "GET" && pathname === "/api/imessage/contacts") {
|
|
120
|
-
const service = resolveService(state);
|
|
121
|
-
if (!service) {
|
|
122
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
const contacts = await service.listAllContacts();
|
|
127
|
-
helpers.json(res, { contacts, count: contacts.length });
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
helpers.error(res, `failed to read contacts: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
131
|
-
}
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
// ── POST /api/imessage/contacts ───────────────────────────────────
|
|
135
|
-
if (method === "POST" && pathname === "/api/imessage/contacts") {
|
|
136
|
-
const service = resolveService(state);
|
|
137
|
-
if (!service) {
|
|
138
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
const body = await helpers.readJsonBody(req, res, { maxBytes: MAX_BODY_BYTES });
|
|
142
|
-
if (!body)
|
|
143
|
-
return true; // helpers.readJsonBody has already sent the error.
|
|
144
|
-
if (!body.firstName && !body.lastName && !body.phones?.length && !body.emails?.length) {
|
|
145
|
-
helpers.error(res, "at least one of firstName, lastName, phones, or emails is required", 400);
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
try {
|
|
149
|
-
const id = await service.addContact({
|
|
150
|
-
firstName: body.firstName,
|
|
151
|
-
lastName: body.lastName,
|
|
152
|
-
phones: body.phones,
|
|
153
|
-
emails: body.emails,
|
|
154
|
-
});
|
|
155
|
-
if (!id) {
|
|
156
|
-
helpers.error(res, "contact creation failed — see server logs. Common cause: Contacts write permission not granted yet.", 500);
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
helpers.json(res, { id, created: true }, 201);
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
helpers.error(res, `addContact threw: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
163
|
-
}
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
// ── PATCH /api/imessage/contacts/:id ──────────────────────────────
|
|
167
|
-
if (method === "PATCH" && pathname.startsWith("/api/imessage/contacts/")) {
|
|
168
|
-
const id = parseContactId(pathname);
|
|
169
|
-
if (!id) {
|
|
170
|
-
helpers.error(res, "contact id is required in the path", 400);
|
|
171
|
-
return true;
|
|
172
|
-
}
|
|
173
|
-
const service = resolveService(state);
|
|
174
|
-
if (!service) {
|
|
175
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
const body = await helpers.readJsonBody(req, res, { maxBytes: MAX_BODY_BYTES });
|
|
179
|
-
if (!body)
|
|
180
|
-
return true;
|
|
181
|
-
try {
|
|
182
|
-
const ok = await service.updateContact(id, {
|
|
183
|
-
firstName: body.firstName,
|
|
184
|
-
lastName: body.lastName,
|
|
185
|
-
addPhones: body.addPhones,
|
|
186
|
-
removePhones: body.removePhones,
|
|
187
|
-
addEmails: body.addEmails,
|
|
188
|
-
removeEmails: body.removeEmails,
|
|
189
|
-
});
|
|
190
|
-
if (!ok) {
|
|
191
|
-
helpers.error(res, "contact update failed — see server logs. Contact may not exist, or write permission may be denied.", 500);
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
helpers.json(res, { id, updated: true });
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
helpers.error(res, `updateContact threw: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
198
|
-
}
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
// ── DELETE /api/imessage/contacts/:id ─────────────────────────────
|
|
202
|
-
if (method === "DELETE" && pathname.startsWith("/api/imessage/contacts/")) {
|
|
203
|
-
const id = parseContactId(pathname);
|
|
204
|
-
if (!id) {
|
|
205
|
-
helpers.error(res, "contact id is required in the path", 400);
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
const service = resolveService(state);
|
|
209
|
-
if (!service) {
|
|
210
|
-
helpers.error(res, "imessage service not registered", 503);
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
try {
|
|
214
|
-
const ok = await service.deleteContact(id);
|
|
215
|
-
if (!ok) {
|
|
216
|
-
helpers.error(res, "contact delete failed — see server logs. Contact may not exist, or write permission may be denied.", 500);
|
|
217
|
-
return true;
|
|
218
|
-
}
|
|
219
|
-
helpers.json(res, { id, deleted: true });
|
|
220
|
-
}
|
|
221
|
-
catch (error) {
|
|
222
|
-
helpers.error(res, `deleteContact threw: ${error instanceof Error ? error.message : String(error)}`, 500);
|
|
223
|
-
}
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
// Path starts with /api/imessage but none of the above matched.
|
|
227
|
-
void meta; // reserved for future telemetry spans
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
//# sourceMappingURL=imessage-routes.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"imessage-routes.js","sourceRoot":"","sources":["../../src/api/imessage-routes.ts"],"names":[],"mappings":"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"}
|