lamda 7.73__tar.gz → 7.75__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. {lamda-7.73 → lamda-7.75}/PKG-INFO +4 -4
  2. {lamda-7.73 → lamda-7.75}/lamda/__init__.py +1 -1
  3. {lamda-7.73 → lamda-7.75}/lamda/client.py +189 -1
  4. {lamda-7.73 → lamda-7.75}/lamda/rpc/services.proto +1 -0
  5. {lamda-7.73 → lamda-7.75}/lamda.egg-info/PKG-INFO +4 -4
  6. {lamda-7.73 → lamda-7.75}/lamda.egg-info/requires.txt +3 -3
  7. {lamda-7.73 → lamda-7.75}/setup.py +3 -3
  8. {lamda-7.73 → lamda-7.75}/README.md +0 -0
  9. {lamda-7.73 → lamda-7.75}/lamda/bcast.proto +0 -0
  10. {lamda-7.73 → lamda-7.75}/lamda/const.py +0 -0
  11. {lamda-7.73 → lamda-7.75}/lamda/exceptions.py +0 -0
  12. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/any.proto +0 -0
  13. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/api.proto +0 -0
  14. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/compiler/plugin.proto +0 -0
  15. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/descriptor.proto +0 -0
  16. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/duration.proto +0 -0
  17. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/empty.proto +0 -0
  18. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/field_mask.proto +0 -0
  19. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/source_context.proto +0 -0
  20. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/struct.proto +0 -0
  21. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/timestamp.proto +0 -0
  22. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/type.proto +0 -0
  23. {lamda-7.73 → lamda-7.75}/lamda/google/protobuf/wrappers.proto +0 -0
  24. {lamda-7.73 → lamda-7.75}/lamda/rpc/application.proto +0 -0
  25. {lamda-7.73 → lamda-7.75}/lamda/rpc/debug.proto +0 -0
  26. {lamda-7.73 → lamda-7.75}/lamda/rpc/file.proto +0 -0
  27. {lamda-7.73 → lamda-7.75}/lamda/rpc/policy.proto +0 -0
  28. {lamda-7.73 → lamda-7.75}/lamda/rpc/proxy.proto +0 -0
  29. {lamda-7.73 → lamda-7.75}/lamda/rpc/settings.proto +0 -0
  30. {lamda-7.73 → lamda-7.75}/lamda/rpc/shell.proto +0 -0
  31. {lamda-7.73 → lamda-7.75}/lamda/rpc/status.proto +0 -0
  32. {lamda-7.73 → lamda-7.75}/lamda/rpc/storage.proto +0 -0
  33. {lamda-7.73 → lamda-7.75}/lamda/rpc/types.proto +0 -0
  34. {lamda-7.73 → lamda-7.75}/lamda/rpc/uiautomator.proto +0 -0
  35. {lamda-7.73 → lamda-7.75}/lamda/rpc/util.proto +0 -0
  36. {lamda-7.73 → lamda-7.75}/lamda/rpc/wifi.proto +0 -0
  37. {lamda-7.73 → lamda-7.75}/lamda/types.py +0 -0
  38. {lamda-7.73 → lamda-7.75}/lamda.egg-info/SOURCES.txt +0 -0
  39. {lamda-7.73 → lamda-7.75}/lamda.egg-info/dependency_links.txt +0 -0
  40. {lamda-7.73 → lamda-7.75}/lamda.egg-info/not-zip-safe +0 -0
  41. {lamda-7.73 → lamda-7.75}/lamda.egg-info/top_level.txt +0 -0
  42. {lamda-7.73 → lamda-7.75}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamda
3
- Version: 7.73
3
+ Version: 7.75
4
4
  Summary: Android reverse engineering & automation framework (Client API)
5
5
  Home-page: https://github.com/firerpa/lamda
6
6
  Author: rev1si0n
@@ -13,9 +13,9 @@ Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Operating System :: Android
14
14
  Classifier: Topic :: Security
15
15
  Requires-Python: >=3.6,<=3.12
16
- Requires-Dist: grpcio-tools<1.60.0,>=1.35.0
17
- Requires-Dist: grpc-interceptor<=0.15.2,>=0.13.0
18
- Requires-Dist: grpcio<1.60.0,>=1.35.0
16
+ Requires-Dist: grpcio-tools<=1.68.0,>=1.35.0
17
+ Requires-Dist: grpc-interceptor<=0.15.4,>=0.13.0
18
+ Requires-Dist: grpcio<=1.68.0,>=1.35.0
19
19
  Requires-Dist: cryptography>=35.0.0
20
20
  Requires-Dist: msgpack>=1.0.0
21
21
  Requires-Dist: asn1crypto<2,>=1.0.0
@@ -2,4 +2,4 @@
2
2
  #
