koishi-plugin-aka-ai-generator 0.7.7 → 0.7.10

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/lib/index.js CHANGED
@@ -1185,7 +1185,9 @@ var UserManager = class {
1185
1185
  usersCache = null;
1186
1186
  pendingVideoCache = null;
1187
1187
  activeTasks = /* @__PURE__ */ new Map();
1188
- // userId -> requestId
1188
+ // userId -> requestId (图像任务锁)
1189
+ activeVideoTasks = /* @__PURE__ */ new Map();
1190
+ // userId -> requestId (视频任务锁,独立于图像任务)
1189
1191
  rateLimitMap = /* @__PURE__ */ new Map();
1190
1192
  // userId -> timestamps
1191
1193
  securityBlockMap = /* @__PURE__ */ new Map();
@@ -1204,6 +1206,7 @@ var UserManager = class {
1204
1206
  }
1205
1207
  }
1206
1208
  // --- 任务管理 ---
1209
+ // 图像任务锁(原有逻辑保持不变)
1207
1210
  startTask(userId) {
1208
1211
  if (this.activeTasks.has(userId)) return false;
1209
1212
  this.activeTasks.set(userId, "processing");
@@ -1215,6 +1218,18 @@ var UserManager = class {
1215
1218
  isTaskActive(userId) {
1216
1219
  return this.activeTasks.has(userId);
1217
1220
  }
1221
+ // 视频任务锁(独立于图像任务,不影响图像生成)
1222
+ startVideoTask(userId) {
1223
+ if (this.activeVideoTasks.has(userId)) return false;
1224
+ this.activeVideoTasks.set(userId, "processing");
1225
+ return true;
1226
+ }
1227
+ endVideoTask(userId) {
1228
+ this.activeVideoTasks.delete(userId);
1229
+ }
1230
+ isVideoTaskActive(userId) {
1231
+ return this.activeVideoTasks.has(userId);
1232
+ }
1218
1233
  // --- 权限管理 ---
1219
1234
  isAdmin(userId, config) {
1220
1235
  return config.adminUsers && config.adminUsers.includes(userId);
@@ -1349,6 +1364,49 @@ var UserManager = class {
1349
1364
  });
1350
1365
  return tasks[0] || null;
1351
1366
  }
1367
+ /**
1368
+ * 统计某个用户未扣费的待结算视频任务数量
1369
+ */
1370
+ async countPendingVideoTasksForUser(userId) {
1371
+ const data = await this.loadPendingVideoTasks();
1372
+ return Object.values(data.tasks).filter((t) => t.userId === userId && !t.charged).length;
1373
+ }
1374
+ /**
1375
+ * 列出某个用户所有未扣费的待结算视频任务
1376
+ */
1377
+ async listPendingVideoTasksForUser(userId) {
1378
+ const data = await this.loadPendingVideoTasks();
1379
+ return Object.values(data.tasks).filter((t) => t.userId === userId && !t.charged).sort((a, b) => {
1380
+ const ta = Date.parse(a.createdAt || "") || 0;
1381
+ const tb = Date.parse(b.createdAt || "") || 0;
1382
+ return tb - ta;
1383
+ });
1384
+ }
1385
+ /**
1386
+ * 添加待结算视频任务,并检查上限(默认max=1)
1387
+ * @returns {Promise<{success: boolean, message?: string}>} 成功返回 {success: true},失败返回 {success: false, message: '错误信息'}
1388
+ */
1389
+ async addPendingVideoTaskWithLimit(task, max = 1) {
1390
+ await this.loadPendingVideoTasks();
1391
+ return await this.pendingLock.acquire(async () => {
1392
+ if (!this.pendingVideoCache) {
1393
+ this.pendingVideoCache = { version: "1.0.0", lastUpdate: (/* @__PURE__ */ new Date()).toISOString(), tasks: {} };
1394
+ }
1395
+ const currentCount = Object.values(this.pendingVideoCache.tasks).filter((t) => t.userId === task.userId && !t.charged).length;
1396
+ if (currentCount >= max) {
1397
+ return {
1398
+ success: false,
1399
+ message: `您当前已有 ${currentCount} 个视频正在生成中(最多允许 ${max} 个),请先使用"查询视频"查看进度或等待完成`
1400
+ };
1401
+ }
1402
+ if (this.pendingVideoCache.tasks[task.taskId]) {
1403
+ return { success: true };
1404
+ }
1405
+ this.pendingVideoCache.tasks[task.taskId] = task;
1406
+ await this.savePendingVideoTasksInternal();
1407
+ return { success: true };
1408
+ });
1409
+ }
1352
1410
  // 获取特定用户数据
1353
1411
  async getUserData(userId, userName) {
1354
1412
  await this.loadUsersData();
@@ -2339,8 +2397,8 @@ ${infoParts.join("\n")}`;
2339
2397
  if (!limitCheck.allowed) {
2340
2398
  return limitCheck.message;
2341
2399
  }
2342
- if (!userManager.startTask(userId)) {
2343
- return "您有一个任务正在进行中,请等待完成";
2400
+ if (!userManager.startVideoTask(userId)) {
2401
+ return "您有一个视频任务正在进行中,请等待完成";
2344
2402
  }
2345
2403
  let createdTaskId = null;
2346
2404
  try {
@@ -2375,15 +2433,6 @@ ${infoParts.join("\n")}`;
2375
2433
  if (!validRatios.includes(ratio)) {
2376
2434
  return `宽高比必须是以下之一: ${validRatios.join(", ")}`;
2377
2435
  }
2378
- await session.send(
2379
- `🎬 开始生成视频...
2380
- 📝 描述:${prompt}
2381
- ⏱️ 时长:${duration}秒
2382
- 📐 宽高比:${ratio}
2383
- ⚠️ 预计需要 1-3 分钟,请耐心等待
2384
- 💡 提示:生成过程中可继续使用其他功能`
2385
- );
2386
- const startTime = Date.now();
2387
2436
  const taskId = await videoProvider.createVideoTask(
2388
2437
  prompt,
2389
2438
  imageUrls[0],
@@ -2393,7 +2442,7 @@ ${infoParts.join("\n")}`;
2393
2442
  }
2394
2443
  );
2395
2444
  createdTaskId = taskId;
2396
- await userManager.addPendingVideoTask({
2445
+ const addResult = await userManager.addPendingVideoTaskWithLimit({
2397
2446
  taskId,
2398
2447
  userId,
2399
2448
  userName,
@@ -2401,64 +2450,158 @@ ${infoParts.join("\n")}`;
2401
2450
  credits: videoCredits,
2402
2451
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2403
2452
  charged: false
2404
- });
2405
- await new Promise((resolve) => setTimeout(resolve, 3e3));
2406
- const videoUrl = await videoProvider.waitForVideo(taskId, config.videoMaxWaitTime);
2407
- await session.send(import_koishi2.h.video(videoUrl));
2408
- await recordUserUsage(session, "图生视频", videoCredits, false);
2409
- await userManager.markPendingVideoTaskCharged(taskId);
2410
- await userManager.deletePendingVideoTask(taskId);
2411
- const totalTime = Math.floor((Date.now() - startTime) / 1e3);
2412
- await session.send(`✅ 视频生成完成!(耗时 ${totalTime} 秒)`);
2413
- } catch (error) {
2414
- logger.error("视频生成失败", { userId, error: sanitizeError(error) });
2415
- const errorMsg = error.message || "";
2416
- if (errorMsg.includes("任务ID:")) {
2417
- return "⏳ 视频生成超时(任务仍在后台继续生成),请稍后发送“查询视频”获取结果";
2453
+ }, 1);
2454
+ if (!addResult.success) {
2455
+ try {
2456
+ await userManager.deletePendingVideoTask(taskId);
2457
+ } catch {
2458
+ }
2459
+ return addResult.message || "队列已满,请先查询已有任务";
2460
+ }
2461
+ await session.send("开始生成视频...");
2462
+ await new Promise((resolve) => setTimeout(resolve, 1e4));
2463
+ try {
2464
+ const firstStatus = await videoProvider.queryTaskStatus(taskId);
2465
+ if (firstStatus.status === "failed") {
2466
+ const errorMsg = firstStatus.error || "视频生成失败";
2467
+ await userManager.deletePendingVideoTask(taskId);
2468
+ return `视频生成失败:${sanitizeString(errorMsg)}`;
2469
+ }
2470
+ if (firstStatus.status === "completed" && firstStatus.videoUrl) {
2471
+ await session.send(import_koishi2.h.video(firstStatus.videoUrl));
2472
+ await recordUserUsage(session, "图生视频", videoCredits, false);
2473
+ await userManager.markPendingVideoTaskCharged(taskId);
2474
+ await userManager.deletePendingVideoTask(taskId);
2475
+ return "视频生成完成!";
2476
+ }
2477
+ await session.send("视频正在生成中,请稍候...");
2478
+ } catch (error) {
2479
+ logger.error("第一次查询视频状态失败", { taskId, error: sanitizeError(error) });
2418
2480
  }
