koishi-plugin-chat-analyse 1.3.6 → 1.3.7

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/lib/index.js +51 -49
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -1697,7 +1697,7 @@ var Renderer = class {
1697
1697
  const selectedPalette = colorfulPalettes[Math.floor(Math.random() * colorfulPalettes.length)];
1698
1698
  const shuffledColors = [...selectedPalette].sort(() => 0.5 - Math.random());
1699
1699
  const seriesColors = series.map((_, index) => shuffledColors[index % shuffledColors.length]);
1700
- const width = 600, height = 300;
1700
+ const width = 600, height = 320;
1701
1701
  const padding = { top: 15, right: 15, bottom: 60, left: 25 };
1702
1702
  const chartWidth = width - padding.left - padding.right;
1703
1703
  const chartHeight = height - padding.top - padding.bottom;
@@ -2318,64 +2318,66 @@ var Analyse = class {
2318
2318
  });
2319
2319
  }
2320
2320
  if (this.config.enableSimilarActivity) {
2321
- cmd.subcommand("simiactive", "相似活跃分析").usage("分析你和群友的活跃度,找出谁和你的活跃度最相似。").option("hours", "-n <hours:number> 指定时长", { fallback: 24 }).option("separate", "-p 分时分析").action(async ({ session, options }) => {
2321
+ cmd.subcommand("simiactive", "相似活跃分析").usage("分析你和群友的活跃规律,找出谁和你的作息最相似。").option("hours", "-n <hours:number> 指定时长", { fallback: 24 }).option("separate", "-p 分时分析").action(async ({ session, options }) => {
2322
2322
  if (!session.guildId) return "请在群组中使用此命令";
2323
2323
  try {
2324
- const until = /* @__PURE__ */ new Date();
2325
- let since;
2326
- let points;
2327
- let title;
2328
- let labels;
2329
- let daysToAnalyze = 0;
2330
- if (options.separate) {
2331
- points = options.hours;
2332
- since = new Date(until.getTime() - options.hours * import_koishi6.Time.hour);
2333
- title = `${options.hours}小时相似活跃分析`;
2334
- labels = Array.from({ length: points }, (_, i) => String(new Date(until.getTime() - (points - 1 - i) * import_koishi6.Time.hour).getHours()));
2335
- } else {
2336
- daysToAnalyze = Math.floor(options.hours / 24);
2337
- if (daysToAnalyze < 1) return "请指定至少 24 小时时长";
2338
- const analysisDurationHours = daysToAnalyze * 24;
2339
- since = new Date(until.getTime() - analysisDurationHours * import_koishi6.Time.hour);
2340
- points = 24;
2341
- title = `${daysToAnalyze}天相似活跃分析`;
2342
- labels = Array.from({ length: 24 }, (_, i) => String(i));
2343
- }
2344
2324
  const guildUsers = await this.ctx.database.get("analyse_user", { channelId: session.guildId });
2345
2325
  if (guildUsers.length < 2) return "暂无用户数据";
2346
2326
  const selfUser = guildUsers.find((u) => u.userId === session.userId);
2347
2327
  const guildUserUids = guildUsers.map((u) => u.uid);
2348
2328
  const uidToNameMap = new Map(guildUsers.map((u) => [u.uid, u.userName]));
2349
- const records = await this.ctx.database.get("analyse_rank", { uid: { $in: guildUserUids }, timestamp: { $gte: since } });
2350
- if (records.length === 0) return "暂无统计数据";
2351
- const activityVectors = /* @__PURE__ */ new Map();
2352
- guildUserUids.forEach((uid) => activityVectors.set(uid, Array(points).fill(0)));
2353
- records.forEach((stat) => {
2354
- let index;
2355
- if (options.separate) {
2356
- const diff = until.getTime() - stat.timestamp.getTime();
2357
- index = points - 1 - Math.floor(diff / import_koishi6.Time.hour);
2358
- } else {
2359
- index = stat.timestamp.getHours();
2360
- }
2361
- if (index >= 0 && index < points) {
2362
- activityVectors.get(stat.uid)[index] += stat.count;
2363
- }
2364
- });
2365
- if (!options.separate && daysToAnalyze > 0) activityVectors.forEach((vector) => {
2366
- for (let i = 0; i < vector.length; i++) vector[i] = vector[i] / daysToAnalyze;
2367
- });
2329
+ const until = /* @__PURE__ */ new Date();
2330
+ let analysisConfig;
2331
+ if (options.separate) {
2332
+ const { hours } = options;
2333
+ analysisConfig = {
2334
+ points: hours,
2335
+ since: new Date(until.getTime() - hours * import_koishi6.Time.hour),
2336
+ title: `${hours}小时相似活跃分析`,
2337
+ labels: Array.from({ length: hours }, (_, i) => String(new Date(until.getTime() - (hours - 1 - i) * import_koishi6.Time.hour).getHours())),
2338
+ getIndex: /* @__PURE__ */ __name((timestamp) => {
2339
+ const diff = until.getTime() - timestamp.getTime();
2340
+ const index = hours - 1 - Math.floor(diff / import_koishi6.Time.hour);
2341
+ return index >= 0 && index < hours ? index : -1;
2342
+ }, "getIndex"),
2343
+ reorderVector: /* @__PURE__ */ __name((vec) => vec, "reorderVector")
2344
+ };
2345
+ } else {
2346
+ const daysToAnalyse = Math.floor(options.hours / 24);
2347
+ if (daysToAnalyse < 1) return "分析时长请指定至少 1 天";
2348
+ const hoursToAnalyse = daysToAnalyse * 24;
2349
+ const currentHour = until.getHours();
2350
+ const labels = Array.from({ length: 24 }, (_, i) => String((currentHour - (23 - i) + 24) % 24));
2351
+ analysisConfig = {
2352
+ points: 24,
2353
+ since: new Date(until.getTime() - hoursToAnalyse * import_koishi6.Time.hour),
2354
+ title: `${daysToAnalyse}天相似活跃分析`,
2355
+ labels,
2356
+ getIndex: /* @__PURE__ */ __name((timestamp) => timestamp.getHours(), "getIndex"),
2357
+ reorderVector: /* @__PURE__ */ __name((vector) => labels.map((label) => vector[parseInt(label)]), "reorderVector")
2358
+ };
2359
+ }
2360
+ const records = await this.ctx.database.get("analyse_rank", { uid: { $in: guildUserUids }, timestamp: { $gte: analysisConfig.since } });
2361
+ if (!records.length) return "暂无统计数据";
2362
+ const activityVectors = new Map(guildUserUids.map((uid) => [uid, Array(analysisConfig.points).fill(0)]));
2363
+ for (const record of records) {
2364
+ const index = analysisConfig.getIndex(record.timestamp);
2365
+ if (index !== -1) activityVectors.get(record.uid)[index] += record.count;
2366
+ }
2368
2367
  const selfVector = activityVectors.get(selfUser.uid);
2369
- if (!selfVector || selfVector.every((v) => v === 0)) return "暂无统计数据";
2370
- const similarities = guildUserUids.filter((uid) => uid !== selfUser.uid && !activityVectors.get(uid).every((v) => v === 0)).map((uid) => ({ uid, score: cosineSimilarity(selfVector, activityVectors.get(uid)) })).sort((a, b) => b.score - a.score);
2371
- if (similarities.length === 0) return "暂无相似用户";
2368
+ const similarities = guildUserUids.filter((uid) => uid !== selfUser.uid && activityVectors.get(uid).some((v) => v !== 0)).map((uid) => ({
2369
+ uid,
2370
+ score: cosineSimilarity(selfVector, activityVectors.get(uid))
2371
+ })).sort((a, b) => b.score - a.score);
2372
+ if (!similarities.length) return "暂无相似用户";
2372
2373
  const top5 = similarities.slice(0, 5);
2373
- const series = [{ name: uidToNameMap.get(selfUser.uid) || "您", data: selfVector }];
2374
- top5.forEach((sim) => {
2374
+ const series = [{ name: uidToNameMap.get(selfUser.uid) || "您", data: analysisConfig.reorderVector(selfVector) }];
2375
+ for (const sim of top5) {
2375
2376
  const name2 = uidToNameMap.get(sim.uid) || `UID ${sim.uid}`;
2376
- series.push({ name: `${name2} (${(sim.score * 100).toFixed(1)}%)`, data: activityVectors.get(sim.uid) });
2377
- });
2378
- const imageGenerator = this.renderer.renderLineChart({ title, time: /* @__PURE__ */ new Date(), series, labels });
2377
+ const data = analysisConfig.reorderVector(activityVectors.get(sim.uid));
2378
+ series.push({ name: `${name2} (${(sim.score * 100).toFixed(1)}%)`, data });
2379
+ }
2380
+ const imageGenerator = this.renderer.renderLineChart({ title: analysisConfig.title, time: /* @__PURE__ */ new Date(), series, labels: analysisConfig.labels });
2379
2381
  for await (const buffer of imageGenerator) await session.send(import_koishi6.h.image(buffer, "image/png"));
2380
2382
  } catch (error) {
2381
2383
  this.ctx.logger.error("生成作息分析图片失败:", error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chat-analyse",
3
3
  "description": "强大而全面的聊天数据分析,支持统计命令,发言,消息类型,活跃度,支持发言排行和生成词云",
4
- "version": "1.3.6",
4
+ "version": "1.3.7",
5
5
  "contributors": [
6
6
  "Yis_Rime <yis_rime@outlook.com>"
7
7
  ],