@xmanrui/dsh-im 0.1.1 → 0.2.0
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 +20 -10
- package/THIRD_PARTY_NOTICES.md +5 -3
- package/lib/client.js +772 -68
- package/lib/index.js +172 -102
- package/package.json +3 -2
- package/plugin-src/client/channel-logos.js +13 -0
- package/plugin-src/client/channels/shared/token-channel.js +32 -15
- package/plugin-src/client/channels/whatsapp/api.js +123 -0
- package/plugin-src/client/channels/whatsapp/index.js +433 -0
- package/plugin-src/client/channels/whatsapp/styles.js +19 -0
- package/plugin-src/client/index.js +20 -2
- package/plugin-src/client/styles.js +3 -1
- package/plugin-src/host/channels/whatsapp/index.mjs +35 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +121 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +140 -0
- package/plugin-src/host/index.mjs +3 -0
- package/scripts/verify-package.mjs +7 -3
- package/src/channels/discord/discord-api.mjs +1 -1
- package/src/channels/weixin/weixin-api.mjs +1 -1
- package/src/channels/whatsapp/config-store.mjs +165 -0
- package/src/channels/whatsapp/harness-client.mjs +3 -0
- package/src/channels/whatsapp/state-store.mjs +3 -0
- package/src/channels/whatsapp/whatsapp-bridge.mjs +15 -0
- package/src/channels/whatsapp/whatsapp-controller.mjs +388 -0
- package/src/channels/whatsapp/whatsapp-runtime.mjs +299 -0
- package/src/channels/whatsapp/whatsapp-web-session.mjs +212 -0
package/lib/client.js
CHANGED
|
@@ -40,7 +40,7 @@ __export(index_exports, {
|
|
|
40
40
|
name: () => name
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(index_exports);
|
|
43
|
-
var
|
|
43
|
+
var React11 = __toESM(require("react"), 1);
|
|
44
44
|
|
|
45
45
|
// plugin-src/client/channel-logos.js
|
|
46
46
|
var React = __toESM(require("react"), 1);
|
|
@@ -147,6 +147,18 @@ function DiscordLogoGlyph({ size } = {}) {
|
|
|
147
147
|
d: "M20.32 4.37a19.8 19.8 0 0 0-4.89-1.51c-.21.38-.46.89-.63 1.29a18.4 18.4 0 0 0-5.59 0 13 13 0 0 0-.64-1.29c-1.71.29-3.36.8-4.89 1.52C.59 9.09-.25 13.68.17 18.2a19.9 19.9 0 0 0 6 3.04c.48-.66.91-1.36 1.28-2.1-.7-.26-1.37-.58-2-.96.17-.12.33-.25.49-.38 3.86 1.79 8.04 1.79 11.86 0 .16.13.32.26.49.38-.64.38-1.31.7-2.01.97.37.73.8 1.44 1.28 2.09a19.8 19.8 0 0 0 6-3.04c.49-5.24-.84-9.79-3.24-13.83ZM8.02 15.42c-1.16 0-2.11-1.07-2.11-2.38s.93-2.38 2.11-2.38c1.18 0 2.13 1.08 2.11 2.38 0 1.31-.93 2.38-2.11 2.38Zm7.95 0c-1.16 0-2.11-1.07-2.11-2.38s.93-2.38 2.11-2.38c1.18 0 2.13 1.08 2.11 2.38 0 1.31-.93 2.38-2.11 2.38Z"
|
|
148
148
|
}));
|
|
149
149
|
}
|
|
150
|
+
function WhatsappLogoGlyph({ size } = {}) {
|
|
151
|
+
return h("svg", {
|
|
152
|
+
...dimensions(size),
|
|
153
|
+
viewBox: "0 0 24 24",
|
|
154
|
+
focusable: "false",
|
|
155
|
+
"aria-hidden": "true",
|
|
156
|
+
"data-im-channel-logo": "whatsapp"
|
|
157
|
+
}, h("path", {
|
|
158
|
+
fill: "currentColor",
|
|
159
|
+
d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.521.149-.173.198-.297.298-.495.099-.198.05-.372-.025-.521-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a12.8 12.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479s1.065 2.875 1.213 3.074c.149.198 2.095 3.2 5.077 4.487.709.306 1.262.489 1.694.626.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.29.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.981.999-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.83 9.83 0 0 1 2.893 6.991c-.003 5.45-4.437 9.884-9.886 9.884m8.413-18.297A11.8 11.8 0 0 0 12.055 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.9 11.9 0 0 0 5.688 1.448h.005c6.557 0 11.892-5.335 11.895-11.893a11.82 11.82 0 0 0-3.486-8.413"
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
150
162
|
|
|
151
163
|
// plugin-src/client/channels/dingtalk/api.js
|
|
152
164
|
var DINGTALK_RPC_CHANNEL = "/dingtalk";
|
|
@@ -186,8 +198,8 @@ function optionalString(value, maxLength = 240) {
|
|
|
186
198
|
return trimmed ? trimmed.slice(0, maxLength) : void 0;
|
|
187
199
|
}
|
|
188
200
|
function opaqueId(value) {
|
|
189
|
-
const
|
|
190
|
-
return
|
|
201
|
+
const id5 = optionalString(value, 128);
|
|
202
|
+
return id5 && /^[a-z\d_-]+$/i.test(id5) ? id5 : void 0;
|
|
191
203
|
}
|
|
192
204
|
function timestamp(value) {
|
|
193
205
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -1418,7 +1430,7 @@ var TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
1418
1430
|
deleteBot: "bot.delete"
|
|
1419
1431
|
});
|
|
1420
1432
|
function createTokenChannelApi(channel3, connectionSummary) {
|
|
1421
|
-
const
|
|
1433
|
+
const unwrapRpcResult9 = (result) => {
|
|
1422
1434
|
if (!isRecord2(result) || typeof result.ok !== "boolean") {
|
|
1423
1435
|
throw new Error(`${channel3} \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94`);
|
|
1424
1436
|
}
|
|
@@ -1429,7 +1441,7 @@ function createTokenChannelApi(channel3, connectionSummary) {
|
|
|
1429
1441
|
}
|
|
1430
1442
|
return result.value;
|
|
1431
1443
|
};
|
|
1432
|
-
const
|
|
1444
|
+
const normalizeBot7 = (value) => {
|
|
1433
1445
|
if (!isRecord2(value) || !id(value.botId)) return void 0;
|
|
1434
1446
|
const connected = value.connected === true;
|
|
1435
1447
|
const state = ACCOUNT_STATES2.has(value.state) ? value.state : "offline";
|
|
@@ -1455,23 +1467,23 @@ function createTokenChannelApi(channel3, connectionSummary) {
|
|
|
1455
1467
|
} : null
|
|
1456
1468
|
};
|
|
1457
1469
|
};
|
|
1458
|
-
const
|
|
1470
|
+
const normalizeSnapshot8 = (value) => {
|
|
1459
1471
|
const source = isRecord2(value?.snapshot) ? value.snapshot : value;
|
|
1460
1472
|
if (!isRecord2(source) || !Array.isArray(source.bots)) {
|
|
1461
1473
|
throw new Error(`${channel3} \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868`);
|
|
1462
1474
|
}
|
|
1463
|
-
const bots = source.bots.map(
|
|
1475
|
+
const bots = source.bots.map(normalizeBot7).filter(Boolean);
|
|
1464
1476
|
return {
|
|
1465
1477
|
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
1466
1478
|
bots,
|
|
1467
1479
|
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length }
|
|
1468
1480
|
};
|
|
1469
1481
|
};
|
|
1470
|
-
const
|
|
1482
|
+
const presentError9 = (error) => ({
|
|
1471
1483
|
code: text(error?.code, `${channel3.toUpperCase()}_ERROR`, 80),
|
|
1472
1484
|
message: text(error?.message, `${channel3}\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`)
|
|
1473
1485
|
});
|
|
1474
|
-
return Object.freeze({ unwrapRpcResult:
|
|
1486
|
+
return Object.freeze({ unwrapRpcResult: unwrapRpcResult9, normalizeSnapshot: normalizeSnapshot8, presentError: presentError9 });
|
|
1475
1487
|
}
|
|
1476
1488
|
|
|
1477
1489
|
// plugin-src/client/channels/discord/api.js
|
|
@@ -1519,7 +1531,14 @@ function createTokenChannelSettings(definition) {
|
|
|
1519
1531
|
tokenPlaceholder,
|
|
1520
1532
|
emptyTitle,
|
|
1521
1533
|
emptyDescription,
|
|
1522
|
-
platformLabel
|
|
1534
|
+
platformLabel,
|
|
1535
|
+
CredentialPanel = null,
|
|
1536
|
+
credentialPayload = ({ secret }) => ({ token: secret }),
|
|
1537
|
+
credentialAriaLabel = `\u4F7F\u7528 Bot Token \u63A5\u5165 ${channel3} \u673A\u5668\u4EBA`,
|
|
1538
|
+
credentialOpenLabel = "\u624B\u52A8\u63A5\u5165",
|
|
1539
|
+
credentialCloseLabel = "\u6536\u8D77\u51ED\u636E",
|
|
1540
|
+
credentialNoun = "Bot Token",
|
|
1541
|
+
emptyActionLabel = "\u586B\u5199 Bot Token"
|
|
1523
1542
|
} = definition;
|
|
1524
1543
|
function AccountCard5({ account, busy, removing, onReconnect, onRequestRemove, onConfirmRemove, onCancelRemove }) {
|
|
1525
1544
|
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
@@ -1599,7 +1618,7 @@ function createTokenChannelSettings(definition) {
|
|
|
1599
1618
|
"div",
|
|
1600
1619
|
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
1601
1620
|
h4("strong", null, `\u4ECE DeepSeek Harness \u79FB\u9664\u201C${account.bot.name}\u201D\uFF1F`),
|
|
1602
|
-
h4("p", null, `\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684
|
|
1621
|
+
h4("p", null, `\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 ${credentialNoun}\u3001\u673A\u5668\u4EBA\u914D\u7F6E\u53CA\u4F1A\u8BDD\u6620\u5C04\u3002${platformLabel}\u4E2D\u7684\u673A\u5668\u4EBA\u4E0D\u4F1A\u88AB\u81EA\u52A8\u5220\u9664\u3002`),
|
|
1603
1622
|
h4(
|
|
1604
1623
|
"div",
|
|
1605
1624
|
{ className: "ddt-actions dim-viewActions" },
|
|
@@ -1673,11 +1692,14 @@ function createTokenChannelSettings(definition) {
|
|
|
1673
1692
|
window.clearInterval(timer);
|
|
1674
1693
|
};
|
|
1675
1694
|
}, [loadStatus, model.phase]);
|
|
1676
|
-
const bindCredentials = React4.useCallback(async (
|
|
1695
|
+
const bindCredentials = React4.useCallback(async (values) => {
|
|
1677
1696
|
setBusy(true);
|
|
1678
1697
|
setCredentialError(null);
|
|
1679
1698
|
try {
|
|
1680
|
-
const snapshot = api3.normalizeSnapshot(await invoke(
|
|
1699
|
+
const snapshot = api3.normalizeSnapshot(await invoke(
|
|
1700
|
+
endpoints.bindCredentials,
|
|
1701
|
+
credentialPayload(values)
|
|
1702
|
+
));
|
|
1681
1703
|
if (!mounted.current) return;
|
|
1682
1704
|
setModel({ phase: "ready", bots: snapshot.bots, totals: snapshot.totals, error: null });
|
|
1683
1705
|
setCredentialOpen(false);
|
|
@@ -1755,8 +1777,8 @@ function createTokenChannelSettings(definition) {
|
|
|
1755
1777
|
},
|
|
1756
1778
|
disabled: busy,
|
|
1757
1779
|
"aria-pressed": credentialOpen,
|
|
1758
|
-
"aria-label":
|
|
1759
|
-
}, h4(CredentialActionIcon), credentialOpen ?
|
|
1780
|
+
"aria-label": credentialAriaLabel
|
|
1781
|
+
}, h4(CredentialActionIcon), credentialOpen ? credentialCloseLabel : credentialOpenLabel)
|
|
1760
1782
|
),
|
|
1761
1783
|
model.totals.configured > 0 ? h4(
|
|
1762
1784
|
"div",
|
|
@@ -1781,7 +1803,15 @@ function createTokenChannelSettings(definition) {
|
|
|
1781
1803
|
) : h4(
|
|
1782
1804
|
React4.Fragment,
|
|
1783
1805
|
null,
|
|
1784
|
-
credentialOpen ? h4(
|
|
1806
|
+
credentialOpen ? CredentialPanel ? h4(CredentialPanel, {
|
|
1807
|
+
busy,
|
|
1808
|
+
error: credentialError,
|
|
1809
|
+
onSubmit: bindCredentials,
|
|
1810
|
+
onCancel: () => {
|
|
1811
|
+
setCredentialOpen(false);
|
|
1812
|
+
setCredentialError(null);
|
|
1813
|
+
}
|
|
1814
|
+
}) : h4(CredentialBindingPanel, {
|
|
1785
1815
|
channel: channel3,
|
|
1786
1816
|
secretLabel: "Bot Token",
|
|
1787
1817
|
secretPlaceholder: tokenPlaceholder,
|
|
@@ -1816,7 +1846,7 @@ function createTokenChannelSettings(definition) {
|
|
|
1816
1846
|
h4(Button3, {
|
|
1817
1847
|
kind: "primary",
|
|
1818
1848
|
onClick: () => setCredentialOpen(true)
|
|
1819
|
-
},
|
|
1849
|
+
}, emptyActionLabel)
|
|
1820
1850
|
)
|
|
1821
1851
|
),
|
|
1822
1852
|
h4("div", {
|
|
@@ -2988,14 +3018,14 @@ var HEALTH_LABELS = {
|
|
|
2988
3018
|
offline: "\u8FDE\u63A5\u4E2D\u65AD",
|
|
2989
3019
|
error: "\u9700\u8981\u5904\u7406"
|
|
2990
3020
|
};
|
|
2991
|
-
function formatCheckedTime(
|
|
2992
|
-
if (!
|
|
3021
|
+
function formatCheckedTime(timestamp7) {
|
|
3022
|
+
if (!timestamp7) return "\u5C1A\u672A\u68C0\u67E5";
|
|
2993
3023
|
try {
|
|
2994
3024
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
2995
3025
|
hour: "2-digit",
|
|
2996
3026
|
minute: "2-digit",
|
|
2997
3027
|
second: "2-digit"
|
|
2998
|
-
}).format(new Date(
|
|
3028
|
+
}).format(new Date(timestamp7));
|
|
2999
3029
|
} catch {
|
|
3000
3030
|
return "\u521A\u521A";
|
|
3001
3031
|
}
|
|
@@ -3334,14 +3364,14 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
3334
3364
|
FEISHU_ENDPOINTS.beginProvisioning,
|
|
3335
3365
|
{ locale: "zh-CN" }
|
|
3336
3366
|
));
|
|
3337
|
-
const
|
|
3338
|
-
setNow(
|
|
3367
|
+
const timestamp7 = Date.now();
|
|
3368
|
+
setNow(timestamp7);
|
|
3339
3369
|
setModel((current) => ({
|
|
3340
3370
|
...current,
|
|
3341
3371
|
provisioning: {
|
|
3342
3372
|
phase: "qr",
|
|
3343
3373
|
...provision2,
|
|
3344
|
-
durationMs: Math.max(1, provision2.expiresAt -
|
|
3374
|
+
durationMs: Math.max(1, provision2.expiresAt - timestamp7),
|
|
3345
3375
|
expired: false
|
|
3346
3376
|
}
|
|
3347
3377
|
}));
|
|
@@ -3397,9 +3427,9 @@ function FeishuSettingsTab({ rpcCall }) {
|
|
|
3397
3427
|
React6.useEffect(() => {
|
|
3398
3428
|
if (!countdownAttemptId || countdownPhase !== "qr" || countdownExpired) return void 0;
|
|
3399
3429
|
const tick = () => {
|
|
3400
|
-
const
|
|
3401
|
-
setNow(
|
|
3402
|
-
if (
|
|
3430
|
+
const timestamp7 = Date.now();
|
|
3431
|
+
setNow(timestamp7);
|
|
3432
|
+
if (timestamp7 >= countdownExpiresAt) {
|
|
3403
3433
|
setModel((current) => current.provisioning?.attemptId === countdownAttemptId ? { ...current, provisioning: { ...current.provisioning, expired: true } } : current);
|
|
3404
3434
|
}
|
|
3405
3435
|
};
|
|
@@ -5440,14 +5470,14 @@ function ProvisionError3({ provision, busy, onRetry, onClose }) {
|
|
|
5440
5470
|
)
|
|
5441
5471
|
);
|
|
5442
5472
|
}
|
|
5443
|
-
function checkedTime5(
|
|
5444
|
-
if (!
|
|
5473
|
+
function checkedTime5(timestamp7) {
|
|
5474
|
+
if (!timestamp7) return "\u5C1A\u672A\u68C0\u67E5";
|
|
5445
5475
|
try {
|
|
5446
5476
|
return new Intl.DateTimeFormat("zh-CN", {
|
|
5447
5477
|
hour: "2-digit",
|
|
5448
5478
|
minute: "2-digit",
|
|
5449
5479
|
second: "2-digit"
|
|
5450
|
-
}).format(new Date(
|
|
5480
|
+
}).format(new Date(timestamp7));
|
|
5451
5481
|
} catch {
|
|
5452
5482
|
return "\u521A\u521A";
|
|
5453
5483
|
}
|
|
@@ -5855,9 +5885,668 @@ function WeixinSettingsTab({ rpcCall }) {
|
|
|
5855
5885
|
);
|
|
5856
5886
|
}
|
|
5857
5887
|
|
|
5888
|
+
// plugin-src/client/channels/whatsapp/api.js
|
|
5889
|
+
var WHATSAPP_RPC_CHANNEL = "/whatsapp";
|
|
5890
|
+
var WHATSAPP_ENDPOINTS = Object.freeze({
|
|
5891
|
+
status: "connection.status",
|
|
5892
|
+
beginProvisioning: "provision.begin",
|
|
5893
|
+
pollProvisioning: "provision.poll",
|
|
5894
|
+
cancelProvisioning: "provision.cancel",
|
|
5895
|
+
reconnectBot: "bot.reconnect",
|
|
5896
|
+
deleteBot: "bot.delete"
|
|
5897
|
+
});
|
|
5898
|
+
var PROVISION_STATES5 = /* @__PURE__ */ new Set(["starting", "pending", "connecting", "connected", "failed", "cancelled"]);
|
|
5899
|
+
var BOT_STATES = /* @__PURE__ */ new Set(["connected", "connecting", "offline", "error"]);
|
|
5900
|
+
var QR_DATA_URL4 = /^data:image\/(?:png|webp);base64,[a-z\d+/]+={0,2}$/i;
|
|
5901
|
+
function isRecord7(value) {
|
|
5902
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5903
|
+
}
|
|
5904
|
+
function text4(value, fallback, max = 240) {
|
|
5905
|
+
return typeof value === "string" && value.trim() ? value.trim().slice(0, max) : fallback;
|
|
5906
|
+
}
|
|
5907
|
+
function id4(value) {
|
|
5908
|
+
const result = text4(value, "", 128);
|
|
5909
|
+
return /^[a-z\d_-]+$/i.test(result) ? result : void 0;
|
|
5910
|
+
}
|
|
5911
|
+
function timestamp6(value) {
|
|
5912
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
5913
|
+
const parsed = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
5914
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
5915
|
+
}
|
|
5916
|
+
function unwrapRpcResult8(result) {
|
|
5917
|
+
if (!isRecord7(result) || typeof result.ok !== "boolean") {
|
|
5918
|
+
throw new Error("WhatsApp \u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94");
|
|
5919
|
+
}
|
|
5920
|
+
if (!result.ok) {
|
|
5921
|
+
const error = new Error(text4(result.error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25"));
|
|
5922
|
+
error.code = text4(result.error?.code, "WHATSAPP_RPC_ERROR", 80);
|
|
5923
|
+
throw error;
|
|
5924
|
+
}
|
|
5925
|
+
return result.value;
|
|
5926
|
+
}
|
|
5927
|
+
function safeQrSource6(value) {
|
|
5928
|
+
return typeof value === "string" && value.length <= 2 * 1024 * 1024 && QR_DATA_URL4.test(value) ? value : void 0;
|
|
5929
|
+
}
|
|
5930
|
+
function normalizeProvisioning6(value, now = Date.now()) {
|
|
5931
|
+
const source = isRecord7(value?.provisioning) ? value.provisioning : value;
|
|
5932
|
+
if (!isRecord7(source)) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u8FDB\u5EA6");
|
|
5933
|
+
const attemptId = id4(source.attemptId);
|
|
5934
|
+
if (!attemptId) throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u626B\u7801\u4EFB\u52A1");
|
|
5935
|
+
const reported = text4(source.status, "failed", 32);
|
|
5936
|
+
const result = {
|
|
5937
|
+
attemptId,
|
|
5938
|
+
status: PROVISION_STATES5.has(reported) ? reported : "failed",
|
|
5939
|
+
expiresAt: timestamp6(source.expiresAt) ?? now + 6e4,
|
|
5940
|
+
pollIntervalMs: Math.min(5e3, Math.max(500, Number(source.pollIntervalMs) || 1e3)),
|
|
5941
|
+
qrRevision: Number.isSafeInteger(source.qrRevision) ? source.qrRevision : 0
|
|
5942
|
+
};
|
|
5943
|
+
const qrCodeDataUrl = safeQrSource6(source.qrCodeDataUrl);
|
|
5944
|
+
if (qrCodeDataUrl) result.qrCodeDataUrl = qrCodeDataUrl;
|
|
5945
|
+
if (id4(source.botId)) result.botId = id4(source.botId);
|
|
5946
|
+
if (isRecord7(source.error)) result.error = {
|
|
5947
|
+
code: text4(source.error.code, "WHATSAPP_PROVISION_FAILED", 80),
|
|
5948
|
+
message: text4(source.error.message, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210")
|
|
5949
|
+
};
|
|
5950
|
+
return result;
|
|
5951
|
+
}
|
|
5952
|
+
function normalizeBot6(value) {
|
|
5953
|
+
if (!isRecord7(value) || !id4(value.botId)) return void 0;
|
|
5954
|
+
const connected = value.connected === true;
|
|
5955
|
+
const state = BOT_STATES.has(value.state) ? value.state : "offline";
|
|
5956
|
+
return {
|
|
5957
|
+
botId: id4(value.botId),
|
|
5958
|
+
connected,
|
|
5959
|
+
state: connected ? "connected" : state,
|
|
5960
|
+
bot: {
|
|
5961
|
+
name: text4(value.bot?.name, "WhatsApp\u673A\u5668\u4EBA", 100),
|
|
5962
|
+
idMasked: text4(value.bot?.idMasked, "WhatsApp\u8D26\u53F7", 140)
|
|
5963
|
+
},
|
|
5964
|
+
health: {
|
|
5965
|
+
summary: text4(value.health?.summary, connected ? "WhatsApp Web \u5173\u8054\u8BBE\u5907\u8FD0\u884C\u6B63\u5E38" : "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA"),
|
|
5966
|
+
lastCheckedAt: timestamp6(value.health?.lastCheckedAt)
|
|
5967
|
+
},
|
|
5968
|
+
error: isRecord7(value.error) ? {
|
|
5969
|
+
code: text4(value.error.code, "WHATSAPP_ACCOUNT_ERROR", 80),
|
|
5970
|
+
message: text4(value.error.message, "WhatsApp \u8FDE\u63A5\u5C1A\u672A\u5C31\u7EEA")
|
|
5971
|
+
} : null
|
|
5972
|
+
};
|
|
5973
|
+
}
|
|
5974
|
+
function normalizeSnapshot7(value) {
|
|
5975
|
+
const source = isRecord7(value?.snapshot) ? value.snapshot : value;
|
|
5976
|
+
if (!isRecord7(source) || !Array.isArray(source.bots)) {
|
|
5977
|
+
throw new Error("WhatsApp \u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u673A\u5668\u4EBA\u5217\u8868");
|
|
5978
|
+
}
|
|
5979
|
+
const bots = source.bots.map(normalizeBot6).filter(Boolean);
|
|
5980
|
+
return {
|
|
5981
|
+
revision: Number.isSafeInteger(source.revision) ? source.revision : 0,
|
|
5982
|
+
bots,
|
|
5983
|
+
totals: { configured: bots.length, connected: bots.filter((bot) => bot.connected).length },
|
|
5984
|
+
provisioning: source.provisioning ? normalizeProvisioning6(source.provisioning) : null
|
|
5985
|
+
};
|
|
5986
|
+
}
|
|
5987
|
+
function presentError8(error) {
|
|
5988
|
+
return {
|
|
5989
|
+
code: text4(error?.code, "WHATSAPP_ERROR", 80),
|
|
5990
|
+
message: text4(error?.message, "WhatsApp \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5")
|
|
5991
|
+
};
|
|
5992
|
+
}
|
|
5993
|
+
function formatRemaining6(milliseconds) {
|
|
5994
|
+
const seconds = Math.max(0, Math.ceil(Number(milliseconds) / 1e3) || 0);
|
|
5995
|
+
return `${String(Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
|
|
5996
|
+
}
|
|
5997
|
+
|
|
5998
|
+
// plugin-src/client/channels/whatsapp/index.js
|
|
5999
|
+
var React10 = __toESM(require("react"), 1);
|
|
6000
|
+
|
|
6001
|
+
// plugin-src/client/channels/whatsapp/styles.js
|
|
6002
|
+
var WHATSAPP_STYLE_ID = "xmanrui-dsh-im-whatsapp-settings";
|
|
6003
|
+
var CSS8 = String.raw`
|
|
6004
|
+
.dwa-page { --ddt-accent: #25d366; --ddt-accent-deep: #128c7e; --ddt-accent-wash: #eafbf0; }
|
|
6005
|
+
.dwa-avatar { color: #fff; background: #25d366; }
|
|
6006
|
+
.dwa-avatar svg { display: block; }
|
|
6007
|
+
`;
|
|
6008
|
+
function installWhatsappStyles() {
|
|
6009
|
+
if (typeof document === "undefined") return () => {
|
|
6010
|
+
};
|
|
6011
|
+
const existing = document.querySelector(`style[data-plugin-css="${WHATSAPP_STYLE_ID}"]`);
|
|
6012
|
+
if (existing) return () => {
|
|
6013
|
+
};
|
|
6014
|
+
const style = document.createElement("style");
|
|
6015
|
+
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
6016
|
+
style.dataset.pluginCss = WHATSAPP_STYLE_ID;
|
|
6017
|
+
style.textContent = CSS8;
|
|
6018
|
+
document.head.appendChild(style);
|
|
6019
|
+
return () => style.remove();
|
|
6020
|
+
}
|
|
6021
|
+
|
|
6022
|
+
// plugin-src/client/channels/whatsapp/index.js
|
|
6023
|
+
var h9 = React10.createElement;
|
|
6024
|
+
var ACTIVE_STATES3 = /* @__PURE__ */ new Set(["pending", "connecting"]);
|
|
6025
|
+
var Button13 = React10.forwardRef(function Button14({ children, kind = "secondary", className = "", ...props }, ref) {
|
|
6026
|
+
return h9("button", {
|
|
6027
|
+
...props,
|
|
6028
|
+
ref,
|
|
6029
|
+
type: "button",
|
|
6030
|
+
className: `ddt-button ${className}`.trim(),
|
|
6031
|
+
"data-kind": kind
|
|
6032
|
+
}, children);
|
|
6033
|
+
});
|
|
6034
|
+
function checkedTime6(value) {
|
|
6035
|
+
if (!value) return "\u5C1A\u672A\u68C0\u67E5";
|
|
6036
|
+
try {
|
|
6037
|
+
return new Intl.DateTimeFormat("zh-CN", {
|
|
6038
|
+
hour: "2-digit",
|
|
6039
|
+
minute: "2-digit",
|
|
6040
|
+
second: "2-digit"
|
|
6041
|
+
}).format(new Date(value));
|
|
6042
|
+
} catch {
|
|
6043
|
+
return "\u521A\u521A";
|
|
6044
|
+
}
|
|
6045
|
+
}
|
|
6046
|
+
function Heading6({ totals, busy, onAdd, addButtonRef }) {
|
|
6047
|
+
return h9(
|
|
6048
|
+
"div",
|
|
6049
|
+
{ className: "ddt-heading" },
|
|
6050
|
+
h9(
|
|
6051
|
+
"div",
|
|
6052
|
+
{ className: "ddt-tools" },
|
|
6053
|
+
h9(
|
|
6054
|
+
"div",
|
|
6055
|
+
{ className: "dim-bindActions" },
|
|
6056
|
+
h9(Button13, {
|
|
6057
|
+
kind: "primary",
|
|
6058
|
+
className: "dim-scanButton",
|
|
6059
|
+
onClick: onAdd,
|
|
6060
|
+
disabled: busy,
|
|
6061
|
+
ref: addButtonRef,
|
|
6062
|
+
"aria-label": "\u626B\u7801\u63A5\u5165 WhatsApp \u673A\u5668\u4EBA"
|
|
6063
|
+
}, h9(QrActionIcon), busy ? "\u6B63\u5728\u63A5\u5165" : "\u626B\u7801\u63A5\u5165\u673A\u5668\u4EBA")
|
|
6064
|
+
),
|
|
6065
|
+
totals.configured > 0 ? h9(
|
|
6066
|
+
"div",
|
|
6067
|
+
{ className: "ddt-badge dim-onlineBadge" },
|
|
6068
|
+
h9("span", null, `${totals.connected} / ${totals.configured} \u5728\u7EBF`)
|
|
6069
|
+
) : null
|
|
6070
|
+
)
|
|
6071
|
+
);
|
|
6072
|
+
}
|
|
6073
|
+
function LoadingView6() {
|
|
6074
|
+
return h9("div", {
|
|
6075
|
+
className: "ddt-card ddt-loading dim-surfaceCard dim-loadingView",
|
|
6076
|
+
"aria-busy": "true"
|
|
6077
|
+
}, h9("div", { className: "ddt-spinner dim-spinner" }), "\u6B63\u5728\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001\u2026");
|
|
6078
|
+
}
|
|
6079
|
+
function EmptyView6({ busy, onStart }) {
|
|
6080
|
+
return h9(
|
|
6081
|
+
"div",
|
|
6082
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
6083
|
+
h9(
|
|
6084
|
+
"div",
|
|
6085
|
+
{ className: "ddt-cardBody ddt-empty dim-surfaceBody dim-emptyView" },
|
|
6086
|
+
h9(
|
|
6087
|
+
"div",
|
|
6088
|
+
{ className: "dim-emptyCopy" },
|
|
6089
|
+
h9(
|
|
6090
|
+
"div",
|
|
6091
|
+
{ className: "ddt-stateLabel dim-stateLabel" },
|
|
6092
|
+
h9("span", { className: "ddt-dot dim-stateDot" }),
|
|
6093
|
+
h9("span", null, "\u5C1A\u672A\u63A5\u5165 WhatsApp \u673A\u5668\u4EBA")
|
|
6094
|
+
),
|
|
6095
|
+
h9("h3", null, "\u626B\u7801\u7ED1\u5B9A WhatsApp \u673A\u5668\u4EBA"),
|
|
6096
|
+
h9("p", null, "\u4F7F\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801\u5373\u53EF\u63A5\u5165\u3002"),
|
|
6097
|
+
h9(
|
|
6098
|
+
"div",
|
|
6099
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
6100
|
+
h9(
|
|
6101
|
+
Button13,
|
|
6102
|
+
{ kind: "primary", onClick: onStart, disabled: busy },
|
|
6103
|
+
busy ? "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" : "\u751F\u6210\u4E8C\u7EF4\u7801"
|
|
6104
|
+
)
|
|
6105
|
+
)
|
|
6106
|
+
),
|
|
6107
|
+
h9("div", {
|
|
6108
|
+
className: "ddt-brandMark dim-emptyBrand dwa-avatar",
|
|
6109
|
+
"aria-hidden": "true"
|
|
6110
|
+
}, h9(WhatsappLogoGlyph, { size: 64 }))
|
|
6111
|
+
)
|
|
6112
|
+
);
|
|
6113
|
+
}
|
|
6114
|
+
function QrPanel5({ provision, now, busy, onRefresh, onCancel }) {
|
|
6115
|
+
const source = safeQrSource6(provision.qrCodeDataUrl);
|
|
6116
|
+
const remaining = Math.max(0, provision.expiresAt - now);
|
|
6117
|
+
const duration = Math.max(1, provision.durationMs ?? 6e4);
|
|
6118
|
+
const progress = Math.round(Math.min(1, remaining / duration) * 100);
|
|
6119
|
+
return h9(
|
|
6120
|
+
"div",
|
|
6121
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
6122
|
+
h9(
|
|
6123
|
+
"div",
|
|
6124
|
+
{ className: "ddt-cardBody ddt-qrLayout dim-surfaceBody dim-qrLayout" },
|
|
6125
|
+
h9(
|
|
6126
|
+
"div",
|
|
6127
|
+
{ className: "ddt-qrColumn dim-qrColumn" },
|
|
6128
|
+
h9(
|
|
6129
|
+
"div",
|
|
6130
|
+
{ className: "ddt-qrFrame dim-qrFrame" },
|
|
6131
|
+
source ? h9("img", {
|
|
6132
|
+
src: source,
|
|
6133
|
+
alt: "\u7528\u4E8E\u5173\u8054 WhatsApp \u8BBE\u5907\u7684\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801"
|
|
6134
|
+
}) : h9("div", { className: "ddt-qrFallback dim-qrFallback" }, "\u4E8C\u7EF4\u7801\u6B63\u5728\u751F\u6210\u2026")
|
|
6135
|
+
),
|
|
6136
|
+
h9(
|
|
6137
|
+
"div",
|
|
6138
|
+
{ className: "ddt-countdown dim-countdown" },
|
|
6139
|
+
h9(
|
|
6140
|
+
"div",
|
|
6141
|
+
{ className: "ddt-countdownTop dim-countdownTop" },
|
|
6142
|
+
h9("span", null, "\u5F53\u524D\u4E8C\u7EF4\u7801\u6709\u6548\u65F6\u95F4"),
|
|
6143
|
+
h9("strong", null, formatRemaining6(remaining))
|
|
6144
|
+
),
|
|
6145
|
+
h9("div", {
|
|
6146
|
+
className: "ddt-progress dim-progress",
|
|
6147
|
+
style: { "--ddt-progress": `${progress}%` }
|
|
6148
|
+
}, h9("span"))
|
|
6149
|
+
)
|
|
6150
|
+
),
|
|
6151
|
+
h9(
|
|
6152
|
+
"div",
|
|
6153
|
+
{ className: "ddt-qrCopy dim-qrCopy" },
|
|
6154
|
+
h9(
|
|
6155
|
+
"div",
|
|
6156
|
+
{ className: "ddt-stateLabel dim-stateLabel" },
|
|
6157
|
+
h9("span", { className: "ddt-dot dim-stateDot", "data-tone": "warning" }),
|
|
6158
|
+
h9("span", null, "\u7B49\u5F85 WhatsApp \u626B\u7801")
|
|
6159
|
+
),
|
|
6160
|
+
h9("h3", null, "\u7528\u624B\u673A WhatsApp \u626B\u63CF\u4E8C\u7EF4\u7801"),
|
|
6161
|
+
h9(
|
|
6162
|
+
"ol",
|
|
6163
|
+
{ className: "ddt-steps dim-steps" },
|
|
6164
|
+
h9("li", null, "\u6253\u5F00 WhatsApp \u2192 \u8BBE\u7F6E \u2192 \u5DF2\u5173\u8054\u8BBE\u5907"),
|
|
6165
|
+
h9("li", null, "\u70B9\u51FB\u201C\u5173\u8054\u8BBE\u5907\u201D\u5E76\u626B\u63CF\u5DE6\u4FA7\u4E8C\u7EF4\u7801")
|
|
6166
|
+
),
|
|
6167
|
+
h9(
|
|
6168
|
+
"div",
|
|
6169
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
6170
|
+
h9(Button13, { onClick: onRefresh, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
6171
|
+
h9(Button13, { kind: "quiet", onClick: onCancel, disabled: busy }, "\u53D6\u6D88")
|
|
6172
|
+
)
|
|
6173
|
+
)
|
|
6174
|
+
)
|
|
6175
|
+
);
|
|
6176
|
+
}
|
|
6177
|
+
function ProvisionView3({ provision, busy, onRetry, onClose }) {
|
|
6178
|
+
if (provision.status === "starting" || provision.status === "connecting") {
|
|
6179
|
+
const starting = provision.status === "starting";
|
|
6180
|
+
return h9(
|
|
6181
|
+
"div",
|
|
6182
|
+
{
|
|
6183
|
+
className: "ddt-card ddt-loading dim-surfaceCard dim-specialView",
|
|
6184
|
+
"aria-busy": "true"
|
|
6185
|
+
},
|
|
6186
|
+
h9("div", { className: "ddt-spinner dim-spinner" }),
|
|
6187
|
+
h9("h3", null, starting ? "\u6B63\u5728\u751F\u6210 WhatsApp \u4E8C\u7EF4\u7801" : "\u5DF2\u626B\u7801\uFF0C\u6B63\u5728\u8FDE\u63A5 WhatsApp"),
|
|
6188
|
+
h9("p", null, starting ? "\u6B63\u5728\u5EFA\u7ACB\u5B89\u5168\u7684\u5173\u8054\u8BBE\u5907\u4F1A\u8BDD\u3002" : "\u5173\u8054\u8BBE\u5907\u6B63\u5728\u63A5\u5165 DeepSeek Harness\u3002")
|
|
6189
|
+
);
|
|
6190
|
+
}
|
|
6191
|
+
const error = provision.error ?? {
|
|
6192
|
+
code: "WHATSAPP_PROVISION_FAILED",
|
|
6193
|
+
message: "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210"
|
|
6194
|
+
};
|
|
6195
|
+
return h9(
|
|
6196
|
+
"div",
|
|
6197
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
6198
|
+
h9(
|
|
6199
|
+
"div",
|
|
6200
|
+
{ className: "ddt-inlineError dim-inlineError", role: "alert" },
|
|
6201
|
+
h9("h3", null, "WhatsApp \u6CA1\u6709\u63A5\u5165\u5B8C\u6210"),
|
|
6202
|
+
h9("p", null, error.message),
|
|
6203
|
+
h9("span", { className: "ddt-errorCode" }, error.code),
|
|
6204
|
+
h9(
|
|
6205
|
+
"div",
|
|
6206
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
6207
|
+
h9(Button13, { kind: "primary", onClick: onRetry, disabled: busy }, "\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801"),
|
|
6208
|
+
h9(Button13, { onClick: onClose, disabled: busy }, "\u5173\u95ED")
|
|
6209
|
+
)
|
|
6210
|
+
)
|
|
6211
|
+
);
|
|
6212
|
+
}
|
|
6213
|
+
function RemoveConfirmation5({ account, busy, onConfirm, onCancel }) {
|
|
6214
|
+
return h9(
|
|
6215
|
+
"div",
|
|
6216
|
+
{ className: "ddt-confirm dim-confirm", role: "alertdialog" },
|
|
6217
|
+
h9("strong", null, `\u4ECE DeepSeek Harness \u79FB\u9664\u201C${account.bot.name}\u201D\uFF1F`),
|
|
6218
|
+
h9("p", null, "\u8FD9\u4F1A\u505C\u6B62\u6D88\u606F\u8FDE\u63A5\uFF0C\u5E76\u5220\u9664\u672C\u673A\u4FDD\u5B58\u7684 WhatsApp \u5173\u8054\u8BBE\u5907\u548C\u4F1A\u8BDD\u6620\u5C04\u3002"),
|
|
6219
|
+
h9(
|
|
6220
|
+
"div",
|
|
6221
|
+
{ className: "ddt-actions dim-viewActions" },
|
|
6222
|
+
h9(Button13, { onClick: onCancel, disabled: busy }, "\u4FDD\u7559\u673A\u5668\u4EBA"),
|
|
6223
|
+
h9(
|
|
6224
|
+
Button13,
|
|
6225
|
+
{ kind: "danger", onClick: onConfirm, disabled: busy },
|
|
6226
|
+
busy ? "\u6B63\u5728\u79FB\u9664\u2026" : "\u786E\u8BA4\u79FB\u9664\u63A5\u5165"
|
|
6227
|
+
)
|
|
6228
|
+
)
|
|
6229
|
+
);
|
|
6230
|
+
}
|
|
6231
|
+
function WhatsappAccountCard({
|
|
6232
|
+
account,
|
|
6233
|
+
busy,
|
|
6234
|
+
removing,
|
|
6235
|
+
onReconnect,
|
|
6236
|
+
onRequestRemove,
|
|
6237
|
+
onConfirmRemove,
|
|
6238
|
+
onCancelRemove
|
|
6239
|
+
}) {
|
|
6240
|
+
const state = busy === "reconnect" ? "connecting" : account.state;
|
|
6241
|
+
const tone = account.connected ? "success" : state === "error" ? "error" : "warning";
|
|
6242
|
+
const stateLabel = account.connected ? "\u8FD0\u884C\u6B63\u5E38" : state === "connecting" ? "\u6B63\u5728\u8FDE\u63A5" : "\u8FDE\u63A5\u672A\u5C31\u7EEA";
|
|
6243
|
+
const summary = account.error?.message ?? (account.connected ? null : account.health.summary);
|
|
6244
|
+
return h9(
|
|
6245
|
+
"article",
|
|
6246
|
+
{ className: "ddt-card dim-botCard", "data-bot-id": account.botId },
|
|
6247
|
+
h9(
|
|
6248
|
+
"div",
|
|
6249
|
+
{ className: "ddt-cardBody dim-botCardBody" },
|
|
6250
|
+
h9(
|
|
6251
|
+
"div",
|
|
6252
|
+
{ className: "ddt-accountTop dim-botCardTop" },
|
|
6253
|
+
h9(
|
|
6254
|
+
"div",
|
|
6255
|
+
{ className: "ddt-accountIdentity dim-botIdentity" },
|
|
6256
|
+
h9("div", {
|
|
6257
|
+
className: "ddt-avatar dim-botAvatar dwa-avatar",
|
|
6258
|
+
"aria-hidden": "true"
|
|
6259
|
+
}, h9(WhatsappLogoGlyph, { size: 29 })),
|
|
6260
|
+
h9(
|
|
6261
|
+
"div",
|
|
6262
|
+
{ className: "dim-botName" },
|
|
6263
|
+
h9("h3", null, account.bot.name),
|
|
6264
|
+
h9("p", null, account.bot.idMasked)
|
|
6265
|
+
)
|
|
6266
|
+
),
|
|
6267
|
+
h9(
|
|
6268
|
+
"div",
|
|
6269
|
+
{ className: "ddt-health dim-botHealth" },
|
|
6270
|
+
h9("span", { className: "ddt-dot dim-healthDot", "data-tone": tone }),
|
|
6271
|
+
h9("span", null, stateLabel)
|
|
6272
|
+
)
|
|
6273
|
+
),
|
|
6274
|
+
h9(
|
|
6275
|
+
"dl",
|
|
6276
|
+
{ className: "ddt-metrics dim-botMetrics" },
|
|
6277
|
+
h9(
|
|
6278
|
+
"div",
|
|
6279
|
+
{ className: "ddt-metric dim-botMetric" },
|
|
6280
|
+
h9("dt", null, "\u6D88\u606F\u901A\u9053"),
|
|
6281
|
+
h9("dd", null, account.connected ? "WhatsApp Web" : "\u79BB\u7EBF")
|
|
6282
|
+
),
|
|
6283
|
+
h9(
|
|
6284
|
+
"div",
|
|
6285
|
+
{ className: "ddt-metric dim-botMetric" },
|
|
6286
|
+
h9("dt", null, "\u6700\u8FD1\u68C0\u67E5"),
|
|
6287
|
+
h9("dd", null, checkedTime6(account.health.lastCheckedAt))
|
|
6288
|
+
)
|
|
6289
|
+
),
|
|
6290
|
+
h9(
|
|
6291
|
+
"div",
|
|
6292
|
+
{ className: "ddt-accountFooter dim-cardFooter" },
|
|
6293
|
+
summary ? h9("div", { className: "ddt-summary dim-cardSummary" }, summary) : null,
|
|
6294
|
+
h9(
|
|
6295
|
+
"div",
|
|
6296
|
+
{ className: "ddt-actions dim-cardActions" },
|
|
6297
|
+
h9(Button13, {
|
|
6298
|
+
className: "dim-cardAction",
|
|
6299
|
+
onClick: onReconnect,
|
|
6300
|
+
disabled: Boolean(busy)
|
|
6301
|
+
}, busy === "reconnect" ? "\u68C0\u67E5\u4E2D\u2026" : account.connected ? "\u68C0\u67E5\u8FDE\u63A5" : "\u91CD\u8BD5\u8FDE\u63A5"),
|
|
6302
|
+
h9(Button13, {
|
|
6303
|
+
className: "dim-cardAction",
|
|
6304
|
+
kind: "danger",
|
|
6305
|
+
onClick: onRequestRemove,
|
|
6306
|
+
disabled: Boolean(busy)
|
|
6307
|
+
}, "\u79FB\u9664\u63A5\u5165")
|
|
6308
|
+
)
|
|
6309
|
+
)
|
|
6310
|
+
),
|
|
6311
|
+
removing ? h9(RemoveConfirmation5, {
|
|
6312
|
+
account,
|
|
6313
|
+
busy: busy === "delete",
|
|
6314
|
+
onConfirm: onConfirmRemove,
|
|
6315
|
+
onCancel: onCancelRemove
|
|
6316
|
+
}) : null
|
|
6317
|
+
);
|
|
6318
|
+
}
|
|
6319
|
+
function WhatsappSettingsTab({ rpcCall }) {
|
|
6320
|
+
const [model, setModel] = React10.useState({
|
|
6321
|
+
phase: "loading",
|
|
6322
|
+
bots: [],
|
|
6323
|
+
totals: { configured: 0, connected: 0 },
|
|
6324
|
+
error: null
|
|
6325
|
+
});
|
|
6326
|
+
const [provision, setProvision] = React10.useState(null);
|
|
6327
|
+
const [busy, setBusy] = React10.useState(false);
|
|
6328
|
+
const [busyByBot, setBusyByBot] = React10.useState({});
|
|
6329
|
+
const [removeTarget, setRemoveTarget] = React10.useState(null);
|
|
6330
|
+
const [now, setNow] = React10.useState(Date.now());
|
|
6331
|
+
const mounted = React10.useRef(true);
|
|
6332
|
+
const addButtonRef = React10.useRef(null);
|
|
6333
|
+
React10.useEffect(() => {
|
|
6334
|
+
const disposeDingtalk = installDingtalkStyles();
|
|
6335
|
+
const disposeWhatsapp = installWhatsappStyles();
|
|
6336
|
+
mounted.current = true;
|
|
6337
|
+
return () => {
|
|
6338
|
+
mounted.current = false;
|
|
6339
|
+
disposeWhatsapp();
|
|
6340
|
+
disposeDingtalk();
|
|
6341
|
+
};
|
|
6342
|
+
}, []);
|
|
6343
|
+
const invoke = React10.useCallback(async (endpoint, payload = {}, signal) => {
|
|
6344
|
+
if (typeof rpcCall !== "function") throw new TypeError("WhatsApp \u8BBE\u7F6E\u9875\u7F3A\u5C11 RPC \u8FDE\u63A5");
|
|
6345
|
+
return unwrapRpcResult8(await rpcCall(endpoint, payload, signal));
|
|
6346
|
+
}, [rpcCall]);
|
|
6347
|
+
const loadStatus = React10.useCallback(async ({ signal, silent = false, restore = false } = {}) => {
|
|
6348
|
+
if (!silent && mounted.current) setModel((current) => ({ ...current, phase: "loading", error: null }));
|
|
6349
|
+
try {
|
|
6350
|
+
const snapshot = normalizeSnapshot7(await invoke(WHATSAPP_ENDPOINTS.status, {}, signal));
|
|
6351
|
+
if (!mounted.current || signal?.aborted) return void 0;
|
|
6352
|
+
setModel({ phase: "ready", bots: snapshot.bots, totals: snapshot.totals, error: null });
|
|
6353
|
+
if (restore && snapshot.provisioning) setProvision({
|
|
6354
|
+
...snapshot.provisioning,
|
|
6355
|
+
durationMs: Math.max(1, snapshot.provisioning.expiresAt - Date.now())
|
|
6356
|
+
});
|
|
6357
|
+
return snapshot;
|
|
6358
|
+
} catch (error) {
|
|
6359
|
+
if (error?.name !== "AbortError" && mounted.current && !signal?.aborted) {
|
|
6360
|
+
setModel((current) => ({
|
|
6361
|
+
...current,
|
|
6362
|
+
phase: silent ? current.phase : "error",
|
|
6363
|
+
error: presentError8(error)
|
|
6364
|
+
}));
|
|
6365
|
+
}
|
|
6366
|
+
return void 0;
|
|
6367
|
+
}
|
|
6368
|
+
}, [invoke]);
|
|
6369
|
+
React10.useEffect(() => {
|
|
6370
|
+
const controller = new AbortController();
|
|
6371
|
+
void loadStatus({ signal: controller.signal, restore: true });
|
|
6372
|
+
return () => controller.abort();
|
|
6373
|
+
}, [loadStatus]);
|
|
6374
|
+
React10.useEffect(() => {
|
|
6375
|
+
if (model.phase !== "ready") return void 0;
|
|
6376
|
+
const controller = new AbortController();
|
|
6377
|
+
const timer = window.setInterval(
|
|
6378
|
+
() => void loadStatus({ signal: controller.signal, silent: true }),
|
|
6379
|
+
15e3
|
|
6380
|
+
);
|
|
6381
|
+
return () => {
|
|
6382
|
+
controller.abort();
|
|
6383
|
+
window.clearInterval(timer);
|
|
6384
|
+
};
|
|
6385
|
+
}, [loadStatus, model.phase]);
|
|
6386
|
+
React10.useEffect(() => {
|
|
6387
|
+
if (!provision || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
6388
|
+
const timer = window.setInterval(() => mounted.current && setNow(Date.now()), 1e3);
|
|
6389
|
+
return () => window.clearInterval(timer);
|
|
6390
|
+
}, [provision?.attemptId, provision?.status]);
|
|
6391
|
+
const startProvisioning = React10.useCallback(async (replace = false) => {
|
|
6392
|
+
setBusy(true);
|
|
6393
|
+
try {
|
|
6394
|
+
if (replace && provision?.attemptId) {
|
|
6395
|
+
await invoke(WHATSAPP_ENDPOINTS.cancelProvisioning, { attemptId: provision.attemptId });
|
|
6396
|
+
}
|
|
6397
|
+
if (!mounted.current) return;
|
|
6398
|
+
setProvision({ status: "starting" });
|
|
6399
|
+
const started = normalizeProvisioning6(await invoke(WHATSAPP_ENDPOINTS.beginProvisioning, {}));
|
|
6400
|
+
if (!mounted.current) return;
|
|
6401
|
+
setNow(Date.now());
|
|
6402
|
+
setProvision({ ...started, durationMs: Math.max(1, started.expiresAt - Date.now()) });
|
|
6403
|
+
} catch (error) {
|
|
6404
|
+
if (mounted.current) setProvision({ status: "failed", error: presentError8(error) });
|
|
6405
|
+
} finally {
|
|
6406
|
+
if (mounted.current) setBusy(false);
|
|
6407
|
+
}
|
|
6408
|
+
}, [invoke, provision?.attemptId]);
|
|
6409
|
+
const closeProvision = React10.useCallback(async () => {
|
|
6410
|
+
setBusy(true);
|
|
6411
|
+
try {
|
|
6412
|
+
if (provision?.attemptId && ACTIVE_STATES3.has(provision.status)) {
|
|
6413
|
+
await invoke(WHATSAPP_ENDPOINTS.cancelProvisioning, { attemptId: provision.attemptId });
|
|
6414
|
+
}
|
|
6415
|
+
if (mounted.current) setProvision(null);
|
|
6416
|
+
} finally {
|
|
6417
|
+
if (mounted.current) setBusy(false);
|
|
6418
|
+
}
|
|
6419
|
+
}, [invoke, provision?.attemptId, provision?.status]);
|
|
6420
|
+
React10.useEffect(() => {
|
|
6421
|
+
const attemptId = provision?.attemptId;
|
|
6422
|
+
if (!attemptId || !ACTIVE_STATES3.has(provision.status)) return void 0;
|
|
6423
|
+
const controller = new AbortController();
|
|
6424
|
+
let disposed = false;
|
|
6425
|
+
let timer;
|
|
6426
|
+
const schedule = (delay) => {
|
|
6427
|
+
if (disposed || controller.signal.aborted) return;
|
|
6428
|
+
timer = window.setTimeout(() => void poll(), delay);
|
|
6429
|
+
};
|
|
6430
|
+
const poll = async () => {
|
|
6431
|
+
try {
|
|
6432
|
+
const current = normalizeProvisioning6(await invoke(
|
|
6433
|
+
WHATSAPP_ENDPOINTS.pollProvisioning,
|
|
6434
|
+
{ attemptId },
|
|
6435
|
+
controller.signal
|
|
6436
|
+
));
|
|
6437
|
+
if (disposed || controller.signal.aborted || !mounted.current) return;
|
|
6438
|
+
if (current.status === "connected") {
|
|
6439
|
+
setProvision(null);
|
|
6440
|
+
await loadStatus({ signal: controller.signal, silent: true });
|
|
6441
|
+
return;
|
|
6442
|
+
}
|
|
6443
|
+
setProvision((previous) => ({
|
|
6444
|
+
...current,
|
|
6445
|
+
durationMs: previous?.durationMs ?? Math.max(1, current.expiresAt - Date.now())
|
|
6446
|
+
}));
|
|
6447
|
+
if (ACTIVE_STATES3.has(current.status)) schedule(current.pollIntervalMs);
|
|
6448
|
+
} catch (error) {
|
|
6449
|
+
if (!disposed && !controller.signal.aborted && mounted.current) {
|
|
6450
|
+
setProvision({ status: "failed", error: presentError8(error) });
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6453
|
+
};
|
|
6454
|
+
schedule(provision.pollIntervalMs ?? 1e3);
|
|
6455
|
+
return () => {
|
|
6456
|
+
disposed = true;
|
|
6457
|
+
controller.abort();
|
|
6458
|
+
if (timer) window.clearTimeout(timer);
|
|
6459
|
+
};
|
|
6460
|
+
}, [invoke, loadStatus, provision?.attemptId, provision?.status]);
|
|
6461
|
+
const botAction = React10.useCallback(async (account, operation, endpoint, payload) => {
|
|
6462
|
+
setBusyByBot((current) => ({ ...current, [account.botId]: operation }));
|
|
6463
|
+
try {
|
|
6464
|
+
const snapshot = normalizeSnapshot7(await invoke(endpoint, payload));
|
|
6465
|
+
if (mounted.current) {
|
|
6466
|
+
setModel({ phase: "ready", bots: snapshot.bots, totals: snapshot.totals, error: null });
|
|
6467
|
+
}
|
|
6468
|
+
} finally {
|
|
6469
|
+
if (mounted.current) setBusyByBot((current) => {
|
|
6470
|
+
const next = { ...current };
|
|
6471
|
+
delete next[account.botId];
|
|
6472
|
+
return next;
|
|
6473
|
+
});
|
|
6474
|
+
}
|
|
6475
|
+
}, [invoke]);
|
|
6476
|
+
const botList = model.bots.length > 0 ? h9(
|
|
6477
|
+
"section",
|
|
6478
|
+
{ className: "dim-listSection" },
|
|
6479
|
+
h9(
|
|
6480
|
+
"div",
|
|
6481
|
+
{ className: "ddt-listHeading dim-listHeading" },
|
|
6482
|
+
h9("h3", null, "\u5DF2\u63A5\u5165\u7684 WhatsApp \u673A\u5668\u4EBA")
|
|
6483
|
+
),
|
|
6484
|
+
h9("ul", { className: "ddt-list dim-botList" }, model.bots.map((account) => h9("li", { key: account.botId }, h9(WhatsappAccountCard, {
|
|
6485
|
+
account,
|
|
6486
|
+
busy: busyByBot[account.botId],
|
|
6487
|
+
removing: removeTarget === account.botId,
|
|
6488
|
+
onReconnect: () => void botAction(
|
|
6489
|
+
account,
|
|
6490
|
+
"reconnect",
|
|
6491
|
+
WHATSAPP_ENDPOINTS.reconnectBot,
|
|
6492
|
+
{ botId: account.botId }
|
|
6493
|
+
),
|
|
6494
|
+
onRequestRemove: () => setRemoveTarget(account.botId),
|
|
6495
|
+
onCancelRemove: () => setRemoveTarget(null),
|
|
6496
|
+
onConfirmRemove: async () => {
|
|
6497
|
+
await botAction(account, "delete", WHATSAPP_ENDPOINTS.deleteBot, {
|
|
6498
|
+
botId: account.botId,
|
|
6499
|
+
confirm: true
|
|
6500
|
+
});
|
|
6501
|
+
if (mounted.current) setRemoveTarget(null);
|
|
6502
|
+
}
|
|
6503
|
+
}))))
|
|
6504
|
+
) : null;
|
|
6505
|
+
return h9(
|
|
6506
|
+
"section",
|
|
6507
|
+
{
|
|
6508
|
+
className: "ddt-page dwa-page dim-channelPage",
|
|
6509
|
+
"aria-label": "WhatsApp \u8BBE\u7F6E"
|
|
6510
|
+
},
|
|
6511
|
+
h9(Heading6, {
|
|
6512
|
+
totals: model.totals,
|
|
6513
|
+
busy,
|
|
6514
|
+
onAdd: () => void startProvisioning(false),
|
|
6515
|
+
addButtonRef
|
|
6516
|
+
}),
|
|
6517
|
+
model.phase === "loading" ? h9(LoadingView6) : model.phase === "error" ? h9(
|
|
6518
|
+
"div",
|
|
6519
|
+
{ className: "ddt-card dim-surfaceCard" },
|
|
6520
|
+
h9(
|
|
6521
|
+
"div",
|
|
6522
|
+
{ className: "ddt-inlineError dim-inlineError" },
|
|
6523
|
+
h9("h3", null, "\u65E0\u6CD5\u8BFB\u53D6 WhatsApp \u673A\u5668\u4EBA\u72B6\u6001"),
|
|
6524
|
+
h9("p", null, model.error?.message),
|
|
6525
|
+
h9(Button13, { onClick: () => void loadStatus() }, "\u91CD\u65B0\u8BFB\u53D6")
|
|
6526
|
+
)
|
|
6527
|
+
) : h9(
|
|
6528
|
+
React10.Fragment,
|
|
6529
|
+
null,
|
|
6530
|
+
provision?.status === "pending" ? h9(QrPanel5, {
|
|
6531
|
+
provision,
|
|
6532
|
+
now,
|
|
6533
|
+
busy,
|
|
6534
|
+
onRefresh: () => void startProvisioning(true),
|
|
6535
|
+
onCancel: () => void closeProvision()
|
|
6536
|
+
}) : provision ? h9(ProvisionView3, {
|
|
6537
|
+
provision,
|
|
6538
|
+
busy,
|
|
6539
|
+
onRetry: () => void startProvisioning(true),
|
|
6540
|
+
onClose: () => void closeProvision()
|
|
6541
|
+
}) : model.bots.length === 0 ? h9(EmptyView6, { busy, onStart: () => void startProvisioning(false) }) : null,
|
|
6542
|
+
botList
|
|
6543
|
+
)
|
|
6544
|
+
);
|
|
6545
|
+
}
|
|
6546
|
+
|
|
5858
6547
|
// plugin-src/client/styles.js
|
|
5859
6548
|
var IM_STYLE_ID = "xmanrui-dsh-im-settings";
|
|
5860
|
-
var
|
|
6549
|
+
var CSS9 = String.raw`
|
|
5861
6550
|
.dim-page {
|
|
5862
6551
|
--dim-blue: #3370ff;
|
|
5863
6552
|
--dim-blue-soft: color-mix(in srgb, var(--dim-blue) 9%, transparent);
|
|
@@ -5894,11 +6583,13 @@ var CSS8 = String.raw`
|
|
|
5894
6583
|
.dim-logoTelegram svg { width: 21px; height: 21px; }
|
|
5895
6584
|
.dim-logoDiscord { color: white; background: #5865f2; }
|
|
5896
6585
|
.dim-logoDiscord svg { width: 21px; height: 21px; }
|
|
6586
|
+
.dim-logoWhatsapp { color: white; background: #25d366; }
|
|
6587
|
+
.dim-logoWhatsapp svg { width: 21px; height: 21px; }
|
|
5897
6588
|
.dim-channelCopy { min-width: 0; display: block; }
|
|
5898
6589
|
.dim-channelCopy strong { overflow: hidden; color: inherit; font-size: 14px; line-height: 20px; font-weight: 680; text-overflow: ellipsis; white-space: nowrap; }
|
|
5899
6590
|
.dim-divider { width: 1px; min-height: 520px; background: var(--dsw-alias-line-divider, #eef0f3); }
|
|
5900
6591
|
.dim-panel { min-width: 0; container-type: inline-size; }
|
|
5901
|
-
.dim-panel .bxf-page, .dim-panel .dxw-page, .dim-panel .ddt-page, .dim-panel .dqq-page, .dim-panel .dwecom-page { width: 100%; max-width: none; padding: 0 0 24px; }
|
|
6592
|
+
.dim-panel .bxf-page, .dim-panel .dxw-page, .dim-panel .ddt-page, .dim-panel .dqq-page, .dim-panel .dwecom-page, .dim-panel .dwa-page { width: 100%; max-width: none; padding: 0 0 24px; }
|
|
5902
6593
|
.dim-panel .bxf-heading, .dim-panel .dxw-heading, .dim-panel .ddt-heading { justify-content: flex-end; }
|
|
5903
6594
|
.dim-panel .bxf-headingTools, .dim-panel .dxw-tools, .dim-panel .ddt-tools { width: 100%; justify-content: space-between; }
|
|
5904
6595
|
.dim-panel .dim-bindActions { min-width: 0; display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; }
|
|
@@ -6044,13 +6735,13 @@ function installImStyles() {
|
|
|
6044
6735
|
const style = document.createElement("style");
|
|
6045
6736
|
style.dataset.plugin = "@xmanrui/dsh-im";
|
|
6046
6737
|
style.dataset.pluginCss = IM_STYLE_ID;
|
|
6047
|
-
style.textContent =
|
|
6738
|
+
style.textContent = CSS9;
|
|
6048
6739
|
document.head.appendChild(style);
|
|
6049
6740
|
return () => style.remove();
|
|
6050
6741
|
}
|
|
6051
6742
|
|
|
6052
6743
|
// plugin-src/client/index.js
|
|
6053
|
-
var
|
|
6744
|
+
var h10 = React11.createElement;
|
|
6054
6745
|
var name = "im-settings";
|
|
6055
6746
|
var inject = ["slots", "connection"];
|
|
6056
6747
|
var CHANNELS = Object.freeze([
|
|
@@ -6060,57 +6751,66 @@ var CHANNELS = Object.freeze([
|
|
|
6060
6751
|
{ id: "wecom", label: "\u4F01\u4E1A\u5FAE\u4FE1" },
|
|
6061
6752
|
{ id: "qq", label: "QQ" },
|
|
6062
6753
|
{ id: "telegram", label: "Telegram" },
|
|
6063
|
-
{ id: "discord", label: "Discord" }
|
|
6754
|
+
{ id: "discord", label: "Discord" },
|
|
6755
|
+
{ id: "whatsapp", label: "WhatsApp" }
|
|
6064
6756
|
]);
|
|
6065
6757
|
function WeixinLogo() {
|
|
6066
|
-
return
|
|
6758
|
+
return h10(
|
|
6067
6759
|
"span",
|
|
6068
6760
|
{ className: "dim-logo dim-logoWeixin", "aria-hidden": "true" },
|
|
6069
|
-
|
|
6761
|
+
h10(WeixinLogoGlyph)
|
|
6070
6762
|
);
|
|
6071
6763
|
}
|
|
6072
6764
|
function FeishuLogo() {
|
|
6073
|
-
return
|
|
6765
|
+
return h10(
|
|
6074
6766
|
"span",
|
|
6075
6767
|
{ className: "dim-logo dim-logoFeishu", "aria-hidden": "true" },
|
|
6076
|
-
|
|
6768
|
+
h10(FeishuLogoGlyph)
|
|
6077
6769
|
);
|
|
6078
6770
|
}
|
|
6079
6771
|
function DingtalkLogo() {
|
|
6080
|
-
return
|
|
6772
|
+
return h10(
|
|
6081
6773
|
"span",
|
|
6082
6774
|
{ className: "dim-logo dim-logoDingtalk", "aria-hidden": "true" },
|
|
6083
|
-
|
|
6775
|
+
h10(DingtalkLogoGlyph)
|
|
6084
6776
|
);
|
|
6085
6777
|
}
|
|
6086
6778
|
function QqLogo() {
|
|
6087
|
-
return
|
|
6779
|
+
return h10("span", { className: "dim-logo dim-logoQq", "aria-hidden": "true" }, h10(QqLogoGlyph));
|
|
6088
6780
|
}
|
|
6089
6781
|
function WecomLogo() {
|
|
6090
|
-
return
|
|
6782
|
+
return h10("span", { className: "dim-logo dim-logoWecom", "aria-hidden": "true" }, h10(WecomLogoGlyph));
|
|
6091
6783
|
}
|
|
6092
6784
|
function TelegramLogo() {
|
|
6093
|
-
return
|
|
6785
|
+
return h10(
|
|
6094
6786
|
"span",
|
|
6095
6787
|
{ className: "dim-logo dim-logoTelegram", "aria-hidden": "true" },
|
|
6096
|
-
|
|
6788
|
+
h10(TelegramLogoGlyph)
|
|
6097
6789
|
);
|
|
6098
6790
|
}
|
|
6099
6791
|
function DiscordLogo() {
|
|
6100
|
-
return
|
|
6792
|
+
return h10(
|
|
6101
6793
|
"span",
|
|
6102
6794
|
{ className: "dim-logo dim-logoDiscord", "aria-hidden": "true" },
|
|
6103
|
-
|
|
6795
|
+
h10(DiscordLogoGlyph)
|
|
6796
|
+
);
|
|
6797
|
+
}
|
|
6798
|
+
function WhatsappLogo() {
|
|
6799
|
+
return h10(
|
|
6800
|
+
"span",
|
|
6801
|
+
{ className: "dim-logo dim-logoWhatsapp", "aria-hidden": "true" },
|
|
6802
|
+
h10(WhatsappLogoGlyph)
|
|
6104
6803
|
);
|
|
6105
6804
|
}
|
|
6106
6805
|
function ChannelLogo({ channel: channel3 }) {
|
|
6107
|
-
if (channel3 === "weixin") return
|
|
6108
|
-
if (channel3 === "feishu") return
|
|
6109
|
-
if (channel3 === "dingtalk") return
|
|
6110
|
-
if (channel3 === "wecom") return
|
|
6111
|
-
if (channel3 === "qq") return
|
|
6112
|
-
if (channel3 === "telegram") return
|
|
6113
|
-
return
|
|
6806
|
+
if (channel3 === "weixin") return h10(WeixinLogo);
|
|
6807
|
+
if (channel3 === "feishu") return h10(FeishuLogo);
|
|
6808
|
+
if (channel3 === "dingtalk") return h10(DingtalkLogo);
|
|
6809
|
+
if (channel3 === "wecom") return h10(WecomLogo);
|
|
6810
|
+
if (channel3 === "qq") return h10(QqLogo);
|
|
6811
|
+
if (channel3 === "telegram") return h10(TelegramLogo);
|
|
6812
|
+
if (channel3 === "discord") return h10(DiscordLogo);
|
|
6813
|
+
return h10(WhatsappLogo);
|
|
6114
6814
|
}
|
|
6115
6815
|
function IMSettingsTab({
|
|
6116
6816
|
dingtalkRpcCall,
|
|
@@ -6119,25 +6819,26 @@ function IMSettingsTab({
|
|
|
6119
6819
|
qqRpcCall,
|
|
6120
6820
|
telegramRpcCall,
|
|
6121
6821
|
wecomRpcCall,
|
|
6122
|
-
weixinRpcCall
|
|
6822
|
+
weixinRpcCall,
|
|
6823
|
+
whatsappRpcCall
|
|
6123
6824
|
}) {
|
|
6124
|
-
const [selected, setSelected] =
|
|
6825
|
+
const [selected, setSelected] = React11.useState("weixin");
|
|
6125
6826
|
const active = CHANNELS.find((channel3) => channel3.id === selected) ?? CHANNELS[0];
|
|
6126
|
-
return
|
|
6827
|
+
return h10(
|
|
6127
6828
|
"section",
|
|
6128
6829
|
{ className: "dim-page", "aria-label": "IM\u673A\u5668\u4EBA\u8BBE\u7F6E" },
|
|
6129
|
-
|
|
6830
|
+
h10(
|
|
6130
6831
|
"header",
|
|
6131
6832
|
{ className: "dim-title" },
|
|
6132
|
-
|
|
6833
|
+
h10("p", null, "\u628A\u673A\u5668\u4EBA\u63A5\u5165 DeepSeek Harness")
|
|
6133
6834
|
),
|
|
6134
|
-
|
|
6835
|
+
h10(
|
|
6135
6836
|
"div",
|
|
6136
6837
|
{ className: "dim-layout" },
|
|
6137
|
-
|
|
6838
|
+
h10(
|
|
6138
6839
|
"nav",
|
|
6139
6840
|
{ className: "dim-rail", role: "tablist", "aria-label": "IM \u6E20\u9053" },
|
|
6140
|
-
CHANNELS.map((channel3) =>
|
|
6841
|
+
CHANNELS.map((channel3) => h10(
|
|
6141
6842
|
"button",
|
|
6142
6843
|
{
|
|
6143
6844
|
key: channel3.id,
|
|
@@ -6149,21 +6850,21 @@ function IMSettingsTab({
|
|
|
6149
6850
|
"aria-controls": `dim-panel-${channel3.id}`,
|
|
6150
6851
|
onClick: () => setSelected(channel3.id)
|
|
6151
6852
|
},
|
|
6152
|
-
|
|
6153
|
-
|
|
6853
|
+
h10(ChannelLogo, { channel: channel3.id }),
|
|
6854
|
+
h10(
|
|
6154
6855
|
"span",
|
|
6155
6856
|
{ className: "dim-channelCopy" },
|
|
6156
|
-
|
|
6857
|
+
h10("strong", null, channel3.label)
|
|
6157
6858
|
)
|
|
6158
6859
|
))
|
|
6159
6860
|
),
|
|
6160
|
-
|
|
6161
|
-
|
|
6861
|
+
h10("div", { className: "dim-divider", "aria-hidden": "true" }),
|
|
6862
|
+
h10("main", {
|
|
6162
6863
|
className: "dim-panel",
|
|
6163
6864
|
role: "tabpanel",
|
|
6164
6865
|
id: `dim-panel-${active.id}`,
|
|
6165
6866
|
"aria-labelledby": `dim-tab-${active.id}`
|
|
6166
|
-
}, active.id === "weixin" ?
|
|
6867
|
+
}, active.id === "weixin" ? h10(WeixinSettingsTab, { rpcCall: weixinRpcCall }) : active.id === "feishu" ? h10(FeishuSettingsTab, { rpcCall: feishuRpcCall }) : active.id === "dingtalk" ? h10(DingtalkSettingsTab, { rpcCall: dingtalkRpcCall }) : active.id === "wecom" ? h10(WecomSettingsTab, { rpcCall: wecomRpcCall }) : active.id === "qq" ? h10(QqSettingsTab, { rpcCall: qqRpcCall }) : active.id === "telegram" ? h10(TelegramSettingsTab, { rpcCall: telegramRpcCall }) : active.id === "discord" ? h10(DiscordSettingsTab, { rpcCall: discordRpcCall }) : h10(WhatsappSettingsTab, { rpcCall: whatsappRpcCall }))
|
|
6167
6868
|
)
|
|
6168
6869
|
);
|
|
6169
6870
|
}
|
|
@@ -6176,6 +6877,7 @@ function apply(ctx) {
|
|
|
6176
6877
|
installQqStyles(),
|
|
6177
6878
|
installTelegramStyles(),
|
|
6178
6879
|
installDiscordStyles(),
|
|
6880
|
+
installWhatsappStyles(),
|
|
6179
6881
|
installImStyles()
|
|
6180
6882
|
];
|
|
6181
6883
|
return () => {
|
|
@@ -6189,6 +6891,7 @@ function apply(ctx) {
|
|
|
6189
6891
|
const wecomRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WECOM_RPC_CHANNEL, endpoint, payload, signal);
|
|
6190
6892
|
const telegramRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(TELEGRAM_RPC_CHANNEL, endpoint, payload, signal);
|
|
6191
6893
|
const discordRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(DISCORD_RPC_CHANNEL, endpoint, payload, signal);
|
|
6894
|
+
const whatsappRpcCall = (endpoint, payload, signal) => ctx.connection.rpc.call(WHATSAPP_RPC_CHANNEL, endpoint, payload, signal);
|
|
6192
6895
|
ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({
|
|
6193
6896
|
name: "settings.plugins.tab",
|
|
6194
6897
|
id: "im",
|
|
@@ -6201,7 +6904,8 @@ function apply(ctx) {
|
|
|
6201
6904
|
qqRpcCall,
|
|
6202
6905
|
telegramRpcCall,
|
|
6203
6906
|
wecomRpcCall,
|
|
6204
|
-
weixinRpcCall
|
|
6907
|
+
weixinRpcCall,
|
|
6908
|
+
whatsappRpcCall
|
|
6205
6909
|
})
|
|
6206
6910
|
}, IMSettingsTab));
|
|
6207
6911
|
}
|