2481
+ await new Promise((resolve) => setTimeout(resolve, config.videoMaxWaitTime * 1e3));
2419
2482
  try {
2420
- if (createdTaskId) await userManager.deletePendingVideoTask(createdTaskId);
2421
- } catch {
2483
+ const secondStatus = await videoProvider.queryTaskStatus(taskId);
2484
+ if (secondStatus.status === "completed" && secondStatus.videoUrl) {
2485
+ await session.send(import_koishi2.h.video(secondStatus.videoUrl));
2486
+ await recordUserUsage(session, "图生视频", videoCredits, false);
2487
+ await userManager.markPendingVideoTaskCharged(taskId);
2488
+ await userManager.deletePendingVideoTask(taskId);
2489
+ return "视频生成完成!";
2490
+ } else if (secondStatus.status === "failed") {
2491
+ const errorMsg = secondStatus.error || "视频生成失败";
2492
+ await userManager.deletePendingVideoTask(taskId);
2493
+ return `视频生成失败:${sanitizeString(errorMsg)}`;
2494
+ } else {
2495
+ return '视频仍在生成中,请稍后使用"查询视频"指令获取结果';
2496
+ }
2497
+ } catch (error) {
2498
+ logger.error("第二次查询视频状态失败", { taskId, error: sanitizeError(error) });
2499
+ return '视频生成中,请稍后使用"查询视频"指令获取结果';
2422
2500
  }
