koishi-plugin-class-score-system 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/lib/index.js CHANGED
@@ -1,32 +1,8 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
- var __export = (target, all) => {
7
- for (var name2 in all)
8
- __defProp(target, name2, { get: all[name2], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
3
 
20
4
  // src/index.ts
21
- var src_exports = {};
22
- __export(src_exports, {
23
- Config: () => Config,
24
- apply: () => apply,
25
- inject: () => inject,
26
- name: () => name
27
- });
28
- module.exports = __toCommonJS(src_exports);
29
- var import_koishi4 = require("koishi");
5
+ import { Schema } from "koishi";
30
6
 
31
7
  // src/models/database.ts
32
8
  function extendDatabase(ctx) {
@@ -833,7 +809,7 @@ function registerBindServerCommand(ctx, serverService, adminService) {
833
809
  __name(registerBindServerCommand, "registerBindServerCommand");
834
810
 
835
811
  // src/utils/image.ts
836
- var import_koishi = require("koishi");
812
+ import { h } from "koishi";
837
813
  async function generateImage(ctx, html, options = {}) {
838
814
  const width = options.width || 450;
839
815
  const height = options.height || 800;
@@ -873,7 +849,7 @@ __name(generateImage, "generateImage");
873
849
  async function sendImageOrText(ctx, session, html, fallbackText, options = {}) {
874
850
  const image = await generateImage(ctx, html, options);
875
851
  if (image) {
876
- await session.send(import_koishi.h.image(image, "image/png"));
852
+ await session.send(h.image(image, "image/png"));
877
853
  } else {
878
854
  await session.send(fallbackText);
879
855
  }
@@ -1429,7 +1405,7 @@ function registerStatisticsCommand(ctx, serverService, bindingService) {
1429
1405
  __name(registerStatisticsCommand, "registerStatisticsCommand");
1430
1406
 
1431
1407
  // src/commands/admin-manager.ts
1432
- var import_koishi2 = require("koishi");
1408
+ import { h as h2 } from "koishi";
1433
1409
  var pendingRequests = /* @__PURE__ */ new Map();
1434
1410
  function generateCode() {
1435
1411
  const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -1453,7 +1429,7 @@ setInterval(cleanupExpiredRequests, 3e4);
1453
1429
  function registerGroupAdminCommand(ctx, adminService) {
1454
1430
  function getAtId(session) {
1455
1431
  if (session.elements) {
1456
- const atElements = import_koishi2.h.select(session.elements, "at");
1432
+ const atElements = h2.select(session.elements, "at");
1457
1433
  if (atElements.length > 0) {
1458
1434
  return String(atElements[0].attrs?.id || "");
1459
1435
  }
@@ -1492,7 +1468,7 @@ function registerGroupAdminCommand(ctx, adminService) {
1492
1468
  });
1493
1469
  await session.send(
1494
1470
  `✅ 已发起加管请求
1495
- ` + import_koishi2.h.at(targetId) + ` 请发送 /确认 ${code} 同意加管
1471
+ ` + h2.at(targetId) + ` 请发送 /确认 ${code} 同意加管
1496
1472
  备注:${adminRemark}
1497
1473
  (120秒内有效)`
1498
1474
  );
@@ -1689,7 +1665,7 @@ ${openId}`;
1689
1665
  __name(registerGroupAdminCommand, "registerGroupAdminCommand");
1690
1666
 
1691
1667
  // src/commands/menu.ts
1692
- var import_koishi3 = require("koishi");
1668
+ import { h as h3 } from "koishi";
1693
1669
  var MENU_HTML = `
1694
1670
  <!DOCTYPE html>
1695
1671
  <html>
@@ -1881,7 +1857,7 @@ function registerMenuCommand(ctx) {
1881
1857
  type: "png",
1882
1858
  clip: { x: 0, y: 0, width: 450, height: 800 }
1883
1859
  });
1884
- await session.send(import_koishi3.h.image(screenshot, "image/png"));
1860
+ await session.send(h3.image(screenshot, "image/png"));
1885
1861
  return "";
1886
1862
  } catch (error) {
1887
1863
  ctx.logger.error("生成菜单图片失败:", error);
@@ -1920,7 +1896,7 @@ __name(registerMenuCommand, "registerMenuCommand");
1920
1896
  // src/index.ts
1921
1897
  var name = "class-score-system";
1922
1898
  var inject = ["database", "puppeteer"];
1923
- var Config = import_koishi4.Schema.object({});
1899
+ var Config = Schema.object({});
1924
1900
  function apply(ctx) {
1925
1901
  ctx.logger.info("班级操行分管理系统插件正在加载...");
1926
1902
  extendDatabase(ctx);
@@ -1938,10 +1914,9 @@ function apply(ctx) {
1938
1914
  ctx.logger.info("班级操行分管理系统插件加载完成");
1939
1915
  }
1940
1916
  __name(apply, "apply");
1941
- // Annotate the CommonJS export names for ESM import in node:
1942
- 0 && (module.exports = {
1917
+ export {
1943
1918
  Config,
1944
1919
  apply,
1945
1920
  inject,
1946
1921
  name
1947
- });
1922
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts", "../src/models/database.ts", "../src/services/api.ts", "../src/services/server.ts", "../src/services/binding.ts", "../src/services/group-admin.ts", "../src/utils/constants.ts", "../src/utils/validator.ts", "../src/utils/formatter.ts", "../src/commands/bind-server.ts", "../src/utils/image.ts", "../src/commands/query-score.ts", "../src/commands/bind-qq.ts", "../src/commands/adjust-score.ts", "../src/commands/ranking.ts", "../src/commands/statistics.ts", "../src/commands/admin-manager.ts", "../src/commands/menu.ts"],
4
+ "sourcesContent": ["import { Context, Schema } from 'koishi'\nimport { extendDatabase } from './models/database'\nimport { ServerConfigService } from './services/server'\nimport { QqBindingService } from './services/binding'\nimport { GroupAdminService } from './services/group-admin'\nimport { registerBindServerCommand } from './commands/bind-server'\nimport { registerQueryScoreCommand } from './commands/query-score'\nimport { registerBindQqCommand } from './commands/bind-qq'\nimport { registerAdjustScoreCommand } from './commands/adjust-score'\nimport { registerRankingCommand } from './commands/ranking'\nimport { registerStatisticsCommand } from './commands/statistics'\nimport { registerGroupAdminCommand } from './commands/admin-manager'\nimport { registerMenuCommand } from './commands/menu'\n\nexport const name = 'class-score-system'\nexport const inject = ['database', 'puppeteer']\n\nexport interface Config {}\n\nexport const Config: Schema<Config> = Schema.object({})\n\nexport function apply(ctx: Context) {\n ctx.logger.info('\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF\u63D2\u4EF6\u6B63\u5728\u52A0\u8F7D...')\n\n extendDatabase(ctx)\n\n const serverService = new ServerConfigService(ctx)\n const bindingService = new QqBindingService(ctx)\n const adminService = new GroupAdminService(ctx)\n\n registerGroupAdminCommand(ctx, adminService)\n registerBindServerCommand(ctx, serverService, adminService)\n registerQueryScoreCommand(ctx, serverService, bindingService)\n registerBindQqCommand(ctx, serverService, bindingService)\n registerAdjustScoreCommand(ctx, serverService, adminService)\n registerRankingCommand(ctx, serverService)\n registerStatisticsCommand(ctx, serverService, bindingService)\n registerMenuCommand(ctx)\n\n ctx.logger.info('\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF\u63D2\u4EF6\u52A0\u8F7D\u5B8C\u6210')\n}", "import { Context, Schema, Tables } from 'koishi'\n\nexport interface ServerConfig {\n id: number\n guildId: string\n name: string\n address: string\n username: string\n token: string\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface QqBinding {\n id: number\n guildId: string\n userId: number\n username: string\n openId: string // Koishi session.userId\uFF08QQ OpenID\uFF0C\u975E\u4F20\u7EDFQQ\u53F7\uFF09\n serverId: number\n createdAt: Date\n updatedAt: Date\n}\n\nexport interface GroupAdmin {\n id: number\n guildId: string\n openId: string // OpenID\uFF08\u7528\u6237\u786E\u8BA4\u65F6\u83B7\u53D6\uFF09\n remark: string // \u5907\u6CE8\uFF08\u7528\u4E8E\u51CF\u7BA1\uFF09\n verify: number // \u9A8C\u8BC1\u72B6\u6001\uFF1A0=\u5F85\u786E\u8BA4, 1=\u5DF2\u786E\u8BA4\n createdAt: Date\n}\n\ndeclare module 'koishi' {\n interface Tables {\n server_configs: ServerConfig\n qq_bindings: QqBinding\n group_admins: GroupAdmin\n }\n}\n\nexport function extendDatabase(ctx: Context) {\n ctx.model.extend('server_configs', {\n id: 'integer',\n guildId: 'string',\n name: 'string',\n address: 'string',\n username: 'string',\n token: 'string',\n createdAt: 'timestamp',\n updatedAt: 'timestamp',\n }, {\n primary: 'id',\n autoInc: true,\n })\n\n ctx.model.extend('qq_bindings', {\n id: 'integer',\n guildId: 'string',\n userId: 'integer',\n username: 'string',\n openId: 'string',\n serverId: 'integer',\n createdAt: 'timestamp',\n updatedAt: 'timestamp',\n }, {\n primary: 'id',\n autoInc: true,\n unique: ['openId', 'guildId'],\n })\n\n ctx.model.extend('group_admins', {\n id: 'integer',\n guildId: 'string',\n openId: 'string',\n remark: 'string',\n verify: 'integer',\n createdAt: 'timestamp',\n }, {\n primary: 'id',\n autoInc: true,\n unique: ['openId', 'guildId'],\n })\n}", "import { Context } from 'koishi'\n\nexport interface CsmsUser {\n id: number\n username: string\n qq_number: string | null\n total_score: number\n add_score: number\n deduct_score: number\n score_count: number\n group_index?: number\n row_index?: number\n col_index?: number\n created_at: string\n}\n\nexport interface CsmsScoreLog {\n id: number\n user_id: number\n score_change: number\n description: string\n created_at: string\n}\n\nexport interface AddScoreUser {\n username: string\n score_change: number\n}\n\nexport interface AddScoreBatchData {\n users: AddScoreUser[]\n description: string\n}\n\nexport interface AddScoreResult {\n success: boolean\n message: string\n summary: {\n success_count: number\n failed_count: number\n total_count: number\n }\n details: Array<{\n username: string\n user_id?: number\n score_change: number\n success: boolean\n error?: string\n }>\n}\n\nexport interface ApiResponse<T = any> {\n data?: T\n error?: string\n success?: boolean\n message?: string\n total?: number\n limit?: number\n offset?: number\n}\n\nexport class CsmsApiService {\n private baseUrl: string\n private token: string\n private ctx: Context\n\n constructor(ctx: Context, baseUrl: string, token: string) {\n this.ctx = ctx\n this.baseUrl = baseUrl.replace(/\\/api\\/global_api\\.php$/, '').replace(/\\/$/, '')\n this.token = token\n }\n\n /**\n * \u53D1\u9001 API \u8BF7\u6C42\n * \u6309\u7167 global_api.md \u6587\u6863\u89C4\u8303\u5B9E\u73B0\n */\n private async request<T>(params: Record<string, string | number | undefined>): Promise<ApiResponse<T>> {\n try {\n const url = `${this.baseUrl}/api/global_api.php`\n // \u8FC7\u6EE4\u6389 undefined \u503C\n const cleanParams: Record<string, string> = {}\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n cleanParams[key] = String(value)\n }\n }\n \n this.ctx.logger.debug(`API\u8BF7\u6C42: ${url}`, cleanParams)\n \n const response = await this.ctx.http.get<ApiResponse<T>>(url, { \n params: cleanParams,\n headers: {\n 'Authorization': this.token,\n }\n })\n \n this.ctx.logger.debug(`API\u54CD\u5E94:`, response)\n return response\n } catch (error: any) {\n this.ctx.logger.error('CSMS API \u8BF7\u6C42\u5931\u8D25:', error)\n return { error: error.message || 'API\u8BF7\u6C42\u5931\u8D25' }\n }\n }\n\n /**\n * \u9A8C\u8BC1 Token - \u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 add_score \u63A5\u53E3\u6D4B\u8BD5\n * \u6CE8\u610F: \u6587\u6863\u672A\u63D0\u4F9B\u4E13\u95E8\u7684 validate_token \u63A5\u53E3\uFF0C\u7528\u6B64\u65B9\u6CD5\u95F4\u63A5\u9A8C\u8BC1\n */\n async validateToken(): Promise<{ valid: boolean; username?: string }> {\n try {\n // \u5C1D\u8BD5\u8C03\u7528 add_score \u63A5\u53E3\uFF08\u9700\u8981\u6709\u6548token\uFF09\uFF0C\u4F20\u5165\u65E0\u6548\u6570\u636E\u6765\u68C0\u6D4Btoken\u662F\u5426\u6709\u6548\n const url = `${this.baseUrl}/api/global_api.php`\n const params = {\n action: 'add_score',\n data: JSON.stringify({\n username: '__validate__',\n score_change: 0,\n description: '__token_validation__'\n }),\n token: this.token,\n }\n \n this.ctx.logger.info(`\u9A8C\u8BC1Token\u4E2D...`)\n const response = await this.ctx.http.get<ApiResponse>(url, { params })\n \n // \u5982\u679C\u8FD4\u56DE error: \"\u7528\u6237\u4E0D\u5B58\u5728\" \u6216\u7C7B\u4F3C\uFF0C\u8BF4\u660E token \u6709\u6548\n // \u5982\u679C\u8FD4\u56DE error: \"\u672A\u6388\u6743\" \u6216 \"Token\u65E0\u6548\"\uFF0C\u8BF4\u660E token \u65E0\u6548\n if (response.error) {\n const errorLower = response.error.toLowerCase()\n if (errorLower.includes('\u672A\u6388\u6743') || errorLower.includes('token') || errorLower.includes('\u65E0\u6548')) {\n this.ctx.logger.warn(`Token\u9A8C\u8BC1\u5931\u8D25: ${response.error}`)\n return { valid: false }\n }\n // \u5176\u4ED6\u9519\u8BEF\uFF08\u5982\u7528\u6237\u4E0D\u5B58\u5728\uFF09\u8BF4\u660Etoken\u6709\u6548\n this.ctx.logger.info(`Token\u9A8C\u8BC1\u6210\u529F`)\n return { valid: true }\n }\n \n return { valid: true }\n } catch (error: any) {\n this.ctx.logger.error(`Token\u9A8C\u8BC1\u5F02\u5E38:`, error)\n return { valid: false }\n }\n }\n\n /**\n * \u67E5\u8BE2\u7528\u6237\u5217\u8868\n * GET /api/global_api.php?users&order_by=xxx&order=DESC&limit=20&offset=0\n */\n async getUsers(options?: {\n where?: Record<string, any>\n order_by?: string\n order?: 'ASC' | 'DESC'\n limit?: number\n offset?: number\n search?: string\n }): Promise<ApiResponse<CsmsUser[]>> {\n const params: Record<string, string> = { users: '' }\n \n if (options?.where) {\n params.where = JSON.stringify(options.where)\n }\n if (options?.order_by) {\n params.order_by = options.order_by\n }\n if (options?.order) {\n params.order = options.order\n }\n if (options?.limit !== undefined) {\n params.limit = options.limit.toString()\n }\n if (options?.offset !== undefined) {\n params.offset = options.offset.toString()\n }\n if (options?.search) {\n params.search = options.search\n }\n \n return this.request<CsmsUser[]>(params)\n }\n\n /**\n * \u67E5\u8BE2\u5355\u4E2A\u7528\u6237\n * GET /api/global_api.php?users&id=xxx\n */\n async getUserById(id: number): Promise<ApiResponse<CsmsUser[]>> {\n return this.request<CsmsUser[]>({ users: '', id: id.toString() })\n }\n\n /**\n * \u6309\u7528\u6237\u540D\u67E5\u8BE2\u7528\u6237\n * GET /api/global_api.php?users&where={\"username\":\"xxx\"}\n */\n async getUserByUsername(username: string): Promise<ApiResponse<CsmsUser[]>> {\n return this.request<CsmsUser[]>({ \n users: '', \n where: JSON.stringify({ username }) \n })\n }\n\n /**\n * \u6309QQ\u53F7\u67E5\u8BE2\u7528\u6237\n * GET /api/global_api.php?users&where={\"qq_number\":\"xxx\"}\n */\n async getUserByQq(qqNumber: string): Promise<ApiResponse<CsmsUser[]>> {\n return this.request<CsmsUser[]>({ \n users: '', \n where: JSON.stringify({ qq_number: qqNumber }) \n })\n }\n\n /**\n * \u83B7\u53D6\u6392\u884C\u699C\uFF08\u6309 total_score \u964D\u5E8F\uFF09\n * GET /api/global_api.php?users&order_by=total_score&order=DESC&limit=20\n */\n async getRanking(limit: number = 20, offset: number = 0): Promise<ApiResponse<CsmsUser[]>> {\n return this.request<CsmsUser[]>({\n users: '',\n order_by: 'total_score',\n order: 'DESC',\n limit: limit.toString(),\n offset: offset.toString(),\n })\n }\n\n /**\n * \u67E5\u8BE2\u79EF\u5206\u8BB0\u5F55\n * GET /api/global_api.php?score_logs&where={\"user_id\":xxx}&order_by=created_at&order=DESC&limit=50\n */\n async getScoreLogs(userId: number, limit: number = 50): Promise<ApiResponse<CsmsScoreLog[]>> {\n return this.request<CsmsScoreLog[]>({\n score_logs: '',\n where: JSON.stringify({ user_id: userId }),\n order_by: 'created_at',\n order: 'DESC',\n limit: limit.toString(),\n })\n }\n\n /**\n * \u521B\u5EFA\u65B0\u7528\u6237\n * GET /api/global_api.php?users&action=create&data={\"username\":\"xxx\"}&token=xxx\n */\n async createUser(username: string): Promise<ApiResponse<CsmsUser>> {\n return this.request<CsmsUser>({\n users: '',\n action: 'create',\n data: JSON.stringify({ username }),\n })\n }\n\n /**\n * \u66F4\u65B0\u7528\u6237\u4FE1\u606F\uFF08\u5982\u7ED1\u5B9AQQ\u53F7\uFF09\n * GET /api/global_api.php?users&action=update&id=xxx&data={\"qq_number\":\"xxx\"}&token=xxx\n */\n async updateUser(userId: number, data: Record<string, any>): Promise<ApiResponse<CsmsUser>> {\n return this.request<CsmsUser>({\n users: '',\n action: 'update',\n id: userId.toString(),\n data: JSON.stringify(data),\n })\n }\n\n /**\n * \u7ED1\u5B9A\u7528\u6237QQ\u53F7\n */\n async bindQq(userId: number, qqNumber: string): Promise<ApiResponse<CsmsUser>> {\n return this.updateUser(userId, { qq_number: qqNumber })\n }\n\n /**\n * \u6279\u91CF\u52A0\u51CF\u5206\n * GET /api/global_api.php?action=add_score&data={\"users\":[...],\"description\":\"xxx\"}&token=xxx\n */\n async batchAddScore(data: AddScoreBatchData): Promise<AddScoreResult> {\n this.ctx.logger.info(`batchAddScore \u8BF7\u6C42\u6570\u636E:`, JSON.stringify(data))\n \n const response = await this.request<AddScoreResult>({\n action: 'add_score',\n data: JSON.stringify(data),\n })\n \n this.ctx.logger.info(`batchAddScore API \u54CD\u5E94:`, JSON.stringify(response))\n \n // \u68C0\u67E5\u9519\u8BEF\n if (response.error) {\n return {\n success: false,\n message: response.error,\n summary: { success_count: 0, failed_count: 0, total_count: 0 },\n details: [],\n }\n }\n \n // CSMS API \u76F4\u63A5\u8FD4\u56DE AddScoreResult \u5BF9\u8C61\uFF0C\u4E0D\u5728 data \u5B57\u6BB5\u4E2D\n // \u68C0\u67E5 response \u662F\u5426\u5C31\u662F AddScoreResult\n if (response.data && typeof response.data === 'object' && 'summary' in response.data) {\n return response.data as AddScoreResult\n }\n \n // \u517C\u5BB9\uFF1A\u68C0\u67E5 response \u672C\u8EAB\u662F\u5426\u5C31\u662F AddScoreResult \u683C\u5F0F\n if (response && typeof response === 'object' && 'summary' in response) {\n return response as AddScoreResult\n }\n \n // \u68C0\u67E5 response.data \u662F\u5426\u4E3A\u6570\u7EC4\u5F62\u5F0F\uFF08\u517C\u5BB9\u67D0\u4E9B\u60C5\u51B5\uFF09\n if (Array.isArray(response.data)) {\n return {\n success: true,\n message: '\u64CD\u4F5C\u5B8C\u6210',\n summary: { success_count: response.data.length, failed_count: 0, total_count: response.data.length },\n details: response.data,\n }\n }\n \n this.ctx.logger.error(`batchAddScore \u8FD4\u56DE\u6570\u636E\u683C\u5F0F\u5F02\u5E38\uFF0C\u539F\u59CB\u54CD\u5E94:`, response)\n return {\n success: false,\n message: 'API \u8FD4\u56DE\u6570\u636E\u683C\u5F0F\u5F02\u5E38',\n summary: { success_count: 0, failed_count: 0, total_count: 0 },\n details: [],\n }\n }\n\n /**\n * \u5355\u7528\u6237\u52A0\u51CF\u5206\n */\n async addScore(username: string, scoreChange: number, description: string): Promise<AddScoreResult> {\n return this.batchAddScore({\n users: [{ username, score_change: scoreChange }],\n description,\n })\n }\n}\n", "import { Context } from 'koishi'\nimport { ServerConfig } from '../models/database'\nimport { CsmsApiService } from './api'\n\nexport class ServerConfigService {\n private ctx: Context\n\n constructor(ctx: Context) {\n this.ctx = ctx\n }\n\n async saveConfig(guildId: string, name: string, address: string, username: string, token: string): Promise<ServerConfig> {\n const now = new Date()\n \n // \u68C0\u67E5\u8BE5\u7FA4\u804A\u662F\u5426\u5DF2\u6709\u914D\u7F6E\n const existingConfigs = await this.ctx.database.get('server_configs', { guildId })\n \n // \u81EA\u52A8\u79FB\u9664 /api/global_api.php \u540E\u7F00\n const baseUrl = address.replace(/\\/api\\/global_api\\.php$/, '').replace(/\\/$/, '')\n \n if (existingConfigs.length > 0) {\n // \u66F4\u65B0\u73B0\u6709\u914D\u7F6E\n await this.ctx.database.set('server_configs', { guildId }, {\n name,\n address: baseUrl,\n username,\n token,\n updatedAt: now,\n })\n return { ...existingConfigs[0], name, address: baseUrl, username, token, updatedAt: now }\n }\n \n // \u521B\u5EFA\u65B0\u914D\u7F6E\n const config = await this.ctx.database.create('server_configs', {\n guildId,\n name,\n address: baseUrl,\n username,\n token,\n createdAt: now,\n updatedAt: now,\n })\n \n return config\n }\n\n async getConfigByGuild(guildId: string): Promise<ServerConfig | null> {\n const configs = await this.ctx.database.get('server_configs', { guildId })\n return configs[0] || null\n }\n\n async getAllConfigs(): Promise<ServerConfig[]> {\n return this.ctx.database.get('server_configs', {})\n }\n\n async deleteConfig(guildId: string): Promise<boolean> {\n await this.ctx.database.remove('server_configs', { guildId })\n return true\n }\n\n async createApiService(guildId: string): Promise<CsmsApiService | null> {\n const config = await this.getConfigByGuild(guildId)\n if (!config) return null\n \n return new CsmsApiService(this.ctx, config.address, config.token)\n }\n\n async validateConfig(address: string, username: string, token: string): Promise<{ valid: boolean; error?: string; actualUsername?: string }> {\n try {\n // \u81EA\u52A8\u79FB\u9664 /api/global_api.php \u540E\u7F00\n const baseUrl = address.replace(/\\/api\\/global_api\\.php$/, '').replace(/\\/$/, '')\n const api = new CsmsApiService(this.ctx, baseUrl, token)\n const result = await api.validateToken()\n \n if (result.valid) {\n // \u5982\u679C\u63D0\u4F9B\u7684\u7528\u6237\u540D\u4E0E\u5B9E\u9645\u767B\u5F55\u7684\u7BA1\u7406\u5458\u7528\u6237\u540D\u4E0D\u540C\uFF0C\u7ED9\u51FA\u63D0\u793A\n if (result.username && result.username !== username) {\n return { \n valid: true, \n actualUsername: result.username,\n error: `\u8B66\u544A\uFF1A\u63D0\u4F9B\u7684\u7528\u6237\u540D \"${username}\" \u4E0E\u5B9E\u9645\u767B\u5F55\u7684\u7BA1\u7406\u5458 \"${result.username}\" \u4E0D\u4E00\u81F4` \n }\n }\n return { valid: true, actualUsername: result.username }\n }\n \n return { valid: false, error: 'Token \u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 Token \u662F\u5426\u6B63\u786E' }\n } catch (error: any) {\n this.ctx.logger.error('\u9A8C\u8BC1\u670D\u52A1\u5668\u914D\u7F6E\u5931\u8D25:', error)\n return { valid: false, error: error.message }\n }\n }\n}", "import { Context } from 'koishi'\nimport { QqBinding } from '../models/database'\n\nexport class QqBindingService {\n private ctx: Context\n\n constructor(ctx: Context) {\n this.ctx = ctx\n }\n\n /**\n * openId \u5373 session.userId\uFF08QQ OpenID\uFF0C\u975E\u4F20\u7EDFQQ\u53F7\uFF09\n */\n async bindQq(guildId: string, userId: number, username: string, openId: string, serverId: number): Promise<QqBinding> {\n const now = new Date()\n \n const bindings = await this.ctx.database.get('qq_bindings', { openId, guildId })\n if (bindings.length > 0) {\n await this.ctx.database.set('qq_bindings', { openId, guildId }, {\n userId,\n username,\n serverId,\n updatedAt: now,\n })\n return { ...bindings[0], userId, username, serverId, updatedAt: now }\n }\n \n const binding = await this.ctx.database.create('qq_bindings', {\n guildId,\n userId,\n username,\n openId,\n serverId,\n createdAt: now,\n updatedAt: now,\n })\n \n return binding\n }\n\n async unbindQq(guildId: string, openId: string): Promise<boolean> {\n await this.ctx.database.remove('qq_bindings', { openId, guildId })\n return true\n }\n\n async unbindByUserId(guildId: string, userId: number): Promise<boolean> {\n await this.ctx.database.remove('qq_bindings', { userId, guildId })\n return true\n }\n\n async getUserByOpenId(guildId: string, openId: string): Promise<QqBinding | null> {\n const bindings = await this.ctx.database.get('qq_bindings', { openId, guildId })\n return bindings[0] || null\n }\n\n async getQqByUserId(guildId: string, userId: number): Promise<QqBinding | null> {\n const bindings = await this.ctx.database.get('qq_bindings', { userId, guildId })\n return bindings[0] || null\n }\n\n async getAllBindings(guildId: string): Promise<QqBinding[]> {\n return this.ctx.database.get('qq_bindings', { guildId })\n }\n\n async getBindingsByServer(guildId: string, serverId: number): Promise<QqBinding[]> {\n return this.ctx.database.get('qq_bindings', { serverId, guildId })\n }\n\n async getBindingsByUsername(guildId: string, username: string): Promise<QqBinding[]> {\n return this.ctx.database.get('qq_bindings', { username, guildId })\n }\n}\n", "import { Context } from 'koishi'\r\nimport { GroupAdmin } from '../models/database'\r\n\r\nexport class GroupAdminService {\r\n private ctx: Context\r\n\r\n constructor(ctx: Context) {\r\n this.ctx = ctx\r\n }\r\n\r\n /**\r\n * \u6DFB\u52A0\u5DF2\u9A8C\u8BC1\u7684\u7BA1\u7406\u5458\uFF08verify = 1\uFF0C\u7528\u4E8E\u7ED1\u5B9A\u670D\u52A1\u5668\u65F6\u81EA\u52A8\u5347\u7EA7\uFF09\r\n */\r\n async addAdmin(guildId: string, openId: string, remark: string): Promise<GroupAdmin> {\r\n const existing = await this.ctx.database.get('group_admins', { guildId, openId })\r\n if (existing.length > 0) {\r\n // \u5DF2\u5B58\u5728\u5219\u66F4\u65B0\u4E3A\u5DF2\u9A8C\u8BC1\r\n await this.ctx.database.set('group_admins', { guildId, openId }, { remark, verify: 1 })\r\n return { ...existing[0], remark, verify: 1 }\r\n }\r\n\r\n return this.ctx.database.create('group_admins', {\r\n guildId,\r\n openId,\r\n remark,\r\n verify: 1,\r\n createdAt: new Date(),\r\n })\r\n }\r\n\r\n /**\r\n * \u521B\u5EFA\u5F85\u786E\u8BA4\u7684\u7FA4\u7BA1\u8BB0\u5F55\uFF08Verify = 0\uFF09\r\n */\r\n async createPendingAdmin(guildId: string, openId: string, remark: string): Promise<GroupAdmin> {\r\n // \u68C0\u67E5\u662F\u5426\u5DF2\u5B58\u5728\uFF08\u6309 openId \u67E5\uFF09\r\n const existing = await this.ctx.database.get('group_admins', { guildId, openId })\r\n if (existing.length > 0) {\r\n return existing[0]\r\n }\r\n\r\n return this.ctx.database.create('group_admins', {\r\n guildId,\r\n openId,\r\n remark,\r\n verify: 0,\r\n createdAt: new Date(),\r\n })\r\n }\r\n\r\n /**\r\n * \u786E\u8BA4\u7FA4\u7BA1\uFF08\u5C06 Verify \u6539\u4E3A 1\uFF09\r\n */\r\n async confirmAdmin(guildId: string, openId: string): Promise<boolean> {\r\n await this.ctx.database.set('group_admins', { guildId, openId }, { verify: 1 })\r\n return true\r\n }\r\n\r\n /**\r\n * \u79FB\u9664\u7FA4\u7BA1\uFF08\u6309\u5907\u6CE8 \u67E5\u627E\u5E76\u5220\u9664\uFF09\r\n */\r\n async removeAdminByRemark(guildId: string, remark: string): Promise<boolean> {\r\n await this.ctx.database.remove('group_admins', { guildId, remark })\r\n return true\r\n }\r\n\r\n /**\r\n * \u68C0\u67E5\u662F\u5426\u4E3A\u5DF2\u786E\u8BA4\u7684\u7FA4\u7BA1\uFF08OpenID + Verify = 1\uFF09\r\n */\r\n async isAdmin(guildId: string, openId: string): Promise<boolean> {\r\n const admins = await this.ctx.database.get('group_admins', { guildId, openId })\r\n return admins.length > 0 && admins[0].verify === 1\r\n }\r\n\r\n /**\r\n * \u83B7\u53D6\u6240\u6709\u7FA4\u7BA1\r\n */\r\n async getAllAdmins(guildId: string): Promise<GroupAdmin[]> {\r\n return this.ctx.database.get('group_admins', { guildId })\r\n }\r\n\r\n /**\r\n * \u68C0\u67E5\u7528\u6237\u662F\u5426\u6709\u7BA1\u7406\u6743\u9650\uFF08\u6309 OpenID + Verify = 1\uFF09\r\n */\r\n async hasAdminPermission(session: any): Promise<boolean> {\r\n const openId = session.userId?.toString()\r\n if (!openId || !session.guildId) return false\r\n return await this.isAdmin(session.guildId, openId)\r\n }\r\n}\r\n", "export const CONSTANTS = {\n TOKEN_PATTERN: /^[A-Z0-9]+$/,\n QQ_PATTERN: /^\\d{5,12}$/,\n SCORE_MIN: -1000,\n SCORE_MAX: 1000,\n RANKING_DEFAULT_LIMIT: 10,\n RANKING_MAX_LIMIT: 50,\n SCORE_LOGS_DEFAULT_LIMIT: 20,\n SCORE_LOGS_MAX_LIMIT: 100,\n USERNAME_MAX_LENGTH: 50,\n DESCRIPTION_MAX_LENGTH: 255,\n}\n\nexport const ERROR_MESSAGES = {\n NO_SERVER_CONFIG: '\u672A\u914D\u7F6ECSMS\u670D\u52A1\u5668\uFF0C\u8BF7\u5148\u4F7F\u7528 /\u7ED1\u5B9A\u670D\u52A1\u5668 \u547D\u4EE4\u914D\u7F6E',\n INVALID_TOKEN: '\u65E0\u6548\u7684Token\u683C\u5F0F\uFF0CToken\u5FC5\u987B\u7531\u6570\u5B57\u548C\u82F1\u6587\u5927\u5199\u5B57\u6BCD\u7EC4\u6210',\n INVALID_QQ: '\u65E0\u6548\u7684QQ\u53F7\u7801\u683C\u5F0F',\n INVALID_SCORE: '\u5206\u6570\u5FC5\u987B\u5728 -1000 \u5230 1000 \u4E4B\u95F4',\n INVALID_USERNAME: '\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A\u4E14\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC750\u4E2A\u5B57\u7B26',\n INVALID_DESCRIPTION: '\u63CF\u8FF0\u4FE1\u606F\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7255\u4E2A\u5B57\u7B26',\n INVALID_LIMIT: '\u6570\u91CF\u5FC5\u987B\u5728 1 \u5230 50 \u4E4B\u95F4',\n SERVER_NOT_FOUND: '\u670D\u52A1\u5668\u672A\u627E\u5230',\n USER_NOT_FOUND: '\u7528\u6237\u672A\u627E\u5230',\n USER_ALREADY_BOUND: '\u8BE5QQ\u53F7\u5DF2\u7ED1\u5B9A\u5176\u4ED6\u7528\u6237',\n USER_NOT_BOUND: '\u8BE5QQ\u53F7\u672A\u7ED1\u5B9A\u4EFB\u4F55\u7528\u6237',\n API_REQUEST_FAILED: 'API\u8BF7\u6C42\u5931\u8D25',\n INSUFFICIENT_PERMISSION: '\u6743\u9650\u4E0D\u8DB3\uFF0C\u4EC5\u7BA1\u7406\u5458\u53EF\u6267\u884C\u6B64\u64CD\u4F5C',\n BINDING_FAILED: '\u7ED1\u5B9A\u5931\u8D25',\n UNBINDING_FAILED: '\u89E3\u9664\u7ED1\u5B9A\u5931\u8D25',\n CONFIGURATION_FAILED: '\u914D\u7F6E\u4FDD\u5B58\u5931\u8D25',\n} as const\n\nexport const SUCCESS_MESSAGES = {\n SERVER_CONFIGURED: '\u670D\u52A1\u5668\u914D\u7F6E\u6210\u529F',\n SERVER_VALIDATED: '\u670D\u52A1\u5668\u914D\u7F6E\u9A8C\u8BC1\u6210\u529F',\n QQ_BOUND: 'QQ\u7ED1\u5B9A\u6210\u529F',\n QQ_UNBOUND: 'QQ\u89E3\u9664\u7ED1\u5B9A\u6210\u529F',\n SCORE_ADJUSTED: '\u79EF\u5206\u8C03\u6574\u6210\u529F',\n USER_CREATED: '\u7528\u6237\u521B\u5EFA\u6210\u529F',\n} as const\n\nexport const HELP_MESSAGES = {\n BIND_SERVER: '\u7ED1\u5B9ACSMS\u670D\u52A1\u5668\\n\u7528\u6CD5\uFF1A/\u7ED1\u5B9A\u670D\u52A1\u5668 <\u670D\u52A1\u5668\u5730\u5740> <\u7BA1\u7406\u5458\u7528\u6237\u540D> <\u7BA1\u7406\u5458Token>\\n\u793A\u4F8B\uFF1A/\u7ED1\u5B9A\u670D\u52A1\u5668 https://example.com admin ABC123',\n QUERY_SCORE: '\u67E5\u8BE2\u79EF\u5206\\n\u7528\u6CD5\uFF1A/\u67E5\u8BE2\u79EF\u5206 [\u7528\u6237\u540D]\\n\u793A\u4F8B\uFF1A/\u67E5\u8BE2\u79EF\u5206 \u5F20\u4E09',\n ADJUST_SCORE: '\u8C03\u6574\u79EF\u5206\\n\u7528\u6CD5\uFF1A/\u8C03\u6574\u79EF\u5206 <\u7528\u6237\u540D> <\u5206\u6570> <\u539F\u56E0>\\n\u793A\u4F8B\uFF1A/\u8C03\u6574\u79EF\u5206 \u5F20\u4E09 +5 \u8868\u73B0\u4F18\u79C0',\n BIND_QQ: '\u7ED1\u5B9AQQ\\n\u7528\u6CD5\uFF1A/\u7ED1\u5B9AQQ <\u7528\u6237\u540D>\\n\u793A\u4F8B\uFF1A/\u7ED1\u5B9AQQ \u5F20\u4E09',\n VIEW_BINDING: '\u67E5\u770B\u7ED1\u5B9A\\n\u7528\u6CD5\uFF1A/\u67E5\u770B\u7ED1\u5B9A [\u7528\u6237\u540D]\\n\u793A\u4F8B\uFF1A/\u67E5\u770B\u7ED1\u5B9A \u5F20\u4E09',\n UNBIND_QQ: '\u89E3\u9664\u7ED1\u5B9A\\n\u7528\u6CD5\uFF1A/\u89E3\u9664\u7ED1\u5B9A <QQ\u53F7>\\n\u793A\u4F8B\uFF1A/\u89E3\u9664\u7ED1\u5B9A 123456789',\n RANKING: '\u6392\u884C\u699C\\n\u7528\u6CD5\uFF1A/\u6392\u884C\u699C [\u6570\u91CF]\\n\u793A\u4F8B\uFF1A/\u6392\u884C\u699C 10',\n STATISTICS: '\u7EDF\u8BA1\\n\u7528\u6CD5\uFF1A/\u7EDF\u8BA1 [\u7528\u6237\u540D]\\n\u793A\u4F8B\uFF1A/\u7EDF\u8BA1 \u5F20\u4E09',\n} as const", "import { CONSTANTS, ERROR_MESSAGES } from './constants'\n\nexport class Validator {\n static validateToken(token: string): boolean {\n return CONSTANTS.TOKEN_PATTERN.test(token)\n }\n\n static validateQq(qqNumber: string): boolean {\n // \u66F4\u5BBD\u677E\u7684\u9A8C\u8BC1\uFF1A\u53EA\u8981\u662F\u6570\u5B57\u6216\u8005\u5305\u542B\u6570\u5B57\u7684\u5B57\u7B26\u4E32\u5373\u53EF\n // \u652F\u6301\u6C99\u76D2\u73AF\u5883\u7684\u7528\u6237ID\u683C\u5F0F\n return qqNumber && qqNumber.length > 0 && /^\\d+$/.test(qqNumber)\n }\n\n static validateScore(score: number): boolean {\n return score >= CONSTANTS.SCORE_MIN && score <= CONSTANTS.SCORE_MAX\n }\n\n static validateUsername(username: string): boolean {\n return username.length > 0 && username.length <= CONSTANTS.USERNAME_MAX_LENGTH\n }\n\n static validateDescription(description: string): boolean {\n return description.length <= CONSTANTS.DESCRIPTION_MAX_LENGTH\n }\n\n static validateLimit(limit: number, max: number = CONSTANTS.RANKING_MAX_LIMIT): boolean {\n return limit > 0 && limit <= max\n }\n\n static validateScoreWithMessage(score: number): string | null {\n if (!this.validateScore(score)) {\n return ERROR_MESSAGES.INVALID_SCORE\n }\n return null\n }\n\n static validateQqWithMessage(qqNumber: string): string | null {\n if (!this.validateQq(qqNumber)) {\n return ERROR_MESSAGES.INVALID_QQ\n }\n return null\n }\n\n static validateTokenWithMessage(token: string): string | null {\n if (!this.validateToken(token)) {\n return ERROR_MESSAGES.INVALID_TOKEN\n }\n return null\n }\n\n static validateUsernameWithMessage(username: string): string | null {\n if (!this.validateUsername(username)) {\n return ERROR_MESSAGES.INVALID_USERNAME\n }\n return null\n }\n\n static validateDescriptionWithMessage(description: string): string | null {\n if (!this.validateDescription(description)) {\n return ERROR_MESSAGES.INVALID_DESCRIPTION\n }\n return null\n }\n\n static validateLimitWithMessage(limit: number, max: number = CONSTANTS.RANKING_MAX_LIMIT): string | null {\n if (!this.validateLimit(limit, max)) {\n return `\u6570\u91CF\u5FC5\u987B\u5728 1 \u5230 ${max} \u4E4B\u95F4`\n }\n return null\n }\n}", "import { CsmsUser, CsmsScoreLog } from '../services/api'\n\nexport class Formatter {\n // QQ \u6D88\u606F\u5355\u6761\u6700\u5927\u957F\u5EA6\u9650\u5236\uFF08\u7559\u6709\u4F59\u91CF\uFF09\n private static readonly MAX_MESSAGE_LENGTH = 1800\n\n static formatScoreInfo(user: CsmsUser, ranking?: number): string {\n return [\n `\u7528\u6237: ${user.username}`,\n `\u6392\u540D: ${ranking || '\u672A\u77E5'}`,\n `\u603B\u79EF\u5206: ${user.total_score}`,\n `\u7D2F\u8BA1\u52A0\u5206: ${user.add_score}`,\n `\u7D2F\u8BA1\u6263\u5206: ${user.deduct_score}`,\n `\u8BB0\u5F55\u6570: ${user.score_count}`,\n ].join('\\n')\n }\n\n static formatRanking(users: CsmsUser[]): string {\n if (users.length === 0) {\n return '\u6682\u65E0\u6392\u540D\u6570\u636E'\n }\n\n const lines = ['\u3010\u79EF\u5206\u6392\u884C\u699C\u3011']\n const displayUsers = users.slice(0, 20) // \u6700\u591A\u663E\u793A20\u4E2A\n\n displayUsers.forEach((user, index) => {\n const medal = index < 3 ? ['\uD83E\uDD47', '\uD83E\uDD48', '\uD83E\uDD49'][index] : `${index + 1}.`\n lines.push(`${medal} ${user.username}: ${user.total_score}\u5206`)\n })\n\n if (users.length > 20) {\n lines.push(`... \u5171 ${users.length} \u4EBA\uFF0C\u663E\u793A\u524D20\u540D`)\n }\n\n return lines.join('\\n')\n }\n\n /**\n * \u683C\u5F0F\u5316\u6392\u884C\u699C\uFF08\u5E26\u5B9E\u9645\u6392\u540D\uFF0C\u7528\u4E8E\u5206\u9875\uFF09\n */\n static formatRankingWithRank(users: CsmsUser[], startRank: number): string {\n if (users.length === 0) {\n return '\u6682\u65E0\u6392\u540D\u6570\u636E'\n }\n\n const lines = ['\u3010\u79EF\u5206\u6392\u884C\u699C\u3011']\n\n users.forEach((user, index) => {\n const rank = startRank + index\n const medal = rank <= 3 ? ['\uD83E\uDD47', '\uD83E\uDD48', '\uD83E\uDD49'][rank - 1] : `${rank}.`\n lines.push(`${medal} ${user.username}: ${user.total_score}\u5206`)\n })\n\n return lines.join('\\n')\n }\n\n static getMedal(index: number): string {\n const medals = ['\uD83E\uDD47', '\uD83E\uDD48', '\uD83E\uDD49']\n return medals[index] || `${index + 1}.`\n }\n\n static formatScoreLogs(logs: CsmsScoreLog[]): string {\n if (logs.length === 0) {\n return '\u6682\u65E0\u79EF\u5206\u8BB0\u5F55'\n }\n\n const lines = ['\u3010\u79EF\u5206\u8BB0\u5F55\u3011']\n const displayLogs = logs.slice(0, 10)\n\n displayLogs.forEach((log) => {\n const change = log.score_change > 0 ? `+${log.score_change}` : log.score_change\n lines.push(`${change}\u5206 - ${log.description}`)\n })\n\n if (logs.length > 10) {\n lines.push(`... \u5171 ${logs.length} \u6761\u8BB0\u5F55`)\n }\n\n return lines.join('\\n')\n }\n\n static formatStatistics(user: CsmsUser, logs: CsmsScoreLog[]): string {\n const lines = [\n `\u3010${user.username} \u7684\u7EDF\u8BA1\u4FE1\u606F\u3011`,\n `\u603B\u79EF\u5206: ${user.total_score}`,\n `\u7D2F\u8BA1\u52A0\u5206: ${user.add_score}`,\n `\u7D2F\u8BA1\u6263\u5206: ${user.deduct_score}`,\n `\u8BB0\u5F55\u6570: ${user.score_count}`,\n '\u6700\u8FD1\u79EF\u5206\u8BB0\u5F55:',\n ]\n\n const recentLogs = logs.slice(0, 5)\n if (recentLogs.length > 0) {\n recentLogs.forEach((log) => {\n const change = log.score_change > 0 ? `+${log.score_change}` : log.score_change\n lines.push(`${change}\u5206 - ${log.description}`)\n })\n } else {\n lines.push('\u6682\u65E0\u8BB0\u5F55')\n }\n\n return lines.join('\\n')\n }\n\n static formatAddScoreResult(result: any): string {\n const status = result.success ? '\u79EF\u5206\u8C03\u6574\u6210\u529F' : '\u79EF\u5206\u8C03\u6574\u5931\u8D25'\n const summary = `\u6210\u529F: ${result.summary.success_count} \u6761\uFF0C\u5931\u8D25: ${result.summary.failed_count} \u6761`\n\n const lines = [status, summary]\n\n // \u5931\u8D25\u65F6\u663E\u793A\u9519\u8BEF\u539F\u56E0\n if (!result.success && result.message) {\n lines.push(`\u539F\u56E0: ${result.message}`)\n }\n\n if (result.details && result.details.length > 0) {\n lines.push('\u8BE6\u60C5:')\n result.details.forEach((detail: any) => {\n if (detail.success) {\n const change = detail.score_change > 0 ? '+' : ''\n lines.push(`[OK] ${detail.username}: ${change}${detail.score_change}\u5206`)\n } else {\n lines.push(`[FAIL] ${detail.username}: ${detail.error || '\u5931\u8D25'}`)\n }\n })\n }\n\n return lines.join('\\n')\n }\n\n static formatDate(dateString: string): string {\n const date = new Date(dateString)\n return date.toLocaleString('zh-CN', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n })\n }\n\n /**\n * \u5B89\u5168\u53D1\u9001\u6D88\u606F\uFF0C\u81EA\u52A8\u5206\u5272\u8FC7\u957F\u7684\u6D88\u606F\n * \u8FD4\u56DE\u6D88\u606F\u7247\u6BB5\u6570\u7EC4\uFF0C\u7531\u8C03\u7528\u8005\u5904\u7406\u53D1\u9001\n */\n static splitMessage(message: string): string[] {\n if (message.length <= this.MAX_MESSAGE_LENGTH) {\n return [message]\n }\n\n const parts = message.split('\\n')\n const result: string[] = []\n let currentPart = ''\n\n for (const line of parts) {\n if ((currentPart + '\\n' + line).length > this.MAX_MESSAGE_LENGTH) {\n if (currentPart) {\n result.push(currentPart)\n }\n currentPart = line\n } else {\n currentPart = currentPart ? currentPart + '\\n' + line : line\n }\n }\n\n if (currentPart) {\n result.push(currentPart)\n }\n\n return result\n }\n}\n", "import { Context } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { GroupAdminService } from '../services/group-admin'\nimport { Validator, HELP_MESSAGES } from '../utils'\n\nexport function registerBindServerCommand(ctx: Context, serverService: ServerConfigService, adminService: GroupAdminService) {\n ctx.command('\u7ED1\u5B9A\u670D\u52A1\u5668 <\u5730\u5740:string> <\u7528\u6237\u540D:string> <token:string>')\n .alias('bind-server')\n .action(async ({ session }, address, username, token) => {\n if (!address || !username || !token) {\n return HELP_MESSAGES.BIND_SERVER\n }\n\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n const openId = session.userId?.toString()\n if (!openId) {\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\n }\n\n // \u68C0\u67E5\u662F\u5426\u5DF2\u6709\u670D\u52A1\u5668\u914D\u7F6E\n const existingConfig = await serverService.getConfigByGuild(session.guildId)\n if (existingConfig) {\n return '\u274C \u8BE5\u7FA4\u804A\u5DF2\u7ED1\u5B9A\u670D\u52A1\u5668\uFF0C\u5982\u9700\u66F4\u6362\u8BF7\u5148\u4F7F\u7528 /\u670D\u52A1\u5668\u89E3\u7ED1'\n }\n\n const tokenError = Validator.validateTokenWithMessage(token)\n if (tokenError) {\n ctx.logger.info(`Token \u683C\u5F0F\u9A8C\u8BC1\u5931\u8D25: ${tokenError}`)\n return `Token \u683C\u5F0F\u9A8C\u8BC1\u5931\u8D25`\n }\n\n try {\n ctx.logger.info(`\u6B63\u5728\u9A8C\u8BC1\u670D\u52A1\u5668\u914D\u7F6E...`)\n \n const result = await serverService.validateConfig(address, username, token)\n if (!result.valid) {\n const errorMsg = result.error || '\u670D\u52A1\u5668\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25'\n ctx.logger.info(`\u670D\u52A1\u5668\u914D\u7F6E\u9A8C\u8BC1\u5931\u8D25: ${errorMsg}`)\n return `\u9A8C\u8BC1\u5931\u8D25: ${errorMsg}`\n }\n\n const actualUsername = result.actualUsername || username\n const config = await serverService.saveConfig(session.guildId, 'CSMS\u670D\u52A1\u5668', address, actualUsername, token)\n \n // \u5C06\u7ED1\u5B9A\u8005\u81EA\u52A8\u6DFB\u52A0\u4E3A\u7BA1\u7406\u5458\n await adminService.addAdmin(session.guildId, openId, '\u7BA1\u7406\u5458')\n ctx.logger.info(`\u7FA4\u804A ${session.guildId} \u7684\u9996\u4E2A\u7ED1\u5B9A\u8005 ${openId} \u88AB\u81EA\u52A8\u6DFB\u52A0\u4E3A\u7BA1\u7406\u5458`)\n \n const domain = config.address.replace(/^https?:\\/\\//, '').split('/')[0]\n ctx.logger.info(`\u670D\u52A1\u5668\u914D\u7F6E\u6210\u529F\uFF0Cdomain=${domain}\uFF0Cusername=${actualUsername}`)\n \n return `\u2705 \u670D\u52A1\u5668\u914D\u7F6E\u6210\u529F`\n } catch (error: any) {\n ctx.logger.error('\u4FDD\u5B58\u670D\u52A1\u5668\u914D\u7F6E\u5931\u8D25:', error)\n return `\u914D\u7F6E\u4FDD\u5B58\u5931\u8D25: ${error.message}`\n }\n })\n\n // \u89E3\u9664\u670D\u52A1\u5668\u7ED1\u5B9A\n ctx.command('\u670D\u52A1\u5668\u89E3\u7ED1')\n .alias('unbind-server')\n .action(async ({ session }) => {\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n // \u6743\u9650\u68C0\u67E5\uFF1A\u5FC5\u987B\u6709\u7BA1\u7406\u5458\u6743\u9650\n const hasPermission = await adminService.hasAdminPermission(session)\n if (!hasPermission) {\n return '\u274C \u6B64\u547D\u4EE4\u4EC5\u9650\u7BA1\u7406\u5458\u4F7F\u7528'\n }\n\n const config = await serverService.getConfigByGuild(session.guildId)\n if (!config) {\n return '\u274C \u8BE5\u7FA4\u804A\u5C1A\u672A\u7ED1\u5B9A\u4EFB\u4F55\u670D\u52A1\u5668'\n }\n\n // \u4E8C\u6B21\u786E\u8BA4\n await session.send('\u26A0\uFE0F \u786E\u5B9A\u8981\u89E3\u9664\u670D\u52A1\u5668\u7ED1\u5B9A\u5417\uFF1F\u89E3\u7ED1\u540E\u5176\u4ED6\u4EBA\u53EF\u91CD\u65B0\u7ED1\u5B9A\u3002\u8BF7\u5728 30 \u79D2\u5185\u8F93\u5165\u300C\u786E\u8BA4\u300D\u6765\u5B8C\u6210\u64CD\u4F5C')\n const reply = await session.prompt(30000)\n if (reply?.trim() !== '\u786E\u8BA4') {\n return '\u2705 \u5DF2\u53D6\u6D88\u89E3\u7ED1\u64CD\u4F5C'\n }\n\n await serverService.deleteConfig(session.guildId)\n ctx.logger.info(`\u7FA4\u804A ${session.guildId} \u89E3\u9664\u4E86\u670D\u52A1\u5668\u7ED1\u5B9A`)\n return `\u2705 \u5DF2\u89E3\u9664\u670D\u52A1\u5668\u7ED1\u5B9A`\n })\n}\n", "import { Context, h } from 'koishi'\r\n\r\n// \u901A\u7528\u7AD6\u7248\u56FE\u7247\u751F\u6210\u51FD\u6570\r\nexport async function generateImage(\r\n ctx: Context,\r\n html: string,\r\n options: { width?: number; height?: number } = {}\r\n): Promise<Buffer | null> {\r\n const width = options.width || 450\r\n const height = options.height || 800\r\n\r\n try {\r\n const page = await (ctx as any).puppeteer.page()\r\n\r\n await page.setViewport({\r\n width,\r\n height,\r\n deviceScaleFactor: 2,\r\n })\r\n\r\n await page.setContent(html, { waitUntil: 'networkidle0' })\r\n await page.evaluateHandle('document.fonts.ready')\r\n\r\n // \u7B49\u5F85\u80CC\u666F\u56FE\u7247\u52A0\u8F7D\r\n await page.evaluate(() => {\r\n return new Promise<void>((resolve) => {\r\n const img = document.querySelector('body') as HTMLElement\r\n if (img && img.style.backgroundImage) {\r\n const bgImg = new Image()\r\n bgImg.onload = () => resolve()\r\n bgImg.onerror = () => resolve()\r\n bgImg.src = img.style.backgroundImage.replace(/url\\(['\"]?(.+?)['\"]?\\)/, '$1')\r\n } else {\r\n resolve()\r\n }\r\n })\r\n })\r\n\r\n const screenshot = await page.screenshot({\r\n type: 'png',\r\n clip: { x: 0, y: 0, width, height },\r\n })\r\n\r\n return screenshot as Buffer\r\n } catch (error) {\r\n ctx.logger.error('\u751F\u6210\u56FE\u7247\u5931\u8D25:', error)\r\n return null\r\n }\r\n}\r\n\r\n// \u53D1\u9001\u56FE\u7247\uFF08\u4F18\u5148\u56FE\u7247\uFF0C\u5931\u8D25\u56DE\u9000\u6587\u5B57\uFF09\r\nexport async function sendImageOrText(\r\n ctx: Context,\r\n session: any,\r\n html: string,\r\n fallbackText: string,\r\n options: { width?: number; height?: number } = {}\r\n): Promise<void> {\r\n const image = await generateImage(ctx, html, options)\r\n if (image) {\r\n await session.send(h.image(image, 'image/png'))\r\n } else {\r\n await session.send(fallbackText)\r\n }\r\n}\r\n\r\n// \u901A\u7528\u57FA\u7840\u6A21\u677F\u6837\u5F0F\r\nexport function getBaseStyles(): string {\r\n return `\r\n * { margin: 0; padding: 0; box-sizing: border-box; }\r\n body {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\r\n background: url('https://api.yppp.net/pe.php') center/cover no-repeat;\r\n width: 450px;\r\n min-height: 800px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: flex-start;\r\n padding: 40px 0;\r\n }\r\n .container {\r\n background: rgba(255, 255, 255, 0.5);\r\n border-radius: 24px;\r\n padding: 28px 24px;\r\n width: 380px;\r\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);\r\n margin: 0 auto;\r\n }\r\n .title {\r\n text-align: center;\r\n font-size: 22px;\r\n font-weight: bold;\r\n color: #2c3e50;\r\n margin-bottom: 20px;\r\n padding-bottom: 12px;\r\n border-bottom: 2px solid #3498db;\r\n }\r\n .content {\r\n color: #555;\r\n font-size: 14px;\r\n line-height: 1.8;\r\n white-space: pre-wrap;\r\n word-break: break-all;\r\n }\r\n .footer {\r\n text-align: center;\r\n margin-top: 16px;\r\n padding-top: 12px;\r\n border-top: 1px solid rgba(0,0,0,0.1);\r\n color: #95a5a6;\r\n font-size: 10px;\r\n }\r\n `\r\n}\r\n", "import { Context, h } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { QqBindingService } from '../services/binding'\nimport { Formatter, ERROR_MESSAGES, CONSTANTS } from '../utils'\nimport { generateImage, getBaseStyles, sendImageOrText } from '../utils/image'\n\nexport function registerQueryScoreCommand(\n ctx: Context,\n serverService: ServerConfigService,\n bindingService: QqBindingService\n) {\n ctx.command('\u67E5\u8BE2\u79EF\u5206 [\u7528\u6237\u540D:string]')\n .alias('query-score')\n .action(async ({ session }, username) => {\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n const api = await serverService.createApiService(session.guildId)\n if (!api) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n try {\n let targetUsername = username\n\n if (!username) {\n const openId = session.userId?.toString()\n if (!openId) {\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\n }\n\n const binding = await bindingService.getUserByOpenId(session.guildId, openId)\n if (!binding) {\n return `${ERROR_MESSAGES.USER_NOT_BOUND}\u3002\u8BF7\u5148\u4F7F\u7528 /\u7ED1\u5B9AQQ <\u7528\u6237\u540D> \u547D\u4EE4\u7ED1\u5B9A\u60A8\u7684\u8D26\u53F7`\n }\n\n targetUsername = binding.username\n }\n\n const response = await api.getUserByUsername(targetUsername)\n if (response.error || !response.data || response.data.length === 0) {\n return ERROR_MESSAGES.USER_NOT_FOUND\n }\n\n const user = response.data[0]\n\n const rankingResponse = await api.getRanking(CONSTANTS.RANKING_MAX_LIMIT, 0)\n let ranking = 0\n if (!rankingResponse.error && rankingResponse.data) {\n const index = rankingResponse.data.findIndex((u) => u.id === user.id)\n ranking = index >= 0 ? index + 1 : 0\n }\n\n const textResult = Formatter.formatScoreInfo(user, ranking)\n\n // \u751F\u6210\u56FE\u7247\n const html = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <style>\n ${getBaseStyles()}\n .info-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-top: 16px;\n }\n .info-item {\n background: rgba(52, 152, 219, 0.1);\n border-radius: 12px;\n padding: 16px;\n text-align: center;\n }\n .info-label {\n color: #7f8c8d;\n font-size: 12px;\n margin-bottom: 8px;\n }\n .info-value {\n color: #2c3e50;\n font-size: 24px;\n font-weight: bold;\n }\n .info-value.score {\n color: #3498db;\n }\n .info-value.rank {\n color: #9b59b6;\n }\n .username {\n text-align: center;\n font-size: 20px;\n font-weight: bold;\n color: #2c3e50;\n margin-bottom: 4px;\n }\n .subtitle {\n text-align: center;\n color: #95a5a6;\n font-size: 12px;\n margin-bottom: 20px;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"title\">\uD83D\uDCCA \u79EF\u5206\u67E5\u8BE2\u7ED3\u679C</div>\n <div class=\"username\">${user.username}</div>\n <div class=\"subtitle\">\u7528\u6237ID: ${user.id}</div>\n <div class=\"info-grid\">\n <div class=\"info-item\">\n <div class=\"info-label\">\u5F53\u524D\u79EF\u5206</div>\n <div class=\"info-value score\">${user.total_score}</div>\n </div>\n <div class=\"info-item\">\n <div class=\"info-label\">\u6392\u884C\u699C</div>\n <div class=\"info-value rank\">#${ranking}</div>\n </div>\n </div>\n <div class=\"footer\">\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF v1.0</div>\n </div>\n</body>\n</html>`\n\n await sendImageOrText(ctx, session, html, textResult, { height: 600 })\n\n return ''\n } catch (error: any) {\n ctx.logger.error('\u67E5\u8BE2\u79EF\u5206\u5931\u8D25:', error)\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n })\n}\n", "import { Context } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { QqBindingService } from '../services/binding'\nimport { Validator, ERROR_MESSAGES, SUCCESS_MESSAGES, HELP_MESSAGES } from '../utils'\n\nexport function registerBindQqCommand(\n ctx: Context,\n serverService: ServerConfigService,\n bindingService: QqBindingService\n) {\n ctx.command('\u7ED1\u5B9AQQ <\u7528\u6237\u540D:string>')\n .alias('bind-qq')\n .action(async ({ session }, username) => {\n if (!username) {\n return HELP_MESSAGES.BIND_QQ\n }\n \n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n \n const usernameError = Validator.validateUsernameWithMessage(username)\n if (usernameError) {\n return usernameError\n }\n \n const openId = session.userId?.toString()\n if (!openId) {\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\n }\n \n ctx.logger.info(`\u83B7\u53D6\u5230\u7684\u7528\u6237 OpenID: ${openId}`)\n\n const config = await serverService.getConfigByGuild(session.guildId)\n if (!config) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n try {\n // \u68C0\u67E5\u662F\u5426\u5DF2\u7ECF\u7ED1\u5B9A\n const existingBinding = await bindingService.getUserByOpenId(session.guildId, openId)\n if (existingBinding) {\n return `\u274C \u60A8\u5DF2\u7ED1\u5B9A\u300C${existingBinding.username}\u300D\uFF0C\u5982\u9700\u66F4\u6362\u8D26\u53F7\u8BF7\u5148\u4F7F\u7528 /\u89E3\u9664\u7ED1\u5B9A \u89E3\u7ED1\u540E\u91CD\u65B0\u7ED1\u5B9A`\n }\n\n // \u68C0\u67E5\u8BE5\u7528\u6237\u540D\u662F\u5426\u5DF2\u88AB\u5176\u4ED6QQ\u7ED1\u5B9A\n const existingBindings = await bindingService.getBindingsByUsername(session.guildId, username)\n if (existingBindings.length > 0) {\n return `\u274C \u7528\u6237\u540D\u300C${username}\u300D\u5DF2\u88AB\u5176\u4ED6QQ\u8D26\u53F7\u7ED1\u5B9A\uFF0C\u6BCF\u4E2A\u7528\u6237\u540D\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2AQQ`\n }\n\n const api = await serverService.createApiService(session.guildId)\n if (!api) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n const response = await api.getUserByUsername(username)\n if (response.error || !response.data || response.data.length === 0) {\n return ERROR_MESSAGES.USER_NOT_FOUND\n }\n\n const user = response.data[0]\n\n await bindingService.bindQq(session.guildId, user.id, username, openId, config.id)\n\n return `\u2705 \u7ED1\u5B9A\u6210\u529F\\n\u7528\u6237\u540D: ${username}`\n } catch (error: any) {\n ctx.logger.error('\u7ED1\u5B9AQQ\u5931\u8D25:', error)\n return ERROR_MESSAGES.BINDING_FAILED\n }\n })\n\n // \u89E3\u9664\u7528\u6237\u7ED1\u5B9A\n ctx.command('\u89E3\u9664\u7ED1\u5B9A')\n .alias('unbind')\n .action(async ({ session }, username?: string) => {\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n const openId = session.userId?.toString()\n if (!openId) {\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\n }\n\n let binding = null\n\n // \u5982\u679C\u6307\u5B9A\u4E86\u7528\u6237\u540D\uFF0C\u5C1D\u8BD5\u89E3\u7ED1\u6307\u5B9A\u7528\u6237\n if (username) {\n const bindings = await bindingService.getBindingsByUsername(session.guildId, username)\n binding = bindings.find(b => b.openId === openId)\n } else {\n // \u672A\u6307\u5B9A\u7528\u6237\u540D\uFF0C\u89E3\u7ED1\u5F53\u524D\u7528\u6237\u7684\u7ED1\u5B9A\n binding = await bindingService.getUserByOpenId(session.guildId, openId)\n }\n\n if (!binding) {\n return `\u274C \u60A8\u5C1A\u672A\u7ED1\u5B9A\u4EFB\u4F55\u8D26\u53F7${username ? `\uFF08\u7528\u6237\uFF1A${username}\uFF09` : ''}`\n }\n\n // \u4E8C\u6B21\u786E\u8BA4\n await session.send(`\u26A0\uFE0F \u786E\u5B9A\u8981\u89E3\u9664\u300C${binding.username}\u300D\u7684\u7ED1\u5B9A\u5417\uFF1F\u8BF7\u5728 30 \u79D2\u5185\u8F93\u5165\u300C\u786E\u8BA4\u300D\u6765\u5B8C\u6210\u64CD\u4F5C`)\n const reply = await session.prompt(30000)\n if (reply?.trim() !== '\u786E\u8BA4') {\n return '\u2705 \u5DF2\u53D6\u6D88\u89E3\u7ED1\u64CD\u4F5C'\n }\n\n await bindingService.unbindQq(session.guildId, openId)\n ctx.logger.info(`\u7528\u6237 ${binding.username}\uFF08OpenID: ${openId}\uFF09\u89E3\u9664\u4E86\u7ED1\u5B9A`)\n return `\u2705 \u5DF2\u89E3\u9664\u300C${binding.username}\u300D\u7684\u7ED1\u5B9A`\n })\n}", "import { Context } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { GroupAdminService } from '../services/group-admin'\nimport { Formatter, Validator, ERROR_MESSAGES, SUCCESS_MESSAGES, HELP_MESSAGES } from '../utils'\n\nexport function registerAdjustScoreCommand(ctx: Context, serverService: ServerConfigService, adminService: GroupAdminService) {\n ctx.command('\u8C03\u6574\u79EF\u5206 <\u7528\u6237\u540D:string> <\u5206\u6570:number> <\u539F\u56E0:text>')\n .alias('adjust-score')\n .action(async ({ session }, username, score, reason) => {\n if (!username || score === undefined || !reason) {\n return HELP_MESSAGES.ADJUST_SCORE\n }\n\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n // \u6743\u9650\u68C0\u67E5\uFF1A\u7FA4\u4E3B\u3001\u7BA1\u7406\u5458\u6216\u81EA\u5B9A\u4E49\u7FA4\u7BA1\n const hasPermission = await adminService.hasAdminPermission(session)\n if (!hasPermission) {\n return ERROR_MESSAGES.INSUFFICIENT_PERMISSION\n }\n\n const usernameError = Validator.validateUsernameWithMessage(username)\n if (usernameError) {\n return usernameError\n }\n\n const scoreError = Validator.validateScoreWithMessage(score)\n if (scoreError) {\n return scoreError\n }\n\n const descriptionError = Validator.validateDescriptionWithMessage(reason)\n if (descriptionError) {\n return descriptionError\n }\n\n const api = await serverService.createApiService(session.guildId)\n if (!api) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n try {\n const data = {\n users: [\n {\n username,\n score_change: score,\n },\n ],\n description: reason,\n }\n\n ctx.logger.info(`\u8C03\u6574\u79EF\u5206\u8BF7\u6C42: \u7528\u6237=${username}, \u5206\u6570=${score}, \u539F\u56E0=${reason}`)\n \n const result = await api.batchAddScore(data)\n ctx.logger.info(`\u8C03\u6574\u79EF\u5206\u7ED3\u679C:`, JSON.stringify(result))\n \n const message = Formatter.formatAddScoreResult(result)\n return Formatter.splitMessage(message)\n } catch (error: any) {\n ctx.logger.error('\u8C03\u6574\u79EF\u5206\u5931\u8D25:', error)\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n })\n\n}\n", "import { Context, h } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { Formatter, ERROR_MESSAGES, CONSTANTS } from '../utils'\nimport { getBaseStyles, sendImageOrText } from '../utils/image'\n\nconst PAGE_SIZE = 10\n\nexport function registerRankingCommand(ctx: Context, serverService: ServerConfigService) {\n ctx.command('\u6392\u884C\u699C [\u9875\u7801:number]')\n .alias('ranking')\n .action(async ({ session }, page = 1) => {\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n const api = await serverService.createApiService(session.guildId)\n if (!api) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n try {\n // \u5148\u83B7\u53D6\u603B\u6570\n const allResponse = await api.getRanking(10000, 0)\n if (allResponse.error || !allResponse.data) {\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n\n const totalUsers = allResponse.data.length\n const totalPages = Math.ceil(totalUsers / PAGE_SIZE)\n\n // \u9A8C\u8BC1\u9875\u7801\n if (page < 1) page = 1\n if (page > totalPages && totalPages > 0) page = totalPages\n\n // \u8BA1\u7B97\u504F\u79FB\u91CF\n const offset = (page - 1) * PAGE_SIZE\n const response = await api.getRanking(PAGE_SIZE, offset)\n if (response.error || !response.data) {\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n\n if (response.data.length === 0) {\n return `\u6682\u65E0\u6392\u884C\u6570\u636E`\n }\n\n // \u683C\u5F0F\u5316\u6570\u636E\uFF0C\u5305\u542B\u5B9E\u9645\u6392\u540D\n const startRank = offset + 1\n const message = Formatter.formatRankingWithRank(response.data, startRank)\n\n // \u751F\u6210\u5206\u9875\u4FE1\u606F\n const pageInfo = totalPages > 1\n ? `\u7B2C ${page}/${totalPages} \u9875\uFF0C\u5171 ${totalUsers} \u4EBA`\n : `\u5171 ${totalUsers} \u4EBA`\n\n // \u751F\u6210\u56FE\u7247 HTML\n const rankItems = response.data.map((user, index) => {\n const rank = startRank + index\n const medal = rank === 1 ? '\uD83E\uDD47' : rank === 2 ? '\uD83E\uDD48' : rank === 3 ? '\uD83E\uDD49' : `${rank}.`\n const scoreColor = user.total_score >= 0 ? '#27ae60' : '#e74c3c'\n return `\n <div class=\"rank-item\">\n <span class=\"rank-num\">${medal}</span>\n <span class=\"rank-name\">${user.username}</span>\n <span class=\"rank-score\" style=\"color: ${scoreColor}\">${user.total_score >= 0 ? '+' : ''}${user.total_score}</span>\n </div>`\n }).join('')\n\n const html = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <style>\n ${getBaseStyles()}\n .rank-list {\n max-height: 550px;\n overflow-y: auto;\n }\n .rank-item {\n display: flex;\n align-items: center;\n padding: 10px 12px;\n margin-bottom: 8px;\n background: rgba(52, 152, 219, 0.08);\n border-radius: 10px;\n }\n .rank-num {\n width: 40px;\n font-size: 16px;\n font-weight: bold;\n color: #3498db;\n }\n .rank-name {\n flex: 1;\n color: #2c3e50;\n font-size: 14px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .rank-score {\n font-size: 14px;\n font-weight: bold;\n margin-left: 12px;\n }\n .page-info {\n text-align: center;\n color: #95a5a6;\n font-size: 12px;\n margin-top: 16px;\n padding-top: 12px;\n border-top: 1px dashed #eee;\n }\n .title-icon {\n font-size: 28px;\n display: block;\n margin-bottom: 8px;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"title\"><span class=\"title-icon\">\uD83C\uDFC6</span>\u79EF\u5206\u6392\u884C\u699C</div>\n <div class=\"rank-list\">\n ${rankItems}\n </div>\n <div class=\"page-info\">${pageInfo}</div>\n <div class=\"footer\">\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF v1.0</div>\n </div>\n</body>\n</html>`\n\n const textResult = message + (totalPages > 1 ? `\\n\\n\uD83D\uDCC4 ${pageInfo}` : '')\n await sendImageOrText(ctx, session, html, textResult, { height: 820 })\n\n return ''\n } catch (error: any) {\n ctx.logger.error('\u83B7\u53D6\u6392\u884C\u699C\u5931\u8D25:', error)\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n })\n}\n", "import { Context, h } from 'koishi'\nimport { ServerConfigService } from '../services/server'\nimport { QqBindingService } from '../services/binding'\nimport { ERROR_MESSAGES } from '../utils'\nimport { getBaseStyles, sendImageOrText } from '../utils/image'\n\nexport function registerStatisticsCommand(\n ctx: Context,\n serverService: ServerConfigService,\n bindingService: QqBindingService\n) {\n ctx.command('\u7EDF\u8BA1 [\u7528\u6237\u540D:string]')\n .alias('statistics')\n .action(async ({ session }, username) => {\n if (!session.guildId) {\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\n }\n\n const api = await serverService.createApiService(session.guildId)\n if (!api) {\n return ERROR_MESSAGES.NO_SERVER_CONFIG\n }\n\n try {\n let targetUsername = username\n\n if (!username) {\n const openId = session.userId?.toString()\n if (!openId) {\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\n }\n\n const binding = await bindingService.getUserByOpenId(session.guildId, openId)\n if (!binding) {\n return `${ERROR_MESSAGES.USER_NOT_BOUND}\\n\\n\u8BF7\u5148\u4F7F\u7528 /\u7ED1\u5B9AQQ <\u7528\u6237\u540D> \u547D\u4EE4\u7ED1\u5B9A\u60A8\u7684\u8D26\u53F7`\n }\n\n targetUsername = binding.username\n }\n\n const userResponse = await api.getUserByUsername(targetUsername)\n if (userResponse.error || !userResponse.data || userResponse.data.length === 0) {\n return ERROR_MESSAGES.USER_NOT_FOUND\n }\n\n const user = userResponse.data[0]\n\n // \u76F4\u63A5\u4F7F\u7528\u7528\u6237\u4FE1\u606F\u4E2D\u7684\u7EDF\u8BA1\u5B57\u6BB5\n const totalScore = Number(user.total_score) || 0\n const addScore = Number(user.add_score) || 0\n const deductScore = Math.abs(Number(user.deduct_score)) || 0\n const scoreCount = Number(user.score_count) || 0\n\n // \u751F\u6210\u56FE\u7247 HTML\n const html = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <style>\n ${getBaseStyles()}\n .user-info {\n text-align: center;\n margin-bottom: 20px;\n }\n .username {\n font-size: 20px;\n font-weight: bold;\n color: #2c3e50;\n }\n .user-id {\n color: #95a5a6;\n font-size: 11px;\n margin-top: 4px;\n }\n .stats-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px;\n margin-top: 16px;\n }\n .stat-card {\n background: rgba(52, 152, 219, 0.1);\n border-radius: 12px;\n padding: 14px;\n text-align: center;\n }\n .stat-card.positive {\n background: rgba(39, 174, 96, 0.1);\n }\n .stat-card.negative {\n background: rgba(231, 76, 60, 0.1);\n }\n .stat-card.total {\n background: rgba(155, 89, 182, 0.1);\n }\n .stat-label {\n color: #7f8c8d;\n font-size: 11px;\n margin-bottom: 6px;\n }\n .stat-value {\n font-size: 20px;\n font-weight: bold;\n color: #2c3e50;\n }\n .stat-value.positive { color: #27ae60; }\n .stat-value.negative { color: #e74c3c; }\n .stat-value.total { color: #9b59b6; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"title\">\uD83D\uDCCA \u79EF\u5206\u7EDF\u8BA1</div>\n <div class=\"user-info\">\n <div class=\"username\">${user.username}</div>\n <div class=\"user-id\">\u7528\u6237ID: ${user.id} | \u5F53\u524D\u79EF\u5206: ${user.total_score}</div>\n </div>\n <div class=\"stats-grid\">\n <div class=\"stat-card positive\">\n <div class=\"stat-label\">\u7D2F\u8BA1\u52A0\u5206</div>\n <div class=\"stat-value positive\">+${addScore}</div>\n </div>\n <div class=\"stat-card negative\">\n <div class=\"stat-label\">\u7D2F\u8BA1\u6263\u5206</div>\n <div class=\"stat-value negative\">-${deductScore}</div>\n </div>\n <div class=\"stat-card total\">\n <div class=\"stat-label\">\u603B\u79EF\u5206</div>\n <div class=\"stat-value total\">${totalScore}</div>\n </div>\n <div class=\"stat-card\">\n <div class=\"stat-label\">\u64CD\u4F5C\u6B21\u6570</div>\n <div class=\"stat-value\">${scoreCount}</div>\n </div>\n </div>\n <div class=\"footer\">\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF v1.0</div>\n </div>\n</body>\n</html>`\n\n const textResult = [\n `\u3010${user.username} \u7684\u7EDF\u8BA1\u4FE1\u606F\u3011`,\n `\u603B\u79EF\u5206: ${user.total_score}`,\n `\u7D2F\u8BA1\u52A0\u5206: +${addScore}`,\n `\u7D2F\u8BA1\u6263\u5206: -${deductScore}`,\n `\u64CD\u4F5C\u6B21\u6570: ${scoreCount}`,\n ].join('\\n')\n\n await sendImageOrText(ctx, session, html, textResult, { height: 550 })\n\n return ''\n } catch (error: any) {\n ctx.logger.error('\u83B7\u53D6\u7EDF\u8BA1\u4FE1\u606F\u5931\u8D25:', error)\n return ERROR_MESSAGES.API_REQUEST_FAILED\n }\n })\n}\n", "import { Context, h } from 'koishi'\r\nimport { GroupAdminService } from '../services/group-admin'\r\nimport { getBaseStyles, sendImageOrText } from '../utils/image'\r\n\r\n// \u5F85\u786E\u8BA4\u7684\u52A0\u7BA1\u8BF7\u6C42\u961F\u5217\uFF1Akey = \u786E\u8BA4\u7801, value = { guildId, remark, createdAt }\r\nconst pendingRequests = new Map<string, {\r\n guildId: string\r\n remark: string\r\n createdAt: number\r\n}>()\r\n\r\n// \u751F\u6210\u968F\u673A\u786E\u8BA4\u7801\r\nfunction generateCode(): string {\r\n const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' // \u6392\u9664\u6613\u6DF7\u6DC6\u5B57\u7B26\r\n let code = ''\r\n for (let i = 0; i < 6; i++) {\r\n code += chars.charAt(Math.floor(Math.random() * chars.length))\r\n }\r\n return code\r\n}\r\n\r\n// \u6E05\u7406\u8FC7\u671F\u7684\u8BF7\u6C42\uFF08120\u79D2\u8D85\u65F6\uFF09\r\nfunction cleanupExpiredRequests() {\r\n const now = Date.now()\r\n for (const [code, req] of pendingRequests) {\r\n if (now - req.createdAt > 120000) {\r\n pendingRequests.delete(code)\r\n }\r\n }\r\n}\r\n\r\nsetInterval(cleanupExpiredRequests, 30000)\r\n\r\nexport function registerGroupAdminCommand(ctx: Context, adminService: GroupAdminService) {\r\n // \u83B7\u53D6 @ \u5143\u7D20\u7684 ID\r\n function getAtId(session: any): string {\r\n if (session.elements) {\r\n const atElements = h.select(session.elements, 'at')\r\n if (atElements.length > 0) {\r\n return String(atElements[0].attrs?.id || '')\r\n }\r\n }\r\n return ''\r\n }\r\n\r\n // \u6DFB\u52A0\u7FA4\u7BA1\uFF08\u7B2C\u4E00\u6B65\uFF1A\u751F\u6210\u786E\u8BA4\u7801\uFF09\r\n ctx.command('\u52A0\u7BA1 [\u5907\u6CE8:string]')\r\n .alias('add-admin')\r\n .action(async ({ session }, remark?: string) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const hasPermission = await adminService.hasAdminPermission(session)\r\n if (!hasPermission) {\r\n return '\u274C \u6B64\u547D\u4EE4\u4EC5\u9650\u7BA1\u7406\u5458\u4F7F\u7528'\r\n }\r\n\r\n // \u83B7\u53D6 @ \u7684\u7528\u6237\r\n const targetId = getAtId(session)\r\n if (!targetId) {\r\n return '\u8BF7\u7528 @ \u6307\u5B9A\u8981\u6DFB\u52A0\u4E3A\u7FA4\u7BA1\u7684\u7528\u6237\uFF1A/\u52A0\u7BA1 @\u67D0\u4EBA'\r\n }\r\n\r\n // \u6E05\u7406\u8FC7\u671F\u8BF7\u6C42\r\n cleanupExpiredRequests()\r\n\r\n // \u68C0\u67E5\u662F\u5426\u5DF2\u6709\u8BE5\u76EE\u6807\u7528\u6237\u7684\u5F85\u786E\u8BA4\u8BF7\u6C42\r\n for (const [, req] of pendingRequests) {\r\n if (req.guildId === session.guildId) {\r\n // \u68C0\u67E5\u8BE5\u7528\u6237\u662F\u5426\u5DF2\u5B58\u5728\u5F85\u786E\u8BA4\u8BB0\u5F55\uFF08\u901A\u8FC7 OpenID \u67E5\uFF09\r\n const admins = await adminService.getAllAdmins(session.guildId)\r\n const existing = admins.find(a => a.verify === 0)\r\n if (existing) {\r\n return `\u274C \u8BE5\u7528\u6237\u5DF2\u6709\u6B63\u5728\u7B49\u5F85\u786E\u8BA4\u7684\u52A0\u7BA1\u8BF7\u6C42`\r\n }\r\n }\r\n }\r\n\r\n // \u4F7F\u7528\u5907\u6CE8\uFF08\u7BA1\u7406\u5458\u6307\u5B9A\uFF09\r\n const adminRemark = remark || '\u672A\u547D\u540D'\r\n\r\n // \u751F\u6210\u786E\u8BA4\u7801\u5E76\u5B58\u50A8\r\n const code = generateCode()\r\n pendingRequests.set(code, {\r\n guildId: session.guildId,\r\n remark: adminRemark,\r\n createdAt: Date.now()\r\n })\r\n\r\n // @\u88AB\u52A0\u7BA1\u7528\u6237\u5E76\u663E\u793A\u786E\u8BA4\u7801\r\n await session.send(\r\n `\u2705 \u5DF2\u53D1\u8D77\u52A0\u7BA1\u8BF7\u6C42\\n` +\r\n h.at(targetId) + ` \u8BF7\u53D1\u9001 /\u786E\u8BA4 ${code} \u540C\u610F\u52A0\u7BA1\\n` +\r\n `\u5907\u6CE8\uFF1A${adminRemark}\\n` +\r\n `\uFF08120\u79D2\u5185\u6709\u6548\uFF09`\r\n )\r\n return ''\r\n })\r\n\r\n // \u786E\u8BA4\u52A0\u7BA1\uFF08\u7B2C\u4E8C\u6B65\uFF1A\u88AB\u52A0\u7BA1\u7528\u6237\u540C\u610F\uFF0C\u83B7\u53D6 OpenID\uFF09\r\n ctx.command('\u786E\u8BA4 [\u786E\u8BA4\u7801:string]')\r\n .alias('confirm')\r\n .action(async ({ session }, code?: string) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const openId = session.userId?.toString()\r\n if (!openId) {\r\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\r\n }\r\n\r\n if (!code) {\r\n return '\u8BF7\u63D0\u4F9B\u786E\u8BA4\u7801\uFF1A/\u786E\u8BA4 [\u786E\u8BA4\u7801]'\r\n }\r\n\r\n // \u6E05\u7406\u8FC7\u671F\u8BF7\u6C42\r\n cleanupExpiredRequests()\r\n\r\n // \u67E5\u627E\u786E\u8BA4\u7801\u5BF9\u5E94\u7684\u8BF7\u6C42\r\n const req = pendingRequests.get(code)\r\n if (!req) {\r\n return '\u274C \u65E0\u6548\u7684\u786E\u8BA4\u7801\u6216\u5DF2\u8FC7\u671F'\r\n }\r\n\r\n // \u68C0\u67E5\u662F\u5426\u5728\u540C\u4E00\u7FA4\r\n if (req.guildId !== session.guildId) {\r\n return '\u274C \u8BF7\u5728\u53D1\u8D77\u52A0\u7BA1\u8BF7\u6C42\u7684\u7FA4\u804A\u4E2D\u786E\u8BA4'\r\n }\r\n\r\n // \u4FDD\u5B58\u5907\u6CE8\r\n const remark = req.remark\r\n\r\n // \u5220\u9664\u8BF7\u6C42\r\n pendingRequests.delete(code)\r\n\r\n // \u521B\u5EFA\u5F85\u786E\u8BA4\u8BB0\u5F55\uFF0CVerify = 0\uFF08\u4F7F\u7528\u7BA1\u7406\u5458\u6307\u5B9A\u7684\u5907\u6CE8\uFF09\r\n await adminService.createPendingAdmin(session.guildId, openId, remark)\r\n ctx.logger.info(`\u7FA4\u804A ${session.guildId} \u7528\u6237\u540C\u610F\u52A0\u7BA1: OpenID=${openId}, \u5907\u6CE8=${remark}, Verify=0`)\r\n\r\n await session.send(\r\n `\u2705 \u60A8\u5DF2\u540C\u610F\u52A0\u7BA1\\n` +\r\n `\u60A8\u7684 OpenID\uFF1A${openId}\\n` +\r\n `\u5907\u6CE8\uFF1A${remark}\\n` +\r\n `\u7B49\u5F85\u7BA1\u7406\u5458\u6267\u884C /\u52A0\u7BA1\u786E\u8BA4 \u5B8C\u6210\u52A0\u7BA1\\n` +\r\n `\uFF08120\u79D2\u5185\u6709\u6548\uFF09`\r\n )\r\n return ''\r\n })\r\n\r\n // \u6700\u7EC8\u786E\u8BA4\u52A0\u7BA1\uFF08\u7B2C\u4E09\u6B65\uFF1A\u7BA1\u7406\u5458\u6700\u7EC8\u786E\u8BA4\uFF0C\u5C06 Verify \u6539\u4E3A 1\uFF09\r\n ctx.command('\u52A0\u7BA1\u786E\u8BA4 [\u786E\u8BA4\u7801:string]')\r\n .alias('confirm-add-admin')\r\n .action(async ({ session }, code?: string) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const hasPermission = await adminService.hasAdminPermission(session)\r\n if (!hasPermission) {\r\n return '\u274C \u6B64\u547D\u4EE4\u4EC5\u9650\u7BA1\u7406\u5458\u4F7F\u7528'\r\n }\r\n\r\n if (!code) {\r\n return '\u8BF7\u63D0\u4F9B\u786E\u8BA4\u7801\uFF1A/\u52A0\u7BA1\u786E\u8BA4 [\u786E\u8BA4\u7801]'\r\n }\r\n\r\n // \u83B7\u53D6\u6240\u6709\u7BA1\u7406\u5458\uFF0C\u627E\u5230 Verify = 0 \u7684\u90A3\u4E2A\r\n const admins = await adminService.getAllAdmins(session.guildId)\r\n const pendingAdmin = admins.find(a => a.verify === 0)\r\n\r\n if (!pendingAdmin) {\r\n return '\u274C \u6CA1\u6709\u5F85\u786E\u8BA4\u7684\u52A0\u7BA1\u8BF7\u6C42'\r\n }\r\n\r\n // \u786E\u8BA4\u8BE5\u7BA1\u7406\u5458\uFF08\u5C06 Verify \u6539\u4E3A 1\uFF09\r\n await adminService.confirmAdmin(session.guildId, pendingAdmin.openId)\r\n ctx.logger.info(`\u7FA4\u804A ${session.guildId} \u6DFB\u52A0\u7FA4\u7BA1\u5B8C\u6210: OpenID=${pendingAdmin.openId}, \u5907\u6CE8=${pendingAdmin.remark}, Verify=1`)\r\n\r\n return `\u2705 \u52A0\u7BA1\u6210\u529F\\n\u5907\u6CE8\uFF1A${pendingAdmin.remark}\\nOpenID\uFF1A${pendingAdmin.openId}`\r\n })\r\n\r\n // \u79FB\u9664\u7FA4\u7BA1\uFF08\u6309\u5907\u6CE8\uFF09\r\n ctx.command('\u51CF\u7BA1 [\u5907\u6CE8:string]')\r\n .alias('remove-admin')\r\n .action(async ({ session }, remark?: string) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const hasPermission = await adminService.hasAdminPermission(session)\r\n if (!hasPermission) {\r\n return '\u274C \u6B64\u547D\u4EE4\u4EC5\u9650\u7BA1\u7406\u5458\u4F7F\u7528'\r\n }\r\n\r\n if (!remark) {\r\n return '\u8BF7\u63D0\u4F9B\u8981\u79FB\u9664\u7684\u7FA4\u7BA1\u5907\u6CE8\uFF1A/\u51CF\u7BA1 [\u5907\u6CE8]'\r\n }\r\n\r\n // \u7528\u5907\u6CE8\u79FB\u9664\u7FA4\u7BA1\r\n await adminService.removeAdminByRemark(session.guildId, remark)\r\n ctx.logger.info(`\u7FA4\u804A ${session.guildId} \u79FB\u9664\u7FA4\u7BA1: \u5907\u6CE8=${remark}`)\r\n return `\u2705 \u5DF2\u79FB\u9664\u7FA4\u7BA1\\n\u5907\u6CE8\uFF1A${remark}`\r\n })\r\n\r\n // \u67E5\u770B\u7FA4\u7BA1\u5217\u8868\r\n ctx.command('\u7FA4\u7BA1\u5217\u8868')\r\n .alias('admin-list')\r\n .action(async ({ session }) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const admins = await adminService.getAllAdmins(session.guildId)\r\n\r\n if (admins.length === 0) {\r\n return '\u5F53\u524D\u7FA4\u804A\u6CA1\u6709\u7BA1\u7406\u5458'\r\n }\r\n\r\n const list = admins.map((admin, index) =>\r\n `${index + 1}. [${admin.remark}] ${admin.openId} ${admin.verify === 1 ? '\u2705' : '\u23F3'}`\r\n ).join('\\n')\r\n\r\n // \u751F\u6210\u56FE\u7247 HTML\r\n const adminItems = admins.map((admin, index) => {\r\n const status = admin.verify === 1 ? '\u2705 \u5DF2\u9A8C\u8BC1' : '\u23F3 \u5F85\u786E\u8BA4'\r\n const statusColor = admin.verify === 1 ? '#27ae60' : '#f39c12'\r\n return `\r\n <div class=\"admin-item\">\r\n <div class=\"admin-left\">\r\n <span class=\"admin-num\">${index + 1}</span>\r\n <span class=\"admin-remark\">${admin.remark}</span>\r\n </div>\r\n <div class=\"admin-right\">\r\n <span class=\"admin-status\" style=\"color: ${statusColor}\">${status}</span>\r\n </div>\r\n </div>\r\n <div class=\"admin-id\">${admin.openId}</div>`\r\n }).join('')\r\n\r\n const html = `\r\n<!DOCTYPE html>\r\n<html>\r\n<head>\r\n <meta charset=\"utf-8\">\r\n <style>\r\n ${getBaseStyles()}\r\n .admin-list {\r\n max-height: 500px;\r\n overflow-y: auto;\r\n }\r\n .admin-item {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 14px;\r\n background: rgba(52, 152, 219, 0.08);\r\n border-radius: 10px;\r\n margin-bottom: 8px;\r\n }\r\n .admin-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n }\r\n .admin-num {\r\n width: 24px;\r\n height: 24px;\r\n background: #3498db;\r\n color: white;\r\n border-radius: 50%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 12px;\r\n font-weight: bold;\r\n }\r\n .admin-remark {\r\n color: #2c3e50;\r\n font-size: 14px;\r\n font-weight: 500;\r\n }\r\n .admin-status {\r\n font-size: 12px;\r\n font-weight: bold;\r\n }\r\n .admin-id {\r\n font-size: 10px;\r\n color: #bdc3c7;\r\n margin-top: -4px;\r\n margin-bottom: 8px;\r\n padding-left: 48px;\r\n word-break: break-all;\r\n }\r\n .count-badge {\r\n text-align: center;\r\n background: rgba(155, 89, 182, 0.1);\r\n border-radius: 20px;\r\n padding: 8px;\r\n margin-bottom: 16px;\r\n color: #9b59b6;\r\n font-size: 13px;\r\n }\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"container\">\r\n <div class=\"title\">\uD83D\uDC65 \u7FA4\u7BA1\u5217\u8868</div>\r\n <div class=\"count-badge\">\u5171 ${admins.length} \u4F4D\u7BA1\u7406\u5458</div>\r\n <div class=\"admin-list\">\r\n ${adminItems}\r\n </div>\r\n <div class=\"footer\">\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF v1.0</div>\r\n </div>\r\n</body>\r\n</html>`\r\n\r\n await sendImageOrText(ctx, session, html, `\u5F53\u524D\u7FA4\u804A\u7684\u7BA1\u7406\u5458\uFF1A\\n${list}`, { height: 600 })\r\n\r\n return ''\r\n })\r\n\r\n // \u67E5\u770B\u81EA\u5DF1\u7684 OpenID\r\n ctx.command('\u6211\u7684ID')\r\n .alias('my-id')\r\n .action(async ({ session }) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n const openId = session.userId?.toString()\r\n if (!openId) {\r\n return '\u65E0\u6CD5\u83B7\u53D6\u60A8\u7684\u7528\u6237ID'\r\n }\r\n\r\n return `\u60A8\u7684 OpenID\uFF1A\\n${openId}`\r\n })\r\n\r\n}\r\n", "import { Context, h } from 'koishi'\r\n\r\nconst MENU_HTML = `\r\n<!DOCTYPE html>\r\n<html>\r\n<head>\r\n <meta charset=\"utf-8\">\r\n <style>\r\n * { margin: 0; padding: 0; box-sizing: border-box; }\r\n body {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;\r\n background: url('https://api.yppp.net/pe.php') center/cover no-repeat;\r\n width: 450px;\r\n min-height: 800px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: flex-start;\r\n padding: 40px 0;\r\n }\r\n .container {\r\n background: rgba(255, 255, 255, 0.5);\r\n border-radius: 24px;\r\n padding: 28px 24px;\r\n width: 380px;\r\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);\r\n margin: 0 auto;\r\n }\r\n .title {\r\n text-align: center;\r\n font-size: 22px;\r\n font-weight: bold;\r\n color: #2c3e50;\r\n margin-bottom: 20px;\r\n padding-bottom: 12px;\r\n border-bottom: 2px solid #3498db;\r\n }\r\n .section {\r\n margin-bottom: 16px;\r\n }\r\n .section-title {\r\n font-size: 14px;\r\n font-weight: bold;\r\n color: #3498db;\r\n margin-bottom: 10px;\r\n display: flex;\r\n align-items: center;\r\n gap: 6px;\r\n }\r\n .section-title::before {\r\n content: '';\r\n display: inline-block;\r\n width: 3px;\r\n height: 16px;\r\n background: linear-gradient(180deg, #3498db, #9b59b6);\r\n border-radius: 2px;\r\n }\r\n .command-list {\r\n list-style: none;\r\n padding-left: 8px;\r\n }\r\n .command-item {\r\n padding: 6px 0;\r\n color: #555;\r\n font-size: 12px;\r\n border-bottom: 1px dashed #eee;\r\n display: flex;\r\n align-items: flex-start;\r\n }\r\n .command-item:last-child {\r\n border-bottom: none;\r\n }\r\n .command-item::before {\r\n content: '\u2022';\r\n color: #9b59b6;\r\n font-weight: bold;\r\n margin-right: 6px;\r\n flex-shrink: 0;\r\n }\r\n .command-name {\r\n color: #2c3e50;\r\n font-weight: 600;\r\n background: #ecf0f1;\r\n padding: 1px 5px;\r\n border-radius: 3px;\r\n font-family: 'Consolas', 'Monaco', monospace;\r\n font-size: 11px;\r\n white-space: nowrap;\r\n }\r\n .command-desc {\r\n color: #7f8c8d;\r\n font-size: 11px;\r\n margin-left: 4px;\r\n }\r\n .footer {\r\n text-align: center;\r\n margin-top: 16px;\r\n padding-top: 12px;\r\n border-top: 1px solid #eee;\r\n color: #95a5a6;\r\n font-size: 10px;\r\n }\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"container\">\r\n <div class=\"title\">\uD83D\uDCCB \u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF\u83DC\u5355</div>\r\n \r\n <div class=\"section\">\r\n <div class=\"section-title\">\uD83D\uDEE0\uFE0F \u57FA\u7840\u6307\u4EE4</div>\r\n <ul class=\"command-list\">\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u67E5\u8BE2\u79EF\u5206</span>\r\n <span class=\"command-desc\">[\u7528\u6237\u540D]</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u7ED1\u5B9AQQ</span>\r\n <span class=\"command-desc\">&lt;\u7528\u6237\u540D&gt;</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u6392\u884C\u699C</span>\r\n <span class=\"command-desc\">[\u6570\u91CF]</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u7EDF\u8BA1</span>\r\n <span class=\"command-desc\">[\u7528\u6237\u540D]</span>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n <div class=\"section\">\r\n <div class=\"section-title\">\u2699\uFE0F \u7BA1\u7406\u5458\u6307\u4EE4</div>\r\n <ul class=\"command-list\">\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u7ED1\u5B9A\u670D\u52A1\u5668</span>\r\n <span class=\"command-desc\">&lt;\u5730\u5740&gt; &lt;\u7528\u6237&gt; &lt;token&gt;</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u670D\u52A1\u5668\u89E3\u7ED1</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u8C03\u6574\u79EF\u5206</span>\r\n <span class=\"command-desc\">&lt;\u7528\u6237&gt; &lt;\u5206\u6570&gt; &lt;\u539F\u56E0&gt;</span>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n <div class=\"section\">\r\n <div class=\"section-title\">\uD83D\uDC64 \u7FA4\u7BA1\u6307\u4EE4</div>\r\n <ul class=\"command-list\">\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u52A0\u7BA1</span>\r\n <span class=\"command-desc\">@\u67D0\u4EBA &lt;\u5907\u6CE8&gt;</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u786E\u8BA4</span>\r\n <span class=\"command-desc\">&lt;\u9A8C\u8BC1\u7801&gt;</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u52A0\u7BA1\u786E\u8BA4</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u51CF\u7BA1</span>\r\n <span class=\"command-desc\">&lt;\u5907\u6CE8&gt;</span>\r\n </li>\r\n <li class=\"command-item\">\r\n <span class=\"command-name\">/\u7FA4\u7BA1\u5217\u8868</span>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n <div class=\"footer\">\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF v1.0</div>\r\n </div>\r\n</body>\r\n</html>\r\n`\r\n\r\nexport function registerMenuCommand(ctx: Context) {\r\n ctx.command('\u83DC\u5355')\r\n .alias('menu')\r\n .action(async ({ session }) => {\r\n if (!session.guildId) {\r\n return '\u6B64\u547D\u4EE4\u53EA\u80FD\u5728\u7FA4\u804A\u4E2D\u4F7F\u7528'\r\n }\r\n\r\n try {\r\n // \u4F7F\u7528 Koishi \u7684 puppeteer \u670D\u52A1\r\n const page = await (ctx as any).puppeteer.page()\r\n \r\n // \u8BBE\u7F6E\u7AD6\u7248\u89C6\u53E3\r\n await page.setViewport({\r\n width: 450,\r\n height: 800,\r\n deviceScaleFactor: 2,\r\n })\r\n \r\n await page.setContent(MENU_HTML, { waitUntil: 'networkidle0' })\r\n\r\n // \u7B49\u5F85\u5B57\u4F53\u52A0\u8F7D\r\n await page.evaluateHandle('document.fonts.ready')\r\n\r\n // \u622A\u56FE\uFF08\u56FA\u5B9A\u89C6\u53E3\u5927\u5C0F\uFF09\r\n const screenshot = await page.screenshot({\r\n type: 'png',\r\n clip: { x: 0, y: 0, width: 450, height: 800 },\r\n })\r\n\r\n // \u5C06\u56FE\u7247\u53D1\u9001\u7ED9\u7528\u6237\r\n await session.send(h.image(screenshot as Buffer, 'image/png'))\r\n\r\n return '' // \u56FE\u7247\u5DF2\u53D1\u9001\uFF0C\u4E0D\u518D\u53D1\u9001\u6587\u5B57\r\n } catch (error: any) {\r\n ctx.logger.error('\u751F\u6210\u83DC\u5355\u56FE\u7247\u5931\u8D25:', error)\r\n // \u5982\u679C\u56FE\u7247\u751F\u6210\u5931\u8D25\uFF0C\u56DE\u9000\u5230\u6587\u5B57\u7248\u672C\r\n return `\uD83D\uDCCB **\u73ED\u7EA7\u64CD\u884C\u5206\u7BA1\u7406\u7CFB\u7EDF\u83DC\u5355**\r\n\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\uD83D\uDEE0\uFE0F **\u57FA\u7840\u6307\u4EE4**\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\u2022 /\u67E5\u8BE2\u79EF\u5206 [\u7528\u6237\u540D] - \u67E5\u8BE2\u79EF\u5206\u548C\u6392\u540D\r\n\u2022 /\u7ED1\u5B9AQQ <\u7528\u6237\u540D> - \u7ED1\u5B9AQQ\u53F7\u4E0E\u7CFB\u7EDF\u8D26\u53F7\r\n\u2022 /\u6392\u884C\u699C [\u6570\u91CF] - \u663E\u793A\u79EF\u5206\u6392\u884C\u699C\r\n\u2022 /\u7EDF\u8BA1 [\u7528\u6237\u540D] - \u663E\u793A\u79EF\u5206\u7EDF\u8BA1\u4FE1\u606F\r\n\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\u2699\uFE0F **\u7BA1\u7406\u5458\u6307\u4EE4**\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\u2022 /\u7ED1\u5B9A\u670D\u52A1\u5668 <\u5730\u5740> <\u7528\u6237\u540D> <token> - \u7ED1\u5B9ACSMS\u670D\u52A1\u5668\r\n\u2022 /\u670D\u52A1\u5668\u89E3\u7ED1 - \u89E3\u9664\u670D\u52A1\u5668\u7ED1\u5B9A\r\n\u2022 /\u8C03\u6574\u79EF\u5206 <\u7528\u6237\u540D> <\u5206\u6570> <\u539F\u56E0> - \u8C03\u6574\u79EF\u5206\r\n\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\uD83D\uDC64 **\u7FA4\u7BA1\u6307\u4EE4**\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\r\n\u2022 /\u52A0\u7BA1 @\u67D0\u4EBA <\u5907\u6CE8> - \u6DFB\u52A0\u7BA1\u7406\u5458\r\n\u2022 /\u786E\u8BA4 <\u9A8C\u8BC1\u7801> - \u786E\u8BA4\u52A0\u7BA1\r\n\u2022 /\u52A0\u7BA1\u786E\u8BA4 - \u5B8C\u6210\u52A0\u7BA1\u6D41\u7A0B\r\n\u2022 /\u51CF\u7BA1 <\u5907\u6CE8> - \u79FB\u9664\u7BA1\u7406\u5458\r\n\u2022 /\u7FA4\u7BA1\u5217\u8868 - \u663E\u793A\u7BA1\u7406\u5458\u5217\u8868\r\n\r\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`\r\n }\r\n })\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["name", "h", "h", "h"]
7
+ }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "koishi-plugin-class-score-system",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "班级操行分管理系统(CSMS) Koishi 插件,CSMS-GitHub:https://github.com/QianKunBoss/ClassScoreManageSystem",
5
5
  "main": "lib/index.js",
6
- "type": "commonjs",
6
+ "type": "module",
7
7
  "typings": "lib/index.d.ts",
8
8
  "files": [
9
9
  "lib",
@@ -11,9 +11,9 @@
11
11
  ],
12
12
  "license": "MIT",
13
13
  "scripts": {
14
- "build": "esbuild src/index.ts --bundle --outfile=lib/index.js --platform=node --target=node18 --format=cjs --external:koishi --sourcemap",
14
+ "build": "esbuild src/index.ts --bundle --outfile=lib/index.js --platform=node --target=node18 --format=esm --external:koishi --sourcemap",
15
15
  "build:dts": "tsc --emitDeclarationOnly --declaration --outDir=lib",
16
- "dev": "esbuild src/index.ts --bundle --outfile=lib/index.js --platform=node --target=node18 --format=cjs --external:koishi --watch"
16
+ "dev": "esbuild src/index.ts --bundle --outfile=lib/index.js --platform=node --target=node18 --format=esm --external:koishi --watch"
17
17
  },
18
18
  "keywords": [
19
19
  "koishi",