ab-ecosystem-cpass 1.0.0 → 1.0.6
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 +121 -21
- package/dist/client.d.ts +38 -0
- package/dist/client.js +49 -5
- package/dist/client.js.map +1 -1
- package/dist/http.d.ts +15 -0
- package/dist/http.js +21 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +24 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/bytes.d.ts +38 -0
- package/dist/internal/bytes.js +84 -0
- package/dist/internal/bytes.js.map +1 -0
- package/dist/internal/device.d.ts +24 -0
- package/dist/internal/device.js +91 -0
- package/dist/internal/device.js.map +1 -0
- package/dist/internal/md5.d.ts +4 -0
- package/dist/internal/md5.js +109 -0
- package/dist/internal/md5.js.map +1 -0
- package/dist/internal/receiver-file.d.ts +106 -0
- package/dist/internal/receiver-file.js +128 -0
- package/dist/internal/receiver-file.js.map +1 -0
- package/dist/realtime/client.d.ts +85 -0
- package/dist/realtime/client.js +126 -0
- package/dist/realtime/client.js.map +1 -0
- package/dist/realtime/events.d.ts +147 -0
- package/dist/realtime/events.js +3 -0
- package/dist/realtime/events.js.map +1 -0
- package/dist/realtime/inbox.d.ts +173 -0
- package/dist/realtime/inbox.js +263 -0
- package/dist/realtime/inbox.js.map +1 -0
- package/dist/realtime/index.d.ts +16 -0
- package/dist/realtime/index.js +37 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/resources/audience/contacts.d.ts +19 -3
- package/dist/resources/audience/contacts.js +19 -3
- package/dist/resources/audience/contacts.js.map +1 -1
- package/dist/resources/audience/inbox-media.d.ts +92 -0
- package/dist/resources/audience/inbox-media.js +127 -0
- package/dist/resources/audience/inbox-media.js.map +1 -0
- package/dist/resources/audience/notifications.d.ts +171 -0
- package/dist/resources/audience/notifications.js +215 -0
- package/dist/resources/audience/notifications.js.map +1 -0
- package/dist/resources/audience/scheduled-messages.d.ts +234 -0
- package/dist/resources/audience/scheduled-messages.js +259 -0
- package/dist/resources/audience/scheduled-messages.js.map +1 -0
- package/dist/resources/campaign-audience.d.ts +132 -0
- package/dist/resources/campaign-audience.js +224 -0
- package/dist/resources/campaign-audience.js.map +1 -0
- package/dist/resources/campaign-report-exports.d.ts +14 -0
- package/dist/resources/campaign-report-exports.js +28 -0
- package/dist/resources/campaign-report-exports.js.map +1 -0
- package/dist/resources/campaign-reports.d.ts +15 -0
- package/dist/resources/campaign-reports.js +25 -0
- package/dist/resources/campaign-reports.js.map +1 -0
- package/dist/resources/campaigns.d.ts +239 -0
- package/dist/resources/campaigns.js +300 -0
- package/dist/resources/campaigns.js.map +1 -0
- package/dist/types/audience.d.ts +93 -1
- package/dist/types/campaign.d.ts +229 -0
- package/dist/types/campaign.js +3 -0
- package/dist/types/campaign.js.map +1 -0
- package/dist/types/contact-filter.d.ts +3 -2
- package/dist/types/contact-filter.js +3 -2
- package/dist/types/contact-filter.js.map +1 -1
- package/dist/types/inbox.d.ts +391 -0
- package/dist/types/inbox.js +16 -0
- package/dist/types/inbox.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/scheduled-message.d.ts +221 -0
- package/dist/types/scheduled-message.js +16 -0
- package/dist/types/scheduled-message.js.map +1 -0
- package/docs/audience/contacts.md +34 -4
- package/docs/audience/notifications.md +263 -0
- package/docs/audience/scheduled-messages.md +557 -0
- package/docs/campaign/campaigns.md +489 -0
- package/docs/contact-filter.md +2 -1
- package/docs/inbox/chats.md +356 -0
- package/docs/inbox/connection.md +171 -0
- package/docs/inbox/media.md +202 -0
- package/docs/inbox/messages.md +338 -0
- package/docs/inbox/referrals.md +72 -0
- package/docs/inbox/sessions.md +74 -0
- package/package.json +28 -2
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InboxClient = void 0;
|
|
4
|
+
const socket_io_client_1 = require("socket.io-client");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const DEFAULT_TIMEOUT = 20_000;
|
|
7
|
+
/**
|
|
8
|
+
* The live-chat inbox over a socket.
|
|
9
|
+
*
|
|
10
|
+
* Requests are promises: each emit carries an acknowledgement callback, so two
|
|
11
|
+
* concurrent reads of different threads cannot be confused for one another. The
|
|
12
|
+
* server also emits replies under the request's own event name for older clients
|
|
13
|
+
* -- {@link InboxClient.on} sees those too, which is why a handler for
|
|
14
|
+
* `chat.action` receives both your own actions and other agents'.
|
|
15
|
+
*
|
|
16
|
+
* Credentials travel in `auth`, not in a header: a browser cannot set headers on
|
|
17
|
+
* a WebSocket upgrade, so a header-based handshake only works for as long as the
|
|
18
|
+
* connection stays on long-polling.
|
|
19
|
+
*/
|
|
20
|
+
class InboxClient {
|
|
21
|
+
options;
|
|
22
|
+
socket;
|
|
23
|
+
timeout;
|
|
24
|
+
/**
|
|
25
|
+
* The uploader this client was built with, if any.
|
|
26
|
+
*
|
|
27
|
+
* Read by `messages.sendMedia` when it is handed a file rather than a link.
|
|
28
|
+
*/
|
|
29
|
+
get uploadMedia() {
|
|
30
|
+
return this.options.uploadMedia;
|
|
31
|
+
}
|
|
32
|
+
constructor(options) {
|
|
33
|
+
this.options = options;
|
|
34
|
+
if (!options.url)
|
|
35
|
+
throw new errors_1.CrmConfigError('An inbox socket url is required');
|
|
36
|
+
if (!options.clientId)
|
|
37
|
+
throw new errors_1.CrmConfigError('A clientId is required');
|
|
38
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
|
|
39
|
+
this.socket = (0, socket_io_client_1.io)(options.url, {
|
|
40
|
+
path: options.path ?? '/socket.io',
|
|
41
|
+
autoConnect: options.autoConnect ?? true,
|
|
42
|
+
transports: ['websocket', 'polling'],
|
|
43
|
+
auth: (cb) => {
|
|
44
|
+
void this.credentials().then(cb);
|
|
45
|
+
},
|
|
46
|
+
...options.socketOptions,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** Resolved per connect, so a reconnect never reuses an expired token. */
|
|
50
|
+
async credentials() {
|
|
51
|
+
const token = typeof this.options.token === 'function' ? await this.options.token() : this.options.token;
|
|
52
|
+
return { token, client_id: this.options.clientId };
|
|
53
|
+
}
|
|
54
|
+
/** The underlying socket, for lifecycle events and anything not wrapped here. */
|
|
55
|
+
get raw() {
|
|
56
|
+
return this.socket;
|
|
57
|
+
}
|
|
58
|
+
get connected() {
|
|
59
|
+
return this.socket.connected;
|
|
60
|
+
}
|
|
61
|
+
connect() {
|
|
62
|
+
this.socket.connect();
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
disconnect() {
|
|
66
|
+
this.socket.disconnect();
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
/** Resolves once connected, or rejects with the handshake's reason. */
|
|
70
|
+
ready() {
|
|
71
|
+
if (this.socket.connected)
|
|
72
|
+
return Promise.resolve();
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const onConnect = () => {
|
|
75
|
+
this.socket.off('connect_error', onError);
|
|
76
|
+
resolve();
|
|
77
|
+
};
|
|
78
|
+
const onError = (err) => {
|
|
79
|
+
this.socket.off('connect', onConnect);
|
|
80
|
+
reject(new errors_1.CrmApiError(401, 'unauthorized', err.message));
|
|
81
|
+
};
|
|
82
|
+
this.socket.once('connect', onConnect);
|
|
83
|
+
this.socket.once('connect_error', onError);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Sends one request and waits for its answer.
|
|
88
|
+
*
|
|
89
|
+
* A refusal rejects with a {@link CrmApiError} carrying the same code and status
|
|
90
|
+
* the REST API would have returned, so one error path covers both transports.
|
|
91
|
+
*/
|
|
92
|
+
request(event, payload) {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
this.socket
|
|
95
|
+
.timeout(this.timeout)
|
|
96
|
+
.emit(event, payload, (err, ack) => {
|
|
97
|
+
if (err) {
|
|
98
|
+
reject(new errors_1.CrmApiError(504, 'timeout', `${event} did not answer in ${this.timeout}ms`));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!ack?.ok) {
|
|
102
|
+
const error = ack?.error;
|
|
103
|
+
reject(new errors_1.CrmApiError(error?.status ?? 500, error?.code ?? 'internal_error', error?.message ?? `${event} failed`, error?.details));
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
resolve(ack.data);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Listens for a pushed event. Returns the unsubscribe function, so a component
|
|
112
|
+
* can tear its own listener down without knowing what else is attached.
|
|
113
|
+
*/
|
|
114
|
+
on(event, handler) {
|
|
115
|
+
this.socket.on(event, handler);
|
|
116
|
+
return () => {
|
|
117
|
+
this.socket.off(event, handler);
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** Fires once, then unsubscribes. */
|
|
121
|
+
once(event, handler) {
|
|
122
|
+
this.socket.once(event, handler);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.InboxClient = InboxClient;
|
|
126
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/realtime/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { AssignBotPayload, BulkTransferResult, Chat, ChatActionPayload, ChatActionResult, ChatList, ChatSession, CtwaReferral, DeleteMessagePayload, FetchMessagePayload, ListChatsPayload, Message, MessageDeleteResult, MessageStatusUpdate, RetryDownloadPayload, SendMessagePayload, UpdateChatPayload, UpdateChatResult } from '../types/inbox';
|
|
2
|
+
/** What a rejected event sends back. The HTTP error body, field for field. */
|
|
3
|
+
export interface InboxError {
|
|
4
|
+
/** The event that failed. */
|
|
5
|
+
event: string;
|
|
6
|
+
code: string;
|
|
7
|
+
message: string;
|
|
8
|
+
status: number;
|
|
9
|
+
details?: unknown;
|
|
10
|
+
requestId: string;
|
|
11
|
+
}
|
|
12
|
+
/** The acknowledgement a request-style event resolves with. */
|
|
13
|
+
export type InboxAck<T> = {
|
|
14
|
+
ok: true;
|
|
15
|
+
data: T;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
error: InboxError;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Every event the client sends, with its payload and what it answers.
|
|
22
|
+
*
|
|
23
|
+
* The server replies two ways, so both generations of client work: through the
|
|
24
|
+
* acknowledgement callback when one is passed, and by emitting the same event
|
|
25
|
+
* name back, which is what the original inbox listens for.
|
|
26
|
+
*/
|
|
27
|
+
export interface InboxRequests {
|
|
28
|
+
ping: {
|
|
29
|
+
payload: unknown;
|
|
30
|
+
result: unknown;
|
|
31
|
+
};
|
|
32
|
+
'contact.list': {
|
|
33
|
+
payload: ListChatsPayload;
|
|
34
|
+
result: ChatList;
|
|
35
|
+
};
|
|
36
|
+
'contact.fetch': {
|
|
37
|
+
payload: {
|
|
38
|
+
id: string;
|
|
39
|
+
};
|
|
40
|
+
result: Chat;
|
|
41
|
+
};
|
|
42
|
+
'contact.update': {
|
|
43
|
+
payload: UpdateChatPayload;
|
|
44
|
+
result: UpdateChatResult;
|
|
45
|
+
};
|
|
46
|
+
'contact.done': {
|
|
47
|
+
payload: {
|
|
48
|
+
id: string;
|
|
49
|
+
isEnded?: boolean;
|
|
50
|
+
};
|
|
51
|
+
result: ChatActionResult;
|
|
52
|
+
};
|
|
53
|
+
'contact.bot_assign': {
|
|
54
|
+
payload: AssignBotPayload;
|
|
55
|
+
result: {
|
|
56
|
+
success: boolean;
|
|
57
|
+
id: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
'chat.action': {
|
|
61
|
+
payload: ChatActionPayload;
|
|
62
|
+
result: ChatActionResult | BulkTransferResult;
|
|
63
|
+
};
|
|
64
|
+
'message.list': {
|
|
65
|
+
payload: {
|
|
66
|
+
id: string;
|
|
67
|
+
limit?: number;
|
|
68
|
+
last_message_id?: string;
|
|
69
|
+
};
|
|
70
|
+
result: Message[];
|
|
71
|
+
};
|
|
72
|
+
'message.fetch': {
|
|
73
|
+
payload: FetchMessagePayload;
|
|
74
|
+
result: Message;
|
|
75
|
+
};
|
|
76
|
+
'message.send': {
|
|
77
|
+
payload: SendMessagePayload;
|
|
78
|
+
result: Message;
|
|
79
|
+
};
|
|
80
|
+
'message.delete': {
|
|
81
|
+
payload: DeleteMessagePayload;
|
|
82
|
+
result: MessageDeleteResult;
|
|
83
|
+
};
|
|
84
|
+
'message.retry_download': {
|
|
85
|
+
payload: RetryDownloadPayload;
|
|
86
|
+
result: Message;
|
|
87
|
+
};
|
|
88
|
+
'ctwa.list': {
|
|
89
|
+
payload: {
|
|
90
|
+
id: string;
|
|
91
|
+
limit?: number;
|
|
92
|
+
};
|
|
93
|
+
result: CtwaReferral[];
|
|
94
|
+
};
|
|
95
|
+
'chat_session.list': {
|
|
96
|
+
payload: {
|
|
97
|
+
id: string;
|
|
98
|
+
channel?: string;
|
|
99
|
+
};
|
|
100
|
+
result: ChatSession[];
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export type InboxRequestName = keyof InboxRequests;
|
|
104
|
+
/**
|
|
105
|
+
* Events the server pushes without being asked.
|
|
106
|
+
*
|
|
107
|
+
* `chat.action` and the `message.*` names appear here as well as in the request
|
|
108
|
+
* map on purpose: an archive performed by another agent arrives under the same
|
|
109
|
+
* name and shape as one you asked for, so a client needs only one handler per
|
|
110
|
+
* kind of change rather than one per cause.
|
|
111
|
+
*/
|
|
112
|
+
export interface InboxPushes {
|
|
113
|
+
/**
|
|
114
|
+
* A message arrived, or one that was sent now exists as a stored row.
|
|
115
|
+
*
|
|
116
|
+
* The second case is how an optimistic bubble is replaced: `message.send`
|
|
117
|
+
* answered with a queue id, and this carries the same message with the
|
|
118
|
+
* provider's real `message_id`.
|
|
119
|
+
*/
|
|
120
|
+
'message.received': Message;
|
|
121
|
+
/**
|
|
122
|
+
* The same row as `message.received`, in the shape it is stored in.
|
|
123
|
+
*
|
|
124
|
+
* Kept because the inbox this replaced listened for one name, `message.send`,
|
|
125
|
+
* for both its own reply and the row that followed. New clients should use
|
|
126
|
+
* `message.received`, which is mapped; this one carries `_id` and `user` as the
|
|
127
|
+
* database holds them.
|
|
128
|
+
*/
|
|
129
|
+
'message.send': Record<string, unknown>;
|
|
130
|
+
/** A delivery state moved: sent, delivered, read, failed. */
|
|
131
|
+
'message.status': MessageStatusUpdate;
|
|
132
|
+
/** A chat changed: unread count, assignment, automation, tags. */
|
|
133
|
+
'chat.action': ChatActionResult;
|
|
134
|
+
/**
|
|
135
|
+
* A contact wrote in for the first time, so a chat row appeared.
|
|
136
|
+
*
|
|
137
|
+
* The stored contact document, not a mapped `Chat` -- it comes from the service
|
|
138
|
+
* that created it.
|
|
139
|
+
*/
|
|
140
|
+
'contact.received': Record<string, unknown>;
|
|
141
|
+
'message.delete': MessageDeleteResult;
|
|
142
|
+
'message.retry_download': Message;
|
|
143
|
+
'contact.done': ChatActionResult;
|
|
144
|
+
/** An event was refused. Carries the event name that failed. */
|
|
145
|
+
error: InboxError;
|
|
146
|
+
}
|
|
147
|
+
export type InboxPushName = keyof InboxPushes;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/realtime/events.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { AssignBotPayload, BulkTransferResult, Chat, ChatActionPayload, ChatActionResult, ChatBlockUpdate, ChatList, ChatSession, CtwaReferral, ListChatsPayload, Message, MessageDeleteResult, SendMediaPayload, SendMessagePayload, UpdateChatPayload, UpdateChatResult } from '../types/inbox';
|
|
2
|
+
import { InboxClient, type InboxClientOptions } from './client';
|
|
3
|
+
/** The chat list and the thirteen actions that change one. */
|
|
4
|
+
export declare class InboxChats {
|
|
5
|
+
private readonly client;
|
|
6
|
+
constructor(client: InboxClient);
|
|
7
|
+
/**
|
|
8
|
+
* One page of the inbox, ordered by last activity.
|
|
9
|
+
*
|
|
10
|
+
* `contact.list` · scope `contacts:read`
|
|
11
|
+
*
|
|
12
|
+
* The reply's `filter` is the filter that was *applied* -- a team member
|
|
13
|
+
* without the unassigned permission asking for `all` is narrowed to `me` -- and
|
|
14
|
+
* `nextPage` is the cursor for the page after this one, or `null` at the end.
|
|
15
|
+
*/
|
|
16
|
+
list(payload?: ListChatsPayload): Promise<ChatList>;
|
|
17
|
+
/**
|
|
18
|
+
* One chat, and a subscription to it: messages and state changes for this
|
|
19
|
+
* thread reach the socket from here on without asking again.
|
|
20
|
+
*
|
|
21
|
+
* `contact.fetch` · scope `contacts:read`
|
|
22
|
+
*/
|
|
23
|
+
get(id: string): Promise<Chat>;
|
|
24
|
+
/** Any action, for callers holding a payload they built elsewhere. */
|
|
25
|
+
act(payload: ChatActionPayload): Promise<ChatActionResult | BulkTransferResult>;
|
|
26
|
+
/** Trashes the chat. It leaves every inbox view; the contact row stays. */
|
|
27
|
+
delete(chat: string): Promise<ChatActionResult>;
|
|
28
|
+
/** Assigns the chat to one member and flags it unread for them. */
|
|
29
|
+
transfer(chat: string, member: string): Promise<ChatActionResult>;
|
|
30
|
+
archive(chat: string): Promise<ChatActionResult>;
|
|
31
|
+
unarchive(chat: string): Promise<ChatActionResult>;
|
|
32
|
+
/** Flips one or more block flags. Flags left out keep their current value. */
|
|
33
|
+
block(chat: string, update: ChatBlockUpdate): Promise<ChatActionResult>;
|
|
34
|
+
/** Clears the unread counter and the by-hand unread flag. */
|
|
35
|
+
markAsRead(chat: string): Promise<ChatActionResult>;
|
|
36
|
+
markAsUnread(chat: string): Promise<ChatActionResult>;
|
|
37
|
+
/** Detaches the flow and holds automation for `chat_metadata.pause_duration`. */
|
|
38
|
+
pauseAutomation(chat: string): Promise<ChatActionResult>;
|
|
39
|
+
resumeAutomation(chat: string): Promise<ChatActionResult>;
|
|
40
|
+
/** Closes the chat and detaches the flow, leaving the assignment alone. */
|
|
41
|
+
close(chat: string): Promise<ChatActionResult>;
|
|
42
|
+
/** Marks the chat done, unassigns it and detaches the flow. */
|
|
43
|
+
done(chat: string, isEnded?: boolean): Promise<ChatActionResult>;
|
|
44
|
+
/** Re-arms the automation pause with a new duration, in seconds. */
|
|
45
|
+
pauseTimer(chat: string, duration: number): Promise<ChatActionResult>;
|
|
46
|
+
/** Replaces the chat's tags outright. */
|
|
47
|
+
updateTags(chat: string, tags: string[]): Promise<ChatActionResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Moves every chat held by one member -- or the unassigned queue -- to another
|
|
50
|
+
* member or a team. Capped at 500 chats per call; each moved chat is broadcast
|
|
51
|
+
* individually as a `transfer`.
|
|
52
|
+
*/
|
|
53
|
+
bulkTransfer(payload: Omit<Extract<ChatActionPayload, {
|
|
54
|
+
action: 'bulk_transfer';
|
|
55
|
+
}>, 'action'>): Promise<BulkTransferResult>;
|
|
56
|
+
/** The narrower action set, answering with the metadata alone. */
|
|
57
|
+
update(payload: UpdateChatPayload): Promise<UpdateChatResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Attaches a flow to the chat, or hands the chat to the bot server to place.
|
|
60
|
+
*
|
|
61
|
+
* `contact.bot_assign` · scope `contacts:write`
|
|
62
|
+
*/
|
|
63
|
+
assignBot(payload: AssignBotPayload): Promise<{
|
|
64
|
+
success: boolean;
|
|
65
|
+
id: string;
|
|
66
|
+
}>;
|
|
67
|
+
private single;
|
|
68
|
+
}
|
|
69
|
+
/** Reading, sending and removing messages in one thread. */
|
|
70
|
+
export declare class InboxMessages {
|
|
71
|
+
private readonly client;
|
|
72
|
+
constructor(client: InboxClient);
|
|
73
|
+
/**
|
|
74
|
+
* One page of a thread, oldest-first, and a subscription to it.
|
|
75
|
+
*
|
|
76
|
+
* `message.list` · scope `messages:read`
|
|
77
|
+
*
|
|
78
|
+
* Pass the `id` of the oldest message you hold as `last_message_id` to walk
|
|
79
|
+
* backwards through the history.
|
|
80
|
+
*/
|
|
81
|
+
list<C extends Message['content'] = Message['content']>(id: string, options?: {
|
|
82
|
+
limit?: number;
|
|
83
|
+
last_message_id?: string;
|
|
84
|
+
}): Promise<Message<C>[]>;
|
|
85
|
+
/** One message by its provider id -- a `wamid`, not the document id. */
|
|
86
|
+
get<C extends Message['content'] = Message['content']>(messageId: string): Promise<Message<C>>;
|
|
87
|
+
/**
|
|
88
|
+
* Sends a message and gets the bubble to draw back immediately.
|
|
89
|
+
*
|
|
90
|
+
* `message.send` · scope `messages:write`
|
|
91
|
+
*
|
|
92
|
+
* The returned message carries a queue id in `message_id`, not a provider id:
|
|
93
|
+
* nothing has been written yet. The stored row arrives moments later as a
|
|
94
|
+
* `message.received` push, with the provider's id in its place -- correlate on
|
|
95
|
+
* the queue id you got back here, not on the final `message_id`.
|
|
96
|
+
*
|
|
97
|
+
* Sending by hand also takes the conversation off its bot, which arrives as a
|
|
98
|
+
* `chat.action` with `action: 'pause_automation'`.
|
|
99
|
+
*/
|
|
100
|
+
send<C extends Message['content'] = Message['content']>(payload: SendMessagePayload): Promise<Message<C>>;
|
|
101
|
+
/**
|
|
102
|
+
* Sends media, uploading it first if you hand over a file.
|
|
103
|
+
*
|
|
104
|
+
* `message.send` · scope `messages:write`
|
|
105
|
+
*
|
|
106
|
+
* Two ways in. With a `link` -- from `crm.inboxMedia.upload()`, or any publicly
|
|
107
|
+
* fetchable URL -- this is `send()` with the content assembled for you:
|
|
108
|
+
*
|
|
109
|
+
* ```ts
|
|
110
|
+
* const link = await crm.inboxMedia.upload(file, { kind: 'image' });
|
|
111
|
+
* await inbox.messages.sendMedia({ channel, contact, kind: 'image', link, caption: 'Your order' });
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* With a `file`, it uploads and sends in one call -- which needs an uploader,
|
|
115
|
+
* because a socket cannot presign. Pass `uploadMedia` when constructing the
|
|
116
|
+
* `Inbox`:
|
|
117
|
+
*
|
|
118
|
+
* ```ts
|
|
119
|
+
* const inbox = new Inbox({ url, clientId, token, uploadMedia: crm.inboxMedia.upload.bind(crm.inboxMedia) });
|
|
120
|
+
* await inbox.messages.sendMedia({ channel, contact, kind: 'image', file, caption: 'Your order' });
|
|
121
|
+
* ```
|
|
122
|
+
*
|
|
123
|
+
* The link is what gets stored on the message, and it does not expire, so the
|
|
124
|
+
* thread still renders the media months later.
|
|
125
|
+
*
|
|
126
|
+
* `filename` is worth setting on a `document`: it is what the recipient sees in
|
|
127
|
+
* their chat, where a bare key would otherwise appear.
|
|
128
|
+
*/
|
|
129
|
+
sendMedia<C extends Message['content'] = Message['content']>(payload: SendMediaPayload): Promise<Message<C>>;
|
|
130
|
+
/** Uploads a file through the hook the client was given, or explains its absence. */
|
|
131
|
+
private resolve;
|
|
132
|
+
/** Removes one message from a thread, for everyone with it open. */
|
|
133
|
+
delete(contactId: string, messageId: string): Promise<MessageDeleteResult>;
|
|
134
|
+
/**
|
|
135
|
+
* Re-fetches media whose first download failed. Inbound media only -- an
|
|
136
|
+
* outbound attachment was ours to begin with.
|
|
137
|
+
*
|
|
138
|
+
* `message.retry_download` · scope `messages:write`
|
|
139
|
+
*/
|
|
140
|
+
retryDownload<C extends Message['content'] = Message['content']>(messageId: string): Promise<Message<C>>;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The live-chat inbox.
|
|
144
|
+
*
|
|
145
|
+
* ```ts
|
|
146
|
+
* const inbox = new Inbox({ url: 'https://inbox.example.com', clientId, token });
|
|
147
|
+
* await inbox.ready();
|
|
148
|
+
*
|
|
149
|
+
* const { contacts } = await inbox.chats.list({ filter: { assignment: 'me', unread: 'unread' } });
|
|
150
|
+
* inbox.on('message.received', (message) => append(message));
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export declare class Inbox extends InboxClient {
|
|
154
|
+
readonly chats: InboxChats;
|
|
155
|
+
readonly messages: InboxMessages;
|
|
156
|
+
constructor(options: InboxClientOptions);
|
|
157
|
+
/**
|
|
158
|
+
* Where a lead came from: the click-to-WhatsApp ad payloads on one contact.
|
|
159
|
+
*
|
|
160
|
+
* `ctwa.list` · scope `contacts:read`
|
|
161
|
+
*/
|
|
162
|
+
referrals(contactId: string, limit?: number): Promise<CtwaReferral[]>;
|
|
163
|
+
/**
|
|
164
|
+
* A contact's reply windows, one per channel they have written from. Read these
|
|
165
|
+
* to tell whether a free-form reply is still allowed on a channel or whether
|
|
166
|
+
* the agent has to start from a template.
|
|
167
|
+
*
|
|
168
|
+
* `chat_session.list` · scope `contacts:read`
|
|
169
|
+
*/
|
|
170
|
+
sessions(contactId: string, channel?: string): Promise<ChatSession[]>;
|
|
171
|
+
/** Round-trips the payload. Useful for checking the connection is live. */
|
|
172
|
+
ping<T>(payload: T): Promise<T>;
|
|
173
|
+
}
|