2423
- return `视频生成失败:${sanitizeString(errorMsg)}`;
2501
+ } catch (error) {
2502
+ logger.error("视频生成任务提交失败", { userId, error: sanitizeError(error) });
2503
+ if (createdTaskId) {
2504
+ try {
2505
+ await userManager.deletePendingVideoTask(createdTaskId);
2506
+ } catch {
2507
+ }
2508
+ }
2509
+ const errorMsg = error.message || "";
2510
+ return `视频生成任务提交失败:${sanitizeString(errorMsg)}`;
2424
2511
  } finally {
2425
- userManager.endTask(userId);
2512
+ userManager.endVideoTask(userId);
2426
2513
  }
2427
2514
  });
2428
2515
  }
2429
2516
  if (config.enableVideoGeneration && videoProvider) {
2430
- ctx.command("查询视频 [taskId:string]", "查询视频生成状态(不传任务ID则查询自己最近一次任务)").action(async ({ session }, taskId) => {
2517
+ ctx.command("查询视频 [taskId:string]", "查询视频生成状态(不传任务ID则查询自己所有待生成任务)").action(async ({ session }, taskId) => {
2431
2518
  if (!session?.userId) return "会话无效";
2432
2519
  const trimmedTaskId = (taskId || "").trim();
2433
- const resolvedTaskId = trimmedTaskId ? trimmedTaskId : (await userManager.getLatestPendingVideoTaskForUser(session.userId))?.taskId;
2434
- if (!resolvedTaskId) {
2435
- return "你当前没有可查询的待生成视频任务";
2436
- }
2437
- try {
2438
- await session.send("🔍 正在查询视频生成状态...");
2439
- const status = await videoProvider.queryTaskStatus(resolvedTaskId);
2440
- if (status.status === "completed" && status.videoUrl) {
2441
- const pending = await userManager.getPendingVideoTask(resolvedTaskId);
2520
+ if (trimmedTaskId) {
2521
+ try {
2522
+ await session.send("正在查询视频生成状态...");
2523
+ const status = await videoProvider.queryTaskStatus(trimmedTaskId);
2524
+ const pending = await userManager.getPendingVideoTask(trimmedTaskId);
2442
2525
  if (pending && pending.userId && pending.userId !== session.userId) {
2443
2526
  return "该任务ID不属于当前用户,无法查询";
2444
2527
  }
2445
- await session.send(import_koishi2.h.video(status.videoUrl));
2446
- if (pending && !pending.charged) {
2447
- await recordUserUsage(session, pending.commandName, pending.credits, false);
2448
- await userManager.markPendingVideoTaskCharged(resolvedTaskId);
2449
- await userManager.deletePendingVideoTask(resolvedTaskId);
2450
- }
2451
- return "✅ 视频已生成完成!";
2452
- } else if (status.status === "processing" || status.status === "pending") {
2453
- const progressText = status.progress ? `(进度:${status.progress}%)` : "";
2454
- return `⏳ 视频正在生成中${progressText},请稍后再次查询`;
2455
- } else if (status.status === "failed") {
2456
- return `❌ 视频生成失败:${status.error || "未知错误"}`;
2457
- } else {
2458
- return `❓ 未知状态:${status.status}`;
2528
+ if (status.status === "completed" && status.videoUrl) {
2529
+ await session.send(import_koishi2.h.video(status.videoUrl));
2530
+ if (pending && !pending.charged) {
2531
+ await recordUserUsage(session, pending.commandName, pending.credits, false);
2532
+ await userManager.markPendingVideoTaskCharged(trimmedTaskId);
2533
+ await userManager.deletePendingVideoTask(trimmedTaskId);
2534
+ }
2535
+ return "视频生成完成!";
2536
+ } else if (status.status === "processing" || status.status === "pending") {
2537
+ const progressText = status.progress ? `(进度:${status.progress}%)` : "";
2538
+ return `视频正在生成中${progressText},请稍后再次查询`;
2539
+ } else if (status.status === "failed") {
2540
+ if (pending && !pending.charged) {
2541
+ await userManager.deletePendingVideoTask(trimmedTaskId);
2542
+ }
2543
+ return `视频生成失败:${status.error || "未知错误"}`;
2544
+ } else {
2545
+ return `❓ 未知状态:${status.status}`;
2546
+ }
2547
+ } catch (error) {
2548
+ logger.error("查询视频任务失败", { taskId: trimmedTaskId, error: sanitizeError(error) });
2549
+ return `查询失败:${sanitizeString(error.message)}`;
2550
+ }
2551
+ }
2552
+ try {
2553
+ const pendingTasks = await userManager.listPendingVideoTasksForUser(session.userId);
2554
+ if (pendingTasks.length === 0) {
2555
+ return "你当前没有可查询的待生成视频任务";
2556
+ }
2557
+ await session.send(`正在查询 ${pendingTasks.length} 个视频任务状态...`);
2558
+ let completedCount = 0;
2559
+ let processingCount = 0;
2560
+ let failedCount = 0;
2561
+ const messages = [];
2562
+ for (const task of pendingTasks) {
2563
+ try {
2564
+ const status = await videoProvider.queryTaskStatus(task.taskId);
2565
+ if (status.status === "completed" && status.videoUrl) {
2566
+ await session.send(import_koishi2.h.video(status.videoUrl));
2567
+ if (!task.charged) {
2568
+ await recordUserUsage(session, task.commandName, task.credits, false);
2569
+ await userManager.markPendingVideoTaskCharged(task.taskId);
2570
+ await userManager.deletePendingVideoTask(task.taskId);
2571
+ }
2572
+ completedCount++;
2573
+ messages.push(`任务 ${task.taskId.substring(0, 20)}... 已完成`);
2574
+ } else if (status.status === "processing" || status.status === "pending") {
2575
+ processingCount++;
2576
+ const progressText = status.progress ? `(进度:${status.progress}%)` : "";
2577
+ messages.push(`任务 ${task.taskId.substring(0, 20)}... 生成中${progressText}`);
2578
+ } else if (status.status === "failed") {
2579
+ if (!task.charged) {
2580
+ await userManager.deletePendingVideoTask(task.taskId);
2581
+ }
2582
+ failedCount++;
2583
+ messages.push(`任务 ${task.taskId.substring(0, 20)}... 失败:${status.error || "未知错误"}`);
2584
+ } else {
2585
+ messages.push(`❓ 任务 ${task.taskId.substring(0, 20)}... 状态:${status.status}`);
2586
+ }
2587
+ } catch (error) {
2588
+ logger.error("查询单个视频任务失败", { taskId: task.taskId, error: sanitizeError(error) });
2589
+ messages.push(`⚠️ 任务 ${task.taskId.substring(0, 20)}... 查询失败:${sanitizeString(error.message)}`);
2590
+ }
2459
2591
  }
2592
+ let summary = `查询结果汇总:
2593
+ `;
2594
+ if (completedCount > 0) summary += `已完成:${completedCount} 个
2595
+ `;
2596
+ if (processingCount > 0) summary += `生成中:${processingCount} 个
2597
+ `;
2598
+ if (failedCount > 0) summary += `失败:${failedCount} 个
2599
+ `;
2600
+ summary += `
2601
+ ${messages.join("\n")}`;
2602
+ return summary;
2460
2603
  } catch (error) {
2461
- logger.error("查询视频任务失败", { taskId: resolvedTaskId, error: sanitizeError(error) });
2604
+ logger.error("查询视频任务列表失败", { userId: session.userId, error: sanitizeError(error) });
2462
2605
  return `查询失败:${sanitizeString(error.message)}`;
2463
2606
  }
2464
2607
  });
@@ -2480,8 +2623,8 @@ ${infoParts.join("\n")}`;
2480
2623
  if (!limitCheck.allowed) {
2481
2624
  return limitCheck.message;
2482
2625
  }
2483
- if (!userManager.startTask(userId)) {
2484
- return "您有一个任务正在进行中,请等待完成";
2626
+ if (!userManager.startVideoTask(userId)) {
2627
+ return "您有一个视频任务正在进行中,请等待完成";
2485
2628
  }
2486
2629
  let createdTaskId = null;
2487
2630
  try {
@@ -2497,11 +2640,6 @@ ${infoParts.join("\n")}`;
2497
2640
  if (extraText) {
2498
2641
  finalPrompt += " - " + extraText;
2499
2642
  }
2500
- await session.send(
2501
- `🎬 开始生成视频(${style.commandName})...
2502
- 📝 描述:${finalPrompt}
2503
- ⏱️ 预计需要 1-3 分钟`
2504
- );
2505
2643
  const taskId = await videoProvider.createVideoTask(
2506
2644
  finalPrompt,
2507
2645
  imageUrls[0],
@@ -2511,7 +2649,7 @@ ${infoParts.join("\n")}`;
2511
2649
  }
2512
2650
  );
2513
2651
  createdTaskId = taskId;
2514
- await userManager.addPendingVideoTask({
2652
+ const addResult = await userManager.addPendingVideoTaskWithLimit({
2515
2653
  taskId,
2516
2654
  userId,
2517
2655
  userName,
@@ -2519,27 +2657,66 @@ ${infoParts.join("\n")}`;
2519
2657
  credits: videoCredits,
2520
2658
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
2521
2659
  charged: false
2522
- });
2523
- await new Promise((resolve) => setTimeout(resolve, 3e3));
2524
- const videoUrl = await videoProvider.waitForVideo(taskId, config.videoMaxWaitTime);
2525
- await session.send(import_koishi2.h.video(videoUrl));
2526
- await recordUserUsage(session, style.commandName, videoCredits, false);
2527
- await userManager.markPendingVideoTaskCharged(taskId);
2528
- await userManager.deletePendingVideoTask(taskId);
2529
- await session.send(`✅ 视频生成完成!`);
2530
- } catch (error) {
2531
- logger.error("视频风格转换失败", { userId, style: style.commandName, error: sanitizeError(error) });
2532
- const errorMsg = error.message || "";
2533
- if (errorMsg.includes("任务ID:")) {
2534
- return "⏳ 视频生成超时(任务仍在后台继续生成),请稍后发送“查询视频”获取结果";
2660
+ }, 1);
2661
+ if (!addResult.success) {
2662
+ try {
2663
+ await userManager.deletePendingVideoTask(taskId);
2664
+ } catch {
2665
+ }
2666
+ return addResult.message || "队列已满,请先查询已有任务";
2535
2667
  }
2668
+ await session.send(`开始生成视频(${style.commandName})...`);
2669
+ await new Promise((resolve) => setTimeout(resolve, 1e4));
2536
2670
  try {
2537
- if (createdTaskId) await userManager.deletePendingVideoTask(createdTaskId);
2538
- } catch {
2671
+ const firstStatus = await videoProvider.queryTaskStatus(taskId);
2672
+ if (firstStatus.status === "failed") {
2673
+ const errorMsg = firstStatus.error || "视频生成失败";
2674
+ await userManager.deletePendingVideoTask(taskId);
2675
+ return `视频生成失败:${sanitizeString(errorMsg)}`;
2676
+ }
2677
+ if (firstStatus.status === "completed" && firstStatus.videoUrl) {
2678
+ await session.send(import_koishi2.h.video(firstStatus.videoUrl));
2679
+ await recordUserUsage(session, style.commandName, videoCredits, false);
2680
+ await userManager.markPendingVideoTaskCharged(taskId);
2681
+ await userManager.deletePendingVideoTask(taskId);
2682
+ return "视频生成完成!";
2683
+ }
2684
+ await session.send("视频正在生成中,请稍候...");
2685
+ } catch (error) {
2686
+ logger.error("第一次查询视频状态失败", { taskId, error: sanitizeError(error) });
2687
+ }
2688
+ await new Promise((resolve) => setTimeout(resolve, config.videoMaxWaitTime * 1e3));
2689
+ try {
2690
+ const secondStatus = await videoProvider.queryTaskStatus(taskId);
2691
+ if (secondStatus.status === "completed" && secondStatus.videoUrl) {
2692
+ await session.send(import_koishi2.h.video(secondStatus.videoUrl));
2693
+ await recordUserUsage(session, style.commandName, videoCredits, false);
2694
+ await userManager.markPendingVideoTaskCharged(taskId);
2695
+ await userManager.deletePendingVideoTask(taskId);
2696
+ return "视频生成完成!";
2697
+ } else if (secondStatus.status === "failed") {
2698
+ const errorMsg = secondStatus.error || "视频生成失败";
2699
+ await userManager.deletePendingVideoTask(taskId);
2700
+ return `视频生成失败:${sanitizeString(errorMsg)}`;
2701
+ } else {
2702
+ return '视频仍在生成中,请稍后使用"查询视频"指令获取结果';
2703
+ }
2704
+ } catch (error) {
2705
+ logger.error("第二次查询视频状态失败", { taskId, error: sanitizeError(error) });
2706
+ return '视频生成中,请稍后使用"查询视频"指令获取结果';
2539
2707
  }
2540
- return `视频生成失败:${sanitizeString(errorMsg)}`;
2708
+ } catch (error) {
2709
+ logger.error("视频风格转换任务提交失败", { userId, style: style.commandName, error: sanitizeError(error) });
2710
+ if (createdTaskId) {
2711
+ try {
2712
+ await userManager.deletePendingVideoTask(createdTaskId);
2713
+ } catch {
2714
+ }
2715
+ }
2716
+ const errorMsg = error.message || "";
2717
+ return `视频生成任务提交失败:${sanitizeString(errorMsg)}`;
2541
2718
  } finally {
2542
- userManager.endTask(userId);
2719
+ userManager.endVideoTask(userId);
2543
2720
  }
2544
2721
  });
2545
2722
  logger.info(`已注册视频风格命令: ${style.commandName}`);
@@ -67,6 +67,7 @@ export declare class UserManager {
67
67
  private usersCache;
68
68
  private pendingVideoCache;
69
69
  private activeTasks;
70
+ private activeVideoTasks;
70
71
  private rateLimitMap;
71
72
  private securityBlockMap;
72
73
  private securityWarningMap;
@@ -74,6 +75,9 @@ export declare class UserManager {
74
75
  startTask(userId: string): boolean;
75
76
  endTask(userId: string): void;
76
77
  isTaskActive(userId: string): boolean;
78
+ startVideoTask(userId: string): boolean;
79
+ endVideoTask(userId: string): void;
80
+ isVideoTaskActive(userId: string): boolean;
77
81
  isAdmin(userId: string, config: Config): boolean;
78
82
  private loadUsersData;
79
83
  private saveUsersDataInternal;
@@ -90,6 +94,22 @@ export declare class UserManager {
90
94
  * 获取某个用户最近一次未扣费的待结算视频任务
91
95
  */
92
96
  getLatestPendingVideoTaskForUser(userId: string): Promise<PendingVideoTask | null>;
97
+ /**
98
+ * 统计某个用户未扣费的待结算视频任务数量
99
+ */
100
+ countPendingVideoTasksForUser(userId: string): Promise<number>;
101
+ /**
102
+ * 列出某个用户所有未扣费的待结算视频任务
103
+ */
104
+ listPendingVideoTasksForUser(userId: string): Promise<PendingVideoTask[]>;
105
+ /**
106
+ * 添加待结算视频任务,并检查上限(默认max=1)
107
+ * @returns {Promise<{success: boolean, message?: string}>} 成功返回 {success: true},失败返回 {success: false, message: '错误信息'}
108
+ */
109
+ addPendingVideoTaskWithLimit(task: PendingVideoTask, max?: number): Promise<{
110
+ success: boolean;
111
+ message?: string;
112
+ }>;
93
113
  getUserData(userId: string, userName: string): Promise<UserData>;
94
114
  getAllUsers(): Promise<UsersData>;
95
115
  updateUsersBatch(updates: (data: UsersData) => void): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-aka-ai-generator",
3
3
  "description": "自用AI生成插件(GPTGod & Yunwu)",
4
- "version": "0.7.7",
4
+ "version": "0.7.10",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [