koishi-plugin-ll-brick 1.0.4 → 1.0.6

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.
Files changed (3) hide show
  1. package/lib/index.js +38 -12
  2. package/package.json +1 -1
  3. package/readme.md +15 -0
package/lib/index.js CHANGED
@@ -55,8 +55,8 @@ exports.inject = ["database"];
55
55
  // QQ 官方机器人的 @ 只有在 markdown 消息里才会渲染,纯文本消息不识别任何 at 标签。
56
56
  // 因此 QQ 平台的回复直接走开放平台 internal API 发 markdown(图片嵌入 markdown),
57
57
  // 与欢迎插件同一方案;其他平台沿用原 h.at 文本消息。
58
- const BRICK_IMG = 'https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/lOIl/240X240/images.jpg/webp';
59
- const FIRE_IMG = 'https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/xsnm/447X447/images_%282%29.jpg/webp';
58
+ const BRICK_IMG = 'https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/lOIl/240X240/images.jpg';
59
+ const FIRE_IMG = 'https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/xsnm/447X447/images_%282%29.jpg';
60
60
  function atUser(session, userId) {
61
61
  if (session?.platform === 'qq') {
62
62
  return `<qqbot-at-user id="${userId}" />`;
@@ -75,13 +75,15 @@ function stripMarkdown(md) {
75
75
  .replace(/\n{3,}/g, '\n\n')
76
76
  .trim();
77
77
  }
78
- async function sendQQMarkdown(session, imageUrl, text) {
78
+ async function sendQQMarkdown(session, imageUrl, imageSize, text) {
79
79
  const channelId = session.guildId;
80
80
  const internal = session.bot?.internal;
81
81
  if (!channelId || !internal || typeof internal.sendMessage !== 'function') {
82
82
  return false;
83
83
  }
84
- const md = imageUrl ? `![](${imageUrl})\n\n${text}` : text;
84
+ // QQ markdown 图片必须带尺寸参数(如 #240px #240px),否则会显示异常/不显示
85
+ const img = imageUrl ? `![砖头 #${imageSize}px #${imageSize}px](${imageUrl})` : '';
86
+ const md = [img, text].filter(Boolean).join('\n\n');
85
87
  const plain = stripMarkdown(md) || ' ';
86
88
  try {
87
89
  await internal.sendMessage(channelId, {
@@ -100,6 +102,22 @@ async function sendQQMarkdown(session, imageUrl, text) {
100
102
  return false;
101
103
  }
102
104
  }
105
+ // QQ 官方适配器未实现 getGuildMemberIter/getGuildMemberList,改走开放平台群成员列表 API
106
+ async function getQQMemberIds(session) {
107
+ const http = session.bot?.http;
108
+ if (!http || typeof http.get !== 'function') return [];
109
+ try {
110
+ const resp = await http.get(`/v2/groups/${session.guildId}/members`);
111
+ const list = resp?.data;
112
+ if (!Array.isArray(list)) return [];
113
+ return list
114
+ .map((m) => m?.member_openid || m?.openid || m?.id || m?.member?.openid || m?.member?.user?.id || m?.user?.id)
115
+ .filter(Boolean);
116
+ }
117
+ catch (e) {
118
+ return [];
119
+ }
120
+ }
103
121
  async function apply(ctx, config) {
104
122
  ctx.model.extend('brick', {
105
123
  id: 'unsigned',
@@ -136,7 +154,7 @@ async function apply(ctx, config) {
136
154
  return `已经在烧砖了`;
137
155
  }
138
156
  users[user].burning = true;
139
- await session.send(`${koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/xsnm/447X447/images_%282%29.jpg/webp')}现在开始烧砖啦,群友每发送${config.cost}条消息就烧好一块砖`);
157
+ await session.send(`${koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/xsnm/447X447/images_%282%29.jpg')}现在开始烧砖啦,群友每发送${config.cost}条消息就烧好一块砖`);
140
158
  let messageCount = 0;
141
159
  const dispose = ctx.guild(session.guildId).middleware(async (session_in, next) => {
142
160
  if (![session.selfId, session.userId].includes(session_in.userId)) {
@@ -151,7 +169,7 @@ async function apply(ctx, config) {
151
169
  users[user].burning = false;
152
170
  const fireDone = `${atUser(session, session.userId)} 砖已经烧好啦`;
153
171
  if (session.platform === 'qq') {
154
- await sendQQMarkdown(session, FIRE_IMG, fireDone);
172
+ await sendQQMarkdown(session, FIRE_IMG, 447, fireDone);
155
173
  }
156
174
  else {
157
175
  await session.send(`${koishi_1.h.image(FIRE_IMG)}${fireDone}`);
@@ -199,7 +217,7 @@ async function apply(ctx, config) {
199
217
  const probability = config.specialUser[targetUserId] !== undefined
200
218
  ? config.specialUser[targetUserId] / 100
201
219
  : config.reverse / 100;
202
- const brickImg = koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/lOIl/240X240/images.jpg/webp');
220
+ const brickImg = koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/lOIl/240X240/images.jpg');
203
221
  const isQQ = session.platform === 'qq';
204
222
  if (koishi_1.Random.bool(probability)) {
205
223
  const muteErr = await tryMute(session.userId);
@@ -207,7 +225,7 @@ async function apply(ctx, config) {
207
225
  if (muteErr)
208
226
  msg += '\n因为我不是群管理员,所以并没什么卵用';
209
227
  if (isQQ) {
210
- await sendQQMarkdown(session, BRICK_IMG, msg);
228
+ await sendQQMarkdown(session, BRICK_IMG, 240, msg);
211
229
  return;
212
230
  }
213
231
  return `${brickImg}${msg}`;
@@ -218,7 +236,7 @@ async function apply(ctx, config) {
218
236
  if (muteErr)
219
237
  msg += '\n因为我不是群管理员,所以并没什么卵用';
220
238
  if (isQQ) {
221
- await sendQQMarkdown(session, BRICK_IMG, msg);
239
+ await sendQQMarkdown(session, BRICK_IMG, 240, msg);
222
240
  return;
223
241
  }
224
242
  return `${brickImg}${msg}`;
@@ -252,8 +270,16 @@ async function apply(ctx, config) {
252
270
  .alias("随机拍人")
253
271
  .action(async ({ session }) => {
254
272
  const guildMember = [];
255
- for await (const member of session.bot.getGuildMemberIter(session.guildId)) {
256
- guildMember.push(member?.user.id);
273
+ if (session.platform === 'qq') {
274
+ guildMember.push(...await getQQMemberIds(session));
275
+ }
276
+ else {
277
+ for await (const member of session.bot.getGuildMemberIter(session.guildId)) {
278
+ guildMember.push(member?.user.id);
279
+ }
280
+ }
281
+ if (!guildMember.length) {
282
+ return '获取群成员列表失败,无法随机拍人';
257
283
  }
258
284
  await session.execute(`砖头.拍人 ${koishi_1.h.at(koishi_1.Random.pick(guildMember))}`);
259
285
  });
@@ -278,7 +304,7 @@ async function apply(ctx, config) {
278
304
  const date = new Date();
279
305
  const today = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
280
306
  let brick = koishi_1.Random.int(config.minGain, config.maxGain + 1);
281
- const signImg = koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/yNf2/447X447/images_%281%29.jpg/webp');
307
+ const signImg = koishi_1.h.image('https://img3.tofaka.com/autoupload/ontjZmlK09ZHnuFOv9znC7KXl_QqVl-bpSwqP4fJO68/20260624/yNf2/447X447/images_%281%29.jpg');
282
308
  const userData = await ctx.database.get('brick', {
283
309
  userId: session.userId,
284
310
  guildId: session.guildId,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-ll-brick",
3
3
  "description": "砖头拍人插件(克隆自 koishi-plugin-brick),非管理员时会提示",
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [
package/readme.md CHANGED
@@ -13,6 +13,21 @@
13
13
  - `砖头 查看` — 查看自己的砖头数量
14
14
  - `砖头 签到`(可选开启)— 每日签到获取随机砖头
15
15
 
16
+ ## v1.0.6 修复
17
+
18
+ - 修复 **`砖头 随机拍人` 报错 `not implemented: getGuildMemberList`**(QQ 官方适配器未实现群成员迭代接口):
19
+ - QQ 平台改为调用开放平台群成员列表 API(`/v2/groups/{openid}/members`)随机挑人;其他平台保持原逻辑
20
+ - 获取不到成员时返回提示,不再崩溃
21
+ - 修复 **拍人/烧砖完成消息中 markdown 图片不显示**:
22
+ - 根因:QQ markdown 图片必须带尺寸参数(如 `#240px #240px`),之前 `![](url)` 没带,图片显示异常
23
+ - 修复:嵌入图片统一加 `#240px #240px`(拍人)/ `#447px #447px`(烧砖)尺寸参数
24
+
25
+ ## v1.0.5 修复
26
+
27
+ - 修复 **手机端 QQ 不显示图片**(电脑端正常)的问题:
28
+ - 根因:三张图片地址带 `/webp` 后缀,返回 `image/webp`,手机端 QQ 不渲染 webp(烧砖那张的 webp 地址甚至直接 404)
29
+ - 修复:全部改用无后缀的 jpg 地址(已验证返回 `image/jpeg`)
30
+
16
31
  ## v1.0.4 修复
17
32
 
18
33
  - 彻底修复 **QQ 官方机器人** 上回复消息中 @(艾特)不生效的问题: