@sfmc-bds/qq-bridge 0.2.2 → 0.2.4
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/README.md +1 -1
- package/dist/commands/interaction-router.js +31 -3
- package/dist/commands/interaction-router.js.map +3 -3
- package/dist/official/events.js +10 -10
- package/dist/official/events.js.map +2 -2
- package/dist/official/group-role.js +31 -0
- package/dist/official/group-role.js.map +7 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -86,7 +86,7 @@ Webhook 进程仅监听云机 `127.0.0.1:3005`。用同机 HTTPS 反向代理把
|
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
`version` 是无法获取实际版本时的备用入服说明,回复会明确标注来源;留空时提示联系管理员。修改后重启 QQ 桥接服务。权限仍由 db-server
|
|
89
|
+
`version` 是无法获取实际版本时的备用入服说明,回复会明确标注来源;留空时提示联系管理员。修改后重启 QQ 桥接服务。权限仍由 db-server 最终校验。群主和群管理员默认具有管理权限(`configs/qq_link.json` 的 `treat_group_admins_as_admins`,缺省为开,只能改文件);查询失败时隐藏受限入口。
|
|
90
90
|
|
|
91
91
|
本期不改变入服规则。申请提交、审核通过和 BDS 写入白名单分别提示,不将审核通过视作已生效。下一阶段再完善自助入服进度和玩家数据服务。
|
|
92
92
|
|
|
@@ -1,6 +1,32 @@
|
|
|
1
|
-
import { ackInteraction } from "@sfmc-bds/sdk/node/qq-official";
|
|
1
|
+
import { ackInteraction, getGroupMember } from "@sfmc-bds/sdk/node/qq-official";
|
|
2
2
|
import { log } from "../log.js";
|
|
3
|
+
import { cachedGroupAdmin, isPrivilegedGroupRole, rememberGroupRole } from "../official/group-role.js";
|
|
3
4
|
import { parseCfgInteractionData } from "./join-settings-ui.js";
|
|
5
|
+
let memberLookupWarned = false;
|
|
6
|
+
async function resolveInteractionGroupAdmin(creds, groupOpenid, memberOpenid, raw) {
|
|
7
|
+
const author = raw["author"] ?? {};
|
|
8
|
+
const direct = raw["member_role"] ?? author["member_role"];
|
|
9
|
+
if (direct != null) {
|
|
10
|
+
const admin2 = isPrivilegedGroupRole(direct);
|
|
11
|
+
rememberGroupRole(memberOpenid, admin2);
|
|
12
|
+
return admin2;
|
|
13
|
+
}
|
|
14
|
+
const cached = cachedGroupAdmin(memberOpenid);
|
|
15
|
+
if (cached !== void 0) return cached;
|
|
16
|
+
const res = await getGroupMember(creds, groupOpenid, memberOpenid);
|
|
17
|
+
if (!res.ok) {
|
|
18
|
+
if (!memberLookupWarned) {
|
|
19
|
+
memberLookupWarned = true;
|
|
20
|
+
log.warn(`\u67E5\u8BE2\u7FA4\u6210\u5458\u89D2\u8272\u5931\u8D25\uFF0C\u6309\u94AE\u56DE\u8C03\u6682\u65E0\u6CD5\u6309\u7FA4\u7BA1\u6388\u6743: ${res.error}`);
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const role = res.json && typeof res.json === "object" ? res.json.member_role : void 0;
|
|
25
|
+
if (role == null) return false;
|
|
26
|
+
const admin = isPrivilegedGroupRole(role);
|
|
27
|
+
rememberGroupRole(memberOpenid, admin);
|
|
28
|
+
return admin;
|
|
29
|
+
}
|
|
4
30
|
function createInteractionRouter(opts) {
|
|
5
31
|
const recent = /* @__PURE__ */ new Map();
|
|
6
32
|
return {
|
|
@@ -19,7 +45,7 @@ function createInteractionRouter(opts) {
|
|
|
19
45
|
}
|
|
20
46
|
const author = d["author"] ?? {};
|
|
21
47
|
const user = String(
|
|
22
|
-
d["user_openid"] || d["member_openid"] || author["member_openid"] || author["user_openid"] || author["id"] || ""
|
|
48
|
+
d["group_member_openid"] || d["user_openid"] || d["member_openid"] || author["member_openid"] || author["user_openid"] || author["id"] || ""
|
|
23
49
|
);
|
|
24
50
|
const group = String(d["group_openid"] ?? "");
|
|
25
51
|
if (!user || !group || group !== opts.groupOpenid) return;
|
|
@@ -38,12 +64,14 @@ function createInteractionRouter(opts) {
|
|
|
38
64
|
const cfg = parseCfgInteractionData(data);
|
|
39
65
|
const join = /^join:(approve|reject):(.+)$/.exec(data);
|
|
40
66
|
const command = cfg ? `/config ${cfg.field === "allowlist_enabled" ? "\u767D\u540D\u5355" : "\u5BA1\u6279"} ${cfg.value ? "\u5F00" : "\u5173"}` : join ? `/${join[1]} ${join[2]}` : "/help";
|
|
67
|
+
const isGroupAdmin = await resolveInteractionGroupAdmin(opts.creds, group, user, d);
|
|
41
68
|
await opts.commandRouter.handle({
|
|
42
69
|
backend: "official",
|
|
43
70
|
groupId: group,
|
|
44
71
|
userId: user,
|
|
45
72
|
userName: "\u7FA4\u6210\u5458",
|
|
46
|
-
text: command
|
|
73
|
+
text: command,
|
|
74
|
+
isGroupAdmin
|
|
47
75
|
});
|
|
48
76
|
}
|
|
49
77
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/interaction-router.ts"],
|
|
4
|
-
"sourcesContent": ["import { ackInteraction, type QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { parseCfgInteractionData } from \"./join-settings-ui.js\";\nimport type { CommandRouter } from \"./router.js\";\n\nexport type InteractionRouterOpts = { creds: QqOfficialCredentials; commandRouter: CommandRouter; groupOpenid: string };\nexport function createInteractionRouter(opts: InteractionRouterOpts) {\n const recent = new Map<string, number>();\n return {\n async handle(raw: unknown): Promise<void> {\n const d = (raw ?? {}) as Record<string, unknown>;\n const id = String(d[\"id\"] ?? \"\");\n if (!id) return;\n for (const [key, time] of recent) if (Date.now() - time > 60_000) recent.delete(key);\n if (recent.has(id)) return;\n recent.set(id, Date.now());\n try {\n const ack = await ackInteraction(opts.creds, id);\n if (!ack.ok) log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${ack.error}`);\n } catch (error) {\n log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${String(error)}`);\n }\n const author = (d[\"author\"] ?? {}) as Record<string, unknown>;\n const user = String(\n d[\"user_openid\"]
|
|
5
|
-
"mappings": "AAAA,SAAS,sBAAkD;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import { ackInteraction, getGroupMember, type QqOfficialCredentials } from \"@sfmc-bds/sdk/node/qq-official\";\nimport { log } from \"../log.js\";\nimport { cachedGroupAdmin, isPrivilegedGroupRole, rememberGroupRole } from \"../official/group-role.js\";\nimport { parseCfgInteractionData } from \"./join-settings-ui.js\";\nimport type { CommandRouter } from \"./router.js\";\n\n/** \u6210\u5458\u63A5\u53E3\u65E0\u6743\u9650\u65F6\u53EA\u63D0\u793A\u4E00\u6B21\uFF0C\u907F\u514D\u6BCF\u6B21\u70B9\u6309\u94AE\u90FD\u5237\u65E5\u5FD7\u3002 */\nlet memberLookupWarned = false;\n\n/**\n * \u6309\u94AE\u56DE\u8C03\u6CA1\u6709 member_role\uFF0C\u5148\u7528\u6700\u8FD1\u7FA4\u6D88\u606F\u7F13\u5B58\uFF0C\u518D\u67E5\u6210\u5458\u63A5\u53E3\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u7FA4\u7BA1\u70B9\u7BA1\u7406\u83DC\u5355\u65F6\u8865\u9F50 isGroupAdmin\uFF0C\u4F9B db-server \u6309\u7FA4\u7BA1\u6388\u6743\u3002\n */\nasync function resolveInteractionGroupAdmin(\n creds: QqOfficialCredentials,\n groupOpenid: string,\n memberOpenid: string,\n raw: Record<string, unknown>\n): Promise<boolean> {\n const author = (raw[\"author\"] ?? {}) as Record<string, unknown>;\n const direct = raw[\"member_role\"] ?? author[\"member_role\"];\n if (direct != null) {\n const admin = isPrivilegedGroupRole(direct);\n rememberGroupRole(memberOpenid, admin);\n return admin;\n }\n const cached = cachedGroupAdmin(memberOpenid);\n if (cached !== undefined) return cached;\n const res = await getGroupMember(creds, groupOpenid, memberOpenid);\n if (!res.ok) {\n if (!memberLookupWarned) {\n memberLookupWarned = true;\n log.warn(`\u67E5\u8BE2\u7FA4\u6210\u5458\u89D2\u8272\u5931\u8D25\uFF0C\u6309\u94AE\u56DE\u8C03\u6682\u65E0\u6CD5\u6309\u7FA4\u7BA1\u6388\u6743: ${res.error}`);\n }\n return false;\n }\n const role =\n res.json && typeof res.json === \"object\" ? (res.json as { member_role?: unknown }).member_role : undefined;\n if (role == null) return false;\n const admin = isPrivilegedGroupRole(role);\n rememberGroupRole(memberOpenid, admin);\n return admin;\n}\n\nexport type InteractionRouterOpts = { creds: QqOfficialCredentials; commandRouter: CommandRouter; groupOpenid: string };\nexport function createInteractionRouter(opts: InteractionRouterOpts) {\n const recent = new Map<string, number>();\n return {\n async handle(raw: unknown): Promise<void> {\n const d = (raw ?? {}) as Record<string, unknown>;\n const id = String(d[\"id\"] ?? \"\");\n if (!id) return;\n for (const [key, time] of recent) if (Date.now() - time > 60_000) recent.delete(key);\n if (recent.has(id)) return;\n recent.set(id, Date.now());\n try {\n const ack = await ackInteraction(opts.creds, id);\n if (!ack.ok) log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${ack.error}`);\n } catch (error) {\n log.warn(`\u6309\u94AE\u5E94\u7B54\u5931\u8D25: ${String(error)}`);\n }\n const author = (d[\"author\"] ?? {}) as Record<string, unknown>;\n const user = String(\n d[\"group_member_openid\"] ||\n d[\"user_openid\"] ||\n d[\"member_openid\"] ||\n author[\"member_openid\"] ||\n author[\"user_openid\"] ||\n author[\"id\"] ||\n \"\"\n );\n const group = String(d[\"group_openid\"] ?? \"\");\n if (!user || !group || group !== opts.groupOpenid) return;\n let data = \"\";\n for (const key of [\"data\", \"button_data\", \"button\", \"event_data\"]) {\n const value = d[key];\n if (typeof value === \"string\") {\n data = value.trim();\n break;\n }\n if (value && typeof value === \"object\" && \"data\" in value) {\n data = String(value.data);\n break;\n }\n }\n const cfg = parseCfgInteractionData(data);\n const join = /^join:(approve|reject):(.+)$/.exec(data);\n const command = cfg\n ? `/config ${cfg.field === \"allowlist_enabled\" ? \"\u767D\u540D\u5355\" : \"\u5BA1\u6279\"} ${cfg.value ? \"\u5F00\" : \"\u5173\"}`\n : join\n ? `/${join[1]} ${join[2]}`\n : \"/help\";\n const isGroupAdmin = await resolveInteractionGroupAdmin(opts.creds, group, user, d);\n await opts.commandRouter.handle({\n backend: \"official\",\n groupId: group,\n userId: user,\n userName: \"\u7FA4\u6210\u5458\",\n text: command,\n isGroupAdmin,\n });\n },\n };\n}\nexport type InteractionRouter = ReturnType<typeof createInteractionRouter>;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["admin"]
|
|
7
7
|
}
|
package/dist/official/events.js
CHANGED
|
@@ -2,6 +2,7 @@ import { stripOfficialAtMention } from "@sfmc-bds/sdk/node/qq-official";
|
|
|
2
2
|
import { RecentMessageDedup } from "../onebot.js";
|
|
3
3
|
import { tryForward } from "../dbserver.js";
|
|
4
4
|
import { log } from "../log.js";
|
|
5
|
+
import { isPrivilegedGroupRole, rememberGroupRole } from "./group-role.js";
|
|
5
6
|
function detectOfficialGroupAdmin(msg) {
|
|
6
7
|
const candidates = [
|
|
7
8
|
msg.author?.member_role,
|
|
@@ -9,17 +10,16 @@ function detectOfficialGroupAdmin(msg) {
|
|
|
9
10
|
msg.member?.role,
|
|
10
11
|
msg.member?.roles
|
|
11
12
|
];
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
const s = String(c).toLowerCase();
|
|
20
|
-
if (s === "owner" || s === "admin" || s === "2" || s === "3") return true;
|
|
13
|
+
let seen = false;
|
|
14
|
+
let admin = false;
|
|
15
|
+
for (const candidate of candidates) {
|
|
16
|
+
if (candidate == null) continue;
|
|
17
|
+
seen = true;
|
|
18
|
+
if (isPrivilegedGroupRole(candidate)) admin = true;
|
|
21
19
|
}
|
|
22
|
-
|
|
20
|
+
const memberId = String(msg.author?.member_openid || msg.author?.id || "").trim();
|
|
21
|
+
if (seen && memberId) rememberGroupRole(memberId, admin);
|
|
22
|
+
return admin;
|
|
23
23
|
}
|
|
24
24
|
function attachmentsPlaceholder(attachments) {
|
|
25
25
|
if (!Array.isArray(attachments) || attachments.length === 0) return "";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/official/events.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * official/events.ts \u2014 \u5B98\u65B9\u7FA4\u6D88\u606F / C2C \u89E3\u6790\u4E0E\u8F6C\u53D1\n */\n\nimport { stripOfficialAtMention } from \"@sfmc-bds/sdk/node/qq-official\";\nimport type { CommandRouter } from \"../commands/index.js\";\nimport { RecentMessageDedup } from \"../onebot.js\";\nimport { tryForward, type DBServerConfig } from \"../dbserver.js\";\nimport { log } from \"../log.js\";\n\nexport type OfficialAttachment = {\n url?: string;\n content_type?: string;\n filename?: string;\n};\n\nexport type OfficialGroupAtMessage = {\n id?: string;\n content?: string;\n group_openid?: string;\n timestamp?: string;\n author?: {\n id?: string;\n member_openid?: string;\n username?: string;\n bot?: boolean;\n /** \
|
|
5
|
-
"mappings": "AAIA,SAAS,8BAA8B;AAEvC,SAAS,0BAA0B;AACnC,SAAS,kBAAuC;AAChD,SAAS,WAAW;AA+
|
|
4
|
+
"sourcesContent": ["/**\n * official/events.ts \u2014 \u5B98\u65B9\u7FA4\u6D88\u606F / C2C \u89E3\u6790\u4E0E\u8F6C\u53D1\n */\n\nimport { stripOfficialAtMention } from \"@sfmc-bds/sdk/node/qq-official\";\nimport type { CommandRouter } from \"../commands/index.js\";\nimport { RecentMessageDedup } from \"../onebot.js\";\nimport { tryForward, type DBServerConfig } from \"../dbserver.js\";\nimport { log } from \"../log.js\";\nimport { isPrivilegedGroupRole, rememberGroupRole } from \"./group-role.js\";\n\nexport type OfficialAttachment = {\n url?: string;\n content_type?: string;\n filename?: string;\n};\n\nexport type OfficialGroupAtMessage = {\n id?: string;\n content?: string;\n group_openid?: string;\n timestamp?: string;\n author?: {\n id?: string;\n member_openid?: string;\n username?: string;\n bot?: boolean;\n /** \u5B98\u65B9\u53D6\u503C member / admin / owner\uFF1B\u65E0\u6B64\u5B57\u6BB5\u65F6\u65E0\u6CD5\u4ECE\u672C\u6761\u4E8B\u4EF6\u5224\u5B9A\u7FA4\u7BA1 */\n roles?: unknown;\n member_role?: unknown;\n };\n member?: {\n roles?: unknown;\n role?: unknown;\n };\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n};\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u53EF\u9009\u5B57\u6BB5\u63A8\u65AD\u7FA4\u4E3B/\u7FA4\u7BA1\uFF08\u65E0\u53EF\u9760\u5B57\u6BB5\u5219 false\uFF09\uFF0C\u5E76\u5199\u5165\u6309\u94AE\u56DE\u8C03\u7528\u7684\u89D2\u8272\u7F13\u5B58 */\nfunction detectOfficialGroupAdmin(msg: OfficialGroupAtMessage): boolean {\n const candidates: unknown[] = [\n msg.author?.member_role,\n msg.author?.roles,\n msg.member?.role,\n msg.member?.roles,\n ];\n let seen = false;\n let admin = false;\n for (const candidate of candidates) {\n if (candidate == null) continue;\n seen = true;\n if (isPrivilegedGroupRole(candidate)) admin = true;\n }\n const memberId = String(msg.author?.member_openid || msg.author?.id || \"\").trim();\n if (seen && memberId) rememberGroupRole(memberId, admin);\n return admin;\n}\n\n/** C2C \u5355\u804A\u4E8B\u4EF6\u4F53 */\nexport type OfficialC2cMessage = {\n id?: string;\n content?: string;\n timestamp?: string;\n author?: {\n id?: string;\n user_openid?: string;\n username?: string;\n bot?: boolean;\n };\n attachments?: OfficialAttachment[];\n};\n\nexport type OfficialForwardFn = (\n db: DBServerConfig,\n fromId: string,\n fromName: string,\n content: string\n) => Promise<void>;\n\nexport type OfficialDispatcherOptions = {\n /** \u5DF2\u914D\u7F6E\u7684\u7FA4 openid\uFF1B\u7A7A = \u53EA\u6253\u65E5\u5FD7\u4E0D\u8F6C\u53D1 */\n groupOpenid: string;\n db: DBServerConfig;\n /** \u53EF\u6CE8\u5165\uFF0C\u9ED8\u8BA4 tryForward\uFF08\u4FBF\u4E8E\u5355\u6D4B\uFF09 */\n forward?: OfficialForwardFn;\n /** QQ \u4FA7\u6307\u4EE4\u8DEF\u7531\uFF1B\u547D\u4E2D\u5219\u4E0D\u8F6C\u53D1 MC */\n commandRouter?: CommandRouter;\n};\n\n/**\n * \u628A attachments \u8F6C\u6210\u4E0E OneBot \u4E00\u81F4\u7684\u5360\u4F4D\u7B26\u540E\u7F00\u3002\n */\nexport function attachmentsPlaceholder(attachments: OfficialAttachment[] | undefined): string {\n if (!Array.isArray(attachments) || attachments.length === 0) return \"\";\n const parts: string[] = [];\n for (const att of attachments) {\n const ct = String(att.content_type ?? \"\").toLowerCase();\n const name = String(att.filename ?? \"\").toLowerCase();\n if (ct.startsWith(\"image/\") || /\\.(png|jpe?g|gif|webp|bmp)$/i.test(name)) {\n parts.push(\"[\u56FE\u7247]\");\n } else if (ct.startsWith(\"video/\") || /\\.(mp4|mov|avi|mkv)$/i.test(name)) {\n parts.push(\"[\u89C6\u9891]\");\n } else if (ct.startsWith(\"audio/\") || /\\.(mp3|wav|amr|silk)$/i.test(name)) {\n parts.push(\"[\u8BED\u97F3]\");\n } else {\n parts.push(\"[\u6587\u4EF6]\");\n }\n }\n return parts.join(\"\");\n}\n\n/** \u4ECE\u5B98\u65B9\u4E8B\u4EF6\u62BD\u51FA\u7EAF\u6587\u672C\uFF08\u53BB @bot + \u9644\u4EF6\u5360\u4F4D\uFF09 */\nexport function extractOfficialText(msg: {\n content?: string;\n attachments?: OfficialAttachment[];\n mentions?: Array<{ is_you?: boolean; username?: string }>;\n}): string {\n let base = stripOfficialAtMention(String(msg.content ?? \"\"));\n const botName = msg.mentions?.find((mention) => mention.is_you)?.username;\n if (botName && base.startsWith(`@${botName}`)) base = base.slice(botName.length + 1).trim();\n const suffix = attachmentsPlaceholder(msg.attachments);\n return `${base}${suffix ? (base ? \" \" : \"\") + suffix : \"\"}`.trim();\n}\n\nexport class OfficialAtMessageDispatcher {\n private readonly opts: OfficialDispatcherOptions;\n private readonly dedup = new RecentMessageDedup();\n private readonly forward: OfficialForwardFn;\n private loggedMissingOpenid = false;\n\n constructor(opts: OfficialDispatcherOptions) {\n this.opts = opts;\n this.forward = opts.forward ?? tryForward;\n }\n\n /** \u5168\u91CF\u7FA4\u6D88\u606F\u5904\u7406\u6307\u4EE4\u548C\u666E\u901A\u804A\u5929\uFF1B\u4E0E @ \u4E8B\u4EF6\u5171\u7528\u6D88\u606F ID \u53BB\u91CD\u3002 */\n async handleGroupMessage(msg: OfficialGroupAtMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\" || msg.author?.bot) return;\n const groupOpenid = String(msg.group_openid ?? \"\");\n if (!groupOpenid || !this.opts.groupOpenid || groupOpenid !== this.opts.groupOpenid) return;\n if (\n /^<@!?/.test(String(msg.content ?? \"\").trim()) &&\n msg.mentions?.length &&\n !msg.mentions.some((mention) => mention.is_you)\n ) return;\n const text = extractOfficialText(msg);\n if (!text) return;\n if (this.dedup.seen(msg.id)) return;\n const router = this.opts.commandRouter;\n const normalized = text.replace(/^[/\uFF0F]+/, \"\").trim();\n const isConfirmation = /^(confirm|\u786E\u8BA4|cancel|\u53D6\u6D88)(?:\\s+\\S+)?$/i.test(normalized);\n const memberId = String(msg.author?.member_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${memberId.slice(0, 8)}`);\n if (\n router &&\n (router.registry.resolve(normalized) || isConfirmation || /^[/\uFF0F]/.test(text)) &&\n await router.handle({\n backend: \"official\",\n scene: \"group\",\n groupId: groupOpenid,\n userId: memberId,\n userName: fromName,\n text,\n isGroupAdmin: detectOfficialGroupAdmin(msg),\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n })\n ) return;\n await this.forward(this.opts.db, `qq_${memberId}`, fromName, text);\n }\n\n async handleGroupAtMessage(msg: OfficialGroupAtMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\") return;\n if (msg.author?.bot) return;\n\n const groupOpenid = String(msg.group_openid ?? \"\");\n if (!groupOpenid) {\n log.warn(\"\u5B98\u65B9\u4E8B\u4EF6\u7F3A group_openid\uFF0C\u8DF3\u8FC7\");\n return;\n }\n\n if (!this.opts.groupOpenid) {\n if (!this.loggedMissingOpenid) {\n log.warn(\n `official.group_openid \u672A\u914D\u7F6E\u3002\u6536\u5230\u7FA4 openid=${groupOpenid}\uFF0C\u8BF7\u5199\u5165 configs/qq_config.json \u540E\u91CD\u542F\uFF08\u672C\u6761\u4E0D\u8F6C\u53D1\uFF09`\n );\n this.loggedMissingOpenid = true;\n } else {\n log.info(`official.group_openid \u672A\u914D\u7F6E\uFF0C\u4E22\u5F03\u7FA4\u6D88\u606F openid=${groupOpenid}`);\n }\n return;\n }\n\n if (groupOpenid !== this.opts.groupOpenid) {\n log.info(`\u975E\u76EE\u6807\u7FA4 openid=${groupOpenid}\uFF0C\u8DF3\u8FC7`);\n return;\n }\n\n if (this.dedup.seen(msg.id)) return;\n\n const text = extractOfficialText(msg);\n if (!text) return;\n\n const memberId = String(msg.author?.member_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${memberId.slice(0, 8)}`);\n const fromId = `qq_${memberId}`;\n\n if (this.opts.commandRouter) {\n const inbound = {\n backend: \"official\" as const,\n scene: \"group\" as const,\n groupId: groupOpenid,\n userId: memberId,\n userName: fromName,\n text,\n isGroupAdmin: detectOfficialGroupAdmin(msg),\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n };\n if (await this.opts.commandRouter.handle(inbound)) return;\n }\n\n await this.forward(this.opts.db, fromId, fromName, text);\n }\n\n /**\n * \u5355\u804A\uFF1A\u4EC5\u8D70\u6307\u4EE4\u8DEF\u7531\uFF08\u83DC\u5355\u70B9\u51FB\u843D\u70B9\uFF09\uFF0C\u4E0D\u8F6C\u53D1 MC\u3002\n */\n async handleC2cMessage(msg: OfficialC2cMessage): Promise<void> {\n if (!msg || typeof msg !== \"object\") return;\n if (msg.author?.bot) return;\n if (this.dedup.seen(msg.id)) return;\n\n const text = extractOfficialText(msg);\n if (!text) return;\n\n const userId = String(msg.author?.user_openid || msg.author?.id || \"unknown\");\n const fromName = String(msg.author?.username || `QQ_${userId.slice(0, 8)}`);\n\n if (!this.opts.commandRouter) {\n log.info(`C2C \u65E0\u6307\u4EE4\u8DEF\u7531\uFF0C\u5FFD\u7565 text=${text.slice(0, 40)}`);\n return;\n }\n\n const inbound = {\n backend: \"official\" as const,\n scene: \"c2c\" as const,\n groupId: `c2c:${userId}`,\n userId,\n userName: fromName,\n text,\n ...(msg.id ? { msgId: String(msg.id) } : {}),\n };\n await this.opts.commandRouter.handle(inbound);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const ROLE_TTL_MS = 30 * 60 * 1e3;
|
|
2
|
+
const roleByMember = /* @__PURE__ */ new Map();
|
|
3
|
+
function isPrivilegedGroupRole(value) {
|
|
4
|
+
if (value == null) return false;
|
|
5
|
+
if (Array.isArray(value)) {
|
|
6
|
+
const joined = value.map((item) => String(item).toLowerCase()).join(",");
|
|
7
|
+
return /\b(owner|admin|2|3)\b/.test(joined);
|
|
8
|
+
}
|
|
9
|
+
const role = String(value).toLowerCase();
|
|
10
|
+
return role === "owner" || role === "admin" || role === "2" || role === "3";
|
|
11
|
+
}
|
|
12
|
+
function rememberGroupRole(memberOpenid, admin) {
|
|
13
|
+
const id = memberOpenid.trim();
|
|
14
|
+
if (!id) return;
|
|
15
|
+
roleByMember.set(id, { admin, at: Date.now() });
|
|
16
|
+
}
|
|
17
|
+
function cachedGroupAdmin(memberOpenid) {
|
|
18
|
+
const hit = roleByMember.get(memberOpenid.trim());
|
|
19
|
+
if (!hit) return void 0;
|
|
20
|
+
if (Date.now() - hit.at > ROLE_TTL_MS) {
|
|
21
|
+
roleByMember.delete(memberOpenid.trim());
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
return hit.admin;
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
cachedGroupAdmin,
|
|
28
|
+
isPrivilegedGroupRole,
|
|
29
|
+
rememberGroupRole
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=group-role.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/official/group-role.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * group-role.ts \u2014 \u5B98\u65B9\u7FA4\u4E3B/\u7FA4\u7BA1\u8EAB\u4EFD\u7684\u77ED\u65F6\u7F13\u5B58\n *\n * \u7FA4\u6D88\u606F\u4E8B\u4EF6\u5E26 author.member_role\uFF1B\u6309\u94AE\u56DE\u8C03 INTERACTION_CREATE \u4E0D\u5E26\u89D2\u8272\u3002\n * \u6D88\u606F\u5904\u7406\u5199\u5165\u7F13\u5B58\uFF0C\u6309\u94AE\u9274\u6743\u5148\u8BFB\u7F13\u5B58\uFF0C\u672A\u547D\u4E2D\u518D\u67E5\u6210\u5458\u63A5\u53E3\u3002\n */\n\n/** \u89D2\u8272\u7F13\u5B58\u6709\u6548\u671F\u3002\u6309\u94AE\u56DE\u8C03\u901A\u5E38\u7D27\u8DDF\u83DC\u5355\u6D88\u606F\uFF0C\u534A\u5C0F\u65F6\u8DB3\u591F\u8986\u76D6\u4E00\u6B21\u7BA1\u7406\u64CD\u4F5C\u3002 */\nconst ROLE_TTL_MS = 30 * 60 * 1000;\n\ntype RoleHit = { admin: boolean; at: number };\n\n/** member_openid \u2192 \u662F\u5426\u7FA4\u4E3B/\u7FA4\u7BA1\u3002\u53EA\u5728\u672C\u8FDB\u7A0B\u5185\u7ED9\u6309\u94AE\u56DE\u8C03\u8865\u89D2\u8272\u3002 */\nconst roleByMember = new Map<string, RoleHit>();\n\n/**\n * \u5224\u65AD\u5B98\u65B9\u89D2\u8272\u5B57\u6BB5\u662F\u5426\u4E3A\u7FA4\u4E3B\u6216\u7FA4\u7BA1\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u6D88\u606F\u4E8B\u4EF6\u7684 member_role\uFF0C\u4EE5\u53CA\u6210\u5458\u67E5\u8BE2\u63A5\u53E3\u7684\u540C\u540D\u5B57\u6BB5\u3002\n */\nexport function isPrivilegedGroupRole(value: unknown): boolean {\n if (value == null) return false;\n if (Array.isArray(value)) {\n const joined = value.map((item) => String(item).toLowerCase()).join(\",\");\n return /\\b(owner|admin|2|3)\\b/.test(joined);\n }\n const role = String(value).toLowerCase();\n return role === \"owner\" || role === \"admin\" || role === \"2\" || role === \"3\";\n}\n\n/**\n * \u8BB0\u4E0B\u5DF2\u786E\u8BA4\u7684\u7FA4\u89D2\u8272\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u89E3\u6790\u5230 member_role \u540E\uFF0C\u4F9B\u968F\u540E\u7684\u6309\u94AE\u56DE\u8C03\u8BFB\u53D6\u3002\n */\nexport function rememberGroupRole(memberOpenid: string, admin: boolean): void {\n const id = memberOpenid.trim();\n if (!id) return;\n roleByMember.set(id, { admin, at: Date.now() });\n}\n\n/**\n * \u8BFB\u53D6\u672A\u8FC7\u671F\u7684\u7FA4\u7BA1\u7F13\u5B58\u3002\n * \u4F7F\u7528\u573A\u666F\uFF1A\u6309\u94AE\u56DE\u8C03\u6CA1\u6709 member_role \u65F6\uFF1B\u6CA1\u6709\u8BB0\u5F55\u8FD4\u56DE undefined\u3002\n */\nexport function cachedGroupAdmin(memberOpenid: string): boolean | undefined {\n const hit = roleByMember.get(memberOpenid.trim());\n if (!hit) return undefined;\n if (Date.now() - hit.at > ROLE_TTL_MS) {\n roleByMember.delete(memberOpenid.trim());\n return undefined;\n }\n return hit.admin;\n}\n"],
|
|
5
|
+
"mappings": "AAQA,MAAM,cAAc,KAAK,KAAK;AAK9B,MAAM,eAAe,oBAAI,IAAqB;AAMvC,SAAS,sBAAsB,OAAyB;AAC7D,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,SAAS,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,EAAE,YAAY,CAAC,EAAE,KAAK,GAAG;AACvE,WAAO,wBAAwB,KAAK,MAAM;AAAA,EAC5C;AACA,QAAM,OAAO,OAAO,KAAK,EAAE,YAAY;AACvC,SAAO,SAAS,WAAW,SAAS,WAAW,SAAS,OAAO,SAAS;AAC1E;AAMO,SAAS,kBAAkB,cAAsB,OAAsB;AAC5E,QAAM,KAAK,aAAa,KAAK;AAC7B,MAAI,CAAC,GAAI;AACT,eAAa,IAAI,IAAI,EAAE,OAAO,IAAI,KAAK,IAAI,EAAE,CAAC;AAChD;AAMO,SAAS,iBAAiB,cAA2C;AAC1E,QAAM,MAAM,aAAa,IAAI,aAAa,KAAK,CAAC;AAChD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,KAAK,IAAI,IAAI,IAAI,KAAK,aAAa;AACrC,iBAAa,OAAO,aAAa,KAAK,CAAC;AACvC,WAAO;AAAA,EACT;AACA,SAAO,IAAI;AACb;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfmc-bds/qq-bridge",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "SFMC QQ ↔ MC bridge — official QQ Open Platform Bot and/or LLBot OneBot 11",
|
|
5
5
|
"author": "Shiroha7z",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"ws": "^8.21.1",
|
|
36
|
-
"@sfmc-bds/sdk": "0.2.
|
|
36
|
+
"@sfmc-bds/sdk": "0.2.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@sfmc-bds/tools": "0.2.
|
|
39
|
+
"@sfmc-bds/tools": "0.2.4"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public",
|