koishi-plugin-starfx-bot 0.26.8 → 0.27.1

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
@@ -3,6 +3,12 @@ export declare const name = "starfx-bot";
3
3
  export declare const inject: {
4
4
  optional: string[];
5
5
  };
6
+ declare module 'koishi' {
7
+ interface Channel {
8
+ pickupLength: number;
9
+ pickupGrant: boolean;
10
+ }
11
+ }
6
12
  export declare let baseDir: string;
7
13
  export declare let assetsDir: string;
8
14
  export declare const starfxLogger: Logger;
@@ -40,6 +46,8 @@ export interface Config {
40
46
  forward: boolean;
41
47
  searchExchangeRate: boolean;
42
48
  intervalGetExchangeRate: boolean;
49
+ roomNumToName: boolean;
50
+ roomNumLength: number;
43
51
  atNotSay: boolean;
44
52
  atNotSayProperty: number;
45
53
  atNotSayOther: boolean;
package/lib/index.js CHANGED
@@ -33,7 +33,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
33
33
  // src/locales/zh-CN.yml
34
34
  var require_zh_CN = __commonJS({
35
35
  "src/locales/zh-CN.yml"(exports2, module2) {
36
- module2.exports = { commands: { roll: { messages: { noParam: "你问啥?", invalid: "你要不看看你说的是啥", "too-many": "太、太多了啦!", noodles: "扔出了{num}个{noodles}面的骰子,点数如下:{points}", possibility: "{param}是{possibility}%", choose: "当然是{option}啦!" } }, "room-number": { messages: { roomNumber: "当前的房间号是: {room}", changeRoom: "已将当前房间号 {oldRoom} 修改为 {newRoom}", newRoom: "已添加房间号: {room}", noRoom: "当前没有保存的房间", delRoom: "已删除房间: {room}", invalid: "无效输入" } }, forward: { messages: { delete: "已删除转发群聊: {gid}", noTarget: "未配置转发群组", success: "已转发消息到: {target}", noMessage: "请引用要转发的消息", setOK: "已配置转发: {target}", forwardContent: "[转发消息]<br/> {content}" } }, "waiting-play": { messages: { addReady: "已添加,当前待机{num}人: <br/>{list}", delReady: "已删除,当前待机{num}人: <br/>{list}", delFailed: "未删除,当前待机{num}人: <br/>{list}", clearReady: "待机列表已清空", listReady: "当前待机{num}人: <br/>{list}", invalid: "输入无效" } } }, middleware: { messages: { atNotReply: "艾特我又不说话", atNotReplyOther: "艾特他又不说话", notBot: "我才不是机器人!", loveMessage: "我喜欢你", iLoveU: "我也喜欢你" } } };
36
+ module2.exports = { commands: { roll: { messages: { noParam: "你问啥?", invalid: "你要不看看你说的是啥", "too-many": "太、太多了啦!", noodles: "扔出了{num}个{noodles}面的骰子,点数如下:{points}", possibility: "{param}是{possibility}%", choose: "当然是{option}啦!" } }, "room-number": { messages: { roomNumber: "当前的房间号是: {room}", changeRoom: "已将当前房间号 {oldRoom} 修改为 {newRoom}", newRoom: "已添加房间号: {room}", noRoom: "当前没有保存的房间", delRoom: "已删除房间: {room}", invalid: "无效输入" } }, forward: { messages: { delete: "已删除转发群聊: {gid}", noTarget: "未配置转发群组", success: "已转发消息到: {target}", noMessage: "请引用要转发的消息", setOK: "已配置转发: {target}", forwardContent: "[转发消息]<br/> {content}" } }, "waiting-play": { messages: { addReady: "已添加,当前待机{num}人: <br/>{list}", delReady: "已删除,当前待机{num}人: <br/>{list}", delFailed: "未删除,当前待机{num}人: <br/>{list}", clearReady: "待机列表已清空", listReady: "当前待机{num}人: <br/>{list}", invalid: "输入无效" } }, 开启车牌检测: { messages: { success: "车牌检测:已打开\n当前车牌位数: {length}", noPermission: "你没有权限开启车牌检测", noGuild: "请在群聊中使用该指令", invalidLength: "位数设定不合理,请输入 1-20 之间的数字" } }, 关闭车牌检测: { messages: { success: "已关闭车牌检测", noPermission: "你没有权限关闭车牌检测", noGuild: "请在群聊中使用该指令" } }, 车牌检测状态: { messages: { enabled: "车牌检测: 已打开\n当前车牌位数: {length}", disabled: "车牌检测: 已关闭", managerEnabled: "管理员权限正常", managerDisabled: "无管理员权限,无法修改群名", noPermission: "你没有权限查看车牌检测状态", noGuild: "请在群聊中使用该指令" } }, 车牌检测权限: { messages: { status: { enabled: "普通群员开关车牌检测: 允许", disabled: "普通群员开关车牌检测: 禁止" }, enabled: "已允许普通群员开关车牌检测", disabled: "已禁止普通群员开关车牌检测", invalid: "无效输入,请输入 开 / 关", noPermission: "你没有权限设置车牌检测权限", noGuild: "请在群聊中使用该指令" } } }, middleware: { messages: { atNotReply: "艾特我又不说话", atNotReplyOther: "艾特他又不说话", notBot: "我才不是机器人!", loveMessage: "我喜欢你", iLoveU: "我也喜欢你", notManager: "当前bot没有管理员权限,无法修改群名", editFuncNotFound: "无法找到设置群名的底层方法", editGroupNameSuccess: "检测到车牌 {content},群名修改成功!", editGroupNameRetrySuccess: '检测到车牌 {content},由于限制已修改为 "{spacedContent}"' } } };
37
37
  }
38
38
  });
39
39
 
@@ -63,7 +63,7 @@ var package_default = {
63
63
  contributors: [
64
64
  "StarFreedomX <starfreedomx@outlook.com>"
65
65
  ],
66
- version: "0.26.7",
66
+ version: "0.27.1",
67
67
  main: "lib/index.js",
68
68
  typings: "lib/index.d.ts",
69
69
  files: [
@@ -866,6 +866,30 @@ function getSharpConstructor(ctx) {
866
866
  return sharpConstructor;
867
867
  }
868
868
  __name(getSharpConstructor, "getSharpConstructor");
869
+ async function getAuthority(session) {
870
+ const user = await session.observeUser(["authority"]);
871
+ const authority = user?.authority || 0;
872
+ const roles = (session.event.member?.roles || []).map(
873
+ (r) => typeof r === "string" ? r : r.id
874
+ );
875
+ return { authority, roles };
876
+ }
877
+ __name(getAuthority, "getAuthority");
878
+ async function canBotManage(session) {
879
+ try {
880
+ const selfMember = await session.bot.getGuildMember(session.guildId, session.selfId);
881
+ const roles = (selfMember.roles || []).map((r) => typeof r === "string" ? r : r.id);
882
+ return roles.includes("admin") || roles.includes("owner");
883
+ } catch (e) {
884
+ return false;
885
+ }
886
+ }
887
+ __name(canBotManage, "canBotManage");
888
+ async function canGrant(session) {
889
+ const { authority, roles } = await getAuthority(session);
890
+ return authority > 1 || roles.includes("admin") || roles.includes("owner");
891
+ }
892
+ __name(canGrant, "canGrant");
869
893
 
870
894
  // src/plugins/drawHead.ts
871
895
  async function handleBanGDreamConfig(options) {
@@ -1275,7 +1299,9 @@ var Config = import_koishi5.Schema.intersect([
1275
1299
  ),
1276
1300
  forward: import_koishi5.Schema.boolean().default(true).description("消息转发功能"),
1277
1301
  searchExchangeRate: import_koishi5.Schema.boolean().default(false).description("查汇率功能"),
1278
- intervalGetExchangeRate: import_koishi5.Schema.boolean().default(false).description("汇率定时推送功能").hidden()
1302
+ intervalGetExchangeRate: import_koishi5.Schema.boolean().default(false).description("汇率定时推送功能").hidden(),
1303
+ roomNumToName: import_koishi5.Schema.boolean().default(false).description("监听车牌修改群名功能"),
1304
+ roomNumLength: import_koishi5.Schema.number().default(5).description("默认车牌位数")
1279
1305
  }).description("指令小功能"),
1280
1306
  import_koishi5.Schema.object({
1281
1307
  atNotSay: import_koishi5.Schema.boolean().default(true).description("开启‘艾特我又不说话’功能"),
@@ -1328,6 +1354,11 @@ var Config = import_koishi5.Schema.intersect([
1328
1354
  }).description("高级配置")
1329
1355
  ]);
1330
1356
  function apply(ctx, cfg) {
1357
+ ctx.model.extend("channel", {
1358
+ pickupLength: "unsigned",
1359
+ // 无符号整数
1360
+ pickupGrant: "boolean"
1361
+ });
1331
1362
  ctx.i18n.define("zh-CN", require_zh_CN());
1332
1363
  baseDir = ctx.baseDir;
1333
1364
  assetsDir = `${ctx.baseDir}/data/starfx-bot/assets`;
@@ -1653,8 +1684,99 @@ function apply(ctx, cfg) {
1653
1684
  }
1654
1685
  });
1655
1686
  }
1687
+ const canTogglePickup = /* @__PURE__ */ __name(async (session) => {
1688
+ if (await canGrant(session)) return true;
1689
+ const channel = await session.observeChannel(["pickupGrant"]);
1690
+ return !!channel.pickupGrant;
1691
+ }, "canTogglePickup");
1692
+ if (cfg.roomNumToName) {
1693
+ ctx.command("车牌检测权限 [allow:text]").channelFields(["pickupGrant"]).action(async ({ session }, allow) => {
1694
+ if (!detectControl(featureControl, session.guildId, "pickup")) return;
1695
+ if (!session.guildId) return session.text(".noGuild");
1696
+ if (!await canGrant(session)) return session.text(".noPermission");
1697
+ if (!allow) {
1698
+ return session.channel.pickupGrant ? session.text(".status.enabled") : session.text(".status.disabled");
1699
+ }
1700
+ const normalized = String(allow).trim().toLowerCase();
1701
+ if (["1", "true", "yes", "y", "on", "开", "开启", "允许"].includes(normalized)) {
1702
+ session.channel.pickupGrant = true;
1703
+ return session.text(".enabled");
1704
+ }
1705
+ if (["0", "false", "no", "n", "off", "关", "关闭", "禁止"].includes(normalized)) {
1706
+ session.channel.pickupGrant = false;
1707
+ return session.text(".disabled");
1708
+ }
1709
+ return session.text(".invalid");
1710
+ });
1711
+ ctx.command("开启车牌检测 [length:number]").alias("打开车牌检测", "打开拾取").channelFields(["pickupLength", "pickupGrant"]).action(async ({ session }, length) => {
1712
+ if (!detectControl(featureControl, session.guildId, "pickup")) return;
1713
+ if (!session.guildId) return session.text(".noGuild");
1714
+ if (!await canTogglePickup(session)) return session.text(".noPermission");
1715
+ if (!await canBotManage(session)) return session.text("middleware.messages.notManager");
1716
+ const finalLength = length || cfg.roomNumLength || 5;
1717
+ if (finalLength < 1 || finalLength > 20) return session.text(".invalidLength");
1718
+ session.channel.pickupLength = finalLength;
1719
+ return session.text(".success", { length: finalLength });
1720
+ });
1721
+ ctx.command("关闭车牌检测").alias("关闭拾取").channelFields(["pickupLength", "pickupGrant"]).action(async ({ session }) => {
1722
+ if (!detectControl(featureControl, session.guildId, "pickup")) return;
1723
+ if (!session.guildId) return session.text(".noGuild");
1724
+ if (!await canTogglePickup(session)) return session.text(".noPermission");
1725
+ session.channel.pickupLength = 0;
1726
+ return session.text(".success");
1727
+ });
1728
+ ctx.command("车牌检测状态").channelFields(["pickupLength", "pickupGrant"]).action(async ({ session }) => {
1729
+ if (!detectControl(featureControl, session.guildId, "pickup")) return;
1730
+ if (!session.guildId) return session.text(".noGuild");
1731
+ return `${session.channel.pickupLength > 0 ? session.text(".enabled", { length: session.channel.pickupLength }) : session.text(".disabled")}
1732
+ ${!!await canBotManage(session) ? session.text(".managerEnabled") : session.text(".managerDisabled")}`;
1733
+ });
1734
+ }
1656
1735
  ctx.middleware(async (session, next) => {
1657
1736
  const elements = session.elements;
1737
+ if (cfg.roomNumToName && session.guildId && detectControl(featureControl, session.guildId, "pickup")) {
1738
+ const channel = await session.observeChannel(["pickupLength", "pickupGrant"]);
1739
+ const targetLength = channel.pickupLength;
1740
+ const content = session.content?.trim();
1741
+ if (targetLength > 0 && new RegExp(`^\\d{${targetLength}}$`).test(content)) {
1742
+ if (!await canBotManage(session)) return session.text("middleware.messages.notManager");
1743
+ const setGroupName = /* @__PURE__ */ __name(async (name2) => {
1744
+ const internal = session.bot.internal;
1745
+ if (typeof internal?._request === "function" && session.platform === "onebot") {
1746
+ const response = await internal._request("set_group_name", {
1747
+ group_id: session.guildId,
1748
+ group_name: name2
1749
+ });
1750
+ if (response && response.retcode !== 0 && response.status !== "ok") {
1751
+ throw new Error(`OneBot 报错 (Code: ${response.retcode}): ${JSON.stringify(response)}`);
1752
+ }
1753
+ return response;
1754
+ }
1755
+ if (internal.set_group_name) {
1756
+ return await internal.set_group_name(session.guildId, name2);
1757
+ }
1758
+ if (session.bot.updateChannel) {
1759
+ return await session.bot.updateChannel(session.guildId, { name: name2 });
1760
+ }
1761
+ throw new Error(session.text("middleware.messages.editFuncNotFound"));
1762
+ }, "setGroupName");
1763
+ try {
1764
+ await setGroupName(content);
1765
+ await session.send(session.text("middleware.messages.editGroupNameSuccess", { content }));
1766
+ return;
1767
+ } catch (e) {
1768
+ starfxLogger.warn(`纯数字修改失败,尝试添加空格重试: ${content}`);
1769
+ try {
1770
+ const spacedContent = content.replace(/(\d{3})(?=\d)/g, "$1 ");
1771
+ await setGroupName(spacedContent);
1772
+ await session.send(session.text("middleware.messages.editGroupNameRetrySuccess", { content, spacedContent }));
1773
+ return;
1774
+ } catch (retryError) {
1775
+ starfxLogger.error(`尝试添加空格修改群名依然失败: ${retryError}`);
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1658
1780
  if (cfg.openRepeat && detectControl(featureControl, session.guildId, "repeat")) {
1659
1781
  const content = session.content;
1660
1782
  const ctxArr = repeatContextMap.get(session.gid);
@@ -17,14 +17,14 @@ export declare function handleBanGDreamConfig(options: any): Promise<{
17
17
  * @param baseImage 被封印的图片url
18
18
  * @return 画完的图片 h对象
19
19
  */
20
- export declare function drawLock(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
20
+ export declare function drawLock(ctx: Context, baseImage: string): Promise<h | "输入无效" | "发生错误">;
21
21
  /**
22
22
  * "卖掉了"绘图函数
23
23
  * @param ctx
24
24
  * @param baseImage
25
25
  * @return 画完的图片 h对象
26
26
  */
27
- export declare function drawSold(ctx: Context, baseImage: string): Promise<"发生错误" | "输入无效" | h>;
27
+ export declare function drawSold(ctx: Context, baseImage: string): Promise<h | "输入无效" | "发生错误">;
28
28
  /**
29
29
  * BanG Dream!边框绘制功能
30
30
  * @param ctx Koishi上下文
package/lib/utils.d.ts CHANGED
@@ -112,4 +112,16 @@ export declare function ready(session: Session, cfg: Config, param: string, read
112
112
  * 安全地从上下文中获取 Sharp 构造函数
113
113
  */
114
114
  export declare function getSharpConstructor(ctx: Context): any;
115
+ /**
116
+ * 检查用户权限
117
+ */
118
+ export declare function getAuthority(session: Session): Promise<{
119
+ authority: number;
120
+ roles: string[];
121
+ }>;
122
+ /**
123
+ * 专门检查机器人是否有权执行群管理操作
124
+ */
125
+ export declare function canBotManage(session: Session): Promise<boolean>;
126
+ export declare function canGrant(session: Session): Promise<boolean>;
115
127
  export {};
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "contributors": [
5
5
  "StarFreedomX <starfreedomx@outlook.com>"
6
6
  ],
7
- "version": "0.26.8",
7
+ "version": "0.27.1",
8
8
  "main": "lib/index.js",
9
9
  "typings": "lib/index.d.ts",
10
10
  "files": [
package/readme.md CHANGED
@@ -70,6 +70,7 @@ StarFreedomX机器人的小功能,自用
70
70
  | `forward` | 消息转发功能 |
71
71
  | `exchangeRate` | 汇率播报功能 |
72
72
  | `myId` | 我的会话信息 |
73
+ | `pickup` | 车牌检测 |
73
74
 
74
75
  ---
75
76
 
@@ -129,3 +130,5 @@ StarFreedomX机器人的小功能,自用
129
130
  | `0.25.1` | 修正功能控制模块功能名相关bug |
130
131
  | `0.26.6` | 修正roll扔骰子的判断错误 |
131
132
  | `0.26.8` | 修复sharp库传回参数改为对象的错误 |
133
+ | `0.27.0` | 新增监听车牌修改群名功能 |
134
+ | `0.27.1` | 车牌监听权限设置 |