@invago/mixin 1.0.8 → 1.0.10
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 +328 -4
- package/README.zh-CN.md +386 -69
- package/package.json +79 -1
- package/src/blaze-service.ts +24 -7
- package/src/channel.ts +185 -42
- package/src/config-schema.ts +36 -1
- package/src/config.ts +103 -10
- package/src/crypto.ts +5 -0
- package/src/inbound-handler.ts +1205 -576
- package/src/mixpay-service.ts +211 -0
- package/src/mixpay-store.ts +205 -0
- package/src/mixpay-worker.ts +353 -0
- package/src/outbound-plan.ts +216 -0
- package/src/reply-format.ts +89 -24
- package/src/runtime.ts +26 -0
- package/src/send-service.ts +35 -27
- package/src/shared.ts +25 -0
- package/src/status.ts +114 -0
- package/src/decrypt.ts +0 -126
package/src/config.ts
CHANGED
|
@@ -1,26 +1,61 @@
|
|
|
1
1
|
import type { OpenClawConfig } from "openclaw/plugin-sdk";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
MixinAccountConfigSchema,
|
|
4
|
+
MixinConversationConfigSchema,
|
|
5
|
+
type MixinAccountConfig,
|
|
6
|
+
type MixinConversationConfig,
|
|
7
|
+
type MixinMixpayConfig,
|
|
8
|
+
} from "./config-schema.js";
|
|
3
9
|
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
type RawMixinConfig = Partial<MixinAccountConfig> & {
|
|
11
|
+
defaultAccount?: string;
|
|
12
|
+
accounts?: Record<string, Partial<MixinAccountConfig> | undefined>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function getRawConfig(cfg: OpenClawConfig): RawMixinConfig {
|
|
16
|
+
return ((cfg.channels as Record<string, unknown>)?.mixin ?? {}) as RawMixinConfig;
|
|
6
17
|
}
|
|
7
18
|
|
|
8
|
-
|
|
19
|
+
function hasTopLevelAccountConfig(raw: RawMixinConfig): boolean {
|
|
20
|
+
return Boolean(raw.appId || raw.sessionId || raw.serverPublicKey || raw.sessionPrivateKey || raw.name);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function resolveDefaultAccountId(cfg: OpenClawConfig): string {
|
|
9
24
|
const raw = getRawConfig(cfg);
|
|
25
|
+
const configuredDefault = raw.defaultAccount?.trim();
|
|
26
|
+
if (configuredDefault && raw.accounts?.[configuredDefault]) {
|
|
27
|
+
return configuredDefault;
|
|
28
|
+
}
|
|
29
|
+
if (configuredDefault === "default") {
|
|
30
|
+
return "default";
|
|
31
|
+
}
|
|
10
32
|
if (raw.accounts && Object.keys(raw.accounts).length > 0) {
|
|
11
|
-
|
|
33
|
+
if (hasTopLevelAccountConfig(raw)) {
|
|
34
|
+
return "default";
|
|
35
|
+
}
|
|
36
|
+
return Object.keys(raw.accounts)[0] ?? "default";
|
|
37
|
+
}
|
|
38
|
+
return "default";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function listAccountIds(cfg: OpenClawConfig): string[] {
|
|
42
|
+
const raw = getRawConfig(cfg);
|
|
43
|
+
const accountIds = raw.accounts ? Object.keys(raw.accounts) : [];
|
|
44
|
+
if (hasTopLevelAccountConfig(raw) || accountIds.length === 0) {
|
|
45
|
+
return ["default", ...accountIds.filter((accountId) => accountId !== "default")];
|
|
12
46
|
}
|
|
13
|
-
return
|
|
47
|
+
return accountIds;
|
|
14
48
|
}
|
|
15
49
|
|
|
16
50
|
export function getAccountConfig(cfg: OpenClawConfig, accountId?: string): MixinAccountConfig {
|
|
17
51
|
const raw = getRawConfig(cfg);
|
|
52
|
+
const resolvedAccountId = accountId ?? resolveDefaultAccountId(cfg);
|
|
18
53
|
let accountRaw: Partial<MixinAccountConfig>;
|
|
19
54
|
|
|
20
|
-
if (
|
|
21
|
-
accountRaw = raw.accounts[
|
|
55
|
+
if (resolvedAccountId !== "default" && raw.accounts?.[resolvedAccountId]) {
|
|
56
|
+
accountRaw = raw.accounts[resolvedAccountId] as Partial<MixinAccountConfig>;
|
|
22
57
|
} else {
|
|
23
|
-
accountRaw = raw
|
|
58
|
+
accountRaw = raw;
|
|
24
59
|
}
|
|
25
60
|
|
|
26
61
|
const result = MixinAccountConfigSchema.safeParse(accountRaw);
|
|
@@ -29,7 +64,7 @@ export function getAccountConfig(cfg: OpenClawConfig, accountId?: string): Mixin
|
|
|
29
64
|
}
|
|
30
65
|
|
|
31
66
|
export function resolveAccount(cfg: OpenClawConfig, accountId?: string) {
|
|
32
|
-
const id = accountId ??
|
|
67
|
+
const id = accountId ?? resolveDefaultAccountId(cfg);
|
|
33
68
|
const config = getAccountConfig(cfg, id);
|
|
34
69
|
const configured = Boolean(config.appId && config.sessionId && config.serverPublicKey && config.sessionPrivateKey);
|
|
35
70
|
return {
|
|
@@ -49,6 +84,64 @@ export function resolveAccount(cfg: OpenClawConfig, accountId?: string) {
|
|
|
49
84
|
};
|
|
50
85
|
}
|
|
51
86
|
|
|
87
|
+
export function resolveMediaMaxMb(cfg: OpenClawConfig, accountId?: string): number | undefined {
|
|
88
|
+
return getAccountConfig(cfg, accountId).mediaMaxMb;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getMixpayConfig(cfg: OpenClawConfig, accountId?: string): MixinMixpayConfig | undefined {
|
|
92
|
+
return getAccountConfig(cfg, accountId).mixpay;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getRawAccountConfig(cfg: OpenClawConfig, accountId?: string): Partial<MixinAccountConfig> {
|
|
96
|
+
const raw = getRawConfig(cfg);
|
|
97
|
+
const resolvedAccountId = accountId ?? resolveDefaultAccountId(cfg);
|
|
98
|
+
if (resolvedAccountId !== "default" && raw.accounts?.[resolvedAccountId]) {
|
|
99
|
+
return raw.accounts[resolvedAccountId] as Partial<MixinAccountConfig>;
|
|
100
|
+
}
|
|
101
|
+
return raw;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getConversationConfig(
|
|
105
|
+
cfg: OpenClawConfig,
|
|
106
|
+
accountId: string,
|
|
107
|
+
conversationId: string,
|
|
108
|
+
): {
|
|
109
|
+
exists: boolean;
|
|
110
|
+
config: MixinConversationConfig;
|
|
111
|
+
} {
|
|
112
|
+
const accountRaw = getRawAccountConfig(cfg, accountId);
|
|
113
|
+
const conversationRaw = accountRaw.conversations?.[conversationId] as Partial<MixinConversationConfig> | undefined;
|
|
114
|
+
const result = MixinConversationConfigSchema.safeParse(conversationRaw ?? {});
|
|
115
|
+
return {
|
|
116
|
+
exists: Boolean(conversationRaw),
|
|
117
|
+
config: result.success ? result.data : MixinConversationConfigSchema.parse({}),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function resolveConversationPolicy(
|
|
122
|
+
cfg: OpenClawConfig,
|
|
123
|
+
accountId: string,
|
|
124
|
+
conversationId: string,
|
|
125
|
+
): {
|
|
126
|
+
enabled: boolean;
|
|
127
|
+
requireMention: boolean;
|
|
128
|
+
mediaBypassMention: boolean;
|
|
129
|
+
groupPolicy: MixinAccountConfig["groupPolicy"];
|
|
130
|
+
groupAllowFrom: string[];
|
|
131
|
+
hasConversationOverride: boolean;
|
|
132
|
+
} {
|
|
133
|
+
const accountConfig = getAccountConfig(cfg, accountId);
|
|
134
|
+
const conversation = getConversationConfig(cfg, accountId, conversationId);
|
|
135
|
+
return {
|
|
136
|
+
enabled: conversation.config.enabled !== false,
|
|
137
|
+
requireMention: conversation.config.requireMention ?? accountConfig.requireMentionInGroup,
|
|
138
|
+
mediaBypassMention: conversation.config.mediaBypassMention ?? accountConfig.mediaBypassMentionInGroup,
|
|
139
|
+
groupPolicy: conversation.config.groupPolicy ?? accountConfig.groupPolicy,
|
|
140
|
+
groupAllowFrom: conversation.config.allowFrom ?? accountConfig.groupAllowFrom ?? [],
|
|
141
|
+
hasConversationOverride: conversation.exists,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
52
145
|
export function isConfigured(account: ReturnType<typeof resolveAccount>): boolean {
|
|
53
146
|
return account.configured;
|
|
54
147
|
}
|
package/src/crypto.ts
CHANGED
|
@@ -12,6 +12,11 @@ function aes256CbcDecrypt(key: Buffer, iv: Buffer, ciphertext: Buffer): Buffer {
|
|
|
12
12
|
const final = Buffer.concat([decrypted, decipher.final()]);
|
|
13
13
|
const padLen = final[final.length - 1];
|
|
14
14
|
if (padLen > 0 && padLen <= 16) {
|
|
15
|
+
for (let i = final.length - padLen; i < final.length; i++) {
|
|
16
|
+
if (final[i] !== padLen) {
|
|
17
|
+
return final;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
15
20
|
return final.slice(0, final.length - padLen);
|
|
16
21
|
}
|
|
17
22
|
return final;
|