botcast-sdk 1.0.6 → 1.0.8
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 +112 -95
- package/dist/admin.cjs +40 -3
- package/dist/admin.d.ts +18 -1
- package/dist/admin.d.ts.map +1 -1
- package/dist/admin.js +40 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Official Node.js and TypeScript SDK for [Botcast](https://botcast.site) — a hi
|
|
|
16
16
|
- **Strict TypeScript Types**: Fully typed request parameters, response models, error classes, and event payloads.
|
|
17
17
|
- **Dual Authentication**:
|
|
18
18
|
- **WhatsApp**: Scan QR code string or request an 8-digit PIN code without a camera.
|
|
19
|
-
- **Telegram**: Scan QR code via
|
|
19
|
+
- **Telegram**: Scan QR code via _Telegram > Settings > Devices > Link Desktop Device_ or authenticate via phone verification code with optional Cloud 2FA password.
|
|
20
20
|
- **Unified Messaging**: Send text messages, automated OTP codes, images, videos, audio, voice notes (PTT), documents, stickers, locations, contact cards, and interactive polls.
|
|
21
21
|
- **Message Operations**: Edit sent messages, delete for everyone (revoke), mark as read, reactions, pin messages, and forward.
|
|
22
22
|
- **Chat & History Management**: Query dialogs, contact lists, and message history for both platforms.
|
|
@@ -46,10 +46,10 @@ bun add botcast-sdk
|
|
|
46
46
|
Use `BotcastAdminClient` with your Master Partner API Key (`bcast_live_...`) to programmatically create and manage customer instances:
|
|
47
47
|
|
|
48
48
|
```typescript
|
|
49
|
-
import { BotcastAdminClient } from
|
|
49
|
+
import { BotcastAdminClient } from "botcast-sdk";
|
|
50
50
|
|
|
51
51
|
const admin = new BotcastAdminClient({
|
|
52
|
-
baseUrl:
|
|
52
|
+
baseUrl: "https://botcast.site",
|
|
53
53
|
apiKey: process.env.BOTCAST_API_KEY!, // Master API Key
|
|
54
54
|
});
|
|
55
55
|
|
|
@@ -58,14 +58,16 @@ const { instances } = await admin.listInstances();
|
|
|
58
58
|
|
|
59
59
|
// Create a new WhatsApp or Telegram instance for a customer
|
|
60
60
|
const { instance } = await admin.createInstance({
|
|
61
|
-
name:
|
|
62
|
-
platform:
|
|
63
|
-
type:
|
|
61
|
+
name: "Customer Store 1",
|
|
62
|
+
platform: "whatsapp",
|
|
63
|
+
type: "paid",
|
|
64
64
|
plan_months: 12,
|
|
65
|
+
expires_at: "2027-12-31T23:59:59.000Z", // Optional exact expiration date
|
|
65
66
|
});
|
|
66
67
|
|
|
67
|
-
// Renew subscription
|
|
68
|
+
// Renew subscription (by months or exact date)
|
|
68
69
|
await admin.renewInstance(instance.id, { months: 12 });
|
|
70
|
+
// or: await admin.setExpiration(instance.id, "2028-06-30T23:59:59.000Z");
|
|
69
71
|
```
|
|
70
72
|
|
|
71
73
|
---
|
|
@@ -73,30 +75,35 @@ await admin.renewInstance(instance.id, { months: 12 });
|
|
|
73
75
|
### 2. WhatsApp Client
|
|
74
76
|
|
|
75
77
|
```typescript
|
|
76
|
-
import { BotcastClient } from
|
|
78
|
+
import { BotcastClient } from "botcast-sdk";
|
|
77
79
|
|
|
78
80
|
const whatsappBot = new BotcastClient({
|
|
79
|
-
baseUrl:
|
|
80
|
-
platform:
|
|
81
|
-
instanceId:
|
|
82
|
-
instanceToken:
|
|
81
|
+
baseUrl: "https://botcast.site", // or your self-hosted server URL
|
|
82
|
+
platform: "whatsapp", // 'whatsapp' (default) or 'telegram'
|
|
83
|
+
instanceId: "your_instance_id",
|
|
84
|
+
instanceToken: "your_instance_token",
|
|
83
85
|
});
|
|
84
86
|
|
|
85
87
|
async function main() {
|
|
86
88
|
// Check connectivity
|
|
87
89
|
const status = await whatsappBot.getStatus();
|
|
88
|
-
console.log(
|
|
90
|
+
console.log(
|
|
91
|
+
`WhatsApp state: ${status.status} (${status.phoneNumber || "Unpaired"})`,
|
|
92
|
+
);
|
|
89
93
|
|
|
90
94
|
// Send a text message
|
|
91
|
-
const res = await whatsappBot.messages.sendText(
|
|
92
|
-
|
|
95
|
+
const res = await whatsappBot.messages.sendText(
|
|
96
|
+
"201012345678",
|
|
97
|
+
"Hello from WhatsApp via Botcast SDK!",
|
|
98
|
+
);
|
|
99
|
+
console.log("Message sent! ID:", res.messageId);
|
|
93
100
|
|
|
94
101
|
// Send a secure 6-digit OTP code
|
|
95
|
-
const otp = await whatsappBot.messages.sendOTP(
|
|
96
|
-
appName:
|
|
102
|
+
const otp = await whatsappBot.messages.sendOTP("201012345678", {
|
|
103
|
+
appName: "My App",
|
|
97
104
|
expiryMinutes: 5,
|
|
98
105
|
});
|
|
99
|
-
console.log(
|
|
106
|
+
console.log("Dispatched OTP:", otp.codeSent);
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
main().catch(console.error);
|
|
@@ -107,13 +114,13 @@ main().catch(console.error);
|
|
|
107
114
|
### 2. Telegram MTProto Client
|
|
108
115
|
|
|
109
116
|
```typescript
|
|
110
|
-
import { BotcastClient } from
|
|
117
|
+
import { BotcastClient } from "botcast-sdk";
|
|
111
118
|
|
|
112
119
|
const telegramBot = new BotcastClient({
|
|
113
|
-
baseUrl:
|
|
114
|
-
platform:
|
|
115
|
-
instanceId:
|
|
116
|
-
instanceToken:
|
|
120
|
+
baseUrl: "https://botcast.site",
|
|
121
|
+
platform: "telegram",
|
|
122
|
+
instanceId: "your_telegram_instance_id",
|
|
123
|
+
instanceToken: "your_telegram_instance_token",
|
|
117
124
|
});
|
|
118
125
|
|
|
119
126
|
async function main() {
|
|
@@ -122,20 +129,23 @@ async function main() {
|
|
|
122
129
|
console.log(`Telegram state: ${status.status}`);
|
|
123
130
|
|
|
124
131
|
// Send a text message to a phone number or @username
|
|
125
|
-
const res = await telegramBot.messages.sendText(
|
|
126
|
-
|
|
132
|
+
const res = await telegramBot.messages.sendText(
|
|
133
|
+
"+1234567890",
|
|
134
|
+
"Hello from Telegram MTProto!",
|
|
135
|
+
);
|
|
136
|
+
console.log("Message ID:", res.messageId);
|
|
127
137
|
|
|
128
138
|
// Send a photo
|
|
129
|
-
await telegramBot.messages.sendImage(
|
|
130
|
-
url:
|
|
131
|
-
caption:
|
|
139
|
+
await telegramBot.messages.sendImage("+1234567890", {
|
|
140
|
+
url: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=800",
|
|
141
|
+
caption: "Welcome flyer",
|
|
132
142
|
});
|
|
133
143
|
|
|
134
144
|
// Send OTP
|
|
135
|
-
const otp = await telegramBot.messages.sendOTP(
|
|
136
|
-
appName:
|
|
145
|
+
const otp = await telegramBot.messages.sendOTP("+1234567890", {
|
|
146
|
+
appName: "Security Portal",
|
|
137
147
|
});
|
|
138
|
-
console.log(
|
|
148
|
+
console.log("Telegram OTP sent:", otp.codeSent);
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
main().catch(console.error);
|
|
@@ -146,12 +156,12 @@ main().catch(console.error);
|
|
|
146
156
|
### CommonJS (require)
|
|
147
157
|
|
|
148
158
|
```javascript
|
|
149
|
-
const { BotcastClient } = require(
|
|
159
|
+
const { BotcastClient } = require("botcast-sdk");
|
|
150
160
|
|
|
151
161
|
const client = new BotcastClient({
|
|
152
|
-
platform:
|
|
153
|
-
instanceId:
|
|
154
|
-
instanceToken:
|
|
162
|
+
platform: "telegram", // or 'whatsapp'
|
|
163
|
+
instanceId: "your_instance_id",
|
|
164
|
+
instanceToken: "your_instance_token",
|
|
155
165
|
});
|
|
156
166
|
```
|
|
157
167
|
|
|
@@ -164,24 +174,24 @@ const client = new BotcastClient({
|
|
|
164
174
|
```typescript
|
|
165
175
|
// 1. Get live status
|
|
166
176
|
const status = await client.instances.getStatus();
|
|
167
|
-
console.log(
|
|
177
|
+
console.log("State:", status.status); // 'connected' | 'qr_ready' | 'stopped' | 'connecting'
|
|
168
178
|
|
|
169
179
|
// 2. Option A: Get QR code string for camera scanning
|
|
170
180
|
// (WhatsApp: Linked Devices | Telegram: Settings > Devices > Link Desktop Device)
|
|
171
181
|
const qr = await client.getQR(); // or client.instances.getQR()
|
|
172
|
-
console.log(
|
|
182
|
+
console.log("QR DataURL:", qr.qr);
|
|
173
183
|
|
|
174
184
|
// 3. Option B: Request Phone Pairing / Login Code
|
|
175
185
|
// (WhatsApp sends 8-digit PIN | Telegram sends verification code into app)
|
|
176
|
-
const pair = await client.pairWithCode(
|
|
177
|
-
console.log(
|
|
186
|
+
const pair = await client.pairWithCode("+1234567890");
|
|
187
|
+
console.log("Code request status:", pair);
|
|
178
188
|
|
|
179
189
|
// 4. Complete Telegram Phone Login (with optional 2FA cloud password)
|
|
180
|
-
await client.instances.verifyCode(
|
|
190
|
+
await client.instances.verifyCode("+1234567890", "12345", "myCloudPassword2fa");
|
|
181
191
|
|
|
182
192
|
// 5. Socket engine controls
|
|
183
|
-
await client.instances.start();
|
|
184
|
-
await client.instances.stop();
|
|
193
|
+
await client.instances.start(); // Boots socket / MTProto connection
|
|
194
|
+
await client.instances.stop(); // Suspends socket session
|
|
185
195
|
await client.instances.logout(); // Unlinks device and clears session credentials
|
|
186
196
|
```
|
|
187
197
|
|
|
@@ -193,51 +203,51 @@ All messaging methods work across both **WhatsApp** and **Telegram**:
|
|
|
193
203
|
|
|
194
204
|
```typescript
|
|
195
205
|
// 1. Text message
|
|
196
|
-
await client.messages.sendText(
|
|
197
|
-
mentions: [
|
|
206
|
+
await client.messages.sendText("+1234567890", "Hello World", {
|
|
207
|
+
mentions: ["1234567890"], // WhatsApp mentions
|
|
198
208
|
});
|
|
199
209
|
|
|
200
210
|
// 2. Image / Photo
|
|
201
|
-
await client.messages.sendImage(
|
|
202
|
-
url:
|
|
203
|
-
caption:
|
|
211
|
+
await client.messages.sendImage("+1234567890", {
|
|
212
|
+
url: "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?w=800",
|
|
213
|
+
caption: "Photo preview",
|
|
204
214
|
});
|
|
205
215
|
|
|
206
216
|
// 3. Video
|
|
207
|
-
await client.messages.sendVideo(
|
|
208
|
-
url:
|
|
209
|
-
caption:
|
|
217
|
+
await client.messages.sendVideo("+1234567890", {
|
|
218
|
+
url: "https://sample-videos.com/video321/mp4/720/big_buck_bunny_720p_1mb.mp4",
|
|
219
|
+
caption: "Product tutorial video",
|
|
210
220
|
});
|
|
211
221
|
|
|
212
222
|
// 4. Voice note and audio
|
|
213
|
-
await client.messages.sendVoice(
|
|
214
|
-
url:
|
|
223
|
+
await client.messages.sendVoice("+1234567890", {
|
|
224
|
+
url: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
|
|
215
225
|
});
|
|
216
226
|
|
|
217
227
|
// 5. Document / PDF / File
|
|
218
|
-
await client.messages.sendDocument(
|
|
219
|
-
url:
|
|
220
|
-
fileName:
|
|
221
|
-
caption:
|
|
228
|
+
await client.messages.sendDocument("+1234567890", {
|
|
229
|
+
url: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
|
|
230
|
+
fileName: "Invoice_2026.pdf",
|
|
231
|
+
caption: "Monthly invoice statement",
|
|
222
232
|
});
|
|
223
233
|
|
|
224
234
|
// 6. Location coordinates
|
|
225
|
-
await client.messages.sendLocation(
|
|
235
|
+
await client.messages.sendLocation("+1234567890", {
|
|
226
236
|
latitude: 24.7136,
|
|
227
237
|
longitude: 46.6753,
|
|
228
|
-
name:
|
|
229
|
-
address:
|
|
238
|
+
name: "Kingdom Tower",
|
|
239
|
+
address: "King Fahd Rd, Riyadh, Saudi Arabia",
|
|
230
240
|
});
|
|
231
241
|
|
|
232
242
|
// 7. Contact Card
|
|
233
|
-
await client.messages.sendContact(
|
|
234
|
-
firstName:
|
|
235
|
-
phone:
|
|
243
|
+
await client.messages.sendContact("+1234567890", {
|
|
244
|
+
firstName: "Support Agent",
|
|
245
|
+
phone: "+1234567890",
|
|
236
246
|
});
|
|
237
247
|
|
|
238
248
|
// 8. Automated OTP verification code
|
|
239
|
-
const otp = await client.messages.sendOTP(
|
|
240
|
-
appName:
|
|
249
|
+
const otp = await client.messages.sendOTP("+1234567890", {
|
|
250
|
+
appName: "Botcast Portal",
|
|
241
251
|
expiryMinutes: 5,
|
|
242
252
|
});
|
|
243
253
|
```
|
|
@@ -248,28 +258,30 @@ const otp = await client.messages.sendOTP('+1234567890', {
|
|
|
248
258
|
|
|
249
259
|
```typescript
|
|
250
260
|
const msgKey = {
|
|
251
|
-
remoteJid:
|
|
261
|
+
remoteJid: "201012345678@s.whatsapp.net",
|
|
252
262
|
fromMe: true,
|
|
253
|
-
id:
|
|
263
|
+
id: "3EB0ABCDEF1234567890",
|
|
254
264
|
};
|
|
255
265
|
|
|
256
266
|
// 1. Edit sent message
|
|
257
|
-
await client.messages.edit(
|
|
267
|
+
await client.messages.edit("201012345678", msgKey, "Corrected text content");
|
|
258
268
|
|
|
259
269
|
// 2. Delete message for everyone (revoke)
|
|
260
|
-
await client.messages.delete(
|
|
270
|
+
await client.messages.delete("201012345678", msgKey);
|
|
261
271
|
|
|
262
272
|
// 3. Mark message as read
|
|
263
273
|
await client.messages.markAsRead(msgKey);
|
|
264
274
|
|
|
265
275
|
// 4. Emoji reaction
|
|
266
|
-
await client.messages.react(
|
|
276
|
+
await client.messages.react("201012345678", msgKey, "👍");
|
|
267
277
|
|
|
268
278
|
// 5. Pin message
|
|
269
|
-
await client.messages.pin(
|
|
279
|
+
await client.messages.pin("201012345678", msgKey, 1, 86400);
|
|
270
280
|
|
|
271
281
|
// 6. Forward message
|
|
272
|
-
await client.messages.forward(
|
|
282
|
+
await client.messages.forward("201012345678", {
|
|
283
|
+
conversation: "Forwarded message text",
|
|
284
|
+
});
|
|
273
285
|
```
|
|
274
286
|
|
|
275
287
|
---
|
|
@@ -284,12 +296,15 @@ const { chats } = await client.chats.list({ limit: 50 });
|
|
|
284
296
|
const { contacts } = await client.chats.listContacts({ limit: 100 });
|
|
285
297
|
|
|
286
298
|
// 3. List messages for a chat
|
|
287
|
-
const { messages } = await client.chats.listMessages({
|
|
299
|
+
const { messages } = await client.chats.listMessages({
|
|
300
|
+
chatJid: "201012345678@s.whatsapp.net",
|
|
301
|
+
limit: 50,
|
|
302
|
+
});
|
|
288
303
|
|
|
289
304
|
// 4. Modify WhatsApp chat state (archive, mute, pin, delete)
|
|
290
|
-
await client.chats.archive(
|
|
291
|
-
await client.chats.mute(
|
|
292
|
-
await client.chats.pin(
|
|
305
|
+
await client.chats.archive("201012345678@s.whatsapp.net");
|
|
306
|
+
await client.chats.mute("201012345678@s.whatsapp.net", 8 * 60 * 60 * 1000); // 8 hours
|
|
307
|
+
await client.chats.pin("201012345678@s.whatsapp.net");
|
|
293
308
|
```
|
|
294
309
|
|
|
295
310
|
---
|
|
@@ -301,24 +316,26 @@ The SDK includes a built-in event dispatcher and middleware for handling inbound
|
|
|
301
316
|
#### Express Example
|
|
302
317
|
|
|
303
318
|
```typescript
|
|
304
|
-
import express from
|
|
305
|
-
import { BotcastClient } from
|
|
319
|
+
import express from "express";
|
|
320
|
+
import { BotcastClient } from "botcast-sdk";
|
|
306
321
|
|
|
307
322
|
const app = express();
|
|
308
323
|
app.use(express.json());
|
|
309
324
|
|
|
310
325
|
const client = new BotcastClient({
|
|
311
|
-
platform:
|
|
312
|
-
instanceId:
|
|
313
|
-
instanceToken:
|
|
326
|
+
platform: "telegram", // or 'whatsapp'
|
|
327
|
+
instanceId: "inst_123",
|
|
328
|
+
instanceToken: "tok_abc",
|
|
314
329
|
});
|
|
315
330
|
|
|
316
331
|
// Listen for incoming messages
|
|
317
332
|
client.webhook.onMessage(async (event) => {
|
|
318
|
-
console.log(
|
|
333
|
+
console.log(
|
|
334
|
+
`Message from ${event.sender}: ${event.message} [Platform: ${event.platform || "whatsapp"}]`,
|
|
335
|
+
);
|
|
319
336
|
|
|
320
|
-
if (event.message.trim().toLowerCase() ===
|
|
321
|
-
await client.messages.sendText(event.sender,
|
|
337
|
+
if (event.message.trim().toLowerCase() === "ping") {
|
|
338
|
+
await client.messages.sendText(event.sender, "pong");
|
|
322
339
|
}
|
|
323
340
|
});
|
|
324
341
|
|
|
@@ -328,9 +345,9 @@ client.webhook.onConnection(async (event) => {
|
|
|
328
345
|
});
|
|
329
346
|
|
|
330
347
|
// Mount middleware on your webhook route
|
|
331
|
-
app.post(
|
|
348
|
+
app.post("/webhook/botcast", client.webhook.middleware());
|
|
332
349
|
|
|
333
|
-
app.listen(3000, () => console.log(
|
|
350
|
+
app.listen(3000, () => console.log("Webhook server running on port 3000"));
|
|
334
351
|
```
|
|
335
352
|
|
|
336
353
|
---
|
|
@@ -348,25 +365,25 @@ import {
|
|
|
348
365
|
BotcastRateLimitError,
|
|
349
366
|
BotcastValidationError,
|
|
350
367
|
BotcastNotFoundError,
|
|
351
|
-
} from
|
|
368
|
+
} from "botcast-sdk";
|
|
352
369
|
|
|
353
370
|
try {
|
|
354
|
-
await client.messages.sendText(
|
|
371
|
+
await client.messages.sendText("+1234567890", "Hello World");
|
|
355
372
|
} catch (error) {
|
|
356
373
|
if (error instanceof BotcastAuthError) {
|
|
357
|
-
console.error(
|
|
374
|
+
console.error("Invalid instance credentials or token.");
|
|
358
375
|
} else if (error instanceof BotcastPaymentRequiredError) {
|
|
359
|
-
console.error(
|
|
376
|
+
console.error("Instance requires payment confirmation.");
|
|
360
377
|
} else if (error instanceof BotcastSubscriptionExpiredError) {
|
|
361
|
-
console.error(
|
|
378
|
+
console.error("Subscription expired on:", error.expiresAt);
|
|
362
379
|
} else if (error instanceof BotcastRateLimitError) {
|
|
363
|
-
console.error(
|
|
380
|
+
console.error("Daily message limit reached.");
|
|
364
381
|
} else if (error instanceof BotcastValidationError) {
|
|
365
|
-
console.error(
|
|
382
|
+
console.error("Validation error:", error.message, error.details);
|
|
366
383
|
} else if (error instanceof BotcastNotFoundError) {
|
|
367
|
-
console.error(
|
|
384
|
+
console.error("Resource not found:", error.message);
|
|
368
385
|
} else {
|
|
369
|
-
console.error(
|
|
386
|
+
console.error("Unexpected error:", error);
|
|
370
387
|
}
|
|
371
388
|
}
|
|
372
389
|
```
|
|
@@ -378,7 +395,7 @@ try {
|
|
|
378
395
|
- Website: [https://botcast.site](https://botcast.site)
|
|
379
396
|
- Documentation: [https://botcast.site/docs](https://botcast.site/docs)
|
|
380
397
|
- NPM Package: [https://www.npmjs.com/package/botcast-sdk](https://www.npmjs.com/package/botcast-sdk)
|
|
381
|
-
- GitHub Repository: [https://github.com/
|
|
398
|
+
- GitHub Repository: [https://github.com/alsasoft-web/Botcast](https://github.com/alsasoft-web/Botcast)
|
|
382
399
|
|
|
383
400
|
---
|
|
384
401
|
|
package/dist/admin.cjs
CHANGED
|
@@ -65,6 +65,12 @@ class BotcastAdminClient {
|
|
|
65
65
|
* Admins are zero-payment, so instances are provisioned as active paid instances.
|
|
66
66
|
*/
|
|
67
67
|
async createInstance(options) {
|
|
68
|
+
const rawExp = options.expires_at || options.expiresAt;
|
|
69
|
+
const expires_at = rawExp
|
|
70
|
+
? rawExp instanceof Date
|
|
71
|
+
? rawExp.toISOString()
|
|
72
|
+
: new Date(rawExp).toISOString()
|
|
73
|
+
: undefined;
|
|
68
74
|
return this.request('/api/instances', {
|
|
69
75
|
method: 'POST',
|
|
70
76
|
body: JSON.stringify({
|
|
@@ -75,29 +81,60 @@ class BotcastAdminClient {
|
|
|
75
81
|
allowed_numbers: options.allowed_numbers || [],
|
|
76
82
|
webhook_url: options.webhook_url || '',
|
|
77
83
|
target_user_id: options.target_user_id,
|
|
84
|
+
expires_at,
|
|
78
85
|
}),
|
|
79
86
|
});
|
|
80
87
|
}
|
|
81
88
|
/**
|
|
82
89
|
* Programmatically renews an instance's subscription without payment transactions.
|
|
90
|
+
* Supports either extending by months or setting an exact expiration date.
|
|
83
91
|
*/
|
|
84
92
|
async renewInstance(instanceId, options) {
|
|
93
|
+
const rawExp = options?.expires_at || options?.expiresAt;
|
|
94
|
+
const expires_at = rawExp
|
|
95
|
+
? rawExp instanceof Date
|
|
96
|
+
? rawExp.toISOString()
|
|
97
|
+
: new Date(rawExp).toISOString()
|
|
98
|
+
: undefined;
|
|
85
99
|
return this.request(`/api/instances/${instanceId}/renew`, {
|
|
86
100
|
method: 'POST',
|
|
87
101
|
body: JSON.stringify({
|
|
88
|
-
months: options?.months || options?.plan_months || 12,
|
|
102
|
+
months: options?.months || options?.plan_months || (expires_at ? undefined : 12),
|
|
103
|
+
expires_at,
|
|
89
104
|
}),
|
|
90
105
|
});
|
|
91
106
|
}
|
|
92
107
|
/**
|
|
93
|
-
* Updates instance configuration (name, webhook URL, allowed recipient numbers).
|
|
108
|
+
* Updates instance configuration (name, webhook URL, allowed recipient numbers, expiration date).
|
|
94
109
|
*/
|
|
95
110
|
async updateInstance(instanceId, updates) {
|
|
111
|
+
const rawExp = updates.expires_at !== undefined ? updates.expires_at : updates.expiresAt;
|
|
112
|
+
let expires_at = undefined;
|
|
113
|
+
if (rawExp !== undefined) {
|
|
114
|
+
if (rawExp === null) {
|
|
115
|
+
expires_at = null;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
expires_at = rawExp instanceof Date ? rawExp.toISOString() : new Date(rawExp).toISOString();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
96
121
|
return this.request(`/api/instances/${instanceId}`, {
|
|
97
122
|
method: 'PUT',
|
|
98
|
-
body: JSON.stringify(
|
|
123
|
+
body: JSON.stringify({
|
|
124
|
+
...updates,
|
|
125
|
+
expires_at,
|
|
126
|
+
}),
|
|
99
127
|
});
|
|
100
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Directly sets or clears the exact expiration date for an instance.
|
|
131
|
+
*
|
|
132
|
+
* @param instanceId Target instance ID (e.g. `ins_paid_...`)
|
|
133
|
+
* @param expiresAt Date instance, ISO string (e.g. `2027-01-01T00:00:00.000Z`), or `null` to remove expiry.
|
|
134
|
+
*/
|
|
135
|
+
async setExpiration(instanceId, expiresAt) {
|
|
136
|
+
return this.updateInstance(instanceId, { expires_at: expiresAt });
|
|
137
|
+
}
|
|
101
138
|
/**
|
|
102
139
|
* Regenerates secret instance token for an instance.
|
|
103
140
|
*/
|
package/dist/admin.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface CreateAdminInstanceOptions {
|
|
|
12
12
|
allowed_numbers?: string[];
|
|
13
13
|
webhook_url?: string;
|
|
14
14
|
target_user_id?: number;
|
|
15
|
+
expires_at?: string | Date;
|
|
16
|
+
expiresAt?: string | Date;
|
|
15
17
|
}
|
|
16
18
|
export interface AdminInstanceRecord {
|
|
17
19
|
id: string;
|
|
@@ -59,26 +61,41 @@ export declare class BotcastAdminClient {
|
|
|
59
61
|
}>;
|
|
60
62
|
/**
|
|
61
63
|
* Programmatically renews an instance's subscription without payment transactions.
|
|
64
|
+
* Supports either extending by months or setting an exact expiration date.
|
|
62
65
|
*/
|
|
63
66
|
renewInstance(instanceId: string, options?: {
|
|
64
67
|
months?: number;
|
|
65
68
|
plan_months?: number;
|
|
69
|
+
expires_at?: string | Date;
|
|
70
|
+
expiresAt?: string | Date;
|
|
66
71
|
}): Promise<{
|
|
67
72
|
success: boolean;
|
|
68
73
|
message: string;
|
|
69
74
|
instance: AdminInstanceRecord;
|
|
70
75
|
}>;
|
|
71
76
|
/**
|
|
72
|
-
* Updates instance configuration (name, webhook URL, allowed recipient numbers).
|
|
77
|
+
* Updates instance configuration (name, webhook URL, allowed recipient numbers, expiration date).
|
|
73
78
|
*/
|
|
74
79
|
updateInstance(instanceId: string, updates: {
|
|
75
80
|
name?: string;
|
|
76
81
|
webhook_url?: string;
|
|
77
82
|
allowed_numbers?: string[];
|
|
83
|
+
expires_at?: string | Date | null;
|
|
84
|
+
expiresAt?: string | Date | null;
|
|
78
85
|
}): Promise<{
|
|
79
86
|
message: string;
|
|
80
87
|
instance: AdminInstanceRecord;
|
|
81
88
|
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Directly sets or clears the exact expiration date for an instance.
|
|
91
|
+
*
|
|
92
|
+
* @param instanceId Target instance ID (e.g. `ins_paid_...`)
|
|
93
|
+
* @param expiresAt Date instance, ISO string (e.g. `2027-01-01T00:00:00.000Z`), or `null` to remove expiry.
|
|
94
|
+
*/
|
|
95
|
+
setExpiration(instanceId: string, expiresAt: string | Date | null): Promise<{
|
|
96
|
+
message: string;
|
|
97
|
+
instance: AdminInstanceRecord;
|
|
98
|
+
}>;
|
|
82
99
|
/**
|
|
83
100
|
* Regenerates secret instance token for an instance.
|
|
84
101
|
*/
|
package/dist/admin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/admin.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../src/admin.ts"],"names":[],"mappings":"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"}
|
package/dist/admin.js
CHANGED
|
@@ -62,6 +62,12 @@ export class BotcastAdminClient {
|
|
|
62
62
|
* Admins are zero-payment, so instances are provisioned as active paid instances.
|
|
63
63
|
*/
|
|
64
64
|
async createInstance(options) {
|
|
65
|
+
const rawExp = options.expires_at || options.expiresAt;
|
|
66
|
+
const expires_at = rawExp
|
|
67
|
+
? rawExp instanceof Date
|
|
68
|
+
? rawExp.toISOString()
|
|
69
|
+
: new Date(rawExp).toISOString()
|
|
70
|
+
: undefined;
|
|
65
71
|
return this.request('/api/instances', {
|
|
66
72
|
method: 'POST',
|
|
67
73
|
body: JSON.stringify({
|
|
@@ -72,29 +78,60 @@ export class BotcastAdminClient {
|
|
|
72
78
|
allowed_numbers: options.allowed_numbers || [],
|
|
73
79
|
webhook_url: options.webhook_url || '',
|
|
74
80
|
target_user_id: options.target_user_id,
|
|
81
|
+
expires_at,
|
|
75
82
|
}),
|
|
76
83
|
});
|
|
77
84
|
}
|
|
78
85
|
/**
|
|
79
86
|
* Programmatically renews an instance's subscription without payment transactions.
|
|
87
|
+
* Supports either extending by months or setting an exact expiration date.
|
|
80
88
|
*/
|
|
81
89
|
async renewInstance(instanceId, options) {
|
|
90
|
+
const rawExp = options?.expires_at || options?.expiresAt;
|
|
91
|
+
const expires_at = rawExp
|
|
92
|
+
? rawExp instanceof Date
|
|
93
|
+
? rawExp.toISOString()
|
|
94
|
+
: new Date(rawExp).toISOString()
|
|
95
|
+
: undefined;
|
|
82
96
|
return this.request(`/api/instances/${instanceId}/renew`, {
|
|
83
97
|
method: 'POST',
|
|
84
98
|
body: JSON.stringify({
|
|
85
|
-
months: options?.months || options?.plan_months || 12,
|
|
99
|
+
months: options?.months || options?.plan_months || (expires_at ? undefined : 12),
|
|
100
|
+
expires_at,
|
|
86
101
|
}),
|
|
87
102
|
});
|
|
88
103
|
}
|
|
89
104
|
/**
|
|
90
|
-
* Updates instance configuration (name, webhook URL, allowed recipient numbers).
|
|
105
|
+
* Updates instance configuration (name, webhook URL, allowed recipient numbers, expiration date).
|
|
91
106
|
*/
|
|
92
107
|
async updateInstance(instanceId, updates) {
|
|
108
|
+
const rawExp = updates.expires_at !== undefined ? updates.expires_at : updates.expiresAt;
|
|
109
|
+
let expires_at = undefined;
|
|
110
|
+
if (rawExp !== undefined) {
|
|
111
|
+
if (rawExp === null) {
|
|
112
|
+
expires_at = null;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
expires_at = rawExp instanceof Date ? rawExp.toISOString() : new Date(rawExp).toISOString();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
93
118
|
return this.request(`/api/instances/${instanceId}`, {
|
|
94
119
|
method: 'PUT',
|
|
95
|
-
body: JSON.stringify(
|
|
120
|
+
body: JSON.stringify({
|
|
121
|
+
...updates,
|
|
122
|
+
expires_at,
|
|
123
|
+
}),
|
|
96
124
|
});
|
|
97
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Directly sets or clears the exact expiration date for an instance.
|
|
128
|
+
*
|
|
129
|
+
* @param instanceId Target instance ID (e.g. `ins_paid_...`)
|
|
130
|
+
* @param expiresAt Date instance, ISO string (e.g. `2027-01-01T00:00:00.000Z`), or `null` to remove expiry.
|
|
131
|
+
*/
|
|
132
|
+
async setExpiration(instanceId, expiresAt) {
|
|
133
|
+
return this.updateInstance(instanceId, { expires_at: expiresAt });
|
|
134
|
+
}
|
|
98
135
|
/**
|
|
99
136
|
* Regenerates secret instance token for an instance.
|
|
100
137
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botcast-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Official TypeScript/JavaScript SDK for Botcast WhatsApp & Telegram MTProto Multi-Instance API Gateway",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"homepage": "https://botcast.site",
|
|
52
52
|
"repository": {
|
|
53
53
|
"type": "git",
|
|
54
|
-
"url": "git+https://github.com/
|
|
54
|
+
"url": "git+https://github.com/alsasoft-web/botcast-sdk.git",
|
|
55
55
|
"directory": "packages/botcast-sdk"
|
|
56
56
|
},
|
|
57
57
|
"bugs": {
|