tiktok-live-api 1.2.12 → 1.2.15

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.
Files changed (2) hide show
  1. package/bin/demo.mjs +203 -9
  2. package/package.json +1 -1
package/bin/demo.mjs CHANGED
@@ -193,10 +193,12 @@ if (!isInteractive) {
193
193
  console.log(" 1) " + C.cyan + "Watch Live Terminal Demo" + R);
194
194
  console.log(" 2) " + C.green + "Scaffold a Nuxt 3 (Vue) App" + R);
195
195
  console.log(" 3) " + C.blue + "Scaffold a Next.js (React) App" + R);
196
- console.log(" 4) " + C.yellow + "Scaffold a Vite (React) App" + R + "\n");
196
+ console.log(" 4) " + C.yellow + "Scaffold a Vite (React) App" + R);
197
+ console.log(" 5) " + C.mag + "Scaffold a Plain Node.js Project" + R);
198
+ console.log(" 6) " + C.pink + "Scaffold a Python Project" + R + "\n");
197
199
 
198
200
  function promptAction() {
199
- rl.question(" Choose [1-4]: ", (answer) => {
201
+ rl.question(" Choose [1-6]: ", (answer) => {
200
202
  handleMenu(answer.trim());
201
203
  });
202
204
  }
@@ -207,7 +209,7 @@ if (!isInteractive) {
207
209
  return runDemo();
208
210
  }
209
211
 
210
- if (!['2', '3', '4'].includes(choice)) {
212
+ if (!['2', '3', '4', '5', '6'].includes(choice)) {
211
213
  console.log(" " + C.red + "Invalid choice." + R);
212
214
  return promptAction();
213
215
  }
@@ -215,6 +217,11 @@ if (!isInteractive) {
215
217
  rl.question("\n Target directory (e.g. ./my-app) [./tiktok-live-project]: ", (dir) => {
216
218
  dir = dir.trim() || './tiktok-live-project';
217
219
 
220
+ if (choice === '6') {
221
+ rl.close();
222
+ return runScaffold(choice, dir, 'pip');
223
+ }
224
+
218
225
  console.log("\n Select Package Manager:");
219
226
  console.log(" 1) npm " + D + "(Default)" + R);
220
227
  console.log(" 2) yarn");
@@ -241,6 +248,8 @@ function runScaffold(choice, targetDir, pm) {
241
248
  const isNuxt = choice === '2';
242
249
  const isNext = choice === '3';
243
250
  const isVite = choice === '4';
251
+ const isNode = choice === '5';
252
+ const isPython = choice === '6';
244
253
  const fullPath = path.resolve(process.cwd(), targetDir);
245
254
 
246
255
  const npxCmd = pm === 'bun' ? 'bunx' : (pm === 'pnpm' ? 'pnpm dlx' : 'npx');
@@ -250,7 +259,11 @@ function runScaffold(choice, targetDir, pm) {
250
259
  console.log("\n " + B + "šŸš€ Scaffolding project into " + targetDir + " using " + pm + "..." + R + "\n");
251
260
 
252
261
  try {
253
- if (isNuxt) {
262
+ if (isNode) {
263
+ if (!fs.existsSync(fullPath)) fs.mkdirSync(fullPath, { recursive: true });
264
+ } else if (isPython) {
265
+ if (!fs.existsSync(fullPath)) fs.mkdirSync(fullPath, { recursive: true });
266
+ } else if (isNuxt) {
254
267
  execSync(npxCmd + ' nuxi@latest init "' + targetDir + '" --packageManager ' + pm, { stdio: 'inherit' });
255
268
  } else if (isNext) {
256
269
  execSync(npxCmd + ' create-next-app@latest "' + targetDir + '" --js --eslint --tailwind --app --src-dir --import-alias "@/*" --use-' + pm, { stdio: 'inherit' });
@@ -259,7 +272,182 @@ function runScaffold(choice, targetDir, pm) {
259
272
  execSync(createCmd + ' "' + targetDir + '" -- --template react', { stdio: 'inherit' });
260
273
  }
261
274
 
262
- if (isNuxt) {
275
+ if (isNode) {
276
+ // ── Plain Node.js Starter Kit ──
277
+ const pkgJson = {
278
+ name: path.basename(fullPath),
279
+ version: '1.0.0',
280
+ type: 'module',
281
+ scripts: { start: 'node index.mjs', dev: 'node --watch index.mjs' },
282
+ dependencies: {}
283
+ };
284
+ fs.writeFileSync(path.join(fullPath, 'package.json'), JSON.stringify(pkgJson, null, 2) + '\n');
285
+
286
+ console.log("\n " + B + "šŸ“¦ Installing " + C.cyan + "tiktok-live-api" + B + " SDK..." + R + "\n");
287
+ execSync(installCmd, { cwd: fullPath, stdio: 'inherit' });
288
+
289
+ fs.writeFileSync(path.join(fullPath, 'index.mjs'), [
290
+ "import { TikTokLive } from 'tiktok-live-api';",
291
+ "",
292
+ "// ── Configuration ───────────────────────────────────────",
293
+ "const USERNAME = 'gbnews'; // TikTok @username",
294
+ "const API_KEY = 'demo_tiktokliveapi_public_2026'; // Get yours at https://tik.tools",
295
+ "",
296
+ "// ── Connect ─────────────────────────────────────────────",
297
+ "const client = new TikTokLive(USERNAME, { apiKey: API_KEY });",
298
+ "",
299
+ "client.on('connected', () => {",
300
+ " console.log('\\nāœ… Connected to @' + USERNAME + '\\n');",
301
+ "});",
302
+ "",
303
+ "client.on('chat', (data) => {",
304
+ " console.log(`šŸ’¬ ${data.user.uniqueId}: ${data.comment}`);",
305
+ "});",
306
+ "",
307
+ "client.on('gift', (data) => {",
308
+ " console.log(`šŸŽ ${data.user.uniqueId} sent ${data.giftName} x${data.repeatCount}`);",
309
+ "});",
310
+ "",
311
+ "client.on('like', (data) => {",
312
+ " console.log(`ā¤ļø ${data.user.uniqueId} liked (total: ${data.totalLikeCount})`);",
313
+ "});",
314
+ "",
315
+ "client.on('member', (data) => {",
316
+ " console.log(`šŸ‘‹ ${data.user.uniqueId} joined`);",
317
+ "});",
318
+ "",
319
+ "client.on('roomUserSeq', (data) => {",
320
+ " console.log(`šŸ‘€ Viewers: ${data.viewerCount}`);",
321
+ "});",
322
+ "",
323
+ "client.on('disconnected', () => {",
324
+ " console.log('\\nāŒ Disconnected\\n');",
325
+ "});",
326
+ "",
327
+ "client.on('error', (err) => {",
328
+ " console.error('āš ļø Error:', err.message);",
329
+ "});",
330
+ "",
331
+ "console.log('šŸ”„ Connecting to @' + USERNAME + '...');",
332
+ "client.connect().catch((err) => {",
333
+ " console.error('Failed to connect:', err.message);",
334
+ " process.exit(1);",
335
+ "});",
336
+ ].join('\n') + '\n');
337
+
338
+ fs.writeFileSync(path.join(fullPath, 'README.md'), [
339
+ '# TikTok Live - Node.js Starter',
340
+ '',
341
+ 'A ready-to-run Node.js project connecting to TikTok LIVE streams.',
342
+ '',
343
+ '## Quick Start',
344
+ '',
345
+ '```bash',
346
+ 'node index.mjs',
347
+ '```',
348
+ '',
349
+ '## Configuration',
350
+ '',
351
+ 'Edit `index.mjs` to change:',
352
+ '- `USERNAME` — the TikTok @username to watch',
353
+ '- `API_KEY` — get your own at [tik.tools](https://tik.tools)',
354
+ '',
355
+ '## Events',
356
+ '',
357
+ 'The demo listens for: `chat`, `gift`, `like`, `member`, `roomUserSeq`.',
358
+ 'See the [full docs](https://www.npmjs.com/package/tiktok-live-api) for all available events.',
359
+ '',
360
+ ].join('\n'));
361
+
362
+ } else if (isPython) {
363
+ // ── Python Starter Kit ──
364
+ fs.writeFileSync(path.join(fullPath, 'main.py'), [
365
+ '"""TikTok Live - Python Starter Kit"""',
366
+ '',
367
+ 'import asyncio',
368
+ 'import json',
369
+ 'import websockets',
370
+ '',
371
+ '# \u2500\u2500 Configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500',
372
+ "USERNAME = 'gbnews' # TikTok @username",
373
+ "API_KEY = 'demo_tiktokliveapi_public_2026' # Get yours at https://tik.tools",
374
+ '',
375
+ '',
376
+ 'async def main():',
377
+ ' """Connect to TikTok LIVE and print events."""',
378
+ ' uri = f"wss://api.tik.tools?uniqueId={USERNAME}&apiKey={API_KEY}"',
379
+ ' print(f"Connecting to @{USERNAME}...")',
380
+ '',
381
+ ' try:',
382
+ ' async with websockets.connect(uri) as ws:',
383
+ ' print(f"Connected to @{USERNAME}")',
384
+ ' print()',
385
+ ' async for raw in ws:',
386
+ ' try:',
387
+ " msg = json.loads(raw)",
388
+ " event = msg.get('event', '')",
389
+ " data = msg.get('data', {})",
390
+ " user = data.get('user', {}).get('uniqueId', '?')",
391
+ '',
392
+ " if event == 'chat':",
393
+ " comment = data.get('comment', '')",
394
+ ' print(f"[chat] {user}: {comment}")',
395
+ " elif event == 'gift':",
396
+ " gift = data.get('giftName', 'a gift')",
397
+ " count = data.get('repeatCount', 1)",
398
+ ' print(f"[gift] {user} sent {gift} x{count}")',
399
+ " elif event == 'like':",
400
+ " total = data.get('totalLikeCount', 0)",
401
+ ' print(f"[like] {user} liked (total: {total})")',
402
+ " elif event == 'member':",
403
+ ' print(f"[join] {user} joined")',
404
+ " elif event == 'roomUserSeq':",
405
+ " viewers = data.get('viewerCount', 0)",
406
+ ' print(f"[viewers] {viewers}")',
407
+ ' except json.JSONDecodeError:',
408
+ ' pass',
409
+ ' except KeyboardInterrupt:',
410
+ ' print("Disconnected.")',
411
+ ' except Exception as e:',
412
+ ' print(f"Error: {e}")',
413
+ '',
414
+ '',
415
+ 'if __name__ == "__main__":',
416
+ ' asyncio.run(main())',
417
+ ].join('\n') + '\n');
418
+
419
+ fs.writeFileSync(path.join(fullPath, 'requirements.txt'), 'websockets>=12.0\n');
420
+
421
+ fs.writeFileSync(path.join(fullPath, 'README.md'), [
422
+ '# TikTok Live - Python Starter',
423
+ '',
424
+ 'A ready-to-run Python project connecting to TikTok LIVE streams.',
425
+ '',
426
+ '## Quick Start',
427
+ '',
428
+ '```bash',
429
+ 'pip install -r requirements.txt',
430
+ 'python main.py',
431
+ '```',
432
+ '',
433
+ '## Configuration',
434
+ '',
435
+ 'Edit `main.py` to change:',
436
+ '- `USERNAME` — the TikTok @username to watch',
437
+ '- `API_KEY` — get your own at [tik.tools](https://tik.tools)',
438
+ '',
439
+ '## Events',
440
+ '',
441
+ 'The demo listens for: `chat`, `gift`, `like`, `member`, `roomUserSeq`.',
442
+ '',
443
+ ].join('\n'));
444
+
445
+ console.log("\n " + B + "šŸ“¦ Installing " + C.cyan + "websockets" + B + "..." + R + "\n");
446
+ try { execSync('pip install websockets', { cwd: fullPath, stdio: 'inherit' }); } catch (e) {
447
+ console.log(" " + C.yellow + "Note: run 'pip install -r requirements.txt' manually if pip failed." + R);
448
+ }
449
+
450
+ } else if (isNuxt) {
263
451
  const isNuxt4 = fs.existsSync(path.join(fullPath, 'app', 'app.vue')) || !fs.existsSync(path.join(fullPath, 'app.vue'));
264
452
  const baseApp = isNuxt4 ? path.join(fullPath, 'app') : fullPath;
265
453
 
@@ -278,7 +466,7 @@ function runScaffold(choice, targetDir, pm) {
278
466
  '</template>'
279
467
  ].join('\n') + '\n');
280
468
  } else {
281
- console.log("\\n " + B + "šŸ“¦ Installing " + C.cyan + "tiktok-live-api" + B + " SDK..." + R + "\\n");
469
+ console.log("\n " + B + "šŸ“¦ Installing " + C.cyan + "tiktok-live-api" + B + " SDK..." + R + "\n");
282
470
  execSync(installCmd, { cwd: fullPath, stdio: 'inherit' });
283
471
 
284
472
  if (isNext) {
@@ -325,10 +513,16 @@ function runScaffold(choice, targetDir, pm) {
325
513
  console.log("\n " + C.green + "āœ” Project successfully scaffolded!" + R + "\n");
326
514
  console.log(" " + B + "Next steps:" + R);
327
515
  console.log(" cd " + targetDir);
328
- if (isVite && pm !== 'bun') {
329
- console.log(" " + pm + " install");
516
+ if (isPython) {
517
+ console.log(" python main.py\n");
518
+ } else if (isNode) {
519
+ console.log(" node index.mjs\n");
520
+ } else {
521
+ if (isVite && pm !== 'bun') {
522
+ console.log(" " + pm + " install");
523
+ }
524
+ console.log(" " + devCmd + "\n");
330
525
  }
331
- console.log(" " + devCmd + "\n");
332
526
 
333
527
  } catch (err) {
334
528
  console.error("\n " + C.red + "Error during scaffolding:" + R, err.message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tiktok-live-api",
3
- "version": "1.2.12",
3
+ "version": "1.2.15",
4
4
  "description": "Unofficial TikTok LIVE API Client — Real-time chat, gifts, viewers, battles, and AI live captions from any TikTok livestream. Managed WebSocket API with 99.9% uptime.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",