koishi-plugin-eqserver-connect 0.0.1 → 0.0.3

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
@@ -10,6 +10,8 @@ export interface Config {
10
10
  timezoneOffset: number;
11
11
  minReward: number;
12
12
  maxReward: number;
13
+ currencyField: string;
14
+ currencyName: string;
13
15
  }
14
16
  export declare const Config: Schema<Config>;
15
17
  export declare function apply(ctx: Context, config: Config): void;
package/lib/index.js CHANGED
@@ -34,7 +34,9 @@ const Config = import_koishi.Schema.object({
34
34
  groupIds: import_koishi.Schema.array(import_koishi.Schema.string()).role("table").default([]).description("\u5141\u8BB8\u7B7E\u5230\u7684\u7FA4\u804A ID \u5217\u8868\uFF0C\u53EF\u586B channelId \u6216 platform:channelId\u3002sandbox \u7FA4\u804A\u9ED8\u8BA4\u5141\u8BB8\u3002"),
35
35
  timezoneOffset: import_koishi.Schema.number().default(8).description("\u7B7E\u5230\u65F6\u533A\u504F\u79FB\uFF08\u5C0F\u65F6\uFF09\uFF0C\u9ED8\u8BA4 +8\u3002"),
36
36
  minReward: import_koishi.Schema.number().default(100).description("\u7B7E\u5230\u6700\u5C0F\u5956\u52B1\u3002"),
37
- maxReward: import_koishi.Schema.number().default(500).description("\u7B7E\u5230\u6700\u5927\u5956\u52B1\u3002")
37
+ maxReward: import_koishi.Schema.number().default(500).description("\u7B7E\u5230\u6700\u5927\u5956\u52B1\u3002"),
38
+ currencyField: import_koishi.Schema.string().default("credits").description("\u7B7E\u5230\u5956\u52B1\u5199\u5165\u7684 store_players \u8D27\u5E01\u5B57\u6BB5\u3002"),
39
+ currencyName: import_koishi.Schema.string().default("\u6069\u60C5\u5E01").description("\u7B7E\u5230\u5956\u52B1\u663E\u793A\u7684\u8D27\u5E01\u540D\u79F0\u3002")
38
40
  });
39
41
  const HOUR_MS = 60 * 60 * 1e3;
40
42
  function getSignDay(now, timezoneOffset) {
@@ -71,6 +73,20 @@ function getRewardRange(minReward, maxReward) {
71
73
  function randomInt(min, max) {
72
74
  return Math.floor(Math.random() * (max - min + 1)) + min;
73
75
  }
76
+ function normalizeColumnName(columnName) {
77
+ const text = typeof columnName === "string" ? columnName.trim() : "";
78
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(text)) {
79
+ throw new Error("currencyField \u53EA\u80FD\u5305\u542B\u82F1\u6587\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4E0D\u80FD\u4EE5\u6570\u5B57\u5F00\u5934\u3002");
80
+ }
81
+ return text;
82
+ }
83
+ function quoteIdentifier(identifier) {
84
+ return `"${identifier.replace(/"/g, '""')}"`;
85
+ }
86
+ function normalizeCurrencyName(currencyName) {
87
+ const text = typeof currencyName === "string" ? currencyName.trim() : "";
88
+ return text || "\u6069\u60C5\u5E01";
89
+ }
74
90
  function isUniqueViolation(error) {
75
91
  if (!error || typeof error !== "object") return false;
76
92
  return error.code === "23505";
@@ -107,6 +123,9 @@ function apply(ctx, config) {
107
123
  });
108
124
  const allowedGroupIds = normalizeGroupIds(config.groupIds);
109
125
  const [minReward, maxReward] = getRewardRange(config.minReward, config.maxReward);
126
+ const currencyField = normalizeColumnName(config.currencyField || "credits");
127
+ const currencyFieldSql = quoteIdentifier(currencyField);
128
+ const currencyName = normalizeCurrencyName(config.currencyName);
110
129
  let initialized = false;
111
130
  let initializeTask = null;
112
131
  async function initDatabase() {
@@ -115,7 +134,7 @@ function apply(ctx, config) {
115
134
  initializeTask = (async () => {
116
135
  const playerIdType = await getStorePlayersColumnType(pool, "id");
117
136
  await getStorePlayersColumnType(pool, "authid");
118
- await getStorePlayersColumnType(pool, "credits");
137
+ await getStorePlayersColumnType(pool, currencyField);
119
138
  await pool.query(`
120
139
  CREATE TABLE IF NOT EXISTS koishi_player_bind (
121
140
  id BIGSERIAL PRIMARY KEY,
@@ -271,7 +290,7 @@ function apply(ctx, config) {
271
290
  );
272
291
  if (existed.rowCount) {
273
292
  await client.query("ROLLBACK");
274
- return `\u4ECA\u5929\u5DF2\u7ECF\u7B7E\u5230\u8FC7\u4E86\uFF0C\u4E0A\u6B21\u83B7\u5F97 ${existed.rows[0].reward} \u6069\u60C5\u5E01\u3002`;
293
+ return `\u4ECA\u5929\u5DF2\u7ECF\u7B7E\u5230\u8FC7\u4E86\uFF0C\u4E0A\u6B21\u83B7\u5F97 ${existed.rows[0].reward} ${currencyName}\u3002`;
275
294
  }
276
295
  await client.query(
277
296
  `
@@ -283,9 +302,9 @@ function apply(ctx, config) {
283
302
  const creditResult = await client.query(
284
303
  `
285
304
  UPDATE store_players
286
- SET credits = COALESCE(credits, 0) + $1
305
+ SET ${currencyFieldSql} = COALESCE(${currencyFieldSql}, 0) + $1
287
306
  WHERE id = $2
288
- RETURNING credits
307
+ RETURNING ${currencyFieldSql} AS credits
289
308
  `,
290
309
  [reward, bind.player_id]
291
310
  );
@@ -293,7 +312,7 @@ function apply(ctx, config) {
293
312
  throw new Error(`\u672A\u627E\u5230\u73A9\u5BB6 ID\uFF1A${String(bind.player_id)}`);
294
313
  }
295
314
  await client.query("COMMIT");
296
- return `\u7B7E\u5230\u6210\u529F\uFF0C\u83B7\u5F97 ${reward} \u6069\u60C5\u5E01\u3002\u5F53\u524D \u6069\u60C5\u5E01\uFF1A${String(creditResult.rows[0].credits)}`;
315
+ return `\u7B7E\u5230\u6210\u529F\uFF0C\u83B7\u5F97 ${reward} ${currencyName}\u3002\u5F53\u524D ${currencyName}\uFF1A${String(creditResult.rows[0].credits)}`;
297
316
  } catch (error) {
298
317
  await client.query("ROLLBACK").catch(() => null);
299
318
  if (isUniqueViolation(error)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-eqserver-connect",
3
3
  "description": "EQ server PostgreSQL connector with register + daily signin",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -5,7 +5,7 @@ PostgreSQL connector plugin for Koishi:
5
5
  - Register player mapping with `注册 <authid>` (alias: `register`).
6
6
  - Daily sign-in with `签到` (alias: `qd`).
7
7
  - One sign-in per day, reset at 12:00 (configurable timezone offset).
8
- - Rewards `100-500` by default, and directly adds to `store_players.credits`.
8
+ - Rewards `100-500` by default, and directly adds to the configured `store_players` currency field (`credits` by default).
9
9
  - Group whitelist in plugin config (`groupIds`), with sandbox groups allowed by default.
10
10
 
11
11
  ## Required database table
@@ -14,6 +14,9 @@ The plugin expects an existing table:
14
14
 
15
15
  - `store_players(id, authid, credits, ...)`
16
16
 
17
+ Set `currencyField` to use a different currency column, for example `shop_credits`.
18
+ Set `currencyName` to change the display name in sign-in messages, for example `商店积分`.
19
+
17
20
  It auto-creates:
18
21
 
19
22
  - `koishi_player_bind` (Koishi user -> player binding)