@lynn123411/dsh-a6api 1.0.1 → 1.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 +4 -2
- package/lib/client.js +547 -72
- package/lib/client.js.map +3 -3
- package/lib/index.js +100 -6
- package/lib/index.js.map +2 -2
- package/lib/types/client/store.d.ts +6 -1
- package/lib/types/server/a6api-client.d.ts +8 -0
- package/lib/types/server/probe.d.ts +2 -2
- package/lib/types/types.d.ts +12 -0
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -892,6 +892,66 @@ async function fetchChannelDetails(channelId, userId, sessionCookie, targetModel
|
|
|
892
892
|
}
|
|
893
893
|
return null;
|
|
894
894
|
}
|
|
895
|
+
async function fetchPriceFluctuation(userId, sessionCookie, accessToken) {
|
|
896
|
+
const token = (accessToken || sessionCookie || "").trim();
|
|
897
|
+
const uid = (userId || "").trim();
|
|
898
|
+
if (!uid && !token) {
|
|
899
|
+
return { pendingCount: 0, unseenCount: 0, totalCount: 0, authError: false };
|
|
900
|
+
}
|
|
901
|
+
const headers = buildWebHeaders(uid || void 0, token || void 0);
|
|
902
|
+
const url = "https://a6api.com/api/marketplace/price-notices";
|
|
903
|
+
try {
|
|
904
|
+
const res = await fetch(url, { headers, signal: AbortSignal.timeout(8e3) });
|
|
905
|
+
if (res.status === 401 || res.status === 403) {
|
|
906
|
+
console.warn("[dsh-a6api] fetchPriceFluctuation auth failed", res.status);
|
|
907
|
+
return { pendingCount: 0, unseenCount: 0, totalCount: 0, authError: true };
|
|
908
|
+
}
|
|
909
|
+
if (!res.ok) {
|
|
910
|
+
console.warn("[dsh-a6api] fetchPriceFluctuation HTTP", res.status);
|
|
911
|
+
return { pendingCount: 0, unseenCount: 0, totalCount: 0 };
|
|
912
|
+
}
|
|
913
|
+
const json = await res.json().catch(() => null);
|
|
914
|
+
if (!json) return { pendingCount: 0, unseenCount: 0, totalCount: 0 };
|
|
915
|
+
if (json.success === false) return { pendingCount: 0, unseenCount: 0, totalCount: 0 };
|
|
916
|
+
let arr = [];
|
|
917
|
+
if (Array.isArray(json)) arr = json;
|
|
918
|
+
else if (Array.isArray(json.data)) arr = json.data;
|
|
919
|
+
else if (Array.isArray(json.data?.notices)) arr = json.data.notices;
|
|
920
|
+
else if (Array.isArray(json.data?.items)) arr = json.data.items;
|
|
921
|
+
else if (Array.isArray(json.notices)) arr = json.notices;
|
|
922
|
+
else if (Array.isArray(json.items)) arr = json.items;
|
|
923
|
+
const pickWithPresent = (keys) => {
|
|
924
|
+
for (const k of keys) {
|
|
925
|
+
const v = json?.data?.[k] ?? json?.[k];
|
|
926
|
+
if (v !== void 0 && v !== null) {
|
|
927
|
+
const n = Number(v);
|
|
928
|
+
if (!Number.isNaN(n)) return { value: n, present: true };
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return { value: 0, present: false };
|
|
932
|
+
};
|
|
933
|
+
const pendingPick = pickWithPresent(["pendingCount", "pending_count", "pending", "openCount"]);
|
|
934
|
+
const unseenPick = pickWithPresent(["unseenCount", "unseen_count", "unseen", "has_unseen_count"]);
|
|
935
|
+
let pending = pendingPick.value;
|
|
936
|
+
let unseen = unseenPick.value;
|
|
937
|
+
const total = arr.length;
|
|
938
|
+
if (!pendingPick.present && arr.length > 0) {
|
|
939
|
+
const counted = arr.filter((n) => {
|
|
940
|
+
const s = String(n.state || n.status || "").toLowerCase();
|
|
941
|
+
return s === "open" || s === "pending" || n.pending === true;
|
|
942
|
+
}).length;
|
|
943
|
+
const hasState = arr.some((n) => n.state !== void 0 || n.status !== void 0);
|
|
944
|
+
if (hasState) pending = counted;
|
|
945
|
+
}
|
|
946
|
+
if (!unseenPick.present && arr.length > 0) {
|
|
947
|
+
unseen = arr.filter((n) => n.has_unseen === true || n.hasUnseen === true || n.unseen === true || n.is_unread === true).length;
|
|
948
|
+
}
|
|
949
|
+
return { pendingCount: pending, unseenCount: unseen, totalCount: total, notices: arr };
|
|
950
|
+
} catch (err) {
|
|
951
|
+
console.warn("[dsh-a6api] fetchPriceFluctuation error", err);
|
|
952
|
+
return { pendingCount: 0, unseenCount: 0, totalCount: 0 };
|
|
953
|
+
}
|
|
954
|
+
}
|
|
895
955
|
|
|
896
956
|
// src/server/probe.ts
|
|
897
957
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -972,13 +1032,14 @@ async function probeSingleModel(baseURL, apiKey, userId, accessToken, modelName)
|
|
|
972
1032
|
error: requestOk ? void 0 : requestError
|
|
973
1033
|
};
|
|
974
1034
|
}
|
|
975
|
-
async function getKnownMerchantsFromLogs(userId, accessToken, modelNames = []) {
|
|
1035
|
+
async function getKnownMerchantsFromLogs(userId, accessToken, modelNames = [], logs) {
|
|
976
1036
|
if (!userId && !accessToken || modelNames.length === 0) return {};
|
|
977
1037
|
const result = {};
|
|
978
1038
|
try {
|
|
979
|
-
const
|
|
1039
|
+
const items = logs !== void 0 ? logs : await fetchRecentLogs(userId, accessToken, 50);
|
|
1040
|
+
const sorted = items.slice().sort((a, b) => (Number(b.created_at) || 0) - (Number(a.created_at) || 0));
|
|
980
1041
|
const modelToLog = /* @__PURE__ */ new Map();
|
|
981
|
-
for (const log of
|
|
1042
|
+
for (const log of sorted) {
|
|
982
1043
|
const mName = log.model_name;
|
|
983
1044
|
const chId = Number(log.channel);
|
|
984
1045
|
if (mName && chId && !modelToLog.has(mName.toLowerCase())) {
|
|
@@ -1377,23 +1438,43 @@ function apply(ctx) {
|
|
|
1377
1438
|
])
|
|
1378
1439
|
];
|
|
1379
1440
|
}
|
|
1441
|
+
const allLogs = await fetchRecentLogs(config.userId, token, 100);
|
|
1442
|
+
allLogs.sort((a, b) => (Number(b.created_at) || 0) - (Number(a.created_at) || 0));
|
|
1380
1443
|
if (config.userId || token) {
|
|
1381
1444
|
const missing = modelIds.filter((m) => {
|
|
1382
1445
|
const entry = merchantCardCache.get(m.toLowerCase());
|
|
1383
1446
|
return !entry || Date.now() - entry.at >= MERCHANT_CARD_TTL_MS;
|
|
1384
1447
|
});
|
|
1385
1448
|
if (missing.length > 0) {
|
|
1386
|
-
|
|
1449
|
+
let found = {};
|
|
1450
|
+
try {
|
|
1451
|
+
found = await Promise.race([
|
|
1452
|
+
getKnownMerchantsFromLogs(config.userId, token, missing, allLogs),
|
|
1453
|
+
new Promise((resolve) => setTimeout(() => resolve({}), 1e4))
|
|
1454
|
+
]);
|
|
1455
|
+
} catch {
|
|
1456
|
+
found = {};
|
|
1457
|
+
}
|
|
1387
1458
|
for (const [mName, card] of Object.entries(found)) {
|
|
1388
1459
|
merchantCardCache.set(mName.toLowerCase(), { card, at: Date.now() });
|
|
1389
1460
|
}
|
|
1390
1461
|
}
|
|
1391
1462
|
}
|
|
1463
|
+
const lastRoutedMap = /* @__PURE__ */ new Map();
|
|
1464
|
+
for (const log of allLogs) {
|
|
1465
|
+
const mName = log.model_name;
|
|
1466
|
+
const chId = Number(log.channel);
|
|
1467
|
+
const ts = Number(log.created_at) || 0;
|
|
1468
|
+
if (mName && chId > 0 && ts > 0 && !lastRoutedMap.has(mName.toLowerCase())) {
|
|
1469
|
+
lastRoutedMap.set(mName.toLowerCase(), ts);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1392
1472
|
const dshSet = new Set(dshConfiguredModels);
|
|
1393
1473
|
const models = modelIds.map((mId) => {
|
|
1394
1474
|
const meta = resolveModelMeta(mId);
|
|
1395
1475
|
const cacheEntry = merchantCardCache.get(mId.toLowerCase());
|
|
1396
1476
|
const cachedCard = cacheEntry && Date.now() - cacheEntry.at < MERCHANT_CARD_TTL_MS ? cacheEntry.card : void 0;
|
|
1477
|
+
const routedAt = lastRoutedMap.get(mId.toLowerCase());
|
|
1397
1478
|
return {
|
|
1398
1479
|
model_name: mId,
|
|
1399
1480
|
brand: meta.brand,
|
|
@@ -1403,10 +1484,12 @@ function apply(ctx) {
|
|
|
1403
1484
|
hasReasoning: Boolean(meta.reasoningEfforts || meta.thinkingFormat),
|
|
1404
1485
|
inDsh: dshSet.has(mId),
|
|
1405
1486
|
merchant: cachedCard,
|
|
1406
|
-
probeStatus: cachedCard ? "success" : "idle"
|
|
1487
|
+
probeStatus: cachedCard ? "success" : "idle",
|
|
1488
|
+
lastRoutedAt: routedAt,
|
|
1489
|
+
lastRoutedText: routedAt ? formatRelativeTime(routedAt) : void 0
|
|
1407
1490
|
};
|
|
1408
1491
|
});
|
|
1409
|
-
const recentLogs =
|
|
1492
|
+
const recentLogs = allLogs.slice(0, 20);
|
|
1410
1493
|
const response = {
|
|
1411
1494
|
config: maskConfig(config),
|
|
1412
1495
|
balance,
|
|
@@ -1494,6 +1577,17 @@ function apply(ctx) {
|
|
|
1494
1577
|
const dshConfiguredModels = await getDshConfiguredModels();
|
|
1495
1578
|
return sendJson(res, 200, { ok: true, dshConfiguredModels });
|
|
1496
1579
|
}
|
|
1580
|
+
if (pathname === "/price-fluctuation" && (req.method === "GET" || req.method === "HEAD")) {
|
|
1581
|
+
const config = await readPluginConfig();
|
|
1582
|
+
const token = config.accessToken || config.sessionCookie || "";
|
|
1583
|
+
if (!token || !config.userId) {
|
|
1584
|
+
return sendJson(res, 200, { ok: true, data: { pendingCount: 0, unseenCount: 0, totalCount: 0, hasAuth: false, authError: false, updatedAt: Date.now() } });
|
|
1585
|
+
}
|
|
1586
|
+
const result = await fetchPriceFluctuation(config.userId, token, token);
|
|
1587
|
+
const { notices, ...counts } = result;
|
|
1588
|
+
const hasAuth = !counts.authError;
|
|
1589
|
+
return sendJson(res, 200, { ok: true, data: { pendingCount: counts.pendingCount, unseenCount: counts.unseenCount, totalCount: counts.totalCount, hasAuth, authError: Boolean(counts.authError), updatedAt: Date.now() } });
|
|
1590
|
+
}
|
|
1497
1591
|
return sendJson(res, 404, { ok: false, error: "Not found" });
|
|
1498
1592
|
} catch (err) {
|
|
1499
1593
|
console.error("[dsh-a6api] API error:", err);
|