3
3
  # Distributed under MIT license.
4
4
  # See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5
- __version__ = "7.73"
5
+ __version__ = "7.75"
@@ -44,7 +44,9 @@ except (ImportError, AttributeError):
44
44
 
45
45
  from . import __version__
46
46
  from . types import AttributeDict, BytesIO
47
- from . exceptions import UnHandledException, DuplicateEntryError, InvalidArgumentError
47
+ from . exceptions import (UnHandledException, DuplicateEntryError,
48
+ InvalidArgumentError, UiObjectNotFoundException,
49
+ IllegalStateException)
48
50
  from . import exceptions
49
51
 
50
52
  handler = logging.StreamHandler()
@@ -63,6 +65,8 @@ __all__ = [
63
65
  "GproxyType",
64
66
  "GrantType",
65
67
  "Group",
68
+ "CustomOcrBackend",
69
+ "OcrEngine",
66
70
  "Key",
67
71
  "Keys",
68
72
  "KeyCode",
@@ -168,6 +172,18 @@ def center(b):
168
172
  y = int(b.top + (b.bottom - b.top)/2)
169
173
  return Point(x=x, y=y)
170
174
 
175
+ def contain(a, b):
176
+ return all([b.top >= a.top,
177
+ b.left >= a.left,
178
+ b.bottom <= a.bottom,
179
+ b.right <= a.right])
180
+
181
+ def equal(a, b):
182
+ return all([b.top == a.top,
183
+ b.left == a.left,
184
+ b.bottom == a.bottom,
185
+ b.right == a.right])
186
+
171
187
  def corner(b, position):
172
188
  ca, cb = position.split("-")
173
189
  return Point(x=getattr(b, cb),
@@ -248,6 +264,8 @@ FindImageArea = protos.FindImageArea
248
264
 
249
265
  Bound.center = center
250
266
  Bound.corner = corner
267
+ Bound.__contains__ = contain
268
+ Bound.__eq__ = equal
251
269
 
252
270
 
253
271
  def load_proto(name):
@@ -267,6 +285,13 @@ def Selector(**kwargs):
267
285
  return sel
268
286
 
269
287
 
288
+ class CustomOcrBackend(object):
289
+ def __init__(self, *args, **kwargs):
290
+ raise NotImplementedError
291
+ def ocr(self, image):
292
+ raise NotImplementedError
293
+
294
+
270
295
  class BaseCryptor(object):
271
296
  def __str__(self):
272
297
  return "{}".format(self.__class__.__name__)
@@ -1100,6 +1125,11 @@ class ApplicationStub(BaseServiceStub):
1100
1125
  app = self.__call__(top.packageName)
1101
1126
  app.activity = top.activity
1102
1127
  return app
1128
+ def get_application_by_name(self, name, user=0):
1129
+ req = protos.String(value=name)
1130
+ r = self.stub.getIdentifierByLabel(req)
1131
+ app = self.__call__(r.value, user=user)
1132
+ return app
1103
1133
  def enumerate_running_processes(self):
1104
1134
  """
1105
1135
  列出设备上所有正在运行的安卓应用进程
@@ -1804,6 +1834,140 @@ class WifiStub(BaseServiceStub):
1804
1834
  raise NotImplementedError
1805
1835
 
1806
1836
 
1837
+ class OcrOperator(object):
1838
+ def __init__(self, device, elements=None,
1839
+ **kwargs):
1840
+ self.elements = elements
1841
+ self.index = kwargs.pop("index", 0)
1842
+ self.func, self.rule = kwargs.popitem()
1843
+ self.match = getattr(self, self.func)
1844
+ self.device = device
1845
+ def text(self, item):
1846
+ return self.rule == item["text"]
1847
+ def textMatches(self, item):
1848
+ return bool(re.match(self.rule, item["text"],
1849
+ re.DOTALL))
1850
+ def textContains(self, item):
1851
+ return self.rule in item["text"]
1852
+ def find_target_item(self):
1853
+ m = [e for e in self.elements \
1854
+ if self.match(e)]
1855
+ o = (m and len(m) > self.index) != True
1856
+ return None if o else m[self.index]
1857
+ def find_item_or_throw(self):
1858
+ item = self.find_target_item()
1859
+ msg = "OcrSelector[{}={}]".format(self.func, self.rule)
1860
+ item or self.throw(UiObjectNotFoundException, msg)
1861
+ return item
1862
+ def find_cb(self, func, ret, *args):
1863
+ item = self.find_target_item()
1864
+ return func(item, *args) if item else ret
1865
+ def find_or_throw_cb(self, func, *args):
1866
+ item = self.find_item_or_throw()
1867
+ return func(item, *args)
1868
+ def throw(self, exception, *args):
1869
+ raise exception(*args)
1870
+ def _screenshot(self, item, quality):
1871
+ return self.device.screenshot(quality,
1872
+ bound=item["bound"])
1873
+ def _click(self, item):
1874
+ point = item["bound"].center()
1875
+ return self.device.click(point)
1876
+ def __str__(self):
1877
+ return "Ocr: {}={}".format(self.func, self.rule)
1878
+ __repr__ = __str__
1879
+ def exists(self):
1880
+ """
1881
+ OCR - 检查元素是否存在
1882
+ """
1883
+ return bool(self.find_target_item())
1884
+ def exist(self):
1885
+ """
1886
+ OCR - 检查元素是否存在
1887
+ """
1888
+ return self.exists()
1889
+ def click(self):
1890
+ """
1891
+ OCR - 点击元素(不存在则报错)
1892
+ """
1893
+ return self.find_or_throw_cb(self._click)
1894
+ def click_exists(self):
1895
+ """
1896
+ OCR - 点击元素(不存在将不会产生异常)
1897
+ """
1898
+ return self.find_cb(self._click, False)
1899
+ def click_exist(self):
1900
+ """
1901
+ OCR - 点击元素(不存在将不会产生异常)
1902
+ """
1903
+ return self.click_exists()
1904
+ def screenshot(self, quality=100):
1905
+ """
1906
+ OCR - 对元素进行截图
1907
+ """
1908
+ return self.find_or_throw_cb(self._screenshot,
1909
+ quality)
1910
+ def take_screenshot(self, quality=100):
1911
+ """
1912
+ OCR - 对元素进行截图
1913
+ """
1914
+ return self.screenshot(quality)
1915
+ def info(self):
1916
+ """
1917
+ OCR - 获取匹配元素的信息
1918
+ """
1919
+ item = self.find_item_or_throw()
1920
+ return item
1921
+
1922
+
1923
+ class OcrEngine(object):
1924
+ def __init__(self, service, *args,
1925
+ **kwargs):
1926
+ args = list(args)
1927
+ if type(service) == type:
1928
+ args.insert(0, service)
1929
+ service = "custom"
1930
+ func = getattr(self, "init_{}".format(service))
1931
+ func(*args, **kwargs)
1932
+ def init_paddleocr(self, *args, **kwargs):
1933
+ from paddleocr import PaddleOCR
1934
+ self._service = PaddleOCR(*args, **kwargs)
1935
+ self._ocr = self.ocr_paddleocr
1936
+ def init_easyocr(self, *args, **kwargs):
1937
+ from easyocr import Reader
1938
+ self._service = Reader(*args, **kwargs)
1939
+ self._ocr = self.ocr_easyocr
1940
+ def init_custom(self, service, *args, **kwargs):
1941
+ self._service = service(*args, **kwargs)
1942
+ self._ocr = self.ocr_custom
1943
+ def ocr_custom(self, image):
1944
+ result = self._service.ocr(image)
1945
+ return result
1946
+ def ocr_paddleocr(self, image):
1947
+ r = self._service.ocr(image)
1948
+ n = bool(r and r[0] and type(r[0][-1])==float)
1949
+ result = (r if n else r[0]) or []
1950
+ output = [[n[0], n[1][0], n[1][1]] for n in result]
1951
+ return output
1952
+ def ocr_easyocr(self, image):
1953
+ result = self._service.readtext(image)
1954
+ return result
1955
+ def ocr(self, screenshot):
1956
+ img = screenshot.getvalue()
1957
+ result = self._ocr(img) or []
1958
+ output = [self.format(*n) for n in result]
1959
+ return output
1960
+ def format(self, box, text, confidence):
1961
+ bound = Bound()
1962
+ bound.left = int(min(p[0] for p in box))
1963
+ bound.top = int(min(p[1] for p in box))
1964
+ bound.bottom = int(max(p[1] for p in box))
1965
+ bound.right = int(max(p[0] for p in box))
1966
+ info = dict(text=text, confidence=confidence,
1967
+ bound=bound)
1968
+ return info
1969
+
1970
+
1807
1971
  class Device(object):
1808
1972
  def __init__(self, host, port=65000,
1809
1973
  certificate=None,
@@ -1827,6 +1991,8 @@ class Device(object):
1827
1991
  interceptors = [ClientSessionMetadataInterceptor(session),
1828
1992
  GrpcRemoteExceptionInterceptor(),
1829
1993
  ClientLoggingInterceptor()]
1994
+ self._ocr = None
1995
+ self._ocr_img_quality = 75
1830
1996
  self.channel = grpc.intercept_channel(self._chan,
1831
1997
  *interceptors)
1832
1998
  self.session = session
@@ -1897,6 +2063,8 @@ class Device(object):
1897
2063
  return self.stub("Application").get_last_activities(count=count)
1898
2064
  def start_activity(self, **activity):
1899
2065
  return self.stub("Application").start_activity(**activity)
2066
+ def get_application_by_name(self, name):
2067
+ return self.stub("Application").get_application_by_name(name)
1900
2068
  def application(self, applicationId, user=0):
1901
2069
  return self.stub("Application")(applicationId, user=user)
1902
2070
  # 快速调用: Util
@@ -2045,6 +2213,26 @@ class Device(object):
2045
2213
  return self.stub("UiAutomator").device_info()
2046
2214
  def __call__(self, **kwargs):
2047
2215
  return self.stub("UiAutomator")(**kwargs)
2216
+ # OCR 功能扩展
2217
+ def ocr(self, index=0, **kwargs):
2218
+ if not isinstance(self._ocr, OcrEngine):
2219
+ raise IllegalStateException("Ocr engine is not setted up")
2220
+ if any(r not in ["text", "textContains", "textMatches"] \
2221
+ for r in kwargs.keys()):
2222
+ raise InvalidArgumentError("Only text* matches are supported")
2223
+ if len(kwargs) != 1:
2224
+ raise InvalidArgumentError("Only or at least one rule can be used")
2225
+ image = self.screenshot(self._ocr_img_quality)
2226
+ return OcrOperator(self,
2227
+ elements=self._ocr.ocr(image),
2228
+ index=index,
2229
+ **kwargs
2230
+ )
2231
+ def setup_ocr_backend(self, service, *args, quality=75,
2232
+ **kwargs):
2233
+ self._ocr_img_quality = quality
2234
+ self._ocr = OcrEngine(service, *args,
2235
+ **kwargs)
2048
2236
  # 日志打印
2049
2237
  def set_debug_log_enabled(self, enable):
2050
2238
  level = logging.DEBUG if enable else logging.WARN
@@ -49,6 +49,7 @@ service Application {
49
49
 
50
50
  rpc addToDozeModeWhiteList(ApplicationRequest) returns (Boolean) {}
51
51
  rpc removeFromDozeModeWhiteList(ApplicationRequest) returns (Boolean) {}
52
+ rpc getIdentifierByLabel(String) returns (String) {}
52
53
  }
53
54
 
54
55
  service Debug {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lamda
3
- Version: 7.73
3
+ Version: 7.75
4
4
  Summary: Android reverse engineering & automation framework (Client API)
5
5
  Home-page: https://github.com/firerpa/lamda
6
6
  Author: rev1si0n
@@ -13,9 +13,9 @@ Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Operating System :: Android
14
14
  Classifier: Topic :: Security
15
15
  Requires-Python: >=3.6,<=3.12
16
- Requires-Dist: grpcio-tools<1.60.0,>=1.35.0
17
- Requires-Dist: grpc-interceptor<=0.15.2,>=0.13.0
18
- Requires-Dist: grpcio<1.60.0,>=1.35.0
16
+ Requires-Dist: grpcio-tools<=1.68.0,>=1.35.0
17
+ Requires-Dist: grpc-interceptor<=0.15.4,>=0.13.0
18
+ Requires-Dist: grpcio<=1.68.0,>=1.35.0
19
19
  Requires-Dist: cryptography>=35.0.0
20
20
  Requires-Dist: msgpack>=1.0.0
21
21
  Requires-Dist: asn1crypto<2,>=1.0.0
@@ -1,6 +1,6 @@
1
- grpcio-tools<1.60.0,>=1.35.0
2
- grpc-interceptor<=0.15.2,>=0.13.0
3
- grpcio<1.60.0,>=1.35.0
1
+ grpcio-tools<=1.68.0,>=1.35.0
2
+ grpc-interceptor<=0.15.4,>=0.13.0
3
+ grpcio<=1.68.0,>=1.35.0
4
4
  cryptography>=35.0.0
5
5
  msgpack>=1.0.0
6
6
  asn1crypto<2,>=1.0.0
@@ -19,9 +19,9 @@ setuptools.setup(
19
19
  ],
20
20
  },
21
21
  install_requires= [
22
- "grpcio-tools>=1.35.0,<1.60.0",
23
- "grpc-interceptor>=0.13.0,<=0.15.2",
24
- "grpcio>=1.35.0,<1.60.0",
22
+ "grpcio-tools>=1.35.0,<=1.68.0",
23
+ "grpc-interceptor>=0.13.0,<=0.15.4",
24
+ "grpcio>=1.35.0,<=1.68.0",
25
25
  "cryptography>=35.0.0",
26
26
  "msgpack>=1.0.0",
27
27
  "asn1crypto>=1.0.0,<2",
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