koishi-plugin-jrys-plus 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
2
  * koishi-plugin-jrys-plus
3
- * 今日运势签到 + 排行榜(精简版)
3
+ * 今日运势签到 + 签到天数排行榜(精简版)
4
4
  *
5
5
  * 改动:
6
6
  * - 移除金币/经验值展示和进度条
7
7
  * - 🍀 替换为 ⭐
8
8
  * - 日期问候模块移除半透明背景
9
- * - 整合排名功能
9
+ * - 仅保留签到天数排行榜
10
10
  */
11
11
  import { Context, Schema } from 'koishi';
12
12
  import * as si from './signin';
@@ -18,12 +18,10 @@ export interface Config {
18
18
  levelSet: si.LevelInfo[];
19
19
  fortuneSet: si.FortuneInfo[];
20
20
  event: RollEvent[];
21
- expCommand: string;
22
21
  signCommand: string;
23
22
  imageMode: boolean;
24
23
  limit: number;
25
24
  borderwidth: number;
26
- next_ExpDisplay: boolean;
27
25
  pre_next_LevelDisplay: boolean;
28
26
  }
29
27
  export declare const Config: Schema<Schemastery.ObjectS<{
@@ -58,12 +56,10 @@ export declare const Config: Schema<Schemastery.ObjectS<{
58
56
  bad: Schema<string, string>;
59
57
  }>[]>;
60
58
  }> | Schemastery.ObjectS<{
61
- expCommand: Schema<string, string>;
62
59
  signCommand: Schema<string, string>;
63
60
  imageMode: Schema<boolean, boolean>;
64
61
  limit: Schema<number, number>;
65
62
  borderwidth: Schema<number, number>;
66
- next_ExpDisplay: Schema<boolean, boolean>;
67
63
  pre_next_LevelDisplay: Schema<boolean, boolean>;
68
64
  }>, {
69
65
  imgUrl: string;
@@ -85,12 +81,10 @@ export declare const Config: Schema<Schemastery.ObjectS<{
85
81
  bad: Schema<string, string>;
86
82
  }>[];
87
83
  } & {
88
- expCommand: string;
89
84
  signCommand: string;
90
85
  imageMode: boolean;
91
86
  limit: number;
92
87
  borderwidth: number;
93
- next_ExpDisplay: boolean;
94
88
  pre_next_LevelDisplay: boolean;
95
89
  }>;
96
90
  export declare const inject: {
@@ -133,12 +127,10 @@ declare const _default: {
133
127
  bad: Schema<string, string>;
134
128
  }>[]>;
135
129
  }> | Schemastery.ObjectS<{
136
- expCommand: Schema<string, string>;
137
130
  signCommand: Schema<string, string>;
138
131
  imageMode: Schema<boolean, boolean>;
139
132
  limit: Schema<number, number>;
140
133
  borderwidth: Schema<number, number>;
141
- next_ExpDisplay: Schema<boolean, boolean>;
142
134
  pre_next_LevelDisplay: Schema<boolean, boolean>;
143
135
  }>, {
144
136
  imgUrl: string;
@@ -160,12 +152,10 @@ declare const _default: {
160
152
  bad: Schema<string, string>;
161
153
  }>[];
162
154
  } & {
163
- expCommand: string;
164
155
  signCommand: string;
165
156
  imageMode: boolean;
166
157
  limit: number;
167
158
  borderwidth: number;
168
- next_ExpDisplay: boolean;
169
159
  pre_next_LevelDisplay: boolean;
170
160
  }>;
171
161
  };
package/lib/index.js CHANGED
@@ -40,13 +40,13 @@ exports.inject = exports.Config = exports.name = void 0;
40
40
  exports.apply = apply;
41
41
  /**
42
42
  * koishi-plugin-jrys-plus
43
- * 今日运势签到 + 排行榜(精简版)
43
+ * 今日运势签到 + 签到天数排行榜(精简版)
44
44
  *
45
45
  * 改动:
46
46
  * - 移除金币/经验值展示和进度条
47
47
  * - 🍀 替换为 ⭐
48
48
  * - 日期问候模块移除半透明背景
49
- * - 整合排名功能
49
+ * - 仅保留签到天数排行榜
50
50
  */
51
51
  const koishi_1 = require("koishi");
52
52
  const url_1 = require("url");
@@ -88,12 +88,10 @@ exports.Config = koishi_1.Schema.intersect([
88
88
  .description('自定义黄历事件'),
89
89
  }).description('签到/运势设置'),
90
90
  koishi_1.Schema.object({
91
- expCommand: koishi_1.Schema.string().description('经验排行榜命令').default('jrysranks'),
92
91
  signCommand: koishi_1.Schema.string().description('签到天数排行榜命令').default('jrysranksign'),
93
92
  imageMode: koishi_1.Schema.boolean().description('排行榜是否使用图片模式(需要 puppeteer)').default(true),
94
93
  limit: koishi_1.Schema.number().description('排行榜显示的最大条目数').min(1).max(100).default(10),
95
94
  borderwidth: koishi_1.Schema.number().description('文本模式边框宽度').default(14),
96
- next_ExpDisplay: koishi_1.Schema.boolean().description('排行榜中显示升级所需经验').default(true),
97
95
  pre_next_LevelDisplay: koishi_1.Schema.boolean().description('排行榜中显示前后等级信息').default(true),
98
96
  }).description('排行榜设置'),
99
97
  ]);
@@ -130,12 +128,14 @@ async function fetchHitokoto() {
130
128
  /* ── 主入口 ── */
131
129
  function apply(ctx, config) {
132
130
  si.initDatabase(ctx);
133
- const signin = new si.Signin(ctx, config);
131
+ const db = ctx.database;
132
+ const puppeteer = ctx.puppeteer;
133
+ const signin = new si.Signin(db, config);
134
134
  const jrys = new roll_1.Jrys();
135
135
  // 合并事件
136
136
  const eventJson = [...event_1.defaultEventJson, ...config.event];
137
137
  // 注册排行榜
138
- (0, ranks_1.registerRanks)(ctx, config, () => config.levelSet);
138
+ (0, ranks_1.registerRanks)(ctx, db, config, () => config.levelSet);
139
139
  /* ── 运势签到命令 ── */
140
140
  ctx.command('jrys', '今日运势')
141
141
  .userFields(['id', 'name'])
@@ -186,7 +186,7 @@ function apply(ctx, config) {
186
186
  .replace('{{BADDO}}', baddo);
187
187
  const outPath = path_1.default.resolve(__dirname, 'templates', '_fortune_render.html');
188
188
  fs_1.default.writeFileSync(outPath, html);
189
- page = await ctx.puppeteer.page();
189
+ page = await puppeteer.page();
190
190
  await page.setViewport({ width: 600, height: 1080 * 2 });
191
191
  await page.goto(`file:///${outPath}`);
192
192
  await page.waitForSelector('#body', { timeout: 10000 });
package/lib/ranks.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { Context } from 'koishi';
1
+ import { Context, Database } from 'koishi';
2
2
  import { LevelInfo } from './signin';
3
- export declare function registerRanks(ctx: Context, config: any, getLevelConfig: () => LevelInfo[]): void;
3
+ export declare function registerRanks(ctx: Context, db: Database<any>, config: any, getLevelConfig: () => LevelInfo[]): void;
package/lib/ranks.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerRanks = registerRanks;
4
4
  const koishi_1 = require("koishi");
5
+ const signin_1 = require("./signin");
5
6
  const fs_1 = require("fs");
6
7
  const path_1 = require("path");
7
8
  /* ── 模板路径候选 ── */
@@ -21,55 +22,7 @@ async function resolveTemplatePath() {
21
22
  }
22
23
  throw new Error('未找到 rank-card.html 模板文件');
23
24
  }
24
- /* ── 等级查询 ── */
25
- const DEFAULT_LEVEL = { level: 0, levelExp: 0, levelName: '无等级', levelColor: '#666666' };
26
- function getLevelInfo(exp, levels) {
27
- if (!levels?.length)
28
- return DEFAULT_LEVEL;
29
- const sorted = [...levels].sort((a, b) => b.levelExp - a.levelExp);
30
- return sorted.find(l => exp >= l.levelExp) || sorted[sorted.length - 1];
31
- }
32
25
  /* ── 文本渲染 ── */
33
- function renderExpText(users, levelConfig, config) {
34
- const divider = '┏' + '—'.repeat(config.borderwidth) + '┓';
35
- const midDivider = '┣' + '—'.repeat(config.borderwidth) + '┫';
36
- const endDivider = '┗' + '—'.repeat(config.borderwidth) + '┛';
37
- const header = [divider, `┃ 🏆 经验排行榜 TOP.${config.limit} `, midDivider].join('\n');
38
- const rankings = users.map((user, index) => {
39
- const medal = index < 3 ? ['👑', '⭐', '✧'][index] : '•';
40
- const expStr = user.exp.toLocaleString();
41
- let lines = [`┃ ${medal} ${index + 1}. ${user.displayName}`];
42
- if (config.next_ExpDisplay) {
43
- const sorted = [...levelConfig].sort((a, b) => a.levelExp - b.levelExp);
44
- const cur = getLevelInfo(user.exp, levelConfig);
45
- const idx = sorted.findIndex(l => l.levelExp === cur.levelExp);
46
- const next = sorted[idx + 1];
47
- lines.push(next ? `┃ ⚡${expStr} exp (下一级:${next.levelExp} exp)` : `┃ ⚡${expStr} (Max)`);
48
- }
49
- else {
50
- lines.push(`┃ ⚡${expStr} exp`);
51
- }
52
- if (config.pre_next_LevelDisplay && levelConfig.length) {
53
- const sorted = [...levelConfig].sort((a, b) => a.levelExp - b.levelExp);
54
- const cur = getLevelInfo(user.exp, levelConfig);
55
- const idx = sorted.findIndex(l => l.levelExp === cur.levelExp);
56
- const prev = sorted[idx - 1]?.levelName;
57
- const next = sorted[idx + 1]?.levelName;
58
- let line = '┃ ✨';
59
- if (prev)
60
- line += `${prev} → `;
61
- line += `「${cur.levelName}」`;
62
- if (next)
63
- line += ` → ${next}`;
64
- lines.push(line);
65
- }
66
- else if (levelConfig.length) {
67
- lines.push(`┃ ✨${getLevelInfo(user.exp, levelConfig).levelName}`);
68
- }
69
- return lines.join('\n');
70
- }).join('\n\n');
71
- return [header, rankings, endDivider].join('\n');
72
- }
73
26
  function renderSignText(users, levelConfig, config) {
74
27
  const divider = '┏' + '—'.repeat(config.borderwidth) + '┓';
75
28
  const midDivider = '┣' + '—'.repeat(config.borderwidth) + '┫';
@@ -80,7 +33,7 @@ function renderSignText(users, levelConfig, config) {
80
33
  let lines = [`┃ ${medal} ${index + 1}. ${user.displayName}`, `┃ 📅${user.signCount.toLocaleString()} 天`];
81
34
  if (config.pre_next_LevelDisplay && levelConfig.length) {
82
35
  const sorted = [...levelConfig].sort((a, b) => a.levelExp - b.levelExp);
83
- const cur = getLevelInfo(user.exp, levelConfig);
36
+ const cur = (0, signin_1.getLevelInfo)(user.exp, levelConfig);
84
37
  const idx = sorted.findIndex(l => l.levelExp === cur.levelExp);
85
38
  const prev = sorted[idx - 1]?.levelName;
86
39
  const next = sorted[idx + 1]?.levelName;
@@ -97,20 +50,20 @@ function renderSignText(users, levelConfig, config) {
97
50
  return [header, rankings, endDivider].join('\n');
98
51
  }
99
52
  /* ── 图片渲染 ── */
100
- async function renderRankImage(ctx, type, users, totalUsers, limit, getLevelConfig) {
53
+ async function renderRankImage(ctx, users, totalUsers, limit, getLevelConfig) {
101
54
  try {
102
55
  const path = await resolveTemplatePath();
103
56
  let template = await fs_1.promises.readFile(path, 'utf-8');
104
57
  const levelConfig = getLevelConfig();
105
58
  const data = {
106
- type,
59
+ type: 'sign',
107
60
  limit,
108
61
  channelName: '当前频道',
109
62
  totalUsers,
110
63
  updateTime: new Date().toLocaleString('zh-CN'),
111
64
  users: users.map(user => {
112
65
  const sorted = [...levelConfig].sort((a, b) => a.levelExp - b.levelExp);
113
- const cur = getLevelInfo(user.exp, levelConfig);
66
+ const cur = (0, signin_1.getLevelInfo)(user.exp, levelConfig);
114
67
  const idx = sorted.findIndex(l => l.levelExp === cur.levelExp);
115
68
  const prev = sorted[idx - 1]?.levelName;
116
69
  const nextObj = sorted[idx + 1];
@@ -124,7 +77,7 @@ async function renderRankImage(ctx, type, users, totalUsers, limit, getLevelConf
124
77
  return {
125
78
  displayName: user.displayName,
126
79
  originalId: user.name,
127
- value: type === 'exp' ? user.exp : user.signCount,
80
+ value: user.signCount,
128
81
  levelName: cur.levelName,
129
82
  levelColor: cur.levelColor,
130
83
  currentLevelExp: cur.levelExp,
@@ -153,13 +106,13 @@ async function renderRankImage(ctx, type, users, totalUsers, limit, getLevelConf
153
106
  }
154
107
  }
155
108
  /* ── 注册排行命令 ── */
156
- function registerRanks(ctx, config, getLevelConfig) {
109
+ function registerRanks(ctx, db, config, getLevelConfig) {
157
110
  const logger = ctx.logger('jrys-plus');
158
111
  function canUseImage() {
159
112
  return config.imageMode && !!ctx.puppeteer;
160
113
  }
161
- async function getRankedUsers(session, sortField) {
162
- const all = await ctx.database.get('jrys', {}, { sort: { [sortField]: 'desc' } });
114
+ async function getRankedUsers() {
115
+ const all = await db.get('jrys', {}, { sort: { signCount: 'desc' } });
163
116
  if (!all.length)
164
117
  return null;
165
118
  const users = all.slice(0, config.limit).map(u => ({
@@ -168,31 +121,16 @@ function registerRanks(ctx, config, getLevelConfig) {
168
121
  }));
169
122
  return users;
170
123
  }
171
- ctx.command(config.expCommand || 'jrysranks')
172
- .action(async ({ session }) => {
173
- const users = await getRankedUsers(session, 'exp');
174
- if (users === null)
175
- return '暂无数据';
176
- if (!users.length)
177
- return '当前频道暂无数据';
178
- if (canUseImage()) {
179
- const total = (await ctx.database.get('jrys', {})).length;
180
- const img = await renderRankImage(ctx, 'exp', users, total, config.limit, getLevelConfig);
181
- if (img)
182
- return img;
183
- }
184
- return renderExpText(users, getLevelConfig(), config);
185
- });
186
124
  ctx.command(config.signCommand || 'jrysranksign')
187
125
  .action(async ({ session }) => {
188
- const users = await getRankedUsers(session, 'signCount');
126
+ const users = await getRankedUsers();
189
127
  if (users === null)
190
128
  return '暂无数据';
191
129
  if (!users.length)
192
130
  return '当前频道暂无数据';
193
131
  if (canUseImage()) {
194
- const total = (await ctx.database.get('jrys', {})).length;
195
- const img = await renderRankImage(ctx, 'sign', users, total, config.limit, getLevelConfig);
132
+ const total = (await db.get('jrys', {})).length;
133
+ const img = await renderRankImage(ctx, users, total, config.limit, getLevelConfig);
196
134
  if (img)
197
135
  return img;
198
136
  }
package/lib/signin.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Context } from 'koishi';
1
+ import { Context, Database } from 'koishi';
2
2
  declare module 'koishi' {
3
3
  interface Tables {
4
4
  jrys: _UserFortune;
@@ -38,21 +38,22 @@ export interface SigninConfig {
38
38
  levelSet: LevelInfo[];
39
39
  fortuneSet: FortuneInfo[];
40
40
  }
41
+ export declare function getLevelInfo(exp: number, levels: LevelInfo[]): LevelInfo;
41
42
  export declare class Signin {
42
- private ctx;
43
+ private db;
43
44
  private cfg;
44
- constructor(ctx: Context, cfg: SigninConfig);
45
+ constructor(db: Database<any>, cfg: SigninConfig);
45
46
  /** 执行签到。返回 0=成功, 1=已签到 */
46
47
  callSignin(uid: number, userid: string, luck: number): Promise<{
47
- status: number;
48
- allExp: number;
49
- signTime: Date;
50
- count: number;
51
- } | {
52
48
  status: number;
53
49
  allExp?: undefined;
54
50
  signTime?: undefined;
55
51
  count?: undefined;
52
+ } | {
53
+ status: number;
54
+ allExp: any;
55
+ signTime: Date;
56
+ count: any;
56
57
  }>;
57
58
  getLevelInfo(exp: number): {
58
59
  levelInfo: LevelInfo;
package/lib/signin.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Signin = exports.defaultFortuneInfo = exports.defaultLevelInfo = void 0;
4
4
  exports.initDatabase = initDatabase;
5
+ exports.getLevelInfo = getLevelInfo;
5
6
  const timeGreetings = [
6
7
  { range: [0, 5], message: '晚安' },
7
8
  { range: [5, 9], message: '早上好' },
@@ -59,24 +60,27 @@ function initDatabase(ctx) {
59
60
  signCount: 'unsigned',
60
61
  });
61
62
  }
62
- /* ── 签到逻辑(无 monetary 依赖) ── */
63
- const roll_1 = require("./roll");
63
+ function getLevelInfo(exp, levels) {
64
+ if (!levels?.length)
65
+ return { level: 0, levelExp: 0, levelName: '无等级', levelColor: '#666666' };
66
+ const sorted = [...levels].sort((a, b) => b.levelExp - a.levelExp);
67
+ return sorted.find(l => exp >= l.levelExp) || sorted[sorted.length - 1];
68
+ }
64
69
  class Signin {
65
- constructor(ctx, cfg) {
66
- this.ctx = ctx;
70
+ constructor(db, cfg) {
71
+ this.db = db;
67
72
  this.cfg = cfg;
68
73
  }
69
74
  /** 执行签到。返回 0=成功, 1=已签到 */
70
75
  async callSignin(uid, userid, luck) {
71
76
  const date = new Date();
72
- const roll = new roll_1.Jrys();
73
77
  // 经验值仅用于后端等级/排行计算,不在签到卡上展示
74
78
  const exp = Math.round((Math.random() * 0.5 + luck / 200) *
75
79
  (this.cfg.signExp[1] - this.cfg.signExp[0])) + this.cfg.signExp[0];
76
- const userData = await this.ctx.database.get('jrys', { id: uid });
80
+ const userData = await this.db.get('jrys', { id: uid });
77
81
  if (userData.length === 0) {
78
82
  const accExp = exp;
79
- await this.ctx.database.create('jrys', {
83
+ await this.db.create('jrys', {
80
84
  id: uid,
81
85
  name: userid,
82
86
  time: date,
@@ -90,7 +94,7 @@ class Signin {
90
94
  }
91
95
  const accExp = userData[0].exp + exp;
92
96
  const accCount = userData[0].signCount + 1;
93
- await this.ctx.database.set('jrys', { id: uid }, {
97
+ await this.db.set('jrys', { id: uid }, {
94
98
  name: userid,
95
99
  time: date,
96
100
  exp: accExp,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-jrys-plus",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "今日运势签到 + 排行榜,精简优化版",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",