koishi-plugin-aka-ai-generator 0.4.4 → 0.5.1

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.d.ts CHANGED
@@ -49,6 +49,8 @@ export interface Config {
49
49
  styles: StyleConfig[];
50
50
  styleGroups?: Record<string, StyleGroupConfig>;
51
51
  logLevel: 'info' | 'debug';
52
+ securityBlockWindow: number;
53
+ securityBlockWarningThreshold: number;
52
54
  }
53
55
  export interface RechargeRecord {
54
56
  id: string;
package/lib/index.js CHANGED
@@ -943,7 +943,10 @@ var Config = import_koishi.Schema.intersect([
943
943
  logLevel: import_koishi.Schema.union([
944
944
  import_koishi.Schema.const("info").description("普通信息"),
945
945
  import_koishi.Schema.const("debug").description("完整的debug信息")
946
- ]).default("info").description("日志输出详细程度")
946
+ ]).default("info").description("日志输出详细程度"),
947
+ // 安全策略拦截设置
948
+ securityBlockWindow: import_koishi.Schema.number().default(600).min(60).max(3600).description("安全策略拦截追踪时间窗口(秒),在此时间窗口内连续触发拦截会被记录"),
949
+ securityBlockWarningThreshold: import_koishi.Schema.number().default(3).min(1).max(10).description("安全策略拦截警示阈值,连续触发此次数拦截后将发送警示消息,再次触发将被扣除积分")
947
950
  }),
948
951
  // 自定义风格命令配置
