@skrillex1224/android-toolkit 1.0.7 → 1.0.9
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/dist/browser.js +1 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +55 -18
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +55 -18
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -25,7 +25,7 @@ var Code = Object.freeze({
|
|
|
25
25
|
ContentUnavailable: 30010003,
|
|
26
26
|
SourceExtractionFailed: 30010004,
|
|
27
27
|
AutomationFailed: 30010005,
|
|
28
|
-
|
|
28
|
+
AppRuntimeUnavailable: 30010008,
|
|
29
29
|
AppNotInstalled: 30010009
|
|
30
30
|
});
|
|
31
31
|
var Status = Object.freeze({
|
package/dist/browser.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/constants.js", "../src/errors.js", "../entrys/browser.js"],
|
|
4
|
-
"sourcesContent": ["export const Code = Object.freeze({\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n InvalidRequest: 30010001,\n AdbUnavailable: 30010002,\n ContentUnavailable: 30010003,\n SourceExtractionFailed: 30010004,\n AutomationFailed: 30010005,\n
|
|
4
|
+
"sourcesContent": ["export const Code = Object.freeze({\n Success: 0,\n UnknownError: -1,\n NotLogin: 30000001,\n Timeout: 30000003,\n InitialTimeout: 30000004,\n OverallTimeout: 30000005,\n InvalidRequest: 30010001,\n AdbUnavailable: 30010002,\n ContentUnavailable: 30010003,\n SourceExtractionFailed: 30010004,\n AutomationFailed: 30010005,\n AppRuntimeUnavailable: 30010008,\n AppNotInstalled: 30010009,\n});\n\nexport const Status = Object.freeze({\n Success: 'SUCCESS',\n Failed: 'FAILED',\n});\n\nexport const UnicodeIme = Object.freeze({\n packageName: 'io.appium.settings',\n component: 'io.appium.settings/.UnicodeIME',\n inputAction: 'ADB_INPUT_TEXT',\n});\n\nexport const AppiumSettings = Object.freeze({\n packageName: 'io.appium.settings',\n clipboardReceiver: 'io.appium.settings/.receivers.ClipboardReceiver',\n clipboardGetAction: 'io.appium.settings.clipboard.get',\n});\n\nconst normalizeShare = (share) => {\n const source = share && typeof share === 'object' ? share : {};\n return {\n mode: 'clipboard',\n prefix: String(source.prefix || '').trim(),\n xurl: Array.isArray(source.xurl) ? source.xurl : [],\n };\n};\n\nconst createActorInfo = (info) => {\n const key = String(info.key || '').trim();\n return Object.freeze({\n key,\n name: String(info.name || key),\n icon: String(info.icon || `https://static.heartbitai.com/general/actors/${key}.png`),\n share: Object.freeze(normalizeShare(info.share)),\n });\n};\n\nexport const ActorInfo = Object.freeze({\n 'doubao.android': createActorInfo({\n key: 'doubao.android',\n name: '\u8C46\u5305 Android',\n share: {\n prefix: 'https://www.doubao.com/thread/',\n xurl: [],\n },\n }),\n});\n", "import { Code } from './constants.js';\n\nexport class CrawlerError extends Error {\n constructor(input = {}, options = {}) {\n const payload = typeof input === 'string' ? { message: input } : input;\n super(payload.message || 'Android crawler error', options);\n this.name = 'CrawlerError';\n this.code = payload.code || Code.UnknownError;\n this.context = payload.context || {};\n }\n\n static isCrawlerError(error) {\n return error instanceof CrawlerError || error?.name === 'CrawlerError';\n }\n\n static from(error, fallback = {}) {\n if (CrawlerError.isCrawlerError(error)) return error;\n return new CrawlerError({\n message: error?.message || String(error),\n code: fallback.code || Code.UnknownError,\n context: fallback.context || {},\n });\n }\n}\n\nexport function serializeError(error) {\n if (!error) return { message: '' };\n return {\n name: error.name || 'Error',\n message: error.message || String(error),\n stack: error.stack || '',\n code: error.code || '',\n context: error.context || undefined,\n };\n}\n", "import * as Constants from '../src/constants.js';\nimport * as Errors from '../src/errors.js';\n\nconst ToolkitMode = Object.freeze({\n default: 'default',\n});\n\nexport const useAndroidToolKit = () => {\n return {\n Constants,\n Errors,\n };\n};\n\nuseAndroidToolKit.Mode = ToolkitMode;\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -57,7 +57,7 @@ var Code = Object.freeze({
|
|
|
57
57
|
ContentUnavailable: 30010003,
|
|
58
58
|
SourceExtractionFailed: 30010004,
|
|
59
59
|
AutomationFailed: 30010005,
|
|
60
|
-
|
|
60
|
+
AppRuntimeUnavailable: 30010008,
|
|
61
61
|
AppNotInstalled: 30010009
|
|
62
62
|
});
|
|
63
63
|
var Status = Object.freeze({
|
|
@@ -1037,7 +1037,10 @@ async function pressEnter2(ctx) {
|
|
|
1037
1037
|
}
|
|
1038
1038
|
async function scroll(ctx, selector, direction, options = {}) {
|
|
1039
1039
|
const node = await DeviceView.find(ctx, selector, options);
|
|
1040
|
-
|
|
1040
|
+
await scrollBounds(ctx, node.bounds, direction, options);
|
|
1041
|
+
}
|
|
1042
|
+
async function scrollBounds(ctx, bounds2, direction, options = {}) {
|
|
1043
|
+
const box = bounds2;
|
|
1041
1044
|
const ratio = Number(options.swipeRatio || 0.72);
|
|
1042
1045
|
const durationMs = Number(options.durationMs || 360);
|
|
1043
1046
|
const x = box.centerX;
|
|
@@ -1064,6 +1067,9 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
|
|
|
1064
1067
|
const maxSwipes = Math.max(1, Number(options.maxSwipes || 20));
|
|
1065
1068
|
const stableRoundsTarget = Math.max(1, Number(options.stableRounds || 2));
|
|
1066
1069
|
const hashSource = String(options.stability || options.hashSource || "view");
|
|
1070
|
+
if (hashSource === "screenshot") {
|
|
1071
|
+
return scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource);
|
|
1072
|
+
}
|
|
1067
1073
|
let lastHash = "";
|
|
1068
1074
|
let stableRounds = 0;
|
|
1069
1075
|
for (let index = 0; index < maxSwipes; index += 1) {
|
|
@@ -1071,7 +1077,7 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
|
|
|
1071
1077
|
if (currentHash === lastHash) {
|
|
1072
1078
|
stableRounds += 1;
|
|
1073
1079
|
if (stableRounds >= stableRoundsTarget) {
|
|
1074
|
-
return { swipes: index, stableRounds, hash: currentHash, hashSource };
|
|
1080
|
+
return { swipes: index, stableRounds, hash: currentHash, hashSource, capped: false };
|
|
1075
1081
|
}
|
|
1076
1082
|
} else {
|
|
1077
1083
|
stableRounds = 0;
|
|
@@ -1079,7 +1085,27 @@ async function scrollUntilStable(ctx, selector, direction, options = {}) {
|
|
|
1079
1085
|
}
|
|
1080
1086
|
await scroll(ctx, selector, direction, options);
|
|
1081
1087
|
}
|
|
1082
|
-
return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource };
|
|
1088
|
+
return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
|
|
1089
|
+
}
|
|
1090
|
+
async function scrollUntilScreenshotStable(ctx, selector, direction, options, maxSwipes, stableRoundsTarget, hashSource) {
|
|
1091
|
+
const node = await DeviceView.find(ctx, selector, options);
|
|
1092
|
+
const bounds2 = node.bounds;
|
|
1093
|
+
let lastHash = await scrollStateHash(ctx, selector, options, hashSource);
|
|
1094
|
+
let stableRounds = 0;
|
|
1095
|
+
for (let index = 0; index < maxSwipes; index += 1) {
|
|
1096
|
+
await scrollBounds(ctx, bounds2, direction, options);
|
|
1097
|
+
const currentHash = await scrollStateHash(ctx, selector, options, hashSource);
|
|
1098
|
+
if (currentHash === lastHash) {
|
|
1099
|
+
stableRounds += 1;
|
|
1100
|
+
if (stableRounds >= stableRoundsTarget) {
|
|
1101
|
+
return { swipes: index + 1, stableRounds, hash: currentHash, hashSource, capped: false };
|
|
1102
|
+
}
|
|
1103
|
+
} else {
|
|
1104
|
+
stableRounds = 0;
|
|
1105
|
+
lastHash = currentHash;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
return { swipes: maxSwipes, stableRounds, hash: lastHash, hashSource, capped: true };
|
|
1083
1109
|
}
|
|
1084
1110
|
async function scrollStateHash(ctx, selector, options, hashSource) {
|
|
1085
1111
|
if (hashSource === "screenshot") {
|
|
@@ -1164,8 +1190,8 @@ async function query(ctx, options = {}) {
|
|
|
1164
1190
|
const dbPaths = await resolveDeviceDbPaths(ctx, config);
|
|
1165
1191
|
if (dbPaths.length === 0) {
|
|
1166
1192
|
throw new CrawlerError({
|
|
1167
|
-
message: "
|
|
1168
|
-
code: Code.
|
|
1193
|
+
message: "app_runtime_unavailable: sqlite database not found",
|
|
1194
|
+
code: Code.AppRuntimeUnavailable,
|
|
1169
1195
|
context: { dbDir: config.dbDir, dbPath: config.dbPath, dbNamePrefix: config.dbNamePrefix }
|
|
1170
1196
|
});
|
|
1171
1197
|
}
|
|
@@ -1214,8 +1240,8 @@ async function resolveDeviceDbPaths(ctx, config) {
|
|
|
1214
1240
|
maxBuffer: 2 * 1024 * 1024
|
|
1215
1241
|
}).catch((error) => {
|
|
1216
1242
|
throw new CrawlerError({
|
|
1217
|
-
message: `
|
|
1218
|
-
code: Code.
|
|
1243
|
+
message: `app_runtime_unavailable: sqlite dbDir unavailable ${error?.message || String(error)}`,
|
|
1244
|
+
code: Code.AppRuntimeUnavailable,
|
|
1219
1245
|
context: { dbDir: config.dbDir }
|
|
1220
1246
|
});
|
|
1221
1247
|
});
|
|
@@ -1240,8 +1266,8 @@ async function pullDatabaseSnapshot(ctx, dbPath, localDir) {
|
|
|
1240
1266
|
await adbSuShell(ctx, copyCommand, { timeoutMs: 3e4, maxBuffer: 4 * 1024 * 1024 });
|
|
1241
1267
|
await adbPull(adbPath, serial, remoteDb, localDb).catch((error) => {
|
|
1242
1268
|
throw new CrawlerError({
|
|
1243
|
-
message: `
|
|
1244
|
-
code: Code.
|
|
1269
|
+
message: `app_runtime_unavailable: sqlite snapshot pull failed ${error?.message || String(error)}`,
|
|
1270
|
+
code: Code.AppRuntimeUnavailable,
|
|
1245
1271
|
context: { dbPath }
|
|
1246
1272
|
});
|
|
1247
1273
|
});
|
|
@@ -1700,17 +1726,28 @@ async function captureScreen(ctx, options = {}) {
|
|
|
1700
1726
|
const frameBuffers = [];
|
|
1701
1727
|
const seen = /* @__PURE__ */ new Set();
|
|
1702
1728
|
const targetSelector = options.selector || { id: "message_list" };
|
|
1703
|
-
|
|
1729
|
+
const shouldHideKeyboard = options.hideKeyboard !== false;
|
|
1730
|
+
if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 2, settleMs: 350 }).catch(() => {
|
|
1704
1731
|
});
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1732
|
+
try {
|
|
1733
|
+
const topResult = await DeviceInput.scrollToTop(ctx, targetSelector, {
|
|
1734
|
+
maxSwipes: Number(options.scrollToTopMaxSwipes || 12),
|
|
1735
|
+
stableRounds: Number(options.scrollToTopStableRounds || 2),
|
|
1736
|
+
settleMs: 400,
|
|
1737
|
+
stability: options.scrollStability || options.stability || "view"
|
|
1738
|
+
});
|
|
1739
|
+
Logger.info("captureScreen scrollToTop", {
|
|
1740
|
+
swipes: topResult?.swipes,
|
|
1741
|
+
stableRounds: topResult?.stableRounds,
|
|
1742
|
+
hashSource: topResult?.hashSource,
|
|
1743
|
+
capped: topResult?.capped === true
|
|
1744
|
+
});
|
|
1745
|
+
} catch (error) {
|
|
1746
|
+
if (options.strictScrollToTop === true) throw error;
|
|
1710
1747
|
Logger.warn("captureScreen scrollToTop skipped", { message: error?.message || String(error) });
|
|
1711
|
-
}
|
|
1748
|
+
}
|
|
1712
1749
|
for (let index = 0; index < DEFAULT_CAPTURE_COUNT; index += 1) {
|
|
1713
|
-
await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
|
|
1750
|
+
if (shouldHideKeyboard) await Device.hideKeyboard(ctx, { attempts: 1, settleMs: 250 }).catch(() => {
|
|
1714
1751
|
});
|
|
1715
1752
|
await sleep(DEFAULT_SETTLE_MS);
|
|
1716
1753
|
const png = await Device.screenshotPng(ctx);
|