lamda 7.90__tar.gz → 8.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {lamda-7.90 → lamda-8.0}/PKG-INFO +1 -1
- {lamda-7.90 → lamda-8.0}/README.md +1 -1
- {lamda-7.90 → lamda-8.0}/lamda/__init__.py +1 -1
- {lamda-7.90 → lamda-8.0}/lamda/client.py +36 -56
- {lamda-7.90 → lamda-8.0}/lamda/exceptions.py +2 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/application.proto +4 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/services.proto +3 -3
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/PKG-INFO +1 -1
- {lamda-7.90 → lamda-8.0}/lamda/bcast.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/const.py +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/any.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/api.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/compiler/plugin.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/descriptor.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/duration.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/empty.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/field_mask.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/source_context.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/struct.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/timestamp.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/type.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/google/protobuf/wrappers.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/debug.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/file.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/policy.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/proxy.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/settings.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/shell.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/status.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/storage.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/types.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/uiautomator.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/util.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/rpc/wifi.proto +0 -0
- {lamda-7.90 → lamda-8.0}/lamda/types.py +0 -0
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/SOURCES.txt +0 -0
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/dependency_links.txt +0 -0
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/not-zip-safe +0 -0
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/requires.txt +0 -0
- {lamda-7.90 → lamda-8.0}/lamda.egg-info/top_level.txt +0 -0
- {lamda-7.90 → lamda-8.0}/setup.cfg +0 -0
- {lamda-7.90 → lamda-8.0}/setup.py +0 -0
@@ -12,7 +12,7 @@
|
|
12
12
|
<img src="https://img.shields.io/github/v/release/rev1si0n/lamda" />
|
13
13
|
</p>
|
14
14
|
|
15
|
-
<p align="center"><a href="https://device-farm.com/doc/index.html">使用文档</a> | <a href="https://t.me/lamda_dev">TELEGRAM</a> | <a href="https://lamda.run/join/qq">QQ 群组</a> | <a href="https://
|
15
|
+
<p align="center"><a href="https://device-farm.com/doc/index.html">使用文档</a> | <a href="https://t.me/lamda_dev">TELEGRAM</a> | <a href="https://lamda.run/join/qq">QQ 群组</a> | <a href="https://device-farm.com/doc/版本历史.html">更新历史</a></p>
|
16
16
|
|
17
17
|
智能机的崛起,传统网页端的普及度也开始显著减弱,数据与应用正加速向移动端转移。越来越多的人选择通过智能手机和平板等移动设备来获取信息和服务。随着移动设备的普及,用户享受到更便捷访问体验,传统的网页内容模式面临重新审视。与此同时,数据采集的技术也亟需适应这一趋势。过去,许多数据采集工具专注于网页内容,在移动端环境中,尤其是在移动端封闭的黑盒中,现今的常规采集技术也面临着新的挑战。LAMDA 的诞生,为这一切创造了可能。
|
18
18
|
|
@@ -302,9 +302,6 @@ class CustomOcrBackend(object):
|
|
302
302
|
|
303
303
|
|
304
304
|
class BaseCryptor(object):
|
305
|
-
def __str__(self):
|
306
|
-
return "{}".format(self.__class__.__name__)
|
307
|
-
__repr__ = __str__
|
308
305
|
def encrypt(self, data):
|
309
306
|
return data
|
310
307
|
def decrypt(self, data):
|
@@ -312,9 +309,6 @@ class BaseCryptor(object):
|
|
312
309
|
|
313
310
|
|
314
311
|
class BaseServiceStub(object):
|
315
|
-
def __str__(self):
|
316
|
-
return "{}".format(self.__class__.__name__)
|
317
|
-
__repr__ = __str__
|
318
312
|
def __init__(self, stub):
|
319
313
|
self.stub = stub
|
320
314
|
|
@@ -467,8 +461,6 @@ class ObjectUiAutomatorOpStub:
|
|
467
461
|
corner=corner)
|
468
462
|
r = self.stub.selectorClickExists(req)
|
469
463
|
return r.value
|
470
|
-
def click_exist(self, *args, **kwargs):
|
471
|
-
return self.click_exists(*args, **kwargs)
|
472
464
|
def long_click(self, corner=Corner.COR_CENTER):
|
473
465
|
"""
|
474
466
|
长按选择器选中的控件
|
@@ -484,26 +476,12 @@ class ObjectUiAutomatorOpStub:
|
|
484
476
|
req = protos.SelectorOnlyRequest(selector=self.selector)
|
485
477
|
r = self.stub.selectorExists(req)
|
486
478
|
return r.value
|
487
|
-
def exist(self, *args, **kwargs):
|
488
|
-
return self.exists(*args, **kwargs)
|
489
479
|
def info(self):
|
490
480
|
"""
|
491
481
|
获取选择器选中控件的信息
|
492
482
|
"""
|
493
483
|
req = protos.SelectorOnlyRequest(selector=self.selector)
|
494
484
|
return self.stub.selectorObjInfo(req)
|
495
|
-
def info_of_all_instances(self):
|
496
|
-
"""
|
497
|
-
获取选择器选中的所有控件的信息
|
498
|
-
"""
|
499
|
-
req = protos.SelectorOnlyRequest(selector=self.selector)
|
500
|
-
r = self.stub.selectorObjInfoOfAllInstances(req)
|
501
|
-
return r.objects
|
502
|
-
def all_instances(self):
|
503
|
-
"""
|
504
|
-
获取选择器选中的所有元素控件
|
505
|
-
"""
|
506
|
-
return list(self)
|
507
485
|
def _new_object(self, **kwargs):
|
508
486
|
selector = copy.deepcopy(self._selector)
|
509
487
|
selector.update(**kwargs)
|
@@ -559,6 +537,11 @@ class ObjectUiAutomatorOpStub:
|
|
559
537
|
return self._new_object(index=idx)
|
560
538
|
def instance(self, idx):
|
561
539
|
return self._new_object(instance=idx)
|
540
|
+
def get(self, idx):
|
541
|
+
"""
|
542
|
+
获取匹配的第 N 个索引的元素
|
543
|
+
"""
|
544
|
+
return self.instance(idx)
|
562
545
|
def __iter__(self):
|
563
546
|
"""
|
564
547
|
遍历所有符合选择器条件的元素实例
|
@@ -1042,16 +1025,21 @@ class AppScriptRpcInterface(object):
|
|
1042
1025
|
self.application = application
|
1043
1026
|
self.stub = stub
|
1044
1027
|
self.name = name
|
1028
|
+
def __str__(self):
|
1029
|
+
return "{}:Script:{}".format(self.application,
|
1030
|
+
self.name)
|
1031
|
+
__repr__ = __str__
|
1045
1032
|
def __call__(self, *args):
|
1046
1033
|
call_args = dict()
|
1047
1034
|
call_args["method"] = self.name
|
1048
1035
|
call_args["args"] = args
|
1049
1036
|
req = HookRpcRequest()
|
1050
1037
|
req.package = self.application.applicationId
|
1038
|
+
req.user = self.application.user
|
1051
1039
|
req.callinfo = json.dumps(call_args)
|
1052
1040
|
result = self.stub.callScript(req)
|
1053
|
-
|
1054
|
-
return
|
1041
|
+
data = json.loads(result.callresult)
|
1042
|
+
return data
|
1055
1043
|
|
1056
1044
|
|
1057
1045
|
class ApplicationOpStub:
|
@@ -1063,8 +1051,8 @@ class ApplicationOpStub:
|
|
1063
1051
|
self.applicationId = applicationId
|
1064
1052
|
self.stub = stub
|
1065
1053
|
def __str__(self):
|
1066
|
-
return "{}
|
1067
|
-
|
1054
|
+
return "Application:{}@{}".format(self.applicationId,
|
1055
|
+
self.user)
|
1068
1056
|
__repr__ = __str__
|
1069
1057
|
def is_foreground(self):
|
1070
1058
|
"""
|
@@ -1118,7 +1106,7 @@ class ApplicationOpStub:
|
|
1118
1106
|
req.user = self.user
|
1119
1107
|
r = self.stub.isPermissionGranted(req)
|
1120
1108
|
return r.value
|
1121
|
-
def
|
1109
|
+
def clear_cache(self):
|
1122
1110
|
"""
|
1123
1111
|
清空应用的缓存数据(非数据仅缓存)
|
1124
1112
|
"""
|
@@ -1126,7 +1114,7 @@ class ApplicationOpStub:
|
|
1126
1114
|
req.user = self.user
|
1127
1115
|
r = self.stub.deleteApplicationCache(req)
|
1128
1116
|
return r.value
|
1129
|
-
def
|
1117
|
+
def reset(self):
|
1130
1118
|
"""
|
1131
1119
|
清空应用的所有数据
|
1132
1120
|
"""
|
@@ -1134,8 +1122,6 @@ class ApplicationOpStub:
|
|
1134
1122
|
req.user = self.user
|
1135
1123
|
r = self.stub.resetApplicationData(req)
|
1136
1124
|
return r.value
|
1137
|
-
def reset(self):
|
1138
|
-
return self.reset_data()
|
1139
1125
|
def start(self):
|
1140
1126
|
"""
|
1141
1127
|
启动应用
|
@@ -1226,27 +1212,34 @@ class ApplicationOpStub:
|
|
1226
1212
|
req.spawn = spawn
|
1227
1213
|
req.destination = emit
|
1228
1214
|
req.encode = encode
|
1215
|
+
req.user = self.user
|
1229
1216
|
r = self.stub.attachScript(req)
|
1230
1217
|
return r.value
|
1231
1218
|
def detach_script(self):
|
1232
1219
|
"""
|
1233
1220
|
移除注入应用的 Hook 脚本
|
1234
1221
|
"""
|
1235
|
-
req = protos.
|
1222
|
+
req = protos.HookRequest()
|
1223
|
+
req.package = self.applicationId
|
1224
|
+
req.user = self.user
|
1236
1225
|
r = self.stub.detachScript(req)
|
1237
1226
|
return r.value
|
1238
1227
|
def is_attached_script(self):
|
1239
1228
|
"""
|
1240
1229
|
检查使用在此应用注入了 Hook 脚本
|
1241
1230
|
"""
|
1242
|
-
req = protos.
|
1231
|
+
req = protos.HookRequest()
|
1232
|
+
req.package = self.applicationId
|
1233
|
+
req.user = self.user
|
1243
1234
|
r = self.stub.isScriptAttached(req)
|
1244
1235
|
return r.value
|
1245
1236
|
def is_script_alive(self):
|
1246
1237
|
"""
|
1247
1238
|
检查应用中的 Hook 脚本是否正常
|
1248
1239
|
"""
|
1249
|
-
req = protos.
|
1240
|
+
req = protos.HookRequest()
|
1241
|
+
req.package = self.applicationId
|
1242
|
+
req.user = self.user
|
1250
1243
|
r = self.stub.isScriptAlive(req)
|
1251
1244
|
return r.value
|
1252
1245
|
def __getattr__(self, name):
|
@@ -1263,7 +1256,7 @@ class ApplicationStub(BaseServiceStub):
|
|
1263
1256
|
获取当前处于前台的应用的信息
|
1264
1257
|
"""
|
1265
1258
|
top = self.stub.currentApplication(protos.Empty())
|
1266
|
-
app = self.__call__(top.packageName)
|
1259
|
+
app = self.__call__(top.packageName, user=top.user)
|
1267
1260
|
app.activity = top.activity
|
1268
1261
|
return app
|
1269
1262
|
def get_application_by_name(self, name, user=0):
|
@@ -1305,6 +1298,7 @@ class ApplicationStub(BaseServiceStub):
|
|
1305
1298
|
安装设备上的 apk 文件(注意此路径为设备上的 apk 路径)
|
1306
1299
|
"""
|
1307
1300
|
req = protos.ApplicationRequest(path=fpath)
|
1301
|
+
req.user = self.user
|
1308
1302
|
r = self.stub.installFromLocalFile(req)
|
1309
1303
|
return r
|
1310
1304
|
def __call__(self, applicationId, user=0):
|
@@ -1312,10 +1306,6 @@ class ApplicationStub(BaseServiceStub):
|
|
1312
1306
|
|
1313
1307
|
|
1314
1308
|
class StorageOpStub:
|
1315
|
-
def __str__(self):
|
1316
|
-
return "{}:{}".format(self.stub.__class__.__name__,
|
1317
|
-
self.name)
|
1318
|
-
__repr__ = __str__
|
1319
1309
|
# 用于容器值序列化的方法
|
1320
1310
|
def _decrypt(self, data):
|
1321
1311
|
return self.cryptor.decrypt(data)
|
@@ -1734,20 +1724,20 @@ class ProxyStub(BaseServiceStub):
|
|
1734
1724
|
|
1735
1725
|
|
1736
1726
|
class SelinuxPolicyStub(BaseServiceStub):
|
1737
|
-
def
|
1727
|
+
def allow(self, source, target, tclass, action):
|
1738
1728
|
"""
|
1739
1729
|
selinux allow
|
1740
1730
|
"""
|
1741
1731
|
req = protos.SelinuxPolicyRequest(source=source, target=target,
|
1742
|
-
|
1732
|
+
tclass=tclass, action=action)
|
1743
1733
|
r = self.stub.policySetAllow(req)
|
1744
1734
|
return r.value
|
1745
|
-
def
|
1735
|
+
def disallow(self, source, target, tclass, action):
|
1746
1736
|
"""
|
1747
1737
|
selinux disallow
|
1748
1738
|
"""
|
1749
1739
|
req = protos.SelinuxPolicyRequest(source=source, target=target,
|
1750
|
-
|
1740
|
+
tclass=tclass, action=action)
|
1751
1741
|
r = self.stub.policySetDisallow(req)
|
1752
1742
|
return r.value
|
1753
1743
|
def get_enforce(self):
|
@@ -1763,27 +1753,27 @@ class SelinuxPolicyStub(BaseServiceStub):
|
|
1763
1753
|
req = protos.Boolean(value=enforced)
|
1764
1754
|
r = self.stub.setEnforce(req)
|
1765
1755
|
return r.value
|
1766
|
-
def
|
1756
|
+
def enabled(self):
|
1767
1757
|
"""
|
1768
1758
|
获取设备上的 selinux 是否已经启用
|
1769
1759
|
"""
|
1770
1760
|
r = self.stub.isEnabled(protos.Empty())
|
1771
1761
|
return r.value
|
1772
|
-
def
|
1762
|
+
def enforce(self, name):
|
1773
1763
|
"""
|
1774
1764
|
设置一个域为 enforce
|
1775
1765
|
"""
|
1776
1766
|
req = protos.String(value=name)
|
1777
1767
|
r = self.stub.policySetEnforce(req)
|
1778
1768
|
return r.value
|
1779
|
-
def
|
1769
|
+
def permissive(self, name):
|
1780
1770
|
"""
|
1781
1771
|
设置一个域为 permissive
|
1782
1772
|
"""
|
1783
1773
|
req = protos.String(value=name)
|
1784
1774
|
r = self.stub.policySetPermissive(req)
|
1785
1775
|
return r.value
|
1786
|
-
def
|
1776
|
+
def create_domain(self, name):
|
1787
1777
|
"""
|
1788
1778
|
新建一个 selinux 域
|
1789
1779
|
"""
|
@@ -2022,11 +2012,6 @@ class OcrOperator(object):
|
|
2022
2012
|
OCR - 检查元素是否存在
|
2023
2013
|
"""
|
2024
2014
|
return bool(self.find_target_item())
|
2025
|
-
def exist(self):
|
2026
|
-
"""
|
2027
|
-
OCR - 检查元素是否存在
|
2028
|
-
"""
|
2029
|
-
return self.exists()
|
2030
2015
|
def click(self):
|
2031
2016
|
"""
|
2032
2017
|
OCR - 点击元素(不存在则报错)
|
@@ -2037,11 +2022,6 @@ class OcrOperator(object):
|
|
2037
2022
|
OCR - 点击元素(不存在将不会产生异常)
|
2038
2023
|
"""
|
2039
2024
|
return self.find_cb(self._click, False)
|
2040
|
-
def click_exist(self):
|
2041
|
-
"""
|
2042
|
-
OCR - 点击元素(不存在将不会产生异常)
|
2043
|
-
"""
|
2044
|
-
return self.click_exists()
|
2045
2025
|
def screenshot(self, quality=100):
|
2046
2026
|
"""
|
2047
2027
|
OCR - 对元素进行截图
|
@@ -22,6 +22,8 @@ class InvalidAndroidPackage(Exception):
|
|
22
22
|
""" Exception """
|
23
23
|
class InvalidArgumentError(Exception):
|
24
24
|
""" Exception """
|
25
|
+
class InvalidOperationError(Exception):
|
26
|
+
""" Exception """
|
25
27
|
class InvalidRootCertificate(Exception):
|
26
28
|
""" Exception """
|
27
29
|
class MethodNotFoundException(Exception):
|
@@ -54,6 +54,7 @@ message ApplicationActivityInfo {
|
|
54
54
|
int64 flags = 7;
|
55
55
|
bool debug = 8;
|
56
56
|
string data = 9;
|
57
|
+
uint32 user = 10;
|
57
58
|
}
|
58
59
|
|
59
60
|
message ApplicationActivityInfoList {
|
@@ -77,6 +78,7 @@ message ApplicationInfo {
|
|
77
78
|
uint32 versionCode = 10;
|
78
79
|
string versionName = 11;
|
79
80
|
string activity = 12;
|
81
|
+
uint32 user = 13;
|
80
82
|
}
|
81
83
|
|
82
84
|
message ApplicationProcess {
|
@@ -102,11 +104,13 @@ message HookRequest {
|
|
102
104
|
DataEncode encode = 5;
|
103
105
|
uint32 standup = 6;
|
104
106
|
bool spawn = 7;
|
107
|
+
uint32 user = 8;
|
105
108
|
}
|
106
109
|
|
107
110
|
message HookRpcRequest {
|
108
111
|
string package = 1;
|
109
112
|
string callinfo = 2;
|
113
|
+
uint32 user = 3;
|
110
114
|
}
|
111
115
|
|
112
116
|
message HookRpcResponse {
|
@@ -52,10 +52,10 @@ service Application {
|
|
52
52
|
rpc getIdentifierByLabel(String) returns (String) {}
|
53
53
|
|
54
54
|
rpc callScript(HookRpcRequest) returns (HookRpcResponse) {}
|
55
|
-
rpc isScriptAlive(
|
56
|
-
rpc isScriptAttached(
|
55
|
+
rpc isScriptAlive(HookRequest) returns (Boolean) {}
|
56
|
+
rpc isScriptAttached(HookRequest) returns (Boolean) {}
|
57
57
|
rpc attachScript(HookRequest) returns (Boolean) {}
|
58
|
-
rpc detachScript(
|
58
|
+
rpc detachScript(HookRequest) returns (Boolean) {}
|
59
59
|
}
|
60
60
|
|
61
61
|
service Debug {
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|