949
952
  import_koishi.Schema.object({
@@ -968,6 +971,8 @@ function apply(ctx, config) {
968
971
  const logger = ctx.logger("aka-ai-generator");
969
972
  const activeTasks = /* @__PURE__ */ new Map();
970
973
  const rateLimitMap = /* @__PURE__ */ new Map();
974
+ const securityBlockMap = /* @__PURE__ */ new Map();
975
+ const securityWarningMap = /* @__PURE__ */ new Map();
971
976
  const providerCache = /* @__PURE__ */ new Map();
972
977
  function getProviderInstance(providerType, modelId) {
973
978
  const cacheKey = `${providerType}:${modelId || "default"}`;
@@ -1393,6 +1398,40 @@ function apply(ctx, config) {
1393
1398
  });
1394
1399
  }
1395
1400
  __name(recordUserUsage, "recordUserUsage");
1401
+ async function recordSecurityBlock(session, numImages = 1) {
1402
+ const userId = session.userId;
1403
+ if (!userId) return;
1404
+ if (isAdmin(userId)) {
1405
+ return;
1406
+ }
1407
+ const now = Date.now();
1408
+ const windowMs = config.securityBlockWindow * 1e3;
1409
+ const windowStart = now - windowMs;
1410
+ let blockTimestamps = securityBlockMap.get(userId) || [];
1411
+ blockTimestamps = blockTimestamps.filter((timestamp) => timestamp > windowStart);
1412
+ blockTimestamps.push(now);
1413
+ securityBlockMap.set(userId, blockTimestamps);
1414
+ const blockCount = blockTimestamps.length;
1415
+ const hasWarning = securityWarningMap.get(userId) || false;
1416
+ logger.info("安全策略拦截记录", {
1417
+ userId,
1418
+ blockCount,
1419
+ threshold: config.securityBlockWarningThreshold,
1420
+ hasWarning,
1421
+ numImages
1422
+ });
1423
+ if (blockCount >= config.securityBlockWarningThreshold && !hasWarning) {
1424
+ securityWarningMap.set(userId, true);
1425
+ await session.send(`⚠️ 安全策略警示
1426
+ 您已连续${config.securityBlockWarningThreshold}次触发安全策略拦截,再次发送被拦截内容将被扣除积分`);
1427
+ logger.warn("用户收到安全策略警示", { userId, blockCount, threshold: config.securityBlockWarningThreshold });
1428
+ } else if (hasWarning) {
1429
+ const commandName = "安全策略拦截";
1430
+ await recordUserUsage(session, commandName, numImages);
1431
+ logger.warn("用户因安全策略拦截被扣除积分", { userId, numImages });
1432
+ }
1433
+ }
1434
+ __name(recordSecurityBlock, "recordSecurityBlock");
1396
1435
  async function getInputData(session, imgParam, mode) {
1397
1436
  const collectedImages = [];
1398
1437
  let collectedText = "";
@@ -1496,11 +1535,19 @@ function apply(ctx, config) {
1496
1535
  new Promise(
1497
1536
  (_, reject) => setTimeout(() => reject(new Error("命令执行超时")), config.commandTimeout * 1e3)
1498
1537
  )
1499
- ]).catch((error) => {
1538
+ ]).catch(async (error) => {
1500
1539
  const userId = session.userId;
1501
1540
  if (userId) activeTasks.delete(userId);
1502
1541
  const sanitizedError = sanitizeError(error);
1503
1542
  logger.error("图像处理超时或失败", { userId, error: sanitizedError });
1543
+ if (error?.message !== "命令执行超时") {
1544
+ const errorMessage = error?.message || "";
1545
+ const isSecurityBlock = errorMessage.includes("内容被安全策略拦截") || errorMessage.includes("内容被安全策略阻止") || errorMessage.includes("内容被阻止") || errorMessage.includes("被阻止") || errorMessage.includes("SAFETY") || errorMessage.includes("RECITATION");
1546
+ if (isSecurityBlock) {
1547
+ const imageCount = requestContext?.numImages || config.defaultNumImages;
1548
+ await recordSecurityBlock(session, imageCount);
1549
+ }
1550
+ }
1504
1551
  const safeMessage = typeof error?.message === "string" ? sanitizeString(error.message) : "未知错误";
1505
1552
  return error.message === "命令执行超时" ? "图像处理超时,请重试" : `图像处理失败:${safeMessage}`;
1506
1553
  });
@@ -1589,6 +1636,11 @@ ${infoParts.join("\n")}`;
1589
1636
  activeTasks.delete(userId);
1590
1637
  const sanitizedError = sanitizeError(error);
1591
1638
  logger.error("图像处理失败", { userId, error: sanitizedError });
1639
+ const errorMessage = error?.message || "";
1640
+ const isSecurityBlock = errorMessage.includes("内容被安全策略拦截") || errorMessage.includes("内容被安全策略阻止") || errorMessage.includes("内容被阻止") || errorMessage.includes("被阻止") || errorMessage.includes("SAFETY") || errorMessage.includes("RECITATION");
1641
+ if (isSecurityBlock) {
1642
+ await recordSecurityBlock(session, imageCount);
1643
+ }
1592
1644
  if (error?.message) {
1593
1645
  const safeMessage = sanitizeString(error.message);
1594
1646
  return `图像处理失败:${safeMessage}`;
@@ -1755,6 +1807,11 @@ Prompt: ${prompt}`);
1755
1807
  activeTasks.delete(userId);
1756
1808
  const sanitizedError = sanitizeError(error);
1757
1809
  logger.error("图片合成失败", { userId, error: sanitizedError });
1810
+ const errorMessage = error?.message || "";
1811
+ const isSecurityBlock = errorMessage.includes("内容被安全策略拦截") || errorMessage.includes("内容被安全策略阻止") || errorMessage.includes("内容被阻止") || errorMessage.includes("被阻止") || errorMessage.includes("SAFETY") || errorMessage.includes("RECITATION");
1812
+ if (isSecurityBlock) {
1813
+ await recordSecurityBlock(session, imageCount);
1814
+ }
1758
1815
  if (error?.message) {
1759
1816
  const safeMessage = sanitizeString(error.message);
1760
1817
  return `图片合成失败:${safeMessage}`;
@@ -1765,11 +1822,19 @@ Prompt: ${prompt}`);
1765
1822
  new Promise(
1766
1823
  (_, reject) => setTimeout(() => reject(new Error("命令执行超时")), config.commandTimeout * 1e3)
1767
1824
  )
1768
- ]).catch((error) => {
1825
+ ]).catch(async (error) => {
1769
1826
  const userId = session.userId;
1770
1827
  if (userId) activeTasks.delete(userId);
1771
1828
  const sanitizedError = sanitizeError(error);
1772
1829
  logger.error("图片合成超时或失败", { userId, error: sanitizedError });
1830
+ if (error?.message !== "命令执行超时") {
1831
+ const errorMessage = error?.message || "";
1832
+ const isSecurityBlock = errorMessage.includes("内容被安全策略拦截") || errorMessage.includes("内容被安全策略阻止") || errorMessage.includes("内容被阻止") || errorMessage.includes("被阻止") || errorMessage.includes("SAFETY") || errorMessage.includes("RECITATION");
1833
+ if (isSecurityBlock) {
1834
+ const imageCount = options?.num || config.defaultNumImages;
1835
+ await recordSecurityBlock(session, imageCount);
1836
+ }
1837
+ }
1773
1838
  const safeMessage = typeof error?.message === "string" ? sanitizeString(error.message) : "未知错误";
1774
1839
  return error.message === "命令执行超时" ? "图片合成超时,请重试" : `图片合成失败:${safeMessage}`;
1775
1840
  });
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.4.4",
4
+ "version": "0.5.1",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [