mioku-plugin-impact 2.0.0 → 2.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.
@@ -1,5 +1,3 @@
1
- import { isOwner } from "mioku";
2
- import { isGroupAdmin } from "../utils";
3
1
  import type { HandlerContext } from "./types";
4
2
 
5
3
  export async function handleOpenModule(
@@ -7,13 +5,6 @@ export async function handleOpenModule(
7
5
  enable: boolean,
8
6
  ): Promise<void> {
9
7
  const { ctx, db, event } = h;
10
- if (!isOwner(event) && !isGroupAdmin(event)) {
11
- await event.reply(
12
- [ctx.segment.text("权限不足喵, 仅管理员/群主/主人可以开关淫趴")],
13
- false,
14
- );
15
- return;
16
- }
17
8
  await db.setGroupAllow(Number(event.group_id), enable);
18
9
  await event.reply(
19
10
  [ctx.segment.text(enable ? "功能已开启喵" : "功能已禁用喵")],
package/handlers/yinpa.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { isOwner } from "mioku";
1
+ import type { MiokuContext } from "mioku";
2
2
  import { checkCooldown, clearCooldown, markCooldown } from "../state";
3
3
  import {
4
4
  getAtUserId,
@@ -27,12 +27,13 @@ export async function handleYinpa(
27
27
  subject: "owner" | "admin" | "member",
28
28
  ): Promise<void> {
29
29
  const { ctx, db, cd, config, event } = h;
30
+ const miokuCtx = ctx as MiokuContext;
30
31
  const uid = Number(event.user_id);
31
32
  const uidKey = String(uid);
32
33
 
33
34
  const cdState = checkCooldown(cd.fuck, uidKey, config.fuckCd);
34
35
  // 主人不受 CD 限制
35
- if (!cdState.ok && !isOwner(event)) {
36
+ if (!cdState.ok && !miokuCtx.isMaster?.(event)) {
36
37
  await event.reply(
37
38
  [
38
39
  ctx.segment.at(String(uid)),
package/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { definePlugin, type MiokuContext } from "mioku";
1
+ import { definePlugin, type CommandDefinition, type MiokuContext } from "mioku";
2
2
  import {
3
3
  cloneConfig,
4
4
  DEFAULT_CONFIG,
@@ -16,14 +16,21 @@ import { handleRank } from "./handlers/rank";
16
16
  import { handleSuo } from "./handlers/suo";
17
17
  import { handleYinpa } from "./handlers/yinpa";
18
18
  import type { HandlerContext } from "./handlers/types";
19
- import { parseImpactCommand } from "./router";
20
19
  import { createCooldownState } from "./state";
21
20
  import { NOT_ALLOW_TEXT, isGroupEvent } from "./utils";
22
21
 
22
+ type HandlerType =
23
+ | "pk"
24
+ | "dajiao"
25
+ | "suo"
26
+ | "queryjj"
27
+ | "rank"
28
+ | "yinpa"
29
+ | "open_module"
30
+ | "query_injection";
31
+
23
32
  const impactPlugin = definePlugin({
24
33
  name: "impact",
25
- version: "1.0.0",
26
- description: "让群友们眼前一黑的淫趴插件(牛子比拼),移植自 nonebot_plugin_impact",
27
34
 
28
35
  async setup(ctx: MiokuContext) {
29
36
  ctx.logger.info("impact 插件正在初始化...");
@@ -74,24 +81,14 @@ const impactPlugin = definePlugin({
74
81
  });
75
82
  }
76
83
 
77
- ctx.handle("message", async (event: any) => {
84
+ const run = (type: HandlerType) => async (event: any, extra?: unknown) => {
78
85
  if (!isGroupEvent(event)) return;
79
- const text = ctx.text(event);
80
- if (!text) return;
81
-
82
- const cmd = parseImpactCommand(text);
83
- if (cmd.type === "none") return;
84
-
85
86
  const h: HandlerContext = { ctx, db, cd, config, screenshot, event };
86
-
87
87
  try {
88
- // open_module 始终可用,不受群开关限制
89
- if (cmd.type === "open_module") {
90
- await handleOpenModule(h, cmd.enable);
88
+ if (type === "open_module") {
89
+ await handleOpenModule(h, extra as boolean);
91
90
  return;
92
91
  }
93
-
94
- // 其余命令需要群开启了银趴
95
92
  if (!db.isGroupAllowed(Number(event.group_id))) {
96
93
  await event.reply(
97
94
  [ctx.segment.at(String(event.user_id)), ctx.segment.text(NOT_ALLOW_TEXT)],
@@ -99,8 +96,7 @@ const impactPlugin = definePlugin({
99
96
  );
100
97
  return;
101
98
  }
102
-
103
- switch (cmd.type) {
99
+ switch (type) {
104
100
  case "pk":
105
101
  return await handlePk(h);
106
102
  case "dajiao":
@@ -112,12 +108,12 @@ const impactPlugin = definePlugin({
112
108
  case "rank":
113
109
  return await handleRank(h);
114
110
  case "yinpa":
115
- return await handleYinpa(h, cmd.subject);
111
+ return await handleYinpa(h, extra as "owner" | "admin" | "member");
116
112
  case "query_injection":
117
- return await handleQueryInjection(h, cmd.mode);
113
+ return await handleQueryInjection(h, extra as "today" | "history");
118
114
  }
119
115
  } catch (error) {
120
- ctx.logger.error(`impact 命令 ${cmd.type} 执行失败: ${error}`);
116
+ ctx.logger.error(`impact 命令 ${type} 执行失败: ${error}`);
121
117
  try {
122
118
  await event.reply(
123
119
  [ctx.segment.text(`淫趴插件出错了喵: ${String(error)}`)],
@@ -127,6 +123,80 @@ const impactPlugin = definePlugin({
127
123
  // 忽略二次失败
128
124
  }
129
125
  }
126
+ };
127
+
128
+ const cmd = (command: CommandDefinition) =>
129
+ ctx.command({ ...command, prefixes: false });
130
+
131
+ cmd({
132
+ id: "开启淫趴",
133
+ name: "开启淫趴",
134
+ match: /^(?:开始银趴|关闭银趴|开启淫趴|禁止淫趴|开启银趴|禁止银趴)\s*$/,
135
+ permission: "admin",
136
+ description: "在本群开启或关闭淫趴功能",
137
+ usage: "开启淫趴 / 关闭银趴",
138
+ handler: ({ event, match }) =>
139
+ run("open_module")(event, match![0].startsWith("开启") || match![0].startsWith("开始")),
140
+ });
141
+ cmd({
142
+ id: "日透",
143
+ name: "日群友",
144
+ match: /^(日群友|透群友|日群主|透群主|日管理|透管理)(?:\s|$|@)/,
145
+ description: "随机或定向选取一位幸运儿进行注入,按命令决定身份",
146
+ usage: "日群友 / 透群友 @某人 / 透群主 / 透管理",
147
+ handler: ({ event, match }) => {
148
+ const word = match![1];
149
+ const subject = word.includes("群主") ? "owner" : word.includes("管理") ? "admin" : "member";
150
+ return run("yinpa")(event, subject);
151
+ },
152
+ });
153
+ cmd({
154
+ id: "pk",
155
+ name: "pk",
156
+ match: /^(?:pk|PK|对决)(?:\s|@|$)/,
157
+ description: "和 @ 的群友进行牛子对决,胜者抢走败者的随机长度",
158
+ usage: "pk @某人",
159
+ handler: ({ event }) => run("pk")(event),
160
+ });
161
+ cmd({
162
+ id: "打胶",
163
+ name: "打胶",
164
+ match: /^(?:打胶|开导)\s*$/,
165
+ description: "给自己的牛子增加一段随机长度",
166
+ handler: ({ event }) => run("dajiao")(event),
167
+ });
168
+ cmd({
169
+ id: "嗦牛子",
170
+ name: "嗦牛子",
171
+ match: /^嗦牛子(?:\s|@|$)/,
172
+ description: "嗦自己或被 @ 的群友的牛子,增加随机长度",
173
+ usage: "嗦牛子 / 嗦牛子 @某人",
174
+ handler: ({ event }) => run("suo")(event),
175
+ });
176
+ cmd({
177
+ id: "查询",
178
+ name: "查询",
179
+ match: /^查询(?:\s|@|$)/,
180
+ description: "查询自己或 @ 的群友的牛子长度",
181
+ usage: "查询 / 查询 @某人",
182
+ handler: ({ event }) => run("queryjj")(event),
183
+ });
184
+ cmd({
185
+ id: "注入查询",
186
+ name: "注入查询",
187
+ match: /^(?:注入查询|摄入查询|射入查询)(.*)$/,
188
+ description: "查询当日或全部历史被注入量,加 历史/全部 看走势图",
189
+ usage: "注入查询 / 注入查询 历史 / 注入查询 @某人 全部",
190
+ handler: ({ event, match }) =>
191
+ run("query_injection")(event, /历史|全部/.test(match![1] || "") ? "history" : "today"),
192
+ });
193
+ cmd({
194
+ id: "jj排行榜",
195
+ name: "jj排行榜",
196
+ match: /^(?:jj|JJ)(?:排行榜|排名|榜单|rank|RANK)(?:\s|$)/,
197
+ description: "查看牛子长度前五与倒数五名的图表",
198
+ usage: "jj排行榜 / jjrank",
199
+ handler: ({ event }) => run("rank")(event),
130
200
  });
131
201
 
132
202
  ctx.logger.info("impact 插件初始化完成");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mioku-plugin-impact",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "让群友们眼前一黑的淫趴插件",
5
5
  "main": "index.ts",
6
6
  "type": "module",
@@ -16,102 +16,7 @@
16
16
  "screenshot",
17
17
  "help",
18
18
  "config"
19
- ],
20
- "accessHooks": [
21
- {
22
- "id": "开启淫趴",
23
- "match": "/^(?:开启|禁止|开始|关闭)(?:淫趴|银趴)\\s*$/",
24
- "description": "群内开启或关闭淫趴功能"
25
- },
26
- {
27
- "id": "日透",
28
- "match": "/^(?:日群友|透群友|日群主|透群主|日管理|透管理)(?:\\s|$|@)/",
29
- "description": "日 / 透 系列命令"
30
- },
31
- {
32
- "id": "打胶",
33
- "match": "/^(?:打胶|开导)\\s*$/",
34
- "description": "打胶 / 开导"
35
- },
36
- {
37
- "id": "嗦牛子",
38
- "match": "/^嗦牛子(?:\\s|$|@)/",
39
- "description": "嗦自己或被 @ 群友的牛子"
40
- },
41
- {
42
- "id": "pk",
43
- "match": "/^(?:pk|PK|对决)(?:\\s|@|$)/",
44
- "description": "牛子对决"
45
- },
46
- {
47
- "id": "查询",
48
- "match": "/^查询(?:\\s|@|$)/",
49
- "description": "查询自己或被 @ 群友的牛子长度"
50
- },
51
- {
52
- "id": "注入查询",
53
- "match": "/^(?:注入查询|摄入查询|射入查询)/",
54
- "description": "查询当日或历史被注入量"
55
- },
56
- {
57
- "id": "jj排行榜",
58
- "match": "/^(?:jj|JJ)(?:排行榜|排名|榜单|rank|RANK)(?:\\s|$)/",
59
- "description": "牛子长度排行榜"
60
- }
61
- ],
62
- "help": {
63
- "title": "淫趴 ",
64
- "description": "让群友们眼前一黑的牛子比拼插件",
65
- "commands": [
66
- {
67
- "cmd": "开启淫趴 / 禁止淫趴",
68
- "desc": "在本群开启或关闭淫趴功能(管理员/群主/主人可用)",
69
- "usage": "开启淫趴 / 关闭银趴",
70
- "role": "admin"
71
- },
72
- {
73
- "cmd": "打胶 / 开导",
74
- "desc": "给自己的牛子增加一段随机长度",
75
- "role": "member"
76
- },
77
- {
78
- "cmd": "嗦牛子",
79
- "desc": "嗦自己或被 @ 的群友的牛子,增加随机长度",
80
- "usage": "嗦牛子 / 嗦牛子 @某人",
81
- "role": "member"
82
- },
83
- {
84
- "cmd": "pk / 对决",
85
- "desc": "和 @ 的群友进行牛子对决,胜者抢走败者的随机长度",
86
- "usage": "pk @某人",
87
- "role": "member"
88
- },
89
- {
90
- "cmd": "查询",
91
- "desc": "查询自己或 @ 的群友的牛子长度",
92
- "usage": "查询 / 查询 @某人",
93
- "role": "member"
94
- },
95
- {
96
- "cmd": "jj排行榜",
97
- "desc": "查看牛子长度前五与倒数五名的图表",
98
- "usage": "jj排行榜 / jjrank",
99
- "role": "member"
100
- },
101
- {
102
- "cmd": "日群友 / 透群友 / 透群主 / 透管理",
103
- "desc": "随机或定向选取一位幸运儿进行注入,按命令决定身份",
104
- "usage": "日群友 / 透群友 @某人 / 透群主 / 透管理",
105
- "role": "member"
106
- },
107
- {
108
- "cmd": "注入查询",
109
- "desc": "查询当日或全部历史被注入量,加 历史/全部 看走势图",
110
- "usage": "注入查询 / 注入查询 历史 / 注入查询 @某人 全部",
111
- "role": "member"
112
- }
113
- ]
114
- }
19
+ ]
115
20
  },
116
21
  "peerDependencies": {
117
22
  "mioku": "^1.0.0"
package/utils.ts CHANGED
@@ -54,11 +54,6 @@ export function isGroupEvent(event: any): boolean {
54
54
  return event?.message_type === "group" && event?.group_id != null;
55
55
  }
56
56
 
57
- export function isGroupAdmin(event: any): boolean {
58
- const role = event?.sender?.role;
59
- return role === "admin" || role === "owner";
60
- }
61
-
62
57
  export function getSenderName(event: any): string {
63
58
  const card = String(event?.sender?.card || "").trim();
64
59
  if (card) return card;
@@ -87,9 +82,9 @@ export function getAvatarUrl(userId: number): string {
87
82
 
88
83
  export function escapeHtml(value: string): string {
89
84
  return String(value)
90
- .replace(/&/g, "&amp);")
91
- .replace(/</g, "&lt);")
92
- .replace(/>/g, "&gt);")
93
- .replace(/"/g, "&quot);")
94
- .replace(/'/g, "&#39);");
85
+ .replace(/&/g, "&amp;")
86
+ .replace(/</g, "&lt;")
87
+ .replace(/>/g, "&gt;")
88
+ .replace(/"/g, "&quot;")
89
+ .replace(/'/g, "&#39;");
95
90
  }
package/router.ts DELETED
@@ -1,94 +0,0 @@
1
- export type ImpactCommand =
2
- | { type: "pk" }
3
- | { type: "dajiao" }
4
- | { type: "suo" }
5
- | { type: "queryjj" }
6
- | { type: "rank" }
7
- | { type: "yinpa"; subject: "member" | "owner" | "admin" }
8
- | { type: "open_module"; enable: boolean }
9
- | { type: "query_injection"; mode: "today" | "history" }
10
- | { type: "none" };
11
-
12
- const YINPA_RE =
13
- /^(?:日群友|透群友|日群主|透群主|日管理|透管理)(?:\s|$|@)/u;
14
-
15
- const OPEN_MODULE_RE =
16
- /^(?:开始银趴|关闭银趴|开启淫趴|禁止淫趴|开启银趴|禁止银趴)\s*$/u;
17
-
18
- const RANK_HEADS = new Set([
19
- "jj排行榜",
20
- "jj排名",
21
- "jj榜单",
22
- "jjrank",
23
- "JJ排行榜",
24
- "JJ排名",
25
- "JJ榜单",
26
- "JJrank",
27
- "JJRANK",
28
- ]);
29
-
30
- /**
31
- * 把消息文本解析成 impact 命令。
32
- * 仅看消息开头(去掉前导空白),命中失败返回 { type: "none" }。
33
- */
34
- export function parseImpactCommand(text: string): ImpactCommand {
35
- const head = text.replace(/^\s+/, "");
36
- if (!head) return { type: "none" };
37
-
38
- // 银趴开关:完整匹配
39
- const open = head.match(OPEN_MODULE_RE);
40
- if (open) {
41
- const word = open[0];
42
- const enable = word.startsWith("开启") || word.startsWith("开始");
43
- return { type: "open_module", enable };
44
- }
45
-
46
- // 透/日 系列
47
- const yinpa = head.match(YINPA_RE);
48
- if (yinpa) {
49
- const word = yinpa[0];
50
- const subject: "owner" | "admin" | "member" = word.includes("群主")
51
- ? "owner"
52
- : word.includes("管理")
53
- ? "admin"
54
- : "member";
55
- return { type: "yinpa", subject };
56
- }
57
-
58
- // pk / 对决:要求形如 "pk @某人" 或 "pk"。具体的 at 校验放到 handler。
59
- if (/^(pk|PK|对决)(\s|@|$)/.test(head)) {
60
- return { type: "pk" };
61
- }
62
-
63
- // 打胶 / 开导:完整匹配
64
- if (/^(打胶|开导)\s*$/.test(head)) {
65
- return { type: "dajiao" };
66
- }
67
-
68
- // 嗦牛子
69
- if (/^嗦牛子(\s|@|$)/.test(head)) {
70
- return { type: "suo" };
71
- }
72
-
73
- // 注入查询 / 摄入查询 / 射入查询
74
- const inj = head.match(/^(?:注入查询|摄入查询|射入查询)(.*)$/u);
75
- if (inj) {
76
- const rest = inj[1] || "";
77
- const mode = /历史|全部/.test(rest) ? "history" : "today";
78
- return { type: "query_injection", mode };
79
- }
80
-
81
- // 排行榜
82
- for (const word of RANK_HEADS) {
83
- if (head === word || head.startsWith(`${word} `) || head.startsWith(`${word}\n`)) {
84
- return { type: "rank" };
85
- }
86
- }
87
-
88
- // 只匹配 "查询" + 空白/at/结束,避免误吞太多文本
89
- if (/^查询(\s|@|$)/.test(head)) {
90
- return { type: "queryjj" };
91
- }
92
-
93
- return { type: "none" };
94
- }