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 +11 -36
- package/lib/index.js.map +7 -0
- package/package.json +4 -4
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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
|
-
` +
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
1942
|
-
0 && (module.exports = {
|
|
1917
|
+
export {
|
|
1943
1918
|
Config,
|
|
1944
1919
|
apply,
|
|
1945
1920
|
inject,
|
|
1946
1921
|
name
|
|
1947
|
-
}
|
|
1922
|
+
};
|
package/lib/index.js.map
ADDED
|
@@ -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\"><\u7528\u6237\u540D></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\"><\u5730\u5740> <\u7528\u6237> <token></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\"><\u7528\u6237> <\u5206\u6570> <\u539F\u56E0></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 <\u5907\u6CE8></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\"><\u9A8C\u8BC1\u7801></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\"><\u5907\u6CE8></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.
|
|
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": "
|
|
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=
|
|
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=
|
|
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",
|