From 83e5fa8b122249faef651d570d0a73e4786d74aa Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Thu, 11 Mar 2021 20:30:15 +0300 Subject: [PATCH] v1.2.0 is released - GUIDE is near --- README.md | 3 +- .../pyOpenRPA-1.1.20.dist-info/INSTALLER | 1 - .../pyOpenRPA-1.1.20.dist-info/METADATA | 88 --- .../pyOpenRPA-1.1.20.dist-info/RECORD | 319 ----------- .../pyOpenRPA-1.1.20.dist-info/REQUESTED | 0 .../pyOpenRPA-1.1.20.dist-info/WHEEL | 5 - .../pyOpenRPA-1.1.20.dist-info/top_level.txt | 1 - .../Orchestrator/BackwardCompatibility.py | 387 ++++++++++++- .../pyOpenRPA/Orchestrator/Orchestrator.py | 205 ------- .../pyOpenRPA/Orchestrator/Processor.py | 397 ++++---------- .../Orchestrator/RobotRDPActive/Connector.py | 35 +- .../RobotRDPActive/RobotRDPActive.py | 180 +++--- .../pyOpenRPA/Orchestrator/Server.py | 411 +++++++------- .../pyOpenRPA/Orchestrator/ServerSettings.py | 513 +++++++++++++----- .../pyOpenRPA/Orchestrator/Web/Index.js | 485 ++++++++++++----- .../pyOpenRPA/Orchestrator/Web/Index.xhtml | 286 ++++++---- .../pyOpenRPA/Orchestrator/__init__.py | 4 +- .../pyOpenRPA/Orchestrator/__main__.py | 3 +- .../pyOpenRPA/Robot/UIDesktop.py | 202 ++++++- .../Lib/site-packages/pyOpenRPA/__init__.py | 2 +- .../pyOpenRPA-1.1.20.dist-info/INSTALLER | 1 - .../pyOpenRPA-1.1.20.dist-info/METADATA | 88 --- .../pyOpenRPA-1.1.20.dist-info/RECORD | 319 ----------- .../pyOpenRPA-1.1.20.dist-info/REQUESTED | 0 .../pyOpenRPA-1.1.20.dist-info/WHEEL | 5 - .../pyOpenRPA-1.1.20.dist-info/top_level.txt | 1 - .../Orchestrator/BackwardCompatibility.py | 387 ++++++++++++- .../pyOpenRPA/Orchestrator/Orchestrator.py | 205 ------- .../pyOpenRPA/Orchestrator/Processor.py | 397 ++++---------- .../Orchestrator/RobotRDPActive/Connector.py | 35 +- .../RobotRDPActive/RobotRDPActive.py | 180 +++--- .../pyOpenRPA/Orchestrator/Server.py | 411 +++++++------- .../pyOpenRPA/Orchestrator/ServerSettings.py | 513 +++++++++++++----- .../pyOpenRPA/Orchestrator/Web/Index.js | 485 ++++++++++++----- .../pyOpenRPA/Orchestrator/Web/Index.xhtml | 286 ++++++---- .../pyOpenRPA/Orchestrator/__init__.py | 4 +- .../pyOpenRPA/Orchestrator/__main__.py | 3 +- .../pyOpenRPA/Robot/UIDesktop.py | 202 ++++++- .../Lib/site-packages/pyOpenRPA/__init__.py | 2 +- Sources/GuideSphinx/02_RoadMap.rst | 21 +- .../GuideSphinx/03_Copyrights_Contacts.rst | 7 +- Sources/GuideSphinx/Robot/01_Robot.rst | 21 +- Sources/GuideSphinx/Robot/02_Defs.rst | 77 +-- Sources/GuideSphinx/Robot/03_HowToUse.rst | 96 ++-- Sources/GuideSphinx/Studio/02_HowToUse.rst | 9 - Sources/GuideSphinx/index.rst | 15 +- Sources/pyOpenRPA/__init__.py | 2 +- Wiki/ENG_Guide/html/02_RoadMap.html | 46 +- .../html/03_Copyrights_Contacts.html | 13 +- Wiki/ENG_Guide/html/Robot/01_Robot.html | 378 +------------ Wiki/ENG_Guide/html/Robot/02_Defs.html | 95 +--- Wiki/ENG_Guide/html/Robot/03_HowToUse.html | 124 +++-- Wiki/ENG_Guide/html/Studio/02_HowToUse.html | 1 - .../html/_sources/02_RoadMap.rst.txt | 21 +- .../_sources/03_Copyrights_Contacts.rst.txt | 7 +- .../html/_sources/Robot/01_Robot.rst.txt | 21 +- .../html/_sources/Robot/02_Defs.rst.txt | 77 +-- .../html/_sources/Robot/03_HowToUse.rst.txt | 96 ++-- .../html/_sources/Studio/02_HowToUse.rst.txt | 9 - Wiki/ENG_Guide/html/_sources/index.rst.txt | 15 +- Wiki/ENG_Guide/html/genindex.html | 48 +- Wiki/ENG_Guide/html/index.html | 23 +- Wiki/ENG_Guide/html/searchindex.js | 2 +- Wiki/ENG_Guide/markdown/02_RoadMap.md | 46 +- .../markdown/03_Copyrights_Contacts.md | 7 +- Wiki/ENG_Guide/markdown/Robot/01_Robot.md | 419 +------------- Wiki/ENG_Guide/markdown/Robot/02_Defs.md | 149 +---- Wiki/ENG_Guide/markdown/Robot/03_HowToUse.md | 133 ++--- Wiki/ENG_Guide/markdown/Studio/02_HowToUse.md | 2 - Wiki/ENG_Guide/markdown/index.md | 66 +-- v1.1.20 | 0 71 files changed, 4221 insertions(+), 4876 deletions(-) delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/INSTALLER delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/METADATA delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/RECORD delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/REQUESTED delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/WHEEL delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/top_level.txt delete mode 100644 Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Orchestrator.py delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/INSTALLER delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/METADATA delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/RECORD delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/REQUESTED delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/WHEEL delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/top_level.txt delete mode 100644 Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Orchestrator.py delete mode 100644 v1.1.20 diff --git a/README.md b/README.md index f5763be8..f21914c0 100644 --- a/README.md +++ b/README.md @@ -35,9 +35,10 @@ Now you can use the following docs: - ENG Guide MarkDown [|OPEN GITLAB|](Wiki/ENG_Guide/markdown/index.md) - ENG Guide PDF [|WAIT|]() -- RUS Article: Less cost - no paid RPA [|OPEN HABR|](https://habr.com/ru/post/509644/) +- RUS Article: Less cost - no paid RPA [|OPEN HABR|](https://habr.com/ru/post/506766/) - RUS Tutorial Desktop UI [|OPEN HABR|](https://habr.com/ru/post/509644/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/DesktopGUI_Habr/index.md) - RUS Tutorial Web UI [|OPEN HABR|](https://habr.com/ru/post/515310/); [|OPEN GITLAB|](Wiki/RUS_Tutorial/WebGUI_Habr/3.%20WebGUI_Habr.md) +- RUS Leaflet pyOpenRPA v4.pdf [|OPEN GITLAB|](https://gitlab.com/UnicodeLabs/OpenRPA/-/tree/master/pyOpenRPA/Wiki/RUS_Leaflet/RUS%20Leaflet%20pyOpenRPA%20v4.pdf) ## Copyrights & Contacts pyOpenRPA is created by Ivan Maslov (Russia). Use it for free (MIT)! diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/INSTALLER b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/INSTALLER deleted file mode 100644 index a1b589e3..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/METADATA b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/METADATA deleted file mode 100644 index 724cd9c7..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/METADATA +++ /dev/null @@ -1,88 +0,0 @@ -Metadata-Version: 2.1 -Name: pyOpenRPA -Version: 1.1.20 -Summary: First open source RPA platform for business -Home-page: https://gitlab.com/UnicodeLabs/OpenRPA -Author: Ivan Maslov -Author-email: Ivan.Maslov@unicodelabs.ru -License: MIT -Keywords: OpenRPA RPA Robot Automation Robotization OpenSource -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: MIT License -Classifier: Intended Audience :: Developers -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Testing -Classifier: Topic :: Software Development :: User Interfaces -Classifier: Topic :: Software Development :: Quality Assurance -Classifier: Topic :: Home Automation -Description-Content-Type: text/markdown -Requires-Dist: pywinauto (>=0.6.8) -Requires-Dist: WMI (>=1.4.9) -Requires-Dist: pillow (>=6.0.0) -Requires-Dist: keyboard (>=0.13.3) -Requires-Dist: pyautogui (>=0.9.44) -Requires-Dist: pywin32 (>=224) -Requires-Dist: crypto (>=1.4.1) - -# OpenRPA -First open source RPA platform for business is released! - -# How to run -Studio -Double click to Studio\StudioRun_32.cmd or Studio\StudioRun_64.cmd - -# Robot how to debug -Robot\PythonDebug_64.cmd -import Robot -Robot.ActivityRun( - { - ModuleName: <"GUI"|..., str>, - ActivityName: , - ArgumentList: [, ...] - optional, - ArgumentDict: {:, ...} - optional - } -) - -# Robot example script: -Robot\Examples\GetFolderList\Python_32_Script_Run.cmd - -# Python 32 bit -Resources\WPy32-3720\python-3.7.2\python.exe - -# Python 64 bit -Resources\WPy64-3720\python-3.7.2.amd64\python.exe - -# Module GUI activity List: -############################ -Новая версия -############################ -Получить список элементов, который удовлетворяет условиям через расширенный движок поиска -[ - { - "index":<Позиция элемента в родительском объекте>, - "depth_start" - глубина, с которой начинается поиск (по умолчанию 1) - "depth_end" - глубина, до которой ведется поиск (по умолчанию 1) - "class_name" - наименование класса, который требуется искать - "title" - наименование заголовка - "rich_text" - наименование rich_text - } -] - - -# Open RPA Wiki -- [Home](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/home) -- [04. Desktop app access (win32 & ui automation)](https://gitlab.com/UnicodeLabs/OpenRPA/wikis/04.-Desktop-app-access-(win32-&-ui-automation)) - -#Dependencies -* Python 3 x32 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* Python 3 x64 [psutil, pywinauto, wmi, PIL, keyboard, pyautogui, win32api (pywin32), selenium, openCV, tesseract, requests, lxml, PyMuPDF] -* pywinauto (Windows GUI automation) -* Semantic UI CSS framework -* JsRender by https://www.jsviews.com (switch to Handlebars) -* Handlebars - -Created by Unicode Labs (Ivan Maslov) - diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/RECORD b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/RECORD deleted file mode 100644 index 1385b6c0..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/RECORD +++ /dev/null @@ -1,319 +0,0 @@ -pyOpenRPA-1.1.20.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pyOpenRPA-1.1.20.dist-info/METADATA,sha256=B3Ph33GyqyoXYSX_0wGNMu6KLwFG_lj6NIXaCKJP-TA,3352 -pyOpenRPA-1.1.20.dist-info/RECORD,, -pyOpenRPA-1.1.20.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA-1.1.20.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 -pyOpenRPA-1.1.20.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 -pyOpenRPA/.idea/inspectionProfiles/profiles_settings.xml,sha256=YXLFmX7rPNGcnKK1uX1uKYPN0fpgskYNe7t0BV7cqkY,174 -pyOpenRPA/.idea/misc.xml,sha256=ySjeaQ1DfqxaRTlFGT_3zW5r9mWuwxoAK_AX4QiuAZM,203 -pyOpenRPA/.idea/modules.xml,sha256=Q__U1JIA2cjxbLRXAv-SfYY00fZA0TNlpkkbY4s3ncg,277 -pyOpenRPA/.idea/pyOpenRPA.iml,sha256=EXh41F8lqRiSBMVg-n2tKaEaHC6_3gGSuKkPJA12Na0,408 -pyOpenRPA/.idea/vcs.xml,sha256=2HygA1oRAwc3VBf-irxHrX5JJG9DXuQwrN0BlubhoKY,191 -pyOpenRPA/.idea/workspace.xml,sha256=kcCP7x0iSOAWJdy7YtntGrgsQ04QIq0b6_9w04DKxfg,2555 -pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85 -pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=y1Dyb8wmRcJmk1SxTVmgpR8r64Aa-Io9MG_5khvYgH0,3672 -pyOpenRPA/Orchestrator/Orchestrator.py,sha256=32AVVDVpMgam9Zg5n79WJDiuhGQTehtBWTFQrm6Mzhg,12387 -pyOpenRPA/Orchestrator/Processor.py,sha256=JI7nnkwXXnpkSJx6GlxoPjjiFOv3q3e-xZDLxKVYKrg,12634 -pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531 -pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=YB5HJL-Qf4IlVrFHyRv_ZMJ0Vo4vjyYqWKjvrTnf1k4,1564 -pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=fEwwCaYggb_KB72_9Bi-bn1zvglssNWNaWz9GTaiVk4,26543 -pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657 -pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=AQ_u9QVSLpce9hhSacm3UT98bErc636MXza4Q6mHsSc,12264 -pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=jCtHXExgRW0licn8K-xSO3tFd6P-4IFzp46TdS57vQ4,10726 -pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144 -pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=JEMVYkEmNcfg_p8isdIyvj9E-2ZB5mj-R3MkcNMKxkA,2426 -pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077 -pyOpenRPA/Orchestrator/RobotRDPActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Orchestrator/RobotRDPActive/__main__.py,sha256=z9PaUK4_nBiGd0YJdYVHV_rFx6VjZaxrrmKxSyoTFwY,2508 -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/CMDStr.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Clipboard.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Connector.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/ConnectorExceptions.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Processor.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/RobotRDPActive.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Scheduler.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 -pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492 -pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 -pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593 -pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Monitor.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Orchestrator/Server.py,sha256=dO82x5_tmPSn0oKgdYs7BzM3kZZkh5MWNegxUEwE01I,25694 -pyOpenRPA/Orchestrator/ServerSettings.py,sha256=dK8pQzg2mcLPjbizOPCP7yHMMVLiTh8RbYVnJXn-Mvg,15640 -pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097 -pyOpenRPA/Orchestrator/Web/Index.js,sha256=zdbj1ioNgxhprLpGIQ2YYraKUMUpkBiVoR-3GXGR5X0,28258 -pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=uRjdlkK8-yyrh4y3BkBYlFkRHzzPlHWz5dRh1FmG5QE,14260 -pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 -pyOpenRPA/Orchestrator/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 -pyOpenRPA/Orchestrator/__main__.py,sha256=cOd8WU77VGgzTZUB0WmWpPmdYyMZY1zVyuU9yx26MKs,144 -pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/Orchestrator.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/Processor.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/Server.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/ServerSettings.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/Timer.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Orchestrator/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293 -pyOpenRPA/Resources/Web/Google/LatoItalic.css,sha256=pB6OZ6F2VsaqkL-g5hW-wE_T0m9H_NltzmzjX-XAKDk,3112 -pyOpenRPA/Resources/Web/Handlebars/handlebars-v4.1.2.js,sha256=h6O4BrhyPtJspLDEQwogC53uHFRozuBpxvN2S4tJHE8,171994 -pyOpenRPA/Resources/Web/JsRender/jsrender.min.js,sha256=00hs6PwCiAfN_gatFdLofj3yBf8ue5Z7jCXX_th2FFg,25927 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/.versions,sha256=gGkuqPk07gAhjnNJVjVR_BA4SSBzqazbY8eEpddH01U,72 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/LICENSE,sha256=ifWbZZ0piwisfkIil1gacnBMxNnAHa7yCn1etItX1Y4,1102 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/README.md,sha256=oITQ5k-7jxoYAAQpzAXFROqgcnGzPrTd7GqkZSGqKW8,448 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/accordion.css,sha256=UC6U37i_pXBVMlUmFMLi1S8FIhFycJjAePP-hRGKzQM,8971 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/accordion.js,sha256=6cCQ6FlT1bM_QA4OpA_vfMljasKU1foGszlAIyhWi3A,20790 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/accordion.min.css,sha256=u9_5Zru9uMTtrXZpdfLawT_kJ5LFcmrMFr1QWXfDqwA,6955 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/accordion.min.js,sha256=kt0Dfi-mrxAU-iYsfDrkROHrb55Hi0lVWC7MT46_xnU,7100 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/ad.css,sha256=CiW55EUiruW1Tp0jrz2yDvQ8jYxDVMDmVcROV5_eBzo,4176 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/ad.min.css,sha256=7D7QYK0TBRyE4dN3SYXD_owb0j8UXywfPKzab2e743I,2066 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/api.js,sha256=Vjx6JZpe0iVJ6t8gp3TO3UjIyZkNBPN-taCS8MWwvJI,40952 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/api.min.js,sha256=und4HgOg2CxzBcqdJOvcT9LfJx0Hf9xQmEO_u7r1Ync,14594 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/breadcrumb.css,sha256=SJD_Mmi9BUmGXVhCXlIM1ei93yJVreQx0FAT68_t01w,2166 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/breadcrumb.min.css,sha256=-40OBPSbvydFFq9P3XPydeyWOrsh8g600mK9HXNoLnI,1192 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/button.css,sha256=wdCjDbx3M-jkpA7whQetZvX3ZE7wyBwRlCbcTVXKobc,116361 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/button.min.css,sha256=37bmMDGVPsjpcyAe7GqWsqv3UpsPTvlE5AiCVtT5NxY,90207 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/card.css,sha256=0oHZ2Qh74uybsgxLhP2ag_kQGTyOx3Kbzsjs6LvARzI,25330 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/card.min.css,sha256=anR2MHuWyx-iEc6wsI5nBMWnboFRqvOT7r-KOrKK-BQ,17410 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/checkbox.css,sha256=5u4dyQfH-wpdFbakv5CV4uIhWbBb2Tge0ZC5-tA2dX8,17473 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/checkbox.js,sha256=s-cRpbhGBxHgpnZdU3yFZciSW4n1QuruHjkX6gCyqT0,26912 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/checkbox.min.css,sha256=cy6WFzeIQ_5hHE7LEFxAK8yfR_zdfjoEubGRy1wCLv4,12727 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/checkbox.min.js,sha256=mlvPY4Gm-w6mgnAZ2GVMiBo5UDU7x_vaxKA5VRxdjR4,11369 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/colorize.js,sha256=imQdcIH6qpozSWEYeIpilPOfKHOJbD6V9RuKOC7yyEE,8710 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/colorize.min.js,sha256=oUDFJRLSaINMaJIZmuzYttfcMgkb7I6CpuEJ6bMfAVI,3270 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/comment.css,sha256=WAotERTFZQyxKNDJiSLlreq5KVja4xNM_bXUeG7NyVQ,5120 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/comment.min.css,sha256=JYlEkH8IupEqfItr2N9WZaNYkyF6rX2bnP6Y8ktXdCU,2945 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/container.css,sha256=bzDnWjcw404DoiHuz6-3iMRmbzJePDPgUGHcx3nFAuU,3099 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/container.min.css,sha256=VizQkNfO7_OANkM37_7xKxHQPEcUTBRuj3R_xkaULO8,1925 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dimmer.css,sha256=xKjQ9JWKG6zlrjyB5zECQc5vLZ7uCg7S5X-aUNKh6b8,5559 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dimmer.js,sha256=TuB9IPn4wx2n47nRVYf9CKvLotDL9d7gQcNArXupiRU,22303 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dimmer.min.css,sha256=-MBET9URQztSrMHpKaB8oyTckkm-lXisQbuxqd2UyOk,3517 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dimmer.min.js,sha256=4jCyaIQIKQX4zzzvspDqEvUmsPnpkr5lFuDOvKR_Wbo,8071 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/divider.css,sha256=a_0UrPhzoGJZZd8PBDgc5C0utGbzM6hjZbkDyy4pzfw,8034 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/divider.min.css,sha256=2XcokR56EPJZJh0ofnGgp-QPx2VpHYzDcdZdtR08uBs,6097 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dropdown.css,sha256=rJfAK26TU_FrVEYQxX1iWS4Z91SORlfnM128BfpI1II,37420 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dropdown.js,sha256=KnpOJhLPr4nCvh6M4qxqs8Y8lPGNZgLK6jZcGWrYzHo,145962 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dropdown.min.css,sha256=7Lwg8bz5Df_7YZ6D-ywoa01hT3IkqC09ZKBKtGe6gow,25679 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/dropdown.min.js,sha256=uEocYy6a0MpPLLHtYV7QAGdOeMRwE0Am2WtnOg_hBfM,50895 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/embed.css,sha256=19QhoCUbplkH_W5a7ejlpO6PoqSEFVA1xdHvaZp98yw,3169 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/embed.js,sha256=O3znHvAxO5xYlwzn4y3lQDde_iTdy29iUAmPqNfg4-0,20926 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/embed.min.css,sha256=SHH3TOGQhg1d5mrYCZeko1qvN3_NoETWQzBmfGUOpjc,1836 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/embed.min.js,sha256=QN4vIzPRpT4BFVPyA702nPG8nZKWfM-HygoF9jPBDJA,7728 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/feed.css,sha256=aFj6fLvIPQfeRxyKu_TlLKeUcwmI5GwOR7pY1Lb0JKM,5845 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/feed.min.css,sha256=-l8OBrtbhQi-fhQLHwA0cut_JWOuRWc44I0KpPxUx_M,3590 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/flag.css,sha256=rvyaZDdUGBPNuvOE8lzpW-Z4q3LYkJi8T99JlN1aF3E,22423 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/flag.min.css,sha256=WX74cISnDHD9kiyzCAiXiUWfnmv6cwdmBXgXtA5TUuw,18577 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/form.css,sha256=oNyqIev2BGrxigiMt72unbkne8-OWJ6UtaUGM4XZ9Y4,29092 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/form.js,sha256=FCxhpdJMgA6H88ka82b0jcqg-a8S53T0sVVbS_chLPA,57618 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/form.min.css,sha256=BmOkPn-zjy4WbHvcIvm18Vq0nhJjwADEBxvsLqX0sXg,21568 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/form.min.js,sha256=fK_KHBgbjblWL2-hRtohUzj6b12XWi6pVujkG1Ru9-w,20458 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/grid.css,sha256=I35Jh57rWCJoLMuJYXksccmBzc6V1XC1Mi_na_oAp84,73036 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/grid.min.css,sha256=5iW6X6_QT_7PgFBce4OTfLOOaSoovOoOb2U8w1yZDtc,57335 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/header.css,sha256=32EgHb7XmTT_AWH7Nr08PjXP2op-xhwlSqSIThcZKmY,13499 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/header.min.css,sha256=hHgAxfAsLFDPcyU6T6cRE_M6R-4rKEfPX5kOHVyJNes,8872 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/icon.css,sha256=CHLhcJDvnks69dz2lyZC0idfGnPFx4qdKA82Hm_bEDo,86945 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/icon.min.css,sha256=4opKQbtTAtsuIkfkEMuIA3eD3T4m1X3mfiCVTS6x2_A,67019 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/image.css,sha256=eZLe0mOsWAJETFvjXHlZXAnSY87SGQlRDJna2_EZ67U,5676 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/image.min.css,sha256=eXzqGHi6p4yiYGCiYPOcGXYbKeQtA0Df_w0gN88KCD0,3727 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/input.css,sha256=lYFTBK5TuWVaB2LSwjdl83iM9l4rn7jPwoFcEfvHQR8,12699 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/input.min.css,sha256=4ouF0Y10UKjiT6iJlHxD5aOe8WljYoAxPqpiy7iEdSw,8692 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/item.css,sha256=O1HR21E9wHtGxCmsqxcEc_65R6Ln3mOvImRwYMQso1g,9753 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/item.min.css,sha256=JRycvfshgviiiwTeAKUj0iPOov4-Uwaue3fTqaY_e5s,5985 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/label.css,sha256=9tLlAtf1Y3NSngCdO1DZ5YcRW_bu2dUKYUAXHPXm2hQ,28382 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/label.min.css,sha256=lzompqItwR2t_PJowmd07tg8QUPAb6yj58N9TwuNS6I,20005 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/list.css,sha256=CI9lvTBhVzN64aRNjJIwhG6bhKydfIbk_RdYQiaAYwE,22486 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/list.min.css,sha256=uXVJMLBcGUe7MZETm-CQO5LMhIbTFxajYZRBFTCTftY,16094 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/loader.css,sha256=Yz3gBB1JS-86XzSzztcNLE24ViO7UnP15A4M4hrFZUY,7128 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/loader.min.css,sha256=XtALKS7EZswkHXCCOthbxsuu36_tpZbqh-LMT1gaRAg,4702 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/menu.css,sha256=aOYMc10qx8D7fVQ7R83XXUkbrrFExpWkWc6ZnECfOJ4,45279 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/menu.min.css,sha256=cRSLOaiPiyfTQ4B4HT1OCF_2CWNzGcPO9Nns6Jrf4hg,31506 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/message.css,sha256=baLR2EbwIWTGTSvNc9qb2FmcWBeZHM3W0kBNvEdxZZU,12466 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/message.min.css,sha256=_plszMa027XkVjjehCTWxgIAftsTT1alP5I6EYfoVMI,8354 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/modal.css,sha256=86mR_k66q9mOP7jwLV6J4iRW1a06eSyQ6tcoZpUlHf8,12800 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/modal.js,sha256=ACX5Za25KIugyXD7eFndkqa18n7LHjZrBkWSpLs8uqQ,33442 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/modal.min.css,sha256=2GGe09HtCS6k__kprnoTwPMNu2CFCjEpaLQ2NBMLua8,8012 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/modal.min.js,sha256=8POmd6680Gev-MdgKbVOHP-9lm-9WB1AVyuLf2WRcxc,12701 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/nag.css,sha256=3Pz6rq1vWHNvB7UHhGFMPYvrP7VZP_pTM4PlwthnviI,2727 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/nag.js,sha256=KuXGvpOopM0i7syRO2cLSXrJ5I7AjwW3m7JMJLfGuN4,15553 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/nag.min.css,sha256=ohX1Du58QE8pgiBVEzmlhuT2rERTdxY4sasod_53NV4,1483 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/nag.min.js,sha256=UN_1Vcu3C_zxEatS7UZKw1x2blSyihZT2F1cmq7UZOk,5696 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/placeholder.css,sha256=ihZF0mK6texbUk_qWnqHqoZ0scXyDhHy-tr77Wougwg,5938 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/placeholder.min.css,sha256=UIFHVCJ1agMPhpUv-aqm6GeN3EmqUv5vClMm_5LEpuM,4452 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/popup.css,sha256=EitCUPKebavrCN6zwsWGZKfKCNjRJhaEGf6dJlCim7g,17407 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/popup.js,sha256=kzErFmfWsOMKZH-mbyLXQpJo_ajderu7pnq_faA7teM,52273 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/popup.min.css,sha256=YlUBHRAaq5FwMcI2g3DQtgcmxmRNG1rEZaGK2LCgVZ0,12032 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/popup.min.js,sha256=VvJYDjsOSD6VaYYZhuQYiPOpBbpRnmaddxVd6shZ9mU,18630 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/progress.css,sha256=p2R5CYj1cVgj0mT7XTBcKKky02140m4A-PumSFirAqc,10669 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/progress.js,sha256=uAQsAqW_DWnH0hK5dC0MVBBwuDyyu8UNolLxO0OSCfs,31204 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/progress.min.css,sha256=JtEqDPto1ZJiE-6k_WoZnzlhFUgwLJqH6VowDWGRez4,7422 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/progress.min.js,sha256=B676J_Jywi6IJ9e_E62nmk7Gn9KDkRQc7RfcIBKPQcI,12331 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rail.css,sha256=XUZeNKRfoqs2bRnKz49lJU8ufQ625eFrtL7IxXLzBD0,2646 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rail.min.css,sha256=4rrNcI5NVX845Bc9aBTWjwjg7tnakWuMHl8zWK-ucmE,1453 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rating.css,sha256=E_jbykfZK88UZ6kKhL0T8mqn29mzefpwNzCDZEkIyKE,20696 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rating.js,sha256=rxHeOv-TB5-ViM9hOfODUZMGqWUMNyPvIVIov306LuQ,14869 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rating.min.css,sha256=4coaKkBwUtNfJL53qHC_TzTE7BmLMuVxDu_Z3gGOs7Q,18393 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/rating.min.js,sha256=jprk9qns6QqU1UWGtHMwug9A_ls7tVMV8p2mueJlj74,5354 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/reset.css,sha256=ygW8luaW-MLjYb6fFQYl0HBo4w-P9zwYkVZLpFOMFh0,9123 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/reset.min.css,sha256=Cm0OrnD_mnGgt3DPmGhhNLeNUAfYfQlCX2uCK7TG_o8,2822 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/reveal.css,sha256=33mQj7j0sprB4_0PrBqMJXxyXXFs4eP2rKoraaht8e8,8177 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/reveal.min.css,sha256=cHuyo1zDTWJH9C1f1GPtKHwuTzA_IUSFAfTH3q5yoME,5784 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/search.css,sha256=XN5UApUr9lkI_R-ThVSHhNM3UEMEvl8Z6LAYhFABPKw,10377 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/search.js,sha256=bm3TK1__R62sMnnTL_haoNAZiWbua0IGEgwfdQRpuRo,51211 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/search.min.css,sha256=HONcBrv7-3sDkmJ9Zwh8KYXWyy_fUw_MjDjhNMtU7hU,6891 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/search.min.js,sha256=gkqnhj5TvM_vwvHKAb4zBC7uL6mndcAlK6CEv5iEUwg,17622 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/segment.css,sha256=FERuSI78q9zgv_iWxHnXIbSnJDsgNKaLh8IgThCD9OM,20063 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/segment.min.css,sha256=zLmNnl__Po9TAZWlayMZpH_DpZXhaHXTcSa8KGeRxMs,13763 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/shape.css,sha256=5sbfPkJ2vSJEo7Ht21qKtfupKDnPdYtwpxkszIHwqsY,3865 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/shape.js,sha256=6D_QO1uZyRzcGRxxaCGP4zRTcnHH-rF11XSDj8fsVn0,29873 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/shape.min.css,sha256=7KDwgqAZXncDCzulBQT3C9UcI_kopiPdoSF2NxpJQWE,2521 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/shape.min.js,sha256=Njt3jnaL2VeRaG0rRHt2niY7YXHeD4Z_fj17tN2syLU,10803 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sidebar.css,sha256=pboKxonzco97CJSpXvUG9Bj65PyqdlTlmi8C_XNQcJI,15757 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sidebar.js,sha256=-nippst3RqSK6cFS0b1VQIhhZ7x455Oq5vpvjxdFOhc,34488 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sidebar.min.css,sha256=FxNmgO-xW6HZ8kqkaDpzZG2GGTYYvBIkhHFsPPUx8f8,10726 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sidebar.min.js,sha256=LxCRzL8rRPXulWQPWkMgncUHL0hBU4IHsuNOVzIMi3I,13466 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/site.css,sha256=tpW_cbiDbTbWVk1ECO4bnddYLlytmUgArSW1Jx3x9DU,3918 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/site.js,sha256=-yF4ejA2WwzIujQ1y9b-i6dxpRYCE8lCSU76CQ9hZhw,14604 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/site.min.css,sha256=AYTFsBcTjn7JH9tBf1s3S68Fxr83IHQf5t5FpD0vGcw,2452 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/site.min.js,sha256=f-45BTFplAj5X_I64VjaIAqTulT6dVhF-rHvOG8pZpM,6066 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/state.js,sha256=rdhOQ83U-t08-IE-ZL7qwiJ_2NPtm0E--BfFJVRylSY,21498 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/state.min.js,sha256=sgXcJIgGI3ymppa7VewFhV3g4rnB_D55Yvoo-QX4Whw,7804 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/statistic.css,sha256=zC6fj8Mg8giRj0rcaq1GVcAfmdLfb0QYgBx_B-7bXlE,13221 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/statistic.min.css,sha256=Nbx1qdI_NIb-YBfRIMcmKn-IdY5OmUdd8gNIGgA2TCs,9594 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/step.css,sha256=3dgzVkMcFYJKP_UPk7quva4L7GLD6sln1aroRZlrcw8,23555 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/step.min.css,sha256=hifahh65UcRx9Cux-rpwi5pTJImD83BlfH1qbkiaWCI,19188 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sticky.css,sha256=eOSA5O3_qugssoDgdTovRNvNMe0kEWqQz1yQGJFZCQM,1288 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sticky.js,sha256=kHIMXTF2Wj8DYTaDRRqQ9ZVNUTOjDbBF84Dwm4tFYaM,31814 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sticky.min.css,sha256=SYOFZjW67UWxBsrtAfD4g0Tvf6CnltYw_IN0VemK2hU,607 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/sticky.min.js,sha256=fu91ThJa6qnZoQAGTpxUw5Q1UN7d2Y_KHS0kjoteWCw,11854 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/tab.css,sha256=aX-PA0rhwxK3q6l3A3przKBvFAQ9LkhlDV3mETbQR98,1865 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/tab.js,sha256=xvNcoJnirQ1TJgVMy_8_AARTIveekx3bgoXNLc-FhC0,33771 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/tab.min.css,sha256=vTnhMR4q6W1dLyB3QYdtwRWnl2XLdtFA0I3kSnZH_EY,1075 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/tab.min.js,sha256=MgUTbr8RHTNylv3wIeBmCec-mS1iL9IJW7Y0NahYmrs,11487 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/table.css,sha256=omOnJC5bkklgjC6vJgTYJae-wbp3MSIu-mUM0gc5Q-o,25536 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/table.min.css,sha256=ODiMJS5bcTBrVMu-BtZytuSNpu3wHtILDb8no5BLNhw,18015 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/transition.css,sha256=XMKp0LQFx2Ec2oOjFuAPJik8VrDUgysP4TNOJH3Rzuw,49176 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/transition.js,sha256=sccxnC8Z9hx9lzlJLPYQ9E5FHETVYEVaA1uIQaA7ubU,36076 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/transition.min.css,sha256=cty1gaoozlRlEnqcQir7t93a7sOy2uCLp0c4jyBLWwA,33525 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/transition.min.js,sha256=k30cmb6hiQ_LGKpX2AcllUduUJ0kA4DKKStgUxkGQzM,13010 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/video.css,sha256=R9cpZZmFTZ70NmFVp7XhHOXaoZ3iodK1WlxGrisY7Tw,2346 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/video.js,sha256=Si_eMYc42BiLyyl4ur4u7K17kyw9biw-eAtbidaQH0c,16252 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/video.min.css,sha256=0MWKfR7_d_meresYhKG49N4ikgDL9YKvdj4ffNqhti0,1328 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/video.min.js,sha256=f7uHgbRqRCqHKBJm7CB31wMMnTjYHPmYaLi1D2i9QfI,6090 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/visibility.js,sha256=p_2kDyoT-GlUY_iLWH8RCRtSl-zunZ1oNx3dJwvyKbA,44180 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/visibility.min.js,sha256=Th3QlAMxD5M2RJ9nNOvuxJZCgZIlavx5-51jABKTs2A,16294 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/visit.js,sha256=9DsUmsPzmp3XD1pplmIeV5tNIeqEHMml5hcr3omsBJw,16142 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/components/visit.min.js,sha256=bT8zWI7mcAwX-Fyt67gogo3u_IT7q8uimamY5Vhk3eU,5887 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/package.js,sha256=BHq6qGCSMdDXDGJxZ4zxnKaREbFM2un2VqCkydrBTf0,774 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/package.json,sha256=Sy3ZVA4SxFzecOO88h1IVAnBiuDpRtXiUg6ME_YArI0,524 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/semantic.css,sha256=aje_ma2N_7VT1k2QTOLeqr3SfQ3Cr-7vB05D2-uo-YQ,869203 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/semantic.js,sha256=t-thIOFbQol3-vcB3C7kRbS49jG2_LC5dEp7NLxBpuA,759089 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/semantic.min.css,sha256=f5Dpq5VRrbzn8POovxN9HR3S7LhHQIAiCKYz4PB4ZZA,628934 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/semantic.min.js,sha256=69cT25pJVUmAyniwWMglXlEOEeZYuhmD8Hbj58gCS7Y,275740 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/brand-icons.eot,sha256=0CPFX94iBJXxOoe3KZXg35jI0ok1dymdGZ2lu_W0_gI,98640 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/brand-icons.svg,sha256=IcTTApw6luFW48z0iPvWxbD_LpBQYBaIN5LGFInrfpU,508636 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/brand-icons.ttf,sha256=QuNp3Iw3KXO6d6gmti0seiBwUyMT34MqIyiN23aXQVg,98404 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/brand-icons.woff,sha256=n6_Ww-e_wUXbQqkG5fpo_mpvlyIfAT0-gz_DIxuZLEQ,63728 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/brand-icons.woff2,sha256=59TVNAu-V6Adj3mSFC4nY9Q41Xg4kMdnSDBu6_oFamk,54488 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.eot,sha256=i04bhH4iIz1PRn00-u_nvL_rzm-pu77lYMRc2JSGh1E,106004 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.otf,sha256=vcXQufOXvoPohsdLAUHRlUqkOEs1nc5JgpmUxKLh978,93888 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.svg,sha256=GzY2PC_CxigjA7ao5Pm45c8-mD38cSHKeoiagKC-kA4,392355 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.ttf,sha256=y3-B9UL1xBiju7mtP5--eEFR0TsEzsUOzt7GATMko9o,105784 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff,sha256=lbakhA-HEeyrQnvCNuuGCY235ceCuvsTnIwwgFql_-E,50524 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff2,sha256=Q0RmtZVFqKHKxt2zgZfNxrNZlamMPzgS-4jWGxwwDdM,40148 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outline-icons.eot,sha256=RTf6BjQO5iwmTp16TYqryrPee9osXMM0AQ9GtoMQb8s,31156 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outline-icons.svg,sha256=T4_RcS28l2Pa57YNTH3ryg_433tFrdN6pDBt0iGL1zE,107567 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outline-icons.ttf,sha256=Zxchcur85FY3JeZhBD1duFS4Z2ip6L05dY2-gcR5aTU,30928 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outline-icons.woff,sha256=S8NZwnBXs-0LrKZtbFNJpdSmBQlvvHh1Bhui2Ro9bQU,14712 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outline-icons.woff2,sha256=TSiDRDsk5CRSf2oKeqKJez33HyOdtANzxP92DkgUeAE,12240 -pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123 -pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713 -pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899 -pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI,722 -pyOpenRPA/Robot/OrchestratorConnector.py,sha256=JUtdiUXCruqUqBD19gJBl9jk_b-tpWWx_v3MfBoKzoQ,20445 -pyOpenRPA/Robot/README.md,sha256=e2hKh7Tx6DAsX6jY_hBDhguL1L2Wiv6iugDB5otMzIA,2293 -pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 -pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 -pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476 -pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 -pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524 -pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039 -pyOpenRPA/Robot/Utils/TimerRepeat.py,sha256=_kTct3X9SIEvS3DKM5bGNnjRBVJasmMFZntQaVbPX_E,961 -pyOpenRPA/Robot/Utils/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 -pyOpenRPA/Robot/Utils/__init__.py,sha256=pHlSQGRFKmn5RCTHIf-3a2ooA9T2xNOWridckynP7W4,28 -pyOpenRPA/Robot/Utils/__pycache__/JSONNormalize.cpython-37.pyc,, -pyOpenRPA/Robot/Utils/__pycache__/ProcessBitness.cpython-37.pyc,, -pyOpenRPA/Robot/Utils/__pycache__/ProcessCommunicator.cpython-37.pyc,, -pyOpenRPA/Robot/Utils/__pycache__/TimerRepeat.cpython-37.pyc,, -pyOpenRPA/Robot/Utils/__pycache__/ValueVerify.cpython-37.pyc,, -pyOpenRPA/Robot/Utils/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Robot/Window.py,sha256=UJl-sg4RvvJ35aG9jZOzqGVwE15XK7qPHqoOBD13xFk,431 -pyOpenRPA/Robot/__init__.py,sha256=L-5tPm6evytGWOzlqIq-2oiIhmQnruaxwIstyyaMkVI,253 -pyOpenRPA/Robot/__main__.py,sha256=l6II8JuXCsnVOcfs6-2jvogKYTVhbfj3Jl2ld3OIP7s,1992 -pyOpenRPA/Robot/__pycache__/Clipboard.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/OrchestratorConnector.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/SettingsTemplate.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/Test.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/UIDesktop.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/Window.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347 -pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912 -pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038 -pyOpenRPA/Studio/Studio.py,sha256=_BXQjAMHew2fRWloXdqPOmYHX6i6C8ELPsW1TZNvjz4,8618 -pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 -pyOpenRPA/Studio/Web/Index.xhtml,sha256=wo3Y5CzWJQYMw9AgNHXynt1yGDLIoihRlt1weFLSuYQ,48240 -pyOpenRPA/Studio/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 -pyOpenRPA/Studio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Studio/__main__.py,sha256=_57Rnq9DKbmmlpGFqIwVrWn_LRcU8jjmMTOny4_zlP8,308 -pyOpenRPA/Studio/__pycache__/JSONNormalize.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/ProcessCommunicator.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/RobotConnector.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 -pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473 -pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655 -pyOpenRPA/Tools/RobotDB/Server.py,sha256=rjW9Sg-j9P8pFQD66Uih-rke6-f6sCulinwi4_W-3mc,19933 -pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 -pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 -pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 -pyOpenRPA/Tools/RobotDB/__pycache__/ExcelCom.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/__pycache__/RobotDB.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/__pycache__/Server.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Tools/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 -pyOpenRPA/Tools/RobotScreenActive/Monitor.py,sha256=TV-YisVqa_uGiyJLG9oK4u-5aDjGiFYZFh1dPjOgYc8,492 -pyOpenRPA/Tools/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 -pyOpenRPA/Tools/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Tools/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593 -pyOpenRPA/Tools/RobotScreenActive/__pycache__/Monitor.cpython-37.pyc,, -pyOpenRPA/Tools/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,, -pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Tools/SafeSource/Crypter.py,sha256=VRrE5-oQxQtvMEPHM1lMXp2CKnceNBmIWJnsJoJkaVE,3616 -pyOpenRPA/Tools/SafeSource/DistrCreate.py,sha256=-_8BTle57LBKVknnB_3af-LghxrRmRGfRNu08CLNIvY,3232 -pyOpenRPA/Tools/SafeSource/DistrRun.py,sha256=zwUh6Jy-rDAZHV6fcTUMupkukojntFMroHJHMsNQgrE,9637 -pyOpenRPA/Tools/SafeSource/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Tools/SafeSource/__main__.py,sha256=g5aYWnuUZoM2jDX2mSIl9tRAJg05tu5VxD2rGJWcACg,649 -pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,, -pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,, -pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,, -pyOpenRPA/Tools/Terminator.py,sha256=VcjX3gFXiCGu3MMCidhrTNsmC9wsAqfjRJdTSU9fLnU,2178 -pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pyOpenRPA/Tools/__pycache__/Terminator.cpython-37.pyc,, -pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/__init__.py,sha256=HIl4GtAt0lGzG2lJPyRwIevTFjIX1iwfYYFpPSUlxAc,175 -pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/REQUESTED b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/REQUESTED deleted file mode 100644 index e69de29b..00000000 diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/WHEEL b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/WHEEL deleted file mode 100644 index e499438d..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/top_level.txt b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/top_level.txt deleted file mode 100644 index 4170df85..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.1.20.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pyOpenRPA diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/BackwardCompatibility.py index 763119c8..0cc82b95 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/BackwardCompatibility.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/BackwardCompatibility.py @@ -1,6 +1,288 @@ # Def to check inGSettings and update structure to the backward compatibility # !!! ATTENTION: Backward compatibility has been started from v1.1.13 !!! # So you can use config of the orchestrator 1.1.13 in new Orchestrator versions and all will be ok :) (hope it's true) +import win32security, json, datetime, time, copy + +# # # # # # # # # # # # # # # # # # # +# Backward compatibility Web defs up to v1.2.0 +# # # # # # # # # # # # # # # # # # # + +# UserAccess get rights hierarchy dict in json +def v1_2_0_UserRoleHierarchyGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + # Create result JSON + lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list + # Send message back to client + message = json.dumps(lResultDict) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") + +from inspect import signature # For detect count of def args +# /Orchestrator/RobotRDPActive/ControlPanelDictGet +def v1_2_0_RobotRDPActive_ControlPanelDictGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + lResultDict = { + "DataList":[ + # {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} + ] + } + # Iterate throught the RDP List + for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: + lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][lRDPSessionKeyStrItem] # Get the configuration dict + lDataItemDict = {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} # Template + lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str + lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex + lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"]["FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window + lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored + lResultDict["DataList"].append(lDataItemDict) + # Send message back to client + message = json.dumps(lResultDict) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") + +# def to check control panels for selected session +def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict): + lL = inGlobalDict["Logger"] # Alias for logger + lLifetimeSecFloat = inGlobalDict["Client"]["Session"]["LifetimeSecFloat"] + lLifetimeRequestSecFloat = inGlobalDict["Client"]["Session"]["LifetimeRequestSecFloat"] + lControlPanelRefreshIntervalSecFloat = inGlobalDict["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"] + lCookieSessionGUIDStr = None # generate the new GUID + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Technicaldef - interval check control panels + check actuality of the session by the datetime + def TechnicalCheck(): + lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] + # Lifetime is ok - check control panel + lDatasetCurrentBytes = v1_2_0_Monitor_ControlPanelDictGet(inRequest,inGlobalDict) # Call the control panel + if lDatasetCurrentBytes != lItemValue["DatasetLast"]["ControlPanel"]["Data"]: # Check if dataset is changed + lItemValue["DatasetLast"]["ControlPanel"]["Data"] = lDatasetCurrentBytes # Set new datset + lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = True # Set flag to return the data + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Technicaldef - Create new session struct + def TechnicalSessionNew(inSessionGUIDStr): + lCookieSessionGUIDStr = inSessionGUIDStr # Generate the new GUID + lSessionNew = { # Session with some GUID str. On client session guid stored in cookie "SessionGUIDStr" + "InitDatetime": datetime.datetime.now(), # Datetime when session GUID was created + "DatasetLast": { + "ControlPanel": { + "Data": None, # Struct to check with new iterations. None if starts + "ReturnBool": False # flag to return, close request and return data as json + } + }, + "ClientRequestHandler": inRequest, # Last client request handler + "UserADStr": inRequest.OpenRPA["User"], # User, who connect. None if user is not exists + "DomainADStr": inRequest.OpenRPA["Domain"], # Domain of the user who connect. None if user is not exists + } + inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict + inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies + if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") + return lCookieSessionGUIDStr + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + lCreateNewSessionBool = False # Flag to create new session structure + # step 1 - get cookie SessionGUIDStr + lSessionGUIDStr = inRequest.headers.get("SessionGUIDStr", None) + if lSessionGUIDStr is not None: # Check if GUID session is ok + #inRequest.OpenRPAResponseDict["StatusCode"] = 301 + #inRequest.OpenRPAResponseDict["Headers"]["Location"] = "/" + #if lL: lL.info(f"GUID is detected - send HTTP 301 to refresh page") + lCookieSessionGUIDStr = lSessionGUIDStr # Get the existing GUID + if lSessionGUIDStr not in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: + lCookieSessionGUIDStr= TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session + else: # Update the datetime of the request session + inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]["InitDatetime"]=datetime.datetime.now() + else: + lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session + # Init the RobotRDPActive in another thread + #lThreadCheckCPInterval = threading.Thread(target=TechnicalIntervalCheck) + #lThreadCheckCPInterval.daemon = True # Run the thread in daemon mode. + #lThreadCheckCPInterval.start() # Start the thread execution. + + # Step 2 - interval check if data is exist + lTimeStartSecFloat = time.time() + lDoWhileBool = True # Flag to iterate throught the lifetime of the request + while lDoWhileBool: + #print(lTechnicalSessionGUIDCache) + #print(lCookieSessionGUIDStr) + if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: + lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] + if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key + if lL: lL.debug(f"Client request lifetime is over") + lDoWhileBool = False # Stop the iterations + if lDoWhileBool: + TechnicalCheck() # Calculate the CP + if lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] == True: # Return data if data flag it True + lDatasetCurrentBytes = lItemValue["DatasetLast"]["ControlPanel"]["Data"] # Set new dataset + inResponseDict = inRequest.OpenRPAResponseDict + inResponseDict["Body"] = lDatasetCurrentBytes + lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = False # Set flag that data was returned + lDoWhileBool = False # Stop the iterations + else: + lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lCookieSessionGUIDStr) # Create new session + if lDoWhileBool: # Sleep if we wait hte next iteration + time.sleep(lControlPanelRefreshIntervalSecFloat) # Sleep to the next iteration + +def v1_2_0_Monitor_ControlPanelDictGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + lL = inGlobalDict["Logger"] # Alias for logger + # Create result JSON + lResultJSON = {"RenderRobotList": [], "RenderRDPList": []} + lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] + for lItem in lRenderFunctionsRobotList: + lUACBool = True # Check if render function is applicable User Access Rights (UAC) + if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: + lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())] + if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]: + lUACBool = False # UAC Check is not passed - False for user + if lUACBool: # Run function if UAC is TRUE + # Выполнить вызов и записать результат + # Call def (inRequest, inGSettings) or def (inGSettings) + lItemResultDict = None + lDEFSignature = signature(lItem["RenderFunction"]) # Get signature of the def + lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args + try: + if lDEFARGLen == 1: # def (inGSettings) + lItemResultDict = lItem["RenderFunction"](inGlobalDict) + elif lDEFARGLen == 2: # def (inRequest, inGSettings) + lItemResultDict = lItem["RenderFunction"](inRequest, inGlobalDict) + elif lDEFARGLen == 0: # def () + lItemResultDict = lItem["RenderFunction"]() + # RunFunction + lResultJSON["RenderRobotList"].append(lItemResultDict) + except Exception as e: + if lL: lL.exception(f"Error in control panel. CP item {lItem}. Exception is below") + # Iterate throught the RDP list + for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: + lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][ + lRDPSessionKeyStrItem] # Get the configuration dict + lDataItemDict = {"SessionKeyStr": "", "SessionHexStr": "", "IsFullScreenBool": False, + "IsIgnoredBool": False} # Template + lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str + lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex + lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"][ + "FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window + lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored + lResultJSON["RenderRDPList"].append(lDataItemDict) + # Send message back to client + message = json.dumps(lResultJSON) + # Write content as utf-8 data + #inResponseDict["Body"] = bytes(message, "utf8") + return bytes(message, "utf8") + + +from . import __Orchestrator__ # For user defs + + + +# v1.2.0 Def for old procesor to new processor +# Return new activity for the new processor +def v1_2_0_ProcessorOld2NewActivityDict(inActivityOld): + if inActivityOld["Type"] == "WindowsLogon": + lResult = { + "Def": __Orchestrator__.OSCredentialsVerify, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":[], # Args list + "ArgDict":{"inUserStr": inActivityOld["User"],"inPasswordStr":inActivityOld["Password"],"inDomainStr":inActivityOld["Domain"]}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "GlobalDictKeyListValueGet": + lResult = { + "Def": __Orchestrator__.GSettingsKeyListValueGet, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":[], # Args list + "ArgDict":{"inKeyList": inActivityOld["KeyList"]}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "CMDStart": + lResult = { + "Def": __Orchestrator__.OSCMD, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inCMDStr": inActivityOld["Command"]}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "OrchestratorRestart": + lResult = { + "Def": __Orchestrator__.OrchestratorRestart, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "OrchestratorSessionSave": + lResult = { + "Def": __Orchestrator__.OrchestratorSessionSave, + # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "GlobalDictKeyListValueSet": + lResult = { + "Def": __Orchestrator__.GSettingsKeyListValueSet, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inKeyList": inActivityOld["KeyList"], "inValue": inActivityOld["Value"]}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "GlobalDictKeyListValueAppend": + lResult = { + "Def": __Orchestrator__.GSettingsKeyListValueAppend, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inKeyList": inActivityOld["KeyList"], "inValue": inActivityOld["Value"]}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "GlobalDictKeyListValueOperator+": + lResult = { + "Def": __Orchestrator__.GSettingsKeyListValueOperatorPlus, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inKeyList": inActivityOld["KeyList"], "inValue": inActivityOld["Value"]}, # Args dictionary + "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "ProcessStart": + lResult = { + "Def": __Orchestrator__.ProcessStart, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inPathStr": inActivityOld["Path"], "inArgList": inActivityOld["ArgList"]}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "ProcessStartIfTurnedOff": + lResult = { + "Def": __Orchestrator__.ProcessStart, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inPathStr": inActivityOld["Path"], "inArgList": inActivityOld["ArgList"], "inStopProcessNameWOExeStr": inActivityOld["CheckTaskName"]}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "ProcessStop": + lResult = { + "Def": __Orchestrator__.ProcessStop, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inProcessNameWOExeStr": inActivityOld["Name"], "inCloseForceBool": inActivityOld["FlagForce"], "inUserNameStr": inActivityOld["User"]}, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + elif inActivityOld["Type"] == "PythonStart": + lResult = { + "Def": __Orchestrator__.PythonStart, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList": [], # Args list + "ArgDict": {"inModulePathStr": inActivityOld["ModuleName"], "inDefNameStr": inActivityOld["FunctionName"], "inArgList": inActivityOld["ArgList"], + "inArgDict": inActivityOld["ArgDict"] }, # Args dictionary + "ArgGSettings": None, # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } + else: + raise Exception(f"BackwardCompatibility up to v1.2.0, old processor: No type {inActivityOld['Type']} has been found in old processor.") + return lResult # return the result + + +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # HERE IS THE MAIN DEF WHICH IS LAUNCHES WHEN START # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def Update(inGSettings): lL = inGSettings["Logger"] # Alias for logger # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @@ -8,7 +290,7 @@ def Update(inGSettings): # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if "Autocleaner" not in inGSettings: # Add "Autocleaner" structure inGSettings["Autocleaner"] = { # Some gurbage is collecting in g settings. So you can configure autocleaner to periodically clear gSettings - "IntervalSecFloat": 600.0, # Sec float to periodically clear gsettings + "IntervalSecFloat": 7200.0, # Sec float to periodically clear gsettings } if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Autocleaner' structure") # Log about compatibility if "Client" not in inGSettings: # Add "Client" structure @@ -34,10 +316,109 @@ def Update(inGSettings): } } if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Client' structure") # Log about compatibility - if "RequestTimeoutSecFloat" not in inGSettings["Server"]: # Add Server > "RequestTimeoutSecFloat" property + if "Server" in inGSettings and "RequestTimeoutSecFloat" not in inGSettings["Server"]: # Add Server > "RequestTimeoutSecFloat" property inGSettings["Server"]["RequestTimeoutSecFloat"] = 300 # Time to handle request in seconds if lL: lL.warning( f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility if "DefSettingsUpdatePathList" not in inGSettings["OrchestratorStart"]: # Add OrchestratorStart > "DefSettingsUpdatePathList" property inGSettings["OrchestratorStart"]["DefSettingsUpdatePathList"] = [] # List of the .py files which should be loaded before init the algorythms - if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility \ No newline at end of file + if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # v1.1.20 to v1.2.0 + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Update Structure gSettings["Processor"] + from . import SettingsTemplate + if "DumpLogListRefreshIntervalSecFloat" not in inGSettings["Client"]: # Create new ProcessorDict structure + inGSettings["Client"].update({ + "DumpLogListRefreshIntervalSecFloat": 3.0, # Duration between updates for the Client + "DumpLogListCountInt": 100, # Set the max row for the dump + "DumpLogList": [], # Will be filled automatically + "DumpLogListHashStr": None, # Will be filled automatically + }) + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'Client > DumpLog... with default parameters'") # Log about compatibility + if "Processor" in inGSettings: # Check if Processor exist + # Update Logger + if lL is not None: + SettingsTemplate.LoggerDumpLogHandlerAdd(inLogger=lL, inGSettingsClientDict=inGSettings["Client"]) + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Add web dump log in logger as handler") # Log about compatibility + del inGSettings["Processor"] # Remove the key + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Remove old structure 'Processor'") # Log about compatibility + if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure + inGSettings["ProcessorDict"]={ + "ActivityList": [ # List of the activities + # { + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3} # Args dictionary + # "ArgGSettings": # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # }, + ], + "AliasDefDict": {} , # Storage for def with Str alias. To use it see pyOpenRPA.Orchestrator.ControlPanel + "CheckIntervalSecFloat": 1.0, # Interval for check gSettings in ProcessorDict > ActivityList + "ExecuteBool": True, # Flag to execute thread processor + "ThreadIdInt": None # Fill thread id when processor will be inited + } + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'") # Log about compatibility + if "VersionStr" not in inGSettings: # Create new ProcessorDict structure + inGSettings["VersionStr"] = None + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'VersionStr'") # Log about compatibility + if "AgentDict" not in inGSettings: # Create new AgentDict structure + inGSettings["AgentDict"]= {} + if lL: lL.warning( + f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'AgentDict'") # Log about compatibility + # Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy + # if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: + # lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())] + # if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]: + # lUACBool = False # UAC Check is not passed - False for user + # # Convert to UACClient dict + if "Server" in inGSettings: + # Check if Server is active > convert to ServerDict + inGSettings["ServerDict"] = inGSettings["Server"] + if lL: lL.warning( + f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility + # Remove old structure Scheduler + del inGSettings["Server"] + lShowWarnBool = False + lRuleDomainUserDeepCopyDict = copy.deepcopy(inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"]) + for lItemKeyTurple in lRuleDomainUserDeepCopyDict: + lDomainUpperStr = lItemKeyTurple[0] + lUserUpperStr = lItemKeyTurple[1] + lItemDict = lRuleDomainUserDeepCopyDict[lItemKeyTurple] + if "ControlPanelKeyAllowedList" in lItemDict: + lShowWarnBool = True + if len(lItemDict["ControlPanelKeyAllowedList"])>0: + lUACClientDict = {"pyOpenRPADict": {"CPKeyDict": {}}} + else: + lUACClientDict = {} + for lAllowedKeyItemStr in lItemDict["ControlPanelKeyAllowedList"]: + lUACClientDict["pyOpenRPADict"]["CPKeyDict"][lAllowedKeyItemStr]=True # Convert + # Send update UACDict for user by the list + __Orchestrator__.UACUpdate(inGSettings=inGSettings,inADLoginStr=lUserUpperStr, inADStr=lDomainUpperStr, inRoleHierarchyAllowedDict=lUACClientDict) + # remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate + #del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"] + if lShowWarnBool: # Show only 1 warning per all run + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert CP allowed list to UAC Client hierarchy (consolidated)") # Log about compatibility + # Check if ControlPanelDict is active > convert to CPDict + if "ControlPanelDict" in inGSettings: + if "CPDict" not in inGSettings: inGSettings["CPDict"]={} + for lItemDict in inGSettings["ControlPanelDict"]["RobotList"]: + inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None} + # Remove old structure ControlPanel + del inGSettings["ControlPanelDict"] + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility + # Check if Scheduler is active > convert to SchedulerDict + if "Scheduler" in inGSettings: + if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]} + if "ActivityTimeCheckLoopSeconds" in inGSettings["Scheduler"]: + inGSettings["SchedulerDict"]["CheckIntervalSecFloat"] = inGSettings["Scheduler"]["ActivityTimeCheckLoopSeconds"] + for lItemDict in inGSettings["Scheduler"]["ActivityTimeList"]: + # Append to the new struct if this is not periodic ("TimeHH:MMStart"and "TimeHH:MMStop") + if "TimeHH:MMStart" not in lItemDict and "TimeHH:MMStop" not in lItemDict: + lItemDict["ActivityList"]=[v1_2_0_ProcessorOld2NewActivityDict(inActivityOld=lItemDict["Activity"])] + del lItemDict["Activity"] + inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) + # Remove old structure Scheduler + del inGSettings["Scheduler"] + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Scheduler to SchedulerDict with new features") # Log about compatibility + diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Orchestrator.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Orchestrator.py deleted file mode 100644 index 7ea775cb..00000000 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Orchestrator.py +++ /dev/null @@ -1,205 +0,0 @@ -import subprocess -import json -import datetime -import time -import codecs -import os -import signal -import sys #Get input argument -import pdb -from . import Server -from . import Timer -from . import Processor -from . import BackwardCompatibility # Backward compatibility from v1.1.13 - -#from .Settings import Settings -import importlib -from importlib import util -import threading # Multi-threading for RobotRDPActive -from .RobotRDPActive import RobotRDPActive #Start robot rdp active -from .RobotScreenActive import Monitor #Start robot screen active -import uuid # Generate uuid -import datetime # datetime - -#Единый глобальный словарь (За основу взять из Settings.py) -global gSettingsDict - -# Interval gsettings auto cleaner -def GSettingsAutocleaner(inGSettings): - while True: - time.sleep(inGSettings["Autocleaner"]["IntervalSecFloat"]) # Wait for the next iteration - lL = inGSettings["Logger"] - if lL: lL.info(f"Autocleaner is running") # Info - lNowDatetime = datetime.datetime.now() # Get now time - # Clean old items in Client > Session > TechnicalSessionGUIDCache - lTechnicalSessionGUIDCacheNew = {} - for lItemKeyStr in inGSettings["Client"]["Session"]["TechnicalSessionGUIDCache"]: - lItemValue = inGSettings["Client"]["Session"]["TechnicalSessionGUIDCache"][lItemKeyStr] - if (lNowDatetime - lItemValue["InitDatetime"]).total_seconds() < inGSettings["Client"]["Session"]["LifetimeSecFloat"]: # Add if lifetime is ok - lTechnicalSessionGUIDCacheNew[lItemKeyStr]=lItemValue # Lifetime is ok - set - else: - if lL: lL.debug(f"Client > Session > TechnicalSessionGUIDCache > lItemKeyStr: Lifetime is expired. Remove from gSettings") # Info - inGSettings["Client"]["Session"]["TechnicalSessionGUIDCache"] = lTechnicalSessionGUIDCacheNew # Set updated Cache - # # # # # # # # # # # # # # # # # # # # # # # # # # -#Call Settings function from argv[1] file -################################################ -lSubmoduleFunctionName = "Settings" -lFileFullPath = sys.argv[1] -lModuleName = (lFileFullPath.split("\\")[-1])[0:-3] -lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) -lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) -lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) -gSettingsDict = None -if lSubmoduleFunctionName in dir(lTechModuleFromSpec): - # Run SettingUpdate function in submodule - gSettingsDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() -################################################# -#mGlobalDict = Settings.Settings(sys.argv[1]) -#Logger alias -lL = gSettingsDict["Logger"] - -if lL: lL.info("Link the gSettings in submodules") #Logging -Processor.gSettingsDict = gSettingsDict -Timer.gSettingsDict = gSettingsDict -Timer.Processor.gSettingsDict = gSettingsDict -Server.gSettingsDict = gSettingsDict -Server.Processor.gSettingsDict = gSettingsDict - -# Check _SessionLast_RDPList.json in working directory. if exist - load into gsettings -# GSettings -#"RobotRDPActive": { -# "RDPList": { -if os.path.exists("_SessionLast_RDPList.json"): - lFile = open("_SessionLast_RDPList.json", "r", encoding="utf-8") - lSessionLastRDPList = json.loads(lFile.read()) - lFile.close() # Close the file - os.remove("_SessionLast_RDPList.json") # remove the temp file - gSettingsDict["RobotRDPActive"]["RDPList"]=lSessionLastRDPList # Set the last session dict - if lL: lL.warning(f"RDP Session List was restored from previous Orchestrator session") - -#Инициализация настроечных параметров -lDaemonLoopSeconds=gSettingsDict["Scheduler"]["ActivityTimeCheckLoopSeconds"] -lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) -lDaemonLastDateTime=datetime.datetime.now() -gSettingsDict["Server"]["WorkingDirectoryPathStr"] = os.getcwd() # Set working directory in g settings - -# Init SettingsUpdate defs from file list (after RDP restore) -lSettingsUpdateFilePathList = gSettingsDict.get("OrchestratorStart", {}).get("DefSettingsUpdatePathList",[]) -lSubmoduleFunctionName = "SettingsUpdate" -lSettingsPath = "\\".join(os.path.join(os.getcwd(), __file__).split("\\")[:-1]) -for lModuleFilePathItem in lSettingsUpdateFilePathList: # Import defs with try catch - try: # Try to init - go next if error and log in logger - lModuleName = lModuleFilePathItem[0:-3] - lFileFullPath = os.path.join(lSettingsPath, lModuleFilePathItem) - lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) - lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) - lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) - if lSubmoduleFunctionName in dir(lTechModuleFromSpec): - # Run SettingUpdate function in submodule - getattr(lTechModuleFromSpec, lSubmoduleFunctionName)(gSettingsDict) - except Exception as e: - if lL: lL.exception(f"Error when init .py file in orchestrator '{lModuleFilePathItem}'. Exception is below:") - -# Turn on backward compatibility -BackwardCompatibility.Update(inGSettings= gSettingsDict) - -#Инициализация сервера -lThreadServer = Server.RobotDaemonServer("ServerThread", gSettingsDict) -lThreadServer.start() -if lL: lL.info("Web server has been started") #Logging - -# Init the RobotScreenActive in another thread -lRobotScreenActiveThread = threading.Thread(target= Monitor.CheckScreen) -lRobotScreenActiveThread.daemon = True # Run the thread in daemon mode. -lRobotScreenActiveThread.start() # Start the thread execution. -if lL: lL.info("Robot Screen active has been started") #Logging - -# Init the RobotRDPActive in another thread -lRobotRDPActiveThread = threading.Thread(target= RobotRDPActive.RobotRDPActive, kwargs={"inGSettings":gSettingsDict}) -lRobotRDPActiveThread.daemon = True # Run the thread in daemon mode. -lRobotRDPActiveThread.start() # Start the thread execution. -if lL: lL.info("Robot RDP active has been started") #Logging - -# Init autocleaner in another thread -lAutocleanerThread = threading.Thread(target= GSettingsAutocleaner, kwargs={"inGSettings":gSettingsDict}) -lAutocleanerThread.daemon = True # Run the thread in daemon mode. -lAutocleanerThread.start() # Start the thread execution. -if lL: lL.info("Autocleaner thread has been started") #Logging - -# Orchestrator start activity -if lL: lL.info("Orchestrator start activity run") #Logging -for lActivityItem in gSettingsDict["OrchestratorStart"]["ActivityList"]: - Processor.ActivityListOrDict(lActivityItem) - -if lL: lL.info("Scheduler loop start") #Logging -gDaemonActivityLogDictRefreshSecInt = 10 # The second period for clear lDaemonActivityLogDict from old items -gDaemonActivityLogDictLastTime = time.time() # The second perioad for clean lDaemonActivityLogDict from old items -while True: - lCurrentDateTime = datetime.datetime.now() - #Циклический обход правил - lFlagSearchActivityType=True - # Periodically clear the lDaemonActivityLogDict - if time.time()-gDaemonActivityLogDictLastTime>=gDaemonActivityLogDictRefreshSecInt: - gDaemonActivityLogDictLastTime = time.time() # Update the time - for lIndex, lItem in enumerate(lDaemonActivityLogDict): - if lItem["ActivityEndDateTime"] and lCurrentDateTime<=lItem["ActivityEndDateTime"]: - pass - # Activity is actual - do not delete now - else: - # remove the activity - not actual - lDaemonActivityLogDict.pop(lIndex,None) - lIterationLastDateTime = lDaemonLastDateTime # Get current datetime before iterator (need for iterate all activities in loop) - # Iterate throught the activity list - for lIndex, lItem in enumerate(gSettingsDict["Scheduler"]["ActivityTimeList"]): - # Prepare GUID of the activity - lGUID = None - if "GUID" in lItem and lItem["GUID"]: - lGUID = lItem["GUID"] - else: - lGUID = str(uuid.uuid4()) - lItem["GUID"]=lGUID - - #Проверка дней недели, в рамках которых можно запускать активность - lItemWeekdayList=lItem.get("WeekdayList", [0, 1, 2, 3, 4, 5, 6]) - if lCurrentDateTime.weekday() in lItemWeekdayList: - if lFlagSearchActivityType: - ####################################################################### - #Branch 1 - if has TimeHH:MM - ####################################################################### - if "TimeHH:MM" in lItem: - #Вид активности - запуск процесса - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MM"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lActivityDateTime>=lDaemonLastDateTime and - lCurrentDateTime>=lActivityDateTime): - # Log info about activity - if lL: lL.info(f"Scheduler:: Activity is started. Scheduler item: {lItem}") #Logging - # Do the activity - Processor.ActivityListOrDict(lItem["Activity"]) - lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity - ####################################################################### - #Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds - ####################################################################### - if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem: - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M") - lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lCurrentDateTime=lActivityDateTime and - (lGUID,lActivityDateTime) not in lDaemonActivityLogDict): - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime} - #Запуск циклической процедуры - Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"]) - lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity - #Уснуть до следующего прогона - time.sleep(lDaemonLoopSeconds) \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py index 2e64edb8..19145583 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py @@ -1,301 +1,100 @@ -import datetime -import http.client -import json -import pdb -import os -import sys -import subprocess -import importlib -import psutil -#Input arg -# [ -# { -# "Type": , -# host: , -# port: , -# bodyObject: -# }, -# { -# "Type": "CMDStart", -# "Command": "" -# }, -# { -# "Type": "OrchestratorRestart" -# }, -# { -# "Type": "OrchestratorSessionSave" -# }, -# { -# "Type": "GlobalDictKeyListValueSet", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueAppend", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueOperator+", -# "KeyList": ["key1","key2",...], -# "Value": -# }, -# { -# "Type": "GlobalDictKeyListValueGet", -# "KeyList": ["key1","key2",...] -# }, -# { -# "Type":"ProcessStart", -# "Path":"", -# "ArgList":[] -# }, -# { -# "Type":"ProcessStartIfTurnedOff", -# "CheckTaskName":"", #Check if current task name is not active (then start process), -# "Path":"", -# "ArgList":[] -# }, -# { -# "Type":"ProcessStop", -# "Name":"", -# "FlagForce":True, -# "User":"" #Empty - all users, user or %username% -# }, -# { -# "Type":"PythonStart", -# "ModuleName":"", -# "FunctionName":"", -# "ArgList":[], -# "ArgDict":{} -# }, -# { -# "Type":"WindowsLogon", -# "Domain":"", -# "User":"", -# "Password":"" -# # Return "Result": True - user is logged on, False - user is not logged on -# } -# ] -################################## -#Output result -# with attributes: -# "DateTimeUTCStringStart" -# "DateTimeUTCStringStop" -# "Result" -gSettingsDict = None -def Activity(inActivity): - #Глобальная переменная - глобальный словарь унаследованный от Settings.py - global gSettingsDict - lL = gSettingsDict["Logger"] # Alias for logger - #Alias (compatibility) - lItem = inActivity - lCurrentDateTime = datetime.datetime.now() - ########################################################### - #Обработка запроса на отправку команды на удаленную машину - ########################################################### - if lItem["Type"]=="RemoteMachineProcessingRun": - lHTTPConnection = http.client.HTTPConnection(lItem["host"], lItem["port"], timeout=5) - try: - lHTTPConnection.request("POST","/ProcessingRun",json.dumps(lItem["bodyObject"])) - except Exception as e: - #Объединение словарей - lItem["Result"] = {"State":"disconnected","ExceptionString":str(e)} +# 1.2.0 - general processor - contains old orchestrator processor + RDPActive processor +import time, copy, threading +# Run processor synchronious +# inThreadControlDict = {"ThreadExecuteBool":True} +def ProcessorRunSync(inGSettings, inRobotRDPThreadControlDict): + """ + "ProcessorDict": { # Has been changed. New general processor (one threaded) v.1.2.0 + "ActivityList": [ # List of the activities + # { + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3}, # Args dictionary + # "ArgGSettings": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # }, + ], + "AliasDefDict": {}, # Storage for def with Str alias. To use it see pyOpenRPA.Orchestrator.ControlPanel + "CheckIntervalSecFloat": 1.0 # Interval for check gSettings in ProcessorDict > ActivityList + "ExecuteBool": True # Flag to execute thread processor + """ + lL = inGSettings["Logger"] # Logger alias + inGSettings["ProcessorDict"]["ThreadIdInt"] = threading.get_ident() # fill Processor thread id + while inGSettings["ProcessorDict"]["ExecuteBool"]: + lActivityList = inGSettings["ProcessorDict"]["ActivityList"] # Alias + if len(lActivityList)>0: + if lL: lL.debug(f'Processor ActivityList len: {len(lActivityList)}') + lActivityItem = inGSettings["ProcessorDict"]["ActivityList"].pop(0) # Extract the first item from processor queue + inRobotRDPThreadControlDict["ThreadExecuteBool"]=False # Stop the RobotRDPActive monitoring + ActivityListExecute(inGSettings = inGSettings, inActivityList = [lActivityItem]) # execute the activity item + inRobotRDPThreadControlDict["ThreadExecuteBool"] = True # Continue the RobotRDPActive monitoring else: - lHTTPResponse=lHTTPConnection.getresponse() - lHTTPResponseByteArray=lHTTPResponse.read() - lItem["Result"] = json.loads(lHTTPResponseByteArray.decode('utf8')) - ########################################################### - #Обработка команды CMDStart - ########################################################### - if lItem["Type"]=="CMDStart": - lCMDCode="cmd /c "+lItem["Command"] - subprocess.Popen(lCMDCode) - lResultCMDRun=1#os.system(lCMDCode) - lItem["Result"] = str(lResultCMDRun) - ########################################################### - #Обработка команды OrchestratorRestart - ########################################################### - if lItem["Type"]=="OrchestratorRestart": - # Dump RDP List in file json - lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") - lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file - lFile.close() # Close the file - if lL: lL.info(f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}. Do restart") - # Restart session - os.execl(sys.executable, os.path.abspath(__file__), *sys.argv) - lItem["Result"] = True - sys.exit(0) - ########################################################### - # Обработка команды OrchestratorSessionSave - ########################################################### - if lItem["Type"] == "OrchestratorSessionSave": - # Dump RDP List in file json - lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") - lFile.write(json.dumps(gSettingsDict["RobotRDPActive"]["RDPList"])) # dump json to file - lFile.close() # Close the file - if lL: lL.info( - f"Orchestrator has dump the RDP list before the restart. The RDP List is {gSettingsDict['RobotRDPActive']['RDPList']}") - lItem["Result"] = True - ########################################################### - #Обработка команды GlobalDictKeyListValueSet - ########################################################### - if lItem["Type"]=="GlobalDictKeyListValueSet": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - #Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2]={} - lDict=lDict[lItem2] - #Set value - lDict[lItem["KeyList"][-1]]=lItem["Value"] - lItem["Result"] = True - ########################################################### - # Обработка команды GlobalDictKeyListValueAppend - ########################################################### - if lItem["Type"] == "GlobalDictKeyListValueAppend": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - # Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2] = {} - lDict = lDict[lItem2] - # Set value - lDict[lItem["KeyList"][-1]].append(lItem["Value"]) - lItem["Result"] = True - ########################################################### - # Обработка команды GlobalDictKeyListValueOperator+ - ########################################################### - if lItem["Type"] == "GlobalDictKeyListValueOperator+": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - # Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2] = {} - lDict = lDict[lItem2] - # Set value - lDict[lItem["KeyList"][-1]]+=lItem["Value"] - lItem["Result"] = True - ########################################################### - #Обработка команды GlobalDictKeyListValueGet - ########################################################### - if lItem["Type"]=="GlobalDictKeyListValueGet": - lDict = gSettingsDict - for lItem2 in lItem["KeyList"][:-1]: - #Check if key - value exists - if lItem2 in lDict: - pass - else: - lDict[lItem2]={} - lDict=lDict[lItem2] - #Return value - lItem["Result"]=lDict.get(lItem["KeyList"][-1],None) - ##################################### - #ProcessStart - ##################################### - if lItem["Type"]=="ProcessStart": - #Вид активности - запуск процесса - #Запись в массив отработанных активностей - #Запустить процесс - lItemArgs=[lItem["Path"]] - lItemArgs.extend(lItem["ArgList"]) - subprocess.Popen(lItemArgs,shell=True) - ##################################### - #ProcessStartIfTurnedOff - ##################################### - if lItem["Type"]=="ProcessStartIfTurnedOff": - #Check if process running - #remove .exe from Taskname if exists - lCheckTaskName = lItem["CheckTaskName"] - if len(lCheckTaskName)>4: - if lCheckTaskName[-4:].upper() != ".EXE": - lCheckTaskName = lCheckTaskName+".exe" - else: - lCheckTaskName = lCheckTaskName+".exe" - #Check if process exist - if not CheckIfProcessRunning(lCheckTaskName): - #Вид активности - запуск процесса - #Запись в массив отработанных активностей - #Запустить процесс - lItemArgs=[lItem["Path"]] - lItemArgs.extend(lItem["ArgList"]) - subprocess.Popen(lItemArgs,shell=True) - ################################# - #ProcessStop - ################################# - if lItem["Type"]=="ProcessStop": - #Вид активности - остановка процесса - #часовой пояс пока не учитываем - #Сформировать команду на завершение - lActivityCloseCommand='taskkill /im '+lItem["Name"] - #TODO Сделать безопасную обработку,если параметра нет в конфигурации - if lItem.get('FlagForce',False): - lActivityCloseCommand+=" /F" - #Завершить процессы только текущего пользоваиеля - if lItem.get('User',"")!="": - lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"' - #Завершить процесс - os.system(lActivityCloseCommand) - ################################# - #PythonStart - ################################# - if lItem["Type"]=="PythonStart": - try: - #Подключить модуль для вызова - lModule=importlib.import_module(lItem["ModuleName"]) - #Найти функцию - lFunction=getattr(lModule,lItem["FunctionName"]) - lItem["Result"]=lFunction(*lItem.get("ArgList",[]),**lItem.get("ArgDict",{})) - except Exception as e: - if lL: lL.exception("Loop activity error: module/function not founded") - ################################# - # Windows logon - ################################# - if lItem["Type"] == "WindowsLogon": - import win32security - try: - hUser = win32security.LogonUser( - lItem["User"], - lItem["Domain"], - lItem["Password"], - win32security.LOGON32_LOGON_NETWORK, - win32security.LOGON32_PROVIDER_DEFAULT - ) - except win32security.error: - lItem["Result"] = False - else: - lItem["Result"] = True - ################################### - #Вернуть результат - return lItem + time.sleep(inGSettings["ProcessorDict"]["CheckIntervalSecFloat"]) # Sleep when list is empty + +# Execute ActivityItem list +# return the def result +def ActivityListExecute(inGSettings, inActivityList): + lL = inGSettings["Logger"] # Logger alias + lResultList = [] # init the result list + try: + for lActivityItem in inActivityList: # Iterate throught the activity list + if lL: lL.info(f'pyOpenRPA Processor.ActivityListExecute:: Def:{str(lActivityItem["Def"])}. Parameters are not available to see.') + lDef = None # Def variable + if callable(lActivityItem["Def"]): # CHeck if def is callable + lDef = lActivityItem["Def"] # Get the def + else: # Is not callable - check alias + lDef = inGSettings["ProcessorDict"]["AliasDefDict"].get(lActivityItem["Def"], None) # get def if def key in Alias def storage + #gSettings + lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) + # # Prepare arg dict - gSettings + if type(lGSettingsDictKey) is str and lGSettingsDictKey is not "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgGSettings is "" + lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict + # # Prepare arg list + elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict + lActivityItem["ArgList"].insert(lGSettingsDictKey,inGSettings)# Set the gSettings in list by the index + #Logger + lLoggerDictKey = lActivityItem.pop("ArgLogger",None) + # # Prepare arg dict - Logger + if type(lLoggerDictKey) is str and lLoggerDictKey is not "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgLogger is "" + lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict + # # Prepare arg list + elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict + lActivityItem["ArgList"].insert(lLoggerDictKey,lL)# Set the lLogger in list by the index + + try: # try to run function from Processor.py + lActivityItemResult = lDef(*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) + lResultList.append(lActivityItemResult) # return the result + except Exception as e: + if lL: lL.exception(f"pyOpenRPA Processor.ActivityListExecute: Exception in def execution - activity will be ignored.") # Logging + lResultList.append(e) # return the generated exception + except Exception as e: + if lL: lL.exception(f"pyOpenRPA Processor.ActivityListExecute: Exception when initialisation - All activity list will be ignored.") # Logging + return lResultList # return the result list + +def __ActivityListVerify__(inActivityList): + """ + Verify ActivityList variable - raise exception if input list is not list of dict with structure: + # "Def":"DefAliasTest", # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + # "ArgList":[1,2,3], # Args list + # "ArgDict":{"ttt":1,"222":2,"dsd":3}, # Args dictionary + # "ArgGSettings": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) + # "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) -def ActivityListOrDict(inActivityListOrDict): - #Check arg type (list or dict) - if type(inActivityListOrDict)==list: - #List activity - lResult=[] - for lItem in inActivityListOrDict: - lResult.append(Activity(lItem)) - return lResult - if type(inActivityListOrDict)==dict: - #Dict activity - return Activity(inActivityListOrDict) - -def CheckIfProcessRunning(processName): - ''' - Check if there is any running process that contains the given name processName. - ''' - #Iterate over the all the running process - for proc in psutil.process_iter(): - try: - # Check if process name contains the given name string. - if processName.lower() in proc.name().lower(): - return True - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): - pass - return False; \ No newline at end of file + :param inActivityList: + :return: + """ + # CASE LIST + if type(inActivityList) is list: + for lItem in inActivityList: + # CASE LIST item is LIST + if type(lItem) is list: + raise Exception(f"pyOpenRPA Processor.__ActivityListVerify__: inActivityList has wrong structure! Details: Your ActivityList item is list too. List of the list :(") + # CASE Item is not dict + if type(lItem) is not dict: + raise Exception(f"pyOpenRPA Processor.__ActivityListVerify__: inActivityList has wrong structure! Details: Your ActivityList item is is not dict") + # CASE HAS NO "Def" + if "Def" not in lItem: + raise Exception(f"pyOpenRPA Processor.__ActivityListVerify__: inActivityList has wrong structure! Details: Activity item has no attribute 'Def'") + #CASE NOT LIST + else: + raise Exception(f"pyOpenRPA Processor.__ActivityListVerify__: inActivityList has wrong structure! Details: Your ActivityList is not a list.") \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py index a5d434e8..b7f62d41 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py @@ -245,6 +245,7 @@ def SessionCMDRun(inSessionHex,inCMDCommandStr = "echo 1", inModeStr="CROSSCHECK # Exit fullscreen mode SessionScreenSize_X_Y_W_H(inSessionHex=inSessionHex, inXInt=10, inYInt=10, inWInt=550, inHInt=350) # Prepare little window + return lResult # Check if session is in Full screen mode # Return True - is in fullscreen # example print(Connector.SessionIsFullScreen("")) @@ -305,11 +306,12 @@ def SystemCMDRun(inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCH Clipboard.TextSet(lClipboardTextOld) lCrosscheckKeyStr = str(random.randrange(999,9999999)) lRecoveryCMDResponsibleRetryIteratorInt = 0 # Init the retry iterator + lCommandIsTooBigBool = False + lCMDPostFixStr = "" # Case default "RUN" while lRecoveryCMDResponsibleRetryIteratorInt= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded - if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error + if lL: lL.warning(f"RDP::SystemCMDRun: CMD command retry count is over. Raise the error.") # Log the error raise ConnectorExceptions.CMDResponsibleError() # Raise the error time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration else: # Data was recieved - do crosscheck @@ -380,7 +401,7 @@ def SystemCMDRun(inSessionHexStr, inCMDCommandStr = "echo 1", inModeStr="CROSSCH lRecoveryCMDResponsibleRetryIteratorInt = lRecoveryCMDResponsibleRetryIteratorInt + 1 # increment the iterator if lL: lL.warning(f"RDP::SystemCMDRun: CMD command doesn't been executed (wrong clipboard data). Wait for {gRecoveryCMDResponsibleRetryIntervalSecInt}[s.] and retry from start window RUN. Current retry iterator is {lRecoveryCMDResponsibleRetryIteratorInt}. CMD Str: {lInputStr}, Clipboard data: {lResult['OutStr']}") # Log the error if lRecoveryCMDResponsibleRetryIteratorInt >= gRecoveryCMDResponsibleRetryCountInt: # raise the error if retry count is exceeded - if lL: lL.warning(f"RDP::SystemCMDRun: Retry count is over. Raise the error.") # Log the error + if lL: lL.warning(f"RDP::SystemCMDRun: CMD command retry count is over. Raise the error.") # Log the error raise ConnectorExceptions.CMDResponsibleError() # Raise the error time.sleep(gRecoveryCMDResponsibleRetryIntervalSecInt) # wait for some seconds before new iteration else: # clipboard data has been changed but mode is not crosscheck - return success from function diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py index f0c66ed9..e0707bb1 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py @@ -5,7 +5,8 @@ from . import ConnectorExceptions # Exceptions classes from . import Connector from . import Processor # Module for process some functions on thr RDP # Main function -def RobotRDPActive(inGSettings): +# inThreadControlDict = {"ThreadExecuteBool":True} +def RobotRDPActive(inGSettings, inThreadControlDict): # inGSettings = { # ... "RobotRDPActive": {} ... # } @@ -36,100 +37,91 @@ def RobotRDPActive(inGSettings): lResponsibilityCheckLastSec = time.time() # Get current time for check interval while lFlagWhile: try: - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Check RDP window is OK - reconnect if connection was lost - lUIOSelectorList = [] - lRDPConfigurationDictList = [] - # Prepare selectors list for check - for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]: - lItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] - lRDPConfigurationDictList.append(lItem) # Add RDP Configuration in list - lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}]) - # Run wait command - lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout) - for lItem in lRDPDissappearList: # Reconnect if connection was lost - lRDPConfigurationDict = lRDPConfigurationDictList[lItem] # Get RDP Configuration list - lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected - # Check if RDP window is not ignored - if not lRDPConfigurationDict["SessionIsIgnoredBool"]: - try: - Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True) - lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started - if lL: lL.info(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging - # catch ConnectorExceptions.SessionWindowNotExistError - except ConnectorExceptions.SessionWindowNotExistError as e: - lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected - if lL: lL.warning(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!") #Logging - # general exceptions - except Exception as e: - if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging - pass - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Safe turn off the - no need because of Orchestrator control - #if inGlobalDict.get("OrchestratorToRobotResetStorage", {}).get("SafeTurnOff", False): - # lFlagWhile = False - # # Set status disconnected for all RDP List - # for lItem in inGlobalDict["RDPList"]: - # lItem["SessionIsWindowExistBool"] = False - # lItem["SessionIsWindowResponsibleBool"] = False - # # Kill all RDP sessions - # os.system('taskkill /F /im mstsc.exe') - # # Return from function - # return - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - Connector.SystemRDPWarningClickOk() # Click all warning messages - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Check if RDP session is full screen (if is not ignored) - if inGlobalDict["FullScreenRDPSessionKeyStr"] is not None: - lRDPSessionKeyStr = inGlobalDict["FullScreenRDPSessionKeyStr"] # Get the RDPSessionKeyStr - if lRDPSessionKeyStr in inGlobalDict["RDPList"]: # Session Key is in dict - lRDPConfigurationDict = inGlobalDict["RDPList"][lRDPSessionKeyStr] - #if not lRDPConfigurationDict["SessionIsIgnoredBool"]: # Session is not ignored - # Check if full screen - lIsFullScreenBool = Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDict["SessionHex"]) - if not lIsFullScreenBool: # If not the full screen - # Check all RDP window and minimize it - for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]: - lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] - if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): - Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"], inXInt=10, inYInt=10, - inWInt=550, - inHInt=350) # Prepare little window - # Set full screen for new window - Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"], inLogger= inGSettings["Logger"], inRDPConfigurationItem=inGlobalDict["RDPList"][lRDPSessionKeyStrItem]) - else: - # Check all RDP window and minimize it + if inThreadControlDict["ThreadExecuteBool"] == True: + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Check RDP window is OK - reconnect if connection was lost + lUIOSelectorList = [] + lRDPConfigurationDictList = [] + # Prepare selectors list for check for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]: - lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] - if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]) or Connector.SessionIsMinimizedScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): # If window is minimized - restore # if window in full screen - resize - Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"], - inXInt=10, inYInt=10, - inWInt=550, - inHInt=350) # Prepare little window - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Iterate the activity list in robot RDP active - lActivityListNew = [] - lActivityListOld = inGlobalDict["ActivityList"] - inGlobalDict["ActivityList"] = [] - for lActivityItem in lActivityListOld: - lSubmoduleFunctionName = lActivityItem["DefNameStr"] - if lSubmoduleFunctionName in dir(Processor): - lActivityItemResult = None # init the variable - try: # try to run function from Processor.py - lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)( - *lActivityItem["ArgList"], **lActivityItem["ArgDict"]) - except Exception as e: - if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging - lActivityItemResult = True # True - clear from repeat list - lActivityItemResultType = type(lActivityItemResult) - # Check if Result is bool - if lActivityItemResultType is bool: - if not lActivityItemResult: - # Activity is not done - add to list (retry in future) - lActivityListNew.append(lActivityItem) - inGlobalDict["ActivityList"] = lActivityListNew # Override the value - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + lItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] + lRDPConfigurationDictList.append(lItem) # Add RDP Configuration in list + lUIOSelectorList.append([{"title_re": f"{lItem['SessionHex']}.*", "backend": "win32"}]) + # Run wait command + lRDPDissappearList = UIDesktop.UIOSelectorsSecs_WaitDisappear_List(lUIOSelectorList, inListUpdateTimeout) + for lItem in lRDPDissappearList: # Reconnect if connection was lost + lRDPConfigurationDict = lRDPConfigurationDictList[lItem] # Get RDP Configuration list + lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected + # Check if RDP window is not ignored + if not lRDPConfigurationDict["SessionIsIgnoredBool"]: + try: + Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True) + lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started + if lL: lL.info(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging + # catch ConnectorExceptions.SessionWindowNotExistError + except ConnectorExceptions.SessionWindowNotExistError as e: + lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected + if lL: lL.warning(f"SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist!") #Logging + # general exceptions + except Exception as e: + if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging + pass + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + Connector.SystemRDPWarningClickOk() # Click all warning messages + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Check if RDP session is full screen (if is not ignored) + if inGlobalDict["FullScreenRDPSessionKeyStr"] is not None: + lRDPSessionKeyStr = inGlobalDict["FullScreenRDPSessionKeyStr"] # Get the RDPSessionKeyStr + if lRDPSessionKeyStr in inGlobalDict["RDPList"]: # Session Key is in dict + lRDPConfigurationDict = inGlobalDict["RDPList"][lRDPSessionKeyStr] + #if not lRDPConfigurationDict["SessionIsIgnoredBool"]: # Session is not ignored + # Check if full screen + lIsFullScreenBool = Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDict["SessionHex"]) + if not lIsFullScreenBool: # If not the full screen + # Check all RDP window and minimize it + for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]: + lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] + if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): + if inThreadControlDict["ThreadExecuteBool"] == True: # TEST FEATURE BEFORE ONE THREAD INTEGRATION + Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"], inXInt=10, inYInt=10, + inWInt=550, + inHInt=350) # Prepare little window + # Set full screen for new window + if inThreadControlDict["ThreadExecuteBool"] == True: # TEST FEATURE BEFORE ONE THREAD INTEGRATION + Connector.SessionScreenFull(inSessionHex=lRDPConfigurationDict["SessionHex"], inLogger= inGSettings["Logger"], inRDPConfigurationItem=inGlobalDict["RDPList"][lRDPSessionKeyStrItem]) + else: + # Check all RDP window and minimize it + for lRDPSessionKeyStrItem in inGlobalDict["RDPList"]: + lRDPConfigurationDictItem = inGlobalDict["RDPList"][lRDPSessionKeyStrItem] + if Connector.SessionIsFullScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]) or Connector.SessionIsMinimizedScreen(inSessionHexStr=lRDPConfigurationDictItem["SessionHex"]): # If window is minimized - restore # if window in full screen - resize + if inThreadControlDict["ThreadExecuteBool"] == True: # TEST FEATURE BEFORE ONE THREAD INTEGRATION + Connector.SessionScreenSize_X_Y_W_H(inSessionHex=lRDPConfigurationDictItem["SessionHex"], + inXInt=10, inYInt=10, + inWInt=550, + inHInt=350) # Prepare little window + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Iterate the activity list in robot RDP active + lActivityListNew = [] + lActivityListOld = inGlobalDict["ActivityList"] + inGlobalDict["ActivityList"] = [] + for lActivityItem in lActivityListOld: + lSubmoduleFunctionName = lActivityItem["DefNameStr"] + if lSubmoduleFunctionName in dir(Processor): + lActivityItemResult = None # init the variable + try: # try to run function from Processor.py + lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)( + *lActivityItem["ArgList"], **lActivityItem["ArgDict"]) + except Exception as e: + if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging + lActivityItemResult = True # True - clear from repeat list + lActivityItemResultType = type(lActivityItemResult) + # Check if Result is bool + if lActivityItemResultType is bool: + if not lActivityItemResult: + # Activity is not done - add to list (retry in future) + lActivityListNew.append(lActivityItem) + inGlobalDict["ActivityList"] = lActivityListNew # Override the value + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # except RuntimeError as e: # case noGUI error passed - do nothing if lL: lL.warning(f"Host session has lost the GUI") #Logging diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py index 43080607..2c16b986 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py @@ -11,7 +11,8 @@ from socketserver import ThreadingMixIn import threading import json from threading import Thread -from . import Processor +from . import Processor # Add new processor +from . import ProcessorOld # Support old processor - deprecated defs only for backward compatibility import urllib.parse # decode URL in string import importlib import pdb @@ -22,9 +23,26 @@ import os #for path operations from http import cookies global gSettingsDict from . import ServerSettings +from . import __Orchestrator__ import copy +# Tool to merge complex dictionaries +def __ComplexDictMerge2to1__(in1Dict, in2Dict): + lPathList=None + if lPathList is None: lPathList = [] + for lKeyStr in in2Dict: + if lKeyStr in in1Dict: + if isinstance(in1Dict[lKeyStr], dict) and isinstance(in2Dict[lKeyStr], dict): + __ComplexDictMerge2to1__(in1Dict[lKeyStr], in2Dict[lKeyStr]) + elif in1Dict[lKeyStr] == in2Dict[lKeyStr]: + pass # same leaf value + else: + raise Exception('Conflict at %s' % '.'.join(lPathList + [str(lKeyStr)])) + else: + in1Dict[lKeyStr] = in2Dict[lKeyStr] + return in1Dict + #Authenticate function () # return dict # { @@ -41,10 +59,10 @@ def AuthenticateVerify(inRequest): lCookieAuthToken = lCookies.get("AuthToken", "").value if lCookieAuthToken: #Find AuthToken in GlobalDict - if lCookieAuthToken in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + if lCookieAuthToken in gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): #Auth Token Has Been Founded - lResult["Domain"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] - lResult["User"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + lResult["Domain"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] #Set auth token inRequest.OpenRPA["AuthToken"] = lCookieAuthToken inRequest.OpenRPA["Domain"] = lResult["Domain"] @@ -63,26 +81,18 @@ def AuthenticateVerify(inRequest): if "\\" in lUser: lDomain = lUser.split("\\")[0] lUser = lUser.split("\\")[1] - #Try to logon - use processor - lLogonResult = Processor.Activity( - { - "Type": "WindowsLogon", - "Domain": lDomain, - "User": lUser, - "Password": lPassword - } - ) + lLogonBool = __Orchestrator__.OSCredentialsVerify(inUserStr=lUser, inPasswordStr=lPassword, inDomainStr=lDomain) #Check result - if lLogonResult["Result"]: - lResult["Domain"] = lLogonResult["Domain"] - lResult["User"] = lLogonResult["User"] + if lLogonBool: + lResult["Domain"] = lDomain + lResult["User"] = lUser #Create token lAuthToken=str(uuid.uuid1()) - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() #Set-cookie inRequest.OpenRPA["AuthToken"] = lAuthToken inRequest.OpenRPA["Domain"] = lResult["Domain"] @@ -123,13 +133,14 @@ def UserAccessCheckBefore(inMethod, inRequest): #go next if user is identified lUserDict = None if lAuthToken: - lUserDict = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] + lUserDict = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] #pdb.set_trace() ######################################## ######################################## #Check general before rule (without User domain) #Check rules - for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []): + inRuleMatchURLList = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []) + for lAccessRuleItem in inRuleMatchURLList: #Go next execution if flag is false if not lResult: #Check if Method is identical @@ -161,31 +172,35 @@ def UserAccessCheckBefore(inMethod, inRequest): #Check access by User Domain #Check rules to find first appicable #Check rules - for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []): - #Go next execution if flag is false - if not lResult: - #Check if Method is identical - if lAccessRuleItem["Method"].upper() == inMethod: - #check Match type variant: BeginWith - if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": - lURLPath = inRequest.path - lURLPath = lURLPath.upper() - if lURLPath.startswith(lAccessRuleItem["URL"].upper()): - lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) - #check Match type variant: Contains - elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": - lURLPath = inRequest.path - lURLPath = lURLPath.upper() - if lURLPath.contains(lAccessRuleItem["URL"].upper()): - lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) - # check Match type variant: Equal - elif lAccessRuleItem["MatchType"].upper() == "EQUAL": - if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): - lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) - # check Match type variant: EqualCase - elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": - if lAccessRuleItem["URL"] == inRequest.path: - lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) + lMethodMatchURLList = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []) + if len(lMethodMatchURLList) > 0: + for lAccessRuleItem in lMethodMatchURLList: + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) + #check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.contains(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, gSettingsDict, lUserDict) + else: + return True ##################################### ##################################### #Return lResult @@ -193,6 +208,8 @@ def UserAccessCheckBefore(inMethod, inRequest): # HTTPRequestHandler class class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): # Def to check User Role access grants + def UACClientCheck(self, inRoleKeyList): # Alias + return self.UserRoleAccessAsk(inRoleKeyList=inRoleKeyList) def UserRoleAccessAsk(self, inRoleKeyList): lResult = True # Init flag lRoleHierarchyDict = self.UserRoleHierarchyGet() # get the Hierarchy @@ -218,7 +235,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): def UserRoleHierarchyGet(self): lDomainUpperStr = self.OpenRPA["Domain"].upper() lUserUpperStr = self.OpenRPA["User"].upper() - return gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) + return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) #Tech def #return {"headers":[],"body":"","statuscode":111} @@ -316,152 +333,168 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): # Write content as utf-8 data self.wfile.write(inResponseDict["Body"]) def do_GET(self): - self.OpenRPA = {} - self.OpenRPA["AuthToken"] = None - self.OpenRPA["Domain"] = None - self.OpenRPA["User"] = None - self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def - self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def - # Prepare result dict - lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None} - self.OpenRPAResponseDict = lResponseDict - ##################################### - #Do authentication - #Check if authentication is turned on - ##################################### - lFlagAccessUserBlock=False - lAuthenticateDict = {"Domain": "", "User": ""} - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): - lAuthenticateDict = AuthenticateVerify(self) - if not lAuthenticateDict["User"]: - lFlagAccessUserBlock=True - # Logging - # gSettingsDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}") - if lFlagAccessUserBlock: - AuthenticateBlock(self) - ##################################### - else: - #Check the user access (if flag) - #################################### - lFlagUserAccess = True - #If need user authentication - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): - lFlagUserAccess = UserAccessCheckBefore("GET", self) - ###################################### - if lFlagUserAccess: - lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) - ############################ - #New server engine (url from global dict (URLList)) - ############################ - for lURLItem in gSettingsDict["Server"]["URLList"]: - #Check if all condition are applied - lFlagURLIsApplied=False - lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") - if lFlagURLIsApplied: - self.ResponseDictSend() - return - #Monitor - if self.path == '/Monitor/JSONDaemonListGet': + try: + self.OpenRPA = {} + self.OpenRPA["AuthToken"] = None + self.OpenRPA["Domain"] = None + self.OpenRPA["User"] = None + self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def + self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def + # Prepare result dict + lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + # Logging + # gSettingsDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}") + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("GET", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in gSettingsDict["ServerDict"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + #Monitor + if self.path == '/Monitor/JSONDaemonListGet': + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type','application/json') + self.end_headers() + # Send message back to client + message = json.dumps(gSettingsDict) + # Write content as utf-8 data + self.wfile.write(bytes(message, "utf8")) + #Filemanager function + if self.path.lower().startswith('/filemanager/'): + lFileURL=self.path[13:] + # check if file in FileURL - File Path Mapping Dict + if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]: + self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL]) + else: + #Set access denied code # Send response status code - self.send_response(200) + self.send_response(403) # Send headers - self.send_header('Content-type','application/json') self.end_headers() - # Send message back to client - message = json.dumps(gSettingsDict) - # Write content as utf-8 data - self.wfile.write(bytes(message, "utf8")) - #Filemanager function - if self.path.lower().startswith('/filemanager/'): - lFileURL=self.path[13:] - # check if file in FileURL - File Path Mapping Dict - if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]: - self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL]) - else: - #Set access denied code - # Send response status code - self.send_response(403) - # Send headers - self.end_headers() + except Exception as e: + lL = gSettingsDict["Logger"] + if lL: lL.exception(f"Server.do_GET: Global error handler - look traceback below.") # POST def do_POST(self): - lL = gSettingsDict["Logger"] - self.OpenRPA = {} - self.OpenRPA["AuthToken"] = None - self.OpenRPA["Domain"] = None - self.OpenRPA["User"] = None - self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def - self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def - # Prepare result dict - #pdb.set_trace() - lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None} - self.OpenRPAResponseDict = lResponseDict - ##################################### - #Do authentication - #Check if authentication is turned on - ##################################### - lFlagAccessUserBlock=False - lAuthenticateDict = {"Domain": "", "User": ""} - lIsSuperToken = False # Is supertoken - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): - lAuthenticateDict = AuthenticateVerify(self) - # Get Flag is supertoken (True|False) - lIsSuperToken = gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get( - self.OpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) - if not lAuthenticateDict["User"]: - lFlagAccessUserBlock=True - if lFlagAccessUserBlock: - AuthenticateBlock(self) - ##################################### - else: - #Check the user access (if flag) - #################################### - lFlagUserAccess = True - #If need user authentication - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): - lFlagUserAccess = UserAccessCheckBefore("POST", self) - ###################################### - if lFlagUserAccess: - lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) - ############################ - #New server engine (url from global dict (URLList)) - ############################ - for lURLItem in gSettingsDict["Server"]["URLList"]: - #Check if all condition are applied - lFlagURLIsApplied=False - lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") - if lFlagURLIsApplied: - self.ResponseDictSend() - return - #Централизованная функция получения запросов/отправки - if self.path == '/Utils/Processor': - #ReadRequest - lInputObject={} - if self.headers.get('Content-Length') is not None: - lInputByteArrayLength = int(self.headers.get('Content-Length')) - lInputByteArray=self.rfile.read(lInputByteArrayLength) - #Превращение массива байт в объект - lInputObject=json.loads(lInputByteArray.decode('utf8')) + try: + lL = gSettingsDict["Logger"] + self.OpenRPA = {} + self.OpenRPA["AuthToken"] = None + self.OpenRPA["Domain"] = None + self.OpenRPA["User"] = None + self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def + self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def + # Prepare result dict + #pdb.set_trace() + lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + lIsSuperToken = False # Is supertoken + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + # Get Flag is supertoken (True|False) + lIsSuperToken = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(self.OpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("POST", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in gSettingsDict["ServerDict"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + #Централизованная функция получения запросов/отправки + if self.path == '/Utils/Processor': + #ReadRequest + lInputObject={} + if self.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(self.headers.get('Content-Length')) + lInputByteArray=self.rfile.read(lInputByteArrayLength) + #Превращение массива байт в объект + lInputObject=json.loads(lInputByteArray.decode('utf8')) + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type','application/json') + self.end_headers() + # Logging info about processor activity if not SuperToken () + if not lIsSuperToken: + lActivityTypeListStr = "" + try: + if type(lInputObject) is list: + for lActivityItem in lInputObject: + lActivityTypeListStr+=f"{lActivityItem['Type']}; " + else: + lActivityTypeListStr += f"{lInputObject['Type']}" + except Exception as e: + lActivityTypeListStr = "Has some error with Activity Type read" + if lL: lL.info(f"Server:: !ATTENTION! /Utils/Processor will be deprecated in future. Use /pyOpenRPA/Processor or /pyOpenRPA/ActivityListExecute. User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}") + # Send message back to client + message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject)) + # Write content as utf-8 data + self.wfile.write(bytes(message, "utf8")) + return + else: + #Set access denied code # Send response status code - self.send_response(200) + self.send_response(403) # Send headers - self.send_header('Content-type','application/json') self.end_headers() - # Logging info about processor activity if not SuperToken () - if not lIsSuperToken: - if lL: lL.info(f"Server:: User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, Activity: {lInputObject}") - # Send message back to client - message = json.dumps(Processor.ActivityListOrDict(lInputObject)) - # Write content as utf-8 data - self.wfile.write(bytes(message, "utf8")) - return - else: - #Set access denied code - # Send response status code - self.send_response(403) - # Send headers - self.end_headers() - return + return + except Exception as e: + lL = gSettingsDict["Logger"] + if lL: lL.exception(f"Server.do_POST: Global error handler - look traceback below.") #Logging #!Turn it on to stop print in console #def log_message(self, format, *args): @@ -470,7 +503,7 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): daemon_threads = True """Handle requests in a separate thread.""" def finish_request(self, request, client_address): - request.settimeout(gSettingsDict["Server"]["RequestTimeoutSecFloat"]) + request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]) # "super" can not be used because BaseServer is not created from object HTTPServer.finish_request(self, request, client_address) #inGlobalDict @@ -483,7 +516,7 @@ class RobotDaemonServer(Thread): ServerSettings.SettingsUpdate(inGlobalDict) def run(self): inServerAddress=""; - inPort = gSettingsDict["Server"]["ListenPort"]; + inPort = gSettingsDict["ServerDict"]["ListenPort"]; # Server settings # Choose port 8080, for port 80, which is normally used for a http server, you need root access server_address = (inServerAddress, inPort) diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/ServerSettings.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/ServerSettings.py index 0f0693d9..be5c1532 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/ServerSettings.py @@ -1,5 +1,7 @@ -import json +import json, os +import copy from inspect import signature # For detect count of def args +from . import __Orchestrator__ #ControlPanelDict from desktopmagic.screengrab_win32 import ( getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, @@ -9,163 +11,234 @@ import uuid # generate UUID4 import time # sleep functions import datetime # datetime functions import threading # Multi-threading +from .Web import Basic +from . import BackwardCompatibility # Support old up to 1.2.0 defs +from . import Processor +from . import SettingsTemplate +# # # # # # # # # # # # +# v 1.2.0 Functionallity +# # # # # # # # # # # # +# Generate JS when page init +def HiddenJSInitGenerate(inRequest, inGSettings): + dUAC = inRequest.UACClientCheck # Alias. + lUACCPTemplateKeyList=["pyOpenRPADict","CPKeyDict"] + lL = inGSettings["Logger"] # Alias for logger + lJSInitResultStr = "" + lRenderFunctionsRobotDict = inGSettings["CPDict"] + for lItemKeyStr in lRenderFunctionsRobotDict: + lItemDict = lRenderFunctionsRobotDict[lItemKeyStr] + lJSInitGeneratorDef = lItemDict.get("JSInitGeneratorDef",None) + lUACBool = dUAC(inRoleKeyList=lUACCPTemplateKeyList+[lItemKeyStr]) # Check if render function is applicable User Access Rights (UAC) + if lItemKeyStr=="VersionCheck": lUACBool=True # For backward compatibility for the old fron version which not reload page when new orch version is comming + if lUACBool: # Run function if UAC is TRUE + # JSONGeneratorDef + if lJSInitGeneratorDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings) + lJSResult = None + lDEFSignature = signature(lJSInitGeneratorDef) # Get signature of the def + lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args + try: + if lDEFARGLen == 1: # def (inGSettings) + lJSResult = lJSInitGeneratorDef(inGSettings) + elif lDEFARGLen == 2: # def (inRequest, inGSettings) + lJSResult = lJSInitGeneratorDef(inRequest, inGSettings) + elif lDEFARGLen == 0: # def () + lJSResult = lJSInitGeneratorDef() + if type(lJSResult) is str: + lJSInitResultStr += "; "+lJSResult # Add delimiter to some cases + else: + if lL: lL.warning(f"JSInitGenerator return bad type: {str(type(lJSResult))}, CP Key {lItemKeyStr}") + except Exception as e: + if lL: lL.exception(f"Error in control panel JSInitGeneratorDef. CP Key {lItemKeyStr}. Exception are below") + return lJSInitResultStr + +# Generate CP HTML + JSON +# Return {"Key":{"",""}} +def HiddenCPDictGenerate(inRequest, inGSettings): + dUAC = inRequest.UACClientCheck # Alias. + lUACCPTemplateKeyList=["pyOpenRPADict","CPKeyDict"] + lL = inGSettings["Logger"] # Alias for logger + # Create result JSON + lCPDict = {} + lRenderFunctionsRobotDict = inGSettings["CPDict"] + for lItemKeyStr in lRenderFunctionsRobotDict: + lItemDict = lRenderFunctionsRobotDict[lItemKeyStr] + lItemHTMLRenderDef = lItemDict.get("HTMLRenderDef",None) + lItemJSONGeneratorDef = lItemDict.get("JSONGeneratorDef",None) + lUACBool = dUAC(inRoleKeyList=lUACCPTemplateKeyList+[lItemKeyStr]) # Check if render function is applicable User Access Rights (UAC) + if lItemKeyStr=="VersionCheck": lUACBool=True # For backward compatibility for the old fron version which not reload page when new orch version is comming + if lUACBool: # Run function if UAC is TRUE + lCPItemDict = {"HTMLStr": None, "JSONDict":None} + # HTMLRenderDef + if lItemHTMLRenderDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings) + lHTMLResult = None + lDEFSignature = signature(lItemHTMLRenderDef) # Get signature of the def + lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args + try: + if lDEFARGLen == 1: # def (inGSettings) + lHTMLResult = lItemHTMLRenderDef(inGSettings) + elif lDEFARGLen == 2: # def (inRequest, inGSettings) + lHTMLResult = lItemHTMLRenderDef(inRequest, inGSettings) + elif lDEFARGLen == 0: # def () + lHTMLResult = lItemHTMLRenderDef() + # RunFunction + # Backward compatibility up to 1.2.0 - call HTML generator if result has no "HTMLStr" + if type(lHTMLResult) is str: + lCPItemDict["HTMLStr"] = lHTMLResult + elif "HTMLStr" in lHTMLResult or "JSONDict" in lHTMLResult: + lCPItemDict = lHTMLResult # new version + else: + # Call backward compatibility HTML generator + lCPItemDict["HTMLStr"] = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult) + except Exception as e: + if lL: lL.exception(f"Error in control panel HTMLRenderDef. CP Key {lItemKeyStr}. Exception are below") + # JSONGeneratorDef + if lItemJSONGeneratorDef is not None: # Call def (inRequest, inGSettings) or def (inGSettings) + lJSONResult = None + lDEFSignature = signature(lItemJSONGeneratorDef) # Get signature of the def + lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args + try: + if lDEFARGLen == 1: # def (inGSettings) + lJSONResult = lItemJSONGeneratorDef(inGSettings) + elif lDEFARGLen == 2: # def (inRequest, inGSettings) + lJSONResult = lItemJSONGeneratorDef(inRequest, inGSettings) + elif lDEFARGLen == 0: # def () + lJSONResult = lItemJSONGeneratorDef() + # RunFunction + # Backward compatibility up to 1.2.0 - call HTML generator if result has no "HTMLStr" + lType = type(lJSONResult) + if lType is str or lJSONResult is None or lType is int or lType is list or lType is dict or lType is bool or lType is float: + lCPItemDict["JSONDict"] = lJSONResult + else: + if lL: lL.warning(f"JSONGenerator return bad type: {str(type(lJSONResult))}, CP Key {lItemKeyStr}") + except Exception as e: + if lL: lL.exception(f"Error in control panel JSONGeneratorDef. CP Key {lItemKeyStr}. Exception are below") + # Insert CPItemDict in result CPDict + lCPDict[lItemKeyStr]=lCPItemDict + return lCPDict + +# Return {"Key":{"",""}} +def HiddenRDPDictGenerate(inRequest, inGSettings): + dUAC = inRequest.UACClientCheck # Alias. + lUACRDPTemplateKeyList=["pyOpenRPADict","RDPKeyDict"] + lRDPDict = {"HandlebarsList":[]} + # Iterate throught the RDP list + for lRDPSessionKeyStrItem in inGSettings["RobotRDPActive"]["RDPList"]: + # Check UAC + if dUAC(inRoleKeyList=lUACRDPTemplateKeyList+[lRDPSessionKeyStrItem]): + lRDPConfiguration = inGSettings["RobotRDPActive"]["RDPList"][ + lRDPSessionKeyStrItem] # Get the configuration dict + lDataItemDict = {"SessionKeyStr": "", "SessionHexStr": "", "IsFullScreenBool": False, + "IsIgnoredBool": False} # Template + lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str + lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex + lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGSettings["RobotRDPActive"][ + "FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window + lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored + lRDPDict[lDataItemDict["SessionKeyStr"]]=lDataItemDict + lHandlebarsDataItemDict = copy.deepcopy(lDataItemDict) + lHandlebarsDataItemDict["SessionKeyStr"]=lDataItemDict["SessionKeyStr"] + lRDPDict["HandlebarsList"].append(lHandlebarsDataItemDict) + return lRDPDict + +# Return {"HostNameUpperStr;UserUpperStr":{"IsListenBool":True}, "HandlebarsList":[{"HostnameUpperStr":"","UserUpperStr":"","IsListenBool":True}]} +def HiddenAgentDictGenerate(inRequest, inGSettings): + dUAC = inRequest.UACClientCheck # Alias. + lUACAgentTemplateKeyList=["pyOpenRPADict","AgentKeyDict"] + lAgentDict = {"HandlebarsList":[]} + # Iterate throught the RDP list + for lAgentItemKeyStrItem in inGSettings["AgentDict"]: + # Check UAC + lKeyStr = f"{lAgentItemKeyStrItem[0]};{lAgentItemKeyStrItem[1]}" # turple ("HostNameUpperStr","UserUpperStr") > Str "HostNameUpperStr;UserUpperStr" + if dUAC(inRoleKeyList=lUACAgentTemplateKeyList+[lKeyStr]): + lDataItemDict = inGSettings["AgentDict"][lAgentItemKeyStrItem] + lAgentDict[lKeyStr]=lDataItemDict + lHandlebarsDataItemDict = copy.deepcopy(lDataItemDict) + lHandlebarsDataItemDict["HostnameUpperStr"]=lAgentItemKeyStrItem[0] + lHandlebarsDataItemDict["UserUpperStr"]=lAgentItemKeyStrItem[1] + lAgentDict["HandlebarsList"].append(lHandlebarsDataItemDict) + return lAgentDict + -# /Orchestrator/RobotRDPActive/ControlPanelDictGet -def RobotRDPActive_ControlPanelDictGet(inRequest,inGlobalDict): +#v1.2.0 Send data container to the client from the server +# /pyOpenRPA/ServerData return {"HashStr" , "ServerDataDict": {"CPKeyStr":{"HTMLStr":"", DataDict:{}}}} + +# Client: mGlobal.pyOpenRPA.ServerDataHashStr +# Client: mGlobal.pyOpenRPA.ServerDataDict +def pyOpenRPA_ServerData(inRequest,inGSettings): + + # Extract the hash value from request + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lValueStr = (lInputByteArray.decode('utf8')) + # Generate ServerDataDict + lFlagDoGenerateBool = True + while lFlagDoGenerateBool: + lServerDataDict = { + "CPDict": HiddenCPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), + "RDPDict": HiddenRDPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), + "AgentDict": HiddenAgentDictGenerate(inRequest=inRequest, inGSettings=inGSettings), + "UserDict": {"UACClientDict": inRequest.OpenRPA["DefUserRoleHierarchyGet"](), "CWDPathStr": os.getcwd(), "VersionStr": inGSettings["VersionStr"]}, + } + # Create JSON + lServerDataDictJSONStr = json.dumps(lServerDataDict) + # Generate hash + lServerDataHashStr = str(hash(lServerDataDictJSONStr)) + if lValueStr!=lServerDataHashStr and lServerDataHashStr!= "" and lServerDataHashStr!= None: # Case if Hash is not equal + lFlagDoGenerateBool = False + else: # Case Hashes are equal + time.sleep(inGSettings["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"]) + # Return the result if Hash is changed + lResult = {"HashStr": lServerDataHashStr, "ServerDataDict": lServerDataDict} inResponseDict = inRequest.OpenRPAResponseDict - lResultDict = { - "DataList":[ - # {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} - ] - } - # Iterate throught the RDP List - for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: - lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][lRDPSessionKeyStrItem] # Get the configuration dict - lDataItemDict = {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} # Template - lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str - lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex - lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"]["FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window - lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored - lResultDict["DataList"].append(lDataItemDict) # Send message back to client - message = json.dumps(lResultDict) + message = json.dumps(lResult) # Write content as utf-8 data inResponseDict["Body"] = bytes(message, "utf8") + return lResult -# def to check control panels for selected session -def Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict): - lL = inGlobalDict["Logger"] # Alias for logger - lLifetimeSecFloat = inGlobalDict["Client"]["Session"]["LifetimeSecFloat"] - lLifetimeRequestSecFloat = inGlobalDict["Client"]["Session"]["LifetimeRequestSecFloat"] - lControlPanelRefreshIntervalSecFloat = inGlobalDict["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"] - lCookieSessionGUIDStr = None # generate the new GUID - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Technicaldef - interval check control panels + check actuality of the session by the datetime - def TechnicalCheck(): - lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] - # Lifetime is ok - check control panel - lDatasetCurrentBytes = Monitor_ControlPanelDictGet(inRequest,inGlobalDict) # Call the control panel - if lDatasetCurrentBytes != lItemValue["DatasetLast"]["ControlPanel"]["Data"]: # Check if dataset is changed - lItemValue["DatasetLast"]["ControlPanel"]["Data"] = lDatasetCurrentBytes # Set new datset - lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = True # Set flag to return the data - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Technicaldef - Create new session struct - def TechnicalSessionNew(inSessionGUIDStr): - lCookieSessionGUIDStr = inSessionGUIDStr # Generate the new GUID - lSessionNew = { # Session with some GUID str. On client session guid stored in cookie "SessionGUIDStr" - "InitDatetime": datetime.datetime.now(), # Datetime when session GUID was created - "DatasetLast": { - "ControlPanel": { - "Data": None, # Struct to check with new iterations. None if starts - "ReturnBool": False # flag to return, close request and return data as json - } - }, - "ClientRequestHandler": inRequest, # Last client request handler - "UserADStr": inRequest.OpenRPA["User"], # User, who connect. None if user is not exists - "DomainADStr": inRequest.OpenRPA["Domain"], # Domain of the user who connect. None if user is not exists - } - inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict - inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies - if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") - return lCookieSessionGUIDStr - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - lCreateNewSessionBool = False # Flag to create new session structure - # step 1 - get cookie SessionGUIDStr - lSessionGUIDStr = inRequest.headers.get("SessionGUIDStr", None) - if lSessionGUIDStr is not None: # Check if GUID session is ok - lCookieSessionGUIDStr = lSessionGUIDStr # Get the existing GUID - if lSessionGUIDStr not in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: - lCookieSessionGUIDStr= TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session - else: # Update the datetime of the request session - inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]["InitDatetime"]=datetime.datetime.now() - else: - lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session - # Init the RobotRDPActive in another thread - #lThreadCheckCPInterval = threading.Thread(target=TechnicalIntervalCheck) - #lThreadCheckCPInterval.daemon = True # Run the thread in daemon mode. - #lThreadCheckCPInterval.start() # Start the thread execution. - - # Step 2 - interval check if data is exist - lTimeStartSecFloat = time.time() - lDoWhileBool = True # Flag to iterate throught the lifetime of the request - while lDoWhileBool: - #print(lTechnicalSessionGUIDCache) - #print(lCookieSessionGUIDStr) - if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: - lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] - if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key - if lL: lL.debug(f"Client request lifetime is over") - lDoWhileBool = False # Stop the iterations - if lDoWhileBool: - TechnicalCheck() # Calculate the CP - if lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] == True: # Return data if data flag it True - lDatasetCurrentBytes = lItemValue["DatasetLast"]["ControlPanel"]["Data"] # Set new dataset - inResponseDict = inRequest.OpenRPAResponseDict - inResponseDict["Body"] = lDatasetCurrentBytes - lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = False # Set flag that data was returned - lDoWhileBool = False # Stop the iterations - else: - lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lCookieSessionGUIDStr) # Create new session - if lDoWhileBool: # Sleep if we wait hte next iteration - time.sleep(lControlPanelRefreshIntervalSecFloat) # Sleep to the next iteration - -def Monitor_ControlPanelDictGet(inRequest,inGlobalDict): +# GET +# /pyOpenRPA/ServerJSInit return JavaScript to init on page +def pyOpenRPA_ServerJSInit(inRequest,inGSettings): + lResultStr = HiddenJSInitGenerate(inRequest=inRequest, inGSettings=inGSettings) inResponseDict = inRequest.OpenRPAResponseDict - lL = inGlobalDict["Logger"] # Alias for logger - # Create result JSON - lResultJSON = {"RenderRobotList": [], "RenderRDPList": []} - lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] - for lItem in lRenderFunctionsRobotList: - lUACBool = True # Check if render function is applicable User Access Rights (UAC) - if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: - lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())] - if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]: - lUACBool = False # UAC Check is not passed - False for user - if lUACBool: # Run function if UAC is TRUE - # Выполнить вызов и записать результат - # Call def (inRequest, inGSettings) or def (inGSettings) - lItemResultDict = None - lDEFSignature = signature(lItem["RenderFunction"]) # Get signature of the def - lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args - try: - if lDEFARGLen == 1: # def (inGSettings) - lItemResultDict = lItem["RenderFunction"](inGlobalDict) - elif lDEFARGLen == 2: # def (inRequest, inGSettings) - lItemResultDict = lItem["RenderFunction"](inRequest, inGlobalDict) - elif lDEFARGLen == 0: # def () - lItemResultDict = lItem["RenderFunction"]() - # RunFunction - lResultJSON["RenderRobotList"].append(lItemResultDict) - except Exception as e: - if lL: lL.exception(f"Error in control panel. CP item {lItem}. Exception is below") - # Iterate throught the RDP list - for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: - lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][ - lRDPSessionKeyStrItem] # Get the configuration dict - lDataItemDict = {"SessionKeyStr": "", "SessionHexStr": "", "IsFullScreenBool": False, - "IsIgnoredBool": False} # Template - lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str - lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex - lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"][ - "FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window - lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored - lResultJSON["RenderRDPList"].append(lDataItemDict) - # Send message back to client - message = json.dumps(lResultJSON) # Write content as utf-8 data - #inResponseDict["Body"] = bytes(message, "utf8") - return bytes(message, "utf8") -# UserAccess get rights hierarchy dict in json -def UserRoleHierarchyGet(inRequest,inGlobalDict): + inResponseDict["Body"] = bytes(lResultStr, "utf8") + +#v1.2.0 Send data container to the client from the server +# /pyOpenRPA/ServerLog return {"HashStr" , "ServerLogList": ["row 1", "row 2"]} +# Client: mGlobal.pyOpenRPA.ServerLogListHashStr +# Client: mGlobal.pyOpenRPA.ServerLogList +def pyOpenRPA_ServerLog(inRequest,inGSDict): + # Extract the hash value from request + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lValueStr = (lInputByteArray.decode('utf8')) + # Generate ServerDataDict + lFlagDoGenerateBool = True + while lFlagDoGenerateBool: + lServerLogList = inGSDict["Client"]["DumpLogList"] + # Get hash + lServerLogListHashStr = inGSDict["Client"]["DumpLogListHashStr"] + if lValueStr!=lServerLogListHashStr and lServerLogListHashStr!= "" and lServerLogListHashStr!= None: # Case if Hash is not equal Fix because None can be obtained without JSON decode + lFlagDoGenerateBool = False + else: # Case Hashes are equal + time.sleep(inGSDict["Client"]["DumpLogListRefreshIntervalSecFloat"]) + # Return the result if Hash is changed + lResult = {"HashStr": lServerLogListHashStr, "ServerLogList": lServerLogList} inResponseDict = inRequest.OpenRPAResponseDict - # Create result JSON - lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list # Send message back to client - message = json.dumps(lResultDict) + message = json.dumps(lResult) # Write content as utf-8 data inResponseDict["Body"] = bytes(message, "utf8") + return lResult -def GetScreenshot(inRequest,inGlobalDict): +def pyOpenRPA_Screenshot(inRequest,inGlobalDict): # Get Screenshot def SaveScreenshot(inFilePath): # grab fullscreen @@ -182,6 +255,139 @@ def GetScreenshot(inRequest,inGlobalDict): inRequest.OpenRPAResponseDict["Body"] = lFileObject.read() # Закрыть файловый объект lFileObject.close() +# Add activity item or activity list to the processor queue +# Body is Activity item or Activity List +def pyOpenRPA_Processor(inRequest, inGSettings): + lL = inGSettings["Logger"] + # Recieve the data + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lInput = json.loads(lInputByteArray.decode('utf8')) + # If list - operator plus + if type(lInput) is list: + # Logging info about processor activity if not SuperToken () + if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + lActivityTypeListStr = "" + try: + for lActivityItem in lInput: + lActivityTypeListStr += f"{lActivityItem['Def']}; " + except Exception as e: + lActivityTypeListStr = "Has some error with Activity Type read" + if lL: lL.info(f"ServerSettings.pyOpenRPA_Processor. User activity from web. Domain: {inRequest.OpenRPA['Domain']}, Username: {inRequest.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}") + # Append in list + inGSettings["ProcessorDict"]["ActivityList"]+=lInput + else: + # Logging info about processor activity if not SuperToken () + if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + lActivityTypeListStr = "" + try: + lActivityTypeListStr = lInput['Def'] + except Exception as e: + lActivityTypeListStr = "Has some error with Activity Type read" + if lL: lL.info(f"ServerSettings.pyOpenRPA_Processor. User activity from web. Domain: {inRequest.OpenRPA['Domain']}, Username: {inRequest.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}") + # Append in list + inGSettings["ProcessorDict"]["ActivityList"].append(lInput) +# Execute activity list +def pyOpenRPA_ActivityListExecute(inRequest, inGSettings): + # Recieve the data + lL = inGSettings["Logger"] + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lInput = json.loads(lInputByteArray.decode('utf8')) + # If list - operator plus + if type(lInput) is list: + # Logging info about processor activity if not SuperToken () + if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + lActivityTypeListStr = "" + try: + for lActivityItem in lInput: + lActivityTypeListStr += f"{lActivityItem['Def']}; " + except Exception as e: + lActivityTypeListStr = "Has some error with Activity Type read" + if lL: lL.info(f"ServerSettings.pyOpenRPA_ActivityListExecute. User activity from web. Domain: {inRequest.OpenRPA['Domain']}, Username: {inRequest.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}") + # Execution + lResultList = Processor.ActivityListExecute(inGSettings = inGSettings, inActivityList = lInput) + inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList), "utf8") + else: + # Logging info about processor activity if not SuperToken () + if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + lActivityTypeListStr = "" + try: + lActivityTypeListStr = lInput['Def'] + except Exception as e: + lActivityTypeListStr = "Has some error with Activity Type read" + if lL: lL.info(f"ServerSettings.pyOpenRPA_ActivityListExecute. User activity from web. Domain: {inRequest.OpenRPA['Domain']}, Username: {inRequest.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}") + # Execution + lResultList = Processor.ActivityListExecute(inGSettings = inGSettings, inActivityList = [lInput]) + inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList[0]), "utf8") + +# See docs in Agent (pyOpenRPA.Agent.O2A) +def pyOpenRPA_Agent_O2A(inRequest, inGSettings): + lL = inGSettings["Logger"] # Alias + lConnectionLifetimeSecFloat = 3600.0 # 60 min * 60 sec 3600.0 + lTimeStartFloat = time.time() + # Recieve the data + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lInput = json.loads(lInputByteArray.decode('utf8')) + # Check if item is created + lAgentDictItemKeyTurple = (lInput["HostNameUpperStr"],lInput["UserUpperStr"]) + if lAgentDictItemKeyTurple not in inGSettings["AgentDict"]: + inGSettings["AgentDict"][lAgentDictItemKeyTurple] = SettingsTemplate.__AgentDictItemCreate__() + lThisAgentDict = inGSettings["AgentDict"][lAgentDictItemKeyTurple] + lThisAgentDict["IsListenBool"]=True # Set is online + lThisAgentDict["ConnectionCountInt"] += 1 # increment connection count + # Test solution + lDoLoopBool = True + while lDoLoopBool: + # Check if lifetime is over + if time.time() - lTimeStartFloat > lConnectionLifetimeSecFloat: # Lifetime is over + lThisAgentDict["IsListenBool"] = False # Set is offline + lDoLoopBool = False + else: # Lifetime is good - do alg + lThisAgentDict["IsListenBool"] = True # Set is online + lQueueList = lThisAgentDict["ActivityList"] + if len(lQueueList)>0:# Do some operations if has queue items + if lL: lL.debug(f'O2A BEFORE: ConnectionCountInt: {lThisAgentDict["ConnectionCountInt"]};ConnectionFirstQueueItemCountInt {lThisAgentDict["ConnectionFirstQueueItemCountInt"]}') + if lThisAgentDict["ConnectionCountInt"] == lThisAgentDict["ConnectionFirstQueueItemCountInt"] + 1: + # POP QUEUE ITEM CONDITION ConnectionCountInt == ConnectionFirstQueueItemCountInt + 1 + lActivityItem = lThisAgentDict["ActivityList"].pop(0) + lThisAgentDict["ConnectionFirstQueueItemCountInt"] = 0 + if lL: lL.debug(f"Activity was deleted from the list: {lThisAgentDict['ActivityList']}") + else: + lActivityItem = lThisAgentDict["ActivityList"][0] + lThisAgentDict["ConnectionFirstQueueItemCountInt"] += 1 + if lL: lL.debug(f"Activity was !not! deleted from the list: {lThisAgentDict['ActivityList']}") + if lL: lL.debug(f'O2A AFTER: ConnectionCountInt: {lThisAgentDict["ConnectionCountInt"]};ConnectionFirstQueueItemCountInt {lThisAgentDict["ConnectionFirstQueueItemCountInt"]}') + # Send QUEUE ITEM + if lL: lL.info(f"Activity item to agent Hostname {lInput['HostNameUpperStr']}, User {lInput['UserUpperStr']}. Activity item: {lActivityItem}") + inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lActivityItem), "utf8") + lDoLoopBool = False # CLose the connection + else: # no queue item - sleep for the next iteration + time.sleep(1) + lThisAgentDict["ConnectionCountInt"] -= 1 # Connection go to be closed - decrement the connection count +# See docs in Agent (pyOpenRPA.Agent.A2O) +def pyOpenRPA_Agent_A2O(inRequest, inGSettings): + # Recieve the data + lValueStr = None + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray = inRequest.rfile.read(lInputByteArrayLength) + # Превращение массива байт в объект + lInput = json.loads(lInputByteArray.decode('utf8')) + if "LogList" in lInput: + for lLogItemStr in lInput["LogList"]: + inGSettings["Logger"].info(lLogItemStr) + def SettingsUpdate(inGlobalConfiguration): import os import pyOpenRPA.Orchestrator @@ -207,10 +413,19 @@ def SettingsUpdate(inGlobalConfiguration): {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff2", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\themes\\default\\assets\\fonts\\icons.woff2"), "ResponseContentType": "font/woff2"}, {"Method":"GET", "URL": "/favicon.ico", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\favicon.ico"), "ResponseContentType": "image/x-icon"}, {"Method":"GET", "URL": "/3rdParty/Handlebars/handlebars-v4.1.2.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js"), "ResponseContentType": "application/javascript"}, - {"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": Monitor_ControlPanelDictGet_SessionCheckInit, "ResponseContentType": "application/json"}, - {"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"}, + {"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": BackwardCompatibility.v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit, "ResponseContentType": "application/json"}, + {"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"}, {"Method": "GET", "URL": "/pyOpenRPA_logo.png", "MatchType": "Equal", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\pyOpenRPA_logo.png"), "ResponseContentType": "image/png"}, - {"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": UserRoleHierarchyGet, "ResponseContentType": "application/json"} + {"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": BackwardCompatibility.v1_2_0_UserRoleHierarchyGet, "ResponseContentType": "application/json"}, + # New way of the v.1.2.0 functionallity (all defs by the URL from /pyOpenRPA/...) + {"Method": "POST", "URL": "/pyOpenRPA/ServerData", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"}, + {"Method": "GET", "URL": "/pyOpenRPA/ServerJSInit", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerJSInit, "ResponseContentType": "application/javascript"}, + {"Method": "POST", "URL": "/pyOpenRPA/ServerLog", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerLog, "ResponseContentType": "application/json"}, + {"Method": "GET", "URL": "/pyOpenRPA/Screenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"}, + {"Method": "POST", "URL": "/pyOpenRPA/ProcessorQueueAdd", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Processor, "ResponseContentType": "application/json"}, + {"Method": "POST", "URL": "/pyOpenRPA/ActivityListExecute", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ActivityListExecute, "ResponseContentType": "application/json"}, + {"Method": "POST", "URL": "/pyOpenRPA/Agent/O2A", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_O2A, "ResponseContentType": "application/json"}, + {"Method": "POST", "URL": "/pyOpenRPA/Agent/A2O", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_A2O, "ResponseContentType": "application/json"}, ] - inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList + inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList return inGlobalConfiguration \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.js b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.js index 17d52f94..81609dcd 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.js +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.js @@ -1,4 +1,5 @@ var mGlobal={} +mGlobal.pyOpenRPA = {} window.onload=function() { //document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; //Render existing data @@ -121,11 +122,17 @@ $(document).ready(function() { lCMDCode=$(".openrpa-controller-cmd-run-input")[0].value ///Подготовить конфигурацию lData = [ - {"Type":"CMDStart", "Command": lCMDCode } + { + "Def":"OSCMD", // def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + "ArgList":[], // Args list + "ArgDict":{"inCMDStr":lCMDCode,"inRunAsyncBool":false}, // Args dictionary + "ArgGSettings": null, // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + "ArgLogger": "inLogger" // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + } ] $.ajax({ type: "POST", - url: 'Utils/Processor', + url: '/pyOpenRPA/ActivityListExecute', data: JSON.stringify(lData), success: function(lData,l2,l3) @@ -221,7 +228,7 @@ $(document).ready(function() { } //inHostURI: http://localhost:8081 mGlobal.Monitor.ScreenshotModal.Show=function(inHostURI=" ") { - $('.ui.modal.daemon-screenshot').modal('show'); + $('.ui.modal.daemon-screenshot').modal({'onHide':function (inElement) {mGlobal.Monitor.ScreenshotModal.Close();} }).modal('show'); //Функция обновления картинки lScreenshotUpdate=function() { @@ -276,125 +283,342 @@ $(document).ready(function() { mGlobal.Monitor.fControlPanelRefresh_TechnicalRender = function() { lResponseJSON = mGlobal.Monitor.mDatasetLast + if (lResponseJSON!= null) { - ///Escape onclick - /// RenderRobotList - lResponseJSON["RenderRobotList"].forEach( - function(lItem){ - if ('FooterButtonX2List' in lItem) { - /// FooterButtonX2List - lItem["FooterButtonX2List"].forEach( - function(lItem2){ - if ('OnClick' in lItem) { - lOnClickEscaped = lItem["OnClick"]; - lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); - lItem["OnClick"] = lOnClickEscaped; + /// New version of control panels + for (var lKeyStr in lResponseJSON){ + if (lKeyStr != "RenderRobotList") { /// Check if not "RenderRobotList" + lCPDict = lResponseJSON[lKeyStr] + /// Render HTML + if ("HTMLStr" in lCPDict) { + + } + } + } + + + /// v1.2.0 Backward compatibility - support old control panels + if ("RenderRobotList" in lResponseJSON) { + ///Escape onclick + /// RenderRobotList + lResponseJSON["RenderRobotList"].forEach( + function(lItem){ + if ('FooterButtonX2List' in lItem) { + /// FooterButtonX2List + lItem["FooterButtonX2List"].forEach( + function(lItem2){ + if ('OnClick' in lItem) { + lOnClickEscaped = lItem["OnClick"]; + lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + lItem["OnClick"] = lOnClickEscaped; + } } - } - ); - /// FooterButtonX1List - lItem["FooterButtonX1List"].forEach( - function(lItem2){ - if ('OnClick' in lItem) { - lOnClickEscaped = lItem["OnClick"]; - lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); - lItem["OnClick"] = lOnClickEscaped; + ); + /// FooterButtonX1List + lItem["FooterButtonX1List"].forEach( + function(lItem2){ + if ('OnClick' in lItem) { + lOnClickEscaped = lItem["OnClick"]; + lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """).replace(/'/g, "'"); + lItem["OnClick"] = lOnClickEscaped; + } } - } - ); + ); + } } - } - ); - ////////////////////////////////////////////////////////// - ///Сформировать HTML код новой таблицы - контрольная панель - lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-control-panel",lResponseJSON) - //Присвоить ответ в mGlobal.Monitor.mResponseList - mGlobal.Monitor.mResponseList = lResponseJSON - ///Set result in mGlobal.DataStorage - lResponseJSON["RenderRobotList"].forEach( - function(lItem){ - if ('DataStorageKey' in lItem) { - mGlobal["DataStorage"][lItem['DataStorageKey']]=lItem + ); + ////////////////////////////////////////////////////////// + ///Сформировать HTML код новой таблицы - контрольная панель + lHTMLCode+=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-control-panel",lResponseJSON) + //Присвоить ответ в mGlobal.Monitor.mResponseList + mGlobal.Monitor.mResponseList = lResponseJSON + ///Set result in mGlobal.DataStorage + lResponseJSON["RenderRobotList"].forEach( + function(lItem){ + if ('DataStorageKey' in lItem) { + mGlobal["DataStorage"][lItem['DataStorageKey']]=lItem + } } + ) + ///Прогрузить новую таблицу + $(".openrpa-control-panel").html(lHTMLCode) + //////////////////////////////////////////////////// + /// !RDP List ! Сформировать HTML код новой таблицы - список RDP + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON) + //Присвоить ответ в mGlobal.RobotRDPActive.mResponseList + mGlobal.RobotRDPActive.mResponseList = lResponseJSON + ///Прогрузить новую таблицу + $(".openrpa-robotrdpactive-control-panel").html(lHTMLCode) + ///Очистить дерево + //mGlobal.ElementTree.fClear(); + //////////////////////////////////////////////////// + /// !UserAgent List ! Сформировать HTML код новой таблицы - список RDP + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".pyOpenRPA-Agent-ListTemplate",lResponseJSON) + //Присвоить ответ в mGlobal.RobotRDPActive.mResponseList + mGlobal.RobotRDPActive.mResponseList = lResponseJSON + ///Прогрузить новую таблицу + $(".pyOpenRPA-Agent-List").html(lHTMLCode) + ///Очистить дерево + //mGlobal.ElementTree.fClear(); + } + } + } + + ///v 1.2.0 pyOpenRPA + /// Execute ActivityItem + mGlobal.pyOpenRPA.ActivityItemExecute=function(inActivityItem) { + ///EXAMPLE + // { + // "Def":"OSCMD", // def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + // "ArgList":[], // Args list + // "ArgDict":{"inCMDStr":lCMDCode,"inRunAsyncBool":false}, // Args dictionary + // "ArgGSettings": null, // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // "ArgLogger": "inLogger" // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // } + ///Подготовить конфигурацию + lData = [inActivityItem] + $.ajax({ + type: "POST", + url: '/pyOpenRPA/ActivityListExecute', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + console.log(lResponseJSON) + }, + dataType: "text" + }); + } + /// Execute ActivityList + mGlobal.pyOpenRPA.ActivityListExecute=function(inActivityList) { + ///EXAMPLE + // [{ + // "Def":"OSCMD", // def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + // "ArgList":[], // Args list + // "ArgDict":{"inCMDStr":lCMDCode,"inRunAsyncBool":false}, // Args dictionary + // "ArgGSettings": null, // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // "ArgLogger": "inLogger" // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // }] + ///Подготовить конфигурацию + lData = inActivityList + $.ajax({ + type: "POST", + url: '/pyOpenRPA/ActivityListExecute', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + console.log(lResponseJSON) + }, + dataType: "text" + }); + } + /// Add ActivityList in processor queue + mGlobal.pyOpenRPA.ProcessorQueueAdd=function(inActivityList) { + ///EXAMPLE + // [{ + // "Def":"OSCMD", // def link or def alias (look gSettings["Processor"]["AliasDefDict"]) + // "ArgList":[], // Args list + // "ArgDict":{"inCMDStr":lCMDCode,"inRunAsyncBool":false}, // Args dictionary + // "ArgGSettings": null, // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // "ArgLogger": "inLogger" // Name of GSettings attribute: str (ArgDict) or index (for ArgList) + // }] + ///Подготовить конфигурацию + lData = inActivityList + $.ajax({ + type: "POST", + url: '/pyOpenRPA/ProcessorQueueAdd', + data: JSON.stringify(lData), + success: + function(lData,l2,l3) + { + var lResponseJSON=JSON.parse(lData) + console.log(lResponseJSON) + }, + dataType: "text" + }); + } + + /// v1.2.0 pyOpenRPA ServerJSInit + mGlobal.pyOpenRPA.ServerJSInitDef=function() { + try { + $.ajax({ + type: "GET", + headers: {}, + url: 'pyOpenRPA/ServerJSInit', + data: mGlobal.pyOpenRPA.ServerDataHashStr, + async: false, + success: function(lJSText) { + try { + eval(lJSText) + } + catch(error) { + console.log(error) + } + }, + dataType: "text", + error: function(jqXHR, textStatus, errorThrown ) { + console.log(textStatus) } - ) + }); + } + catch(error) { + console.log(error) + } + } + + /// v1.2.0 pyOpenRPA ServerData + mGlobal.pyOpenRPA.ServerDataDict = null + mGlobal.pyOpenRPA.ServerDataHashStr = "" + mGlobal.pyOpenRPA.ServerDataRefreshDef_TechnicalRender = function() + { + lResponseJSON = mGlobal.pyOpenRPA.ServerDataDict + if (lResponseJSON!= null) { + /// New version of control panels + lHTMLCode = '
' + for (var lKeyStr in lResponseJSON["CPDict"]){ + lCPDict = lResponseJSON["CPDict"][lKeyStr] + /// Render HTML + if ("HTMLStr" in lCPDict) { + lHTMLCode+=lCPDict["HTMLStr"] + } + } + lHTMLCode += '
' ///Прогрузить новую таблицу $(".openrpa-control-panel").html(lHTMLCode) //////////////////////////////////////////////////// - ///Сформировать HTML код новой таблицы - список RDP - lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON) + /// !RDP List ! Сформировать HTML код новой таблицы - список RDP + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON["RDPDict"]) //Присвоить ответ в mGlobal.RobotRDPActive.mResponseList - mGlobal.RobotRDPActive.mResponseList = lResponseJSON + mGlobal.RobotRDPActive.mResponseList = lResponseJSON["RDPDict"] ///Прогрузить новую таблицу $(".openrpa-robotrdpactive-control-panel").html(lHTMLCode) ///Очистить дерево //mGlobal.ElementTree.fClear(); + //////////////////////////////////////////////////// + /// !UserAgent List ! Сформировать HTML код новой таблицы - список RDP + lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".pyOpenRPA-Agent-ListTemplate",lResponseJSON["AgentDict"]) + ///Прогрузить новую таблицу + $(".pyOpenRPA-Agent-List").html(lHTMLCode) + ///Очистить дерево + //mGlobal.ElementTree.fClear(); } } - mGlobal.Monitor.mDatasetLast = null - mGlobal.Monitor.fControlPanelRefresh=function() { + mGlobal.pyOpenRPA.ServerDataRefreshDef=function() { try { - //var XHR = new XMLHttpRequest(); - //XHR.setRequestHeader("Cookies",document.cookie) - ///Загрузка данных - //console.log("Request is sent") - //console.log(document.cookie) $.ajax({ - type: "GET", - headers: {"SessionGUIDStr":mGlobal.SessionGUIDStr}, - url: 'Monitor/ControlPanelDictGet', - data: '', - //cache: false, - //xhr: XHR, + type: "POST", + headers: {}, + url: 'pyOpenRPA/ServerData', + data: mGlobal.pyOpenRPA.ServerDataHashStr, success: function(lData,l2,l3) { try { var lResponseJSON=JSON.parse(lData) - mGlobal.Monitor.mDatasetLast = lResponseJSON - mGlobal.Monitor.fControlPanelRefresh_TechnicalRender() + mGlobal.VersionStr = lResponseJSON["ServerDataDict"]["UserDict"]["VersionStr"] + mGlobal.pyOpenRPA.ServerDataDict = lResponseJSON["ServerDataDict"] + mGlobal.pyOpenRPA.ServerDataHashStr = lResponseJSON["HashStr"] + mGlobal.pyOpenRPA.ServerDataRefreshDef_TechnicalRender() + mGlobal.UserRoleUpdate(); + setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,600) // If LOGS are update every ms - set some limit in ms on the client side + //mGlobal.pyOpenRPA.ServerDataRefreshDef() // Go to the next call } catch(error) { + console.log(error) + setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000) } - mGlobal.Monitor.fControlPanelRefresh() // recursive + //mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive }, dataType: "text", error: function(jqXHR, textStatus, errorThrown ) { - sleep(3000) - mGlobal.Monitor.fControlPanelRefresh() // recursive + setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000) + //sleep(3000) + //mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive } }); } catch(error) { - sleep(3000) - mGlobal.Monitor.fControlPanelRefresh() // recursive + setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000) + //sleep(3000) + //mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive } - //mGlobal.Monitor.fControlPanelRefresh() // recursive } - mGlobal.Monitor.fControlPanelRefresh() - mGlobal.Test=function() { - ///Обнулить таблицу - lData = [ - { - "Type":"GlobalDictKeyListValueSet", - "key_list":["Storage","Robot_R01"], - "value":{ - "RunDateTimeString":"Test1", - "StepCurrentName":"Test2", - "StepCurrentDuration":"Test3" + ///////////////////////////////////////////////////////////// + /// v1.2.0 pyOpenRPA ServerLogs + mGlobal.pyOpenRPA.ServerLogList = null + mGlobal.pyOpenRPA.ServerLogListHashStr = "" + mGlobal.pyOpenRPA.ServerLogListDoRenderBool = true + ///Turn OFF rendering + mGlobal.pyOpenRPA.ServerLogListDoRenderFalse = function() { + ///Set unfreeze button + $("a.mGlobal-pyOpenRPA-ServerLogListDoRender").html("Unfreeze textarea") + $("a.mGlobal-pyOpenRPA-ServerLogListDoRender").attr("onclick","mGlobal.pyOpenRPA.ServerLogListDoRenderTrue()") + $("textarea.mGlobal-pyOpenRPA-ServerLogList").css("background-color","#b9e2e8") + mGlobal.pyOpenRPA.ServerLogListDoRenderBool = false + } + ///Turn ON rendering + mGlobal.pyOpenRPA.ServerLogListDoRenderTrue = function() { + mGlobal.pyOpenRPA.ServerLogListDoRenderBool = true + ///Render last data + mGlobal.pyOpenRPA.ServerLogListRefreshDef_TechnicalRender() + ///Set unfreeze button + $("a.mGlobal-pyOpenRPA-ServerLogListDoRender").html("Freeze textarea") + $("a.mGlobal-pyOpenRPA-ServerLogListDoRender").attr("onclick","mGlobal.pyOpenRPA.ServerLogListDoRenderFalse()") + $("textarea.mGlobal-pyOpenRPA-ServerLogList").css("background-color","") + + } + mGlobal.pyOpenRPA.ServerLogListScrollBottomDef = function() { + var lTA = $("textarea.mGlobal-pyOpenRPA-ServerLogList")[0]; + lTA.scrollTop = lTA.scrollHeight; + } + mGlobal.pyOpenRPA.ServerLogListRefreshDef_TechnicalRender = function() + { + lResponseJSON = mGlobal.pyOpenRPA.ServerLogList + if (lResponseJSON!= null && mGlobal.pyOpenRPA.ServerLogListDoRenderBool==true) { + lText = lResponseJSON.join("\n") /// Code for the processing the text + $("textarea.mGlobal-pyOpenRPA-ServerLogList")[0].value= lText ///Прогрузить новую таблицу + mGlobal.pyOpenRPA.ServerLogListScrollBottomDef() //Scroll to the bottom + } + } + mGlobal.pyOpenRPA.ServerLogListRefreshDef=function() { + try { + $.ajax({ + type: "POST", + headers: {}, + url: 'pyOpenRPA/ServerLog', + data: mGlobal.pyOpenRPA.ServerLogListHashStr, + success: function(lData,l2,l3) { + try { + var lResponseJSON=JSON.parse(lData) + mGlobal.pyOpenRPA.ServerLogList = lResponseJSON["ServerLogList"] + mGlobal.pyOpenRPA.ServerLogListHashStr = lResponseJSON["HashStr"] + mGlobal.pyOpenRPA.ServerLogListRefreshDef_TechnicalRender() + } + catch(error) { + } + setTimeout(mGlobal.pyOpenRPA.ServerLogListRefreshDef,600) // If LOGS are update every ms - set some limit in ms on the client side + //mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive + }, + dataType: "text", + error: function(jqXHR, textStatus, errorThrown ) { + setTimeout(mGlobal.pyOpenRPA.ServerLogListRefreshDef,3000) + //sleep(3000) + //mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive } - } - ] - $.ajax({ - type: "POST", - url: 'Utils/Processor', - data: JSON.stringify(lData), - success: - function(lData,l2,l3) - { - //console.log(lData) - }, - dataType: "text" - }); + }); + } + catch(error) { + setTimeout(mGlobal.pyOpenRPA.ServerLogListRefreshDef,3000) + //sleep(3000) + //mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive + } } + ///////////////////////////////////////////////////////////// + + + mGlobal.Monitor.mDatasetLast = null + /////////////////////////////// ///Processor functions /////////////////////////////// @@ -615,7 +839,7 @@ $(document).ready(function() { // UAC Ask mGlobal.UserRoleAsk=function(inList) { var lResult = true; // Init flag - var lRoleHierarchyDict = mGlobal.UserRoleHierarchyDict; // get the Hierarchy + var lRoleHierarchyDict = mGlobal.pyOpenRPA.ServerDataDict.UserDict.UACClientDict; // get the Hierarchy // Try to get value from key list var lKeyValue = lRoleHierarchyDict; // Init the base var lListLength = inList.length; @@ -641,64 +865,31 @@ $(document).ready(function() { } // Check user roles and update the Orchestrator UI mGlobal.UserRoleUpdate=function() { - $.ajax({ - type: "POST", - url: 'Orchestrator/UserRoleHierarchyGet', - data: "", - success: - function(lData,l2,l3) - { - var lUACAsk = mGlobal.UserRoleAsk // Alias - var lResponseDict=JSON.parse(lData) - mGlobal.UserRoleHierarchyDict = lResponseDict // set the user role hierarchy - //Turn on the Lookmachine screenshot button - if (lUACAsk(["Orchestrator","Controls","LookMachineScreenshots"])) { - $(".openrpa-control-lookmachinescreenshot").show() //Show button - } - //Turn on the restart orchestrator button - if (lUACAsk(["Orchestrator","Controls","RestartOrchestrator"])) { - $(".openrpa-control-restartorchestrator").show() //Show button - } - //Turn on the rdp session list - if (lUACAsk(["Orchestrator","RDPActive","ListRead"])) { - $(".openrpa-rdpactive-title").show() //Show section - $(".openrpa-robotrdpactive-control-panel-general").show() //Show section - } - //Turn on the restart PC button - if (lUACAsk(["Orchestrator","Controls","RestartPC"])) { - $(".openrpa-control-restartpc").show() //Show button - } - //Turn on the git update + restart orchestrator - if (lUACAsk(["Orchestrator","Controls","GITRestartOrchestrator"])) { - $(".openrpa-control-gitrestartorchestrator").show() //Show button - } - }, - dataType: "text" - }); - } - mGlobal.UserRoleUpdate() // Cal the update User Roles function - // Orchestrator model - mGlobal.WorkingDirectoryPathStr = null - mGlobal.OrchestratorModelUpdate=function() { - lData = [ - { - "Type": "GlobalDictKeyListValueGet", - "KeyList": ["Server","WorkingDirectoryPathStr"] - } - ] - $.ajax({ - type: "POST", - url: 'Utils/Processor', - data: JSON.stringify(lData), - success: - function(lData,l2,l3) - { - var lUACAsk = mGlobal.UserRoleAsk // Alias - var lResponseList=JSON.parse(lData) - mGlobal.WorkingDirectoryPathStr = lResponseList[0]["Result"] - }, - dataType: "text" - }); + var lUACAsk = mGlobal.UserRoleAsk // Alias + //CPKeyDict + if (lUACAsk(["pyOpenRPADict","CPKeyDict"])) { $(".UACClient-pyOpenRPADict-CPKeyDict").show(); } + + //RDPKeyDict + if (lUACAsk(["pyOpenRPADict","RDPKeyDict"])) { $(".UACClient-pyOpenRPADict-RDPKeyDict").show(); } + + //AgentKeyDict + if (lUACAsk(["pyOpenRPADict","AgentKeyDict"])) { $(".UACClient-pyOpenRPADict-AgentKeyDict").show(); } + + // AdminDict + if (lUACAsk(["pyOpenRPADict","AdminDict","LogViewerBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-LogViewerBool").show(); } + if (lUACAsk(["pyOpenRPADict","AdminDict","CMDInputBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-CMDInputBool").show(); } + if (lUACAsk(["pyOpenRPADict","AdminDict","ScreenshotViewerBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-ScreenshotViewerBool").show(); } + if (lUACAsk(["pyOpenRPADict","AdminDict","RestartOrchestratorBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorBool").show(); } + if (lUACAsk(["pyOpenRPADict","AdminDict","RestartOrchestratorGITPullBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorGITPullBool").show(); } + if (lUACAsk(["pyOpenRPADict","AdminDict","RestartPCBool"])) { $(".UACClient-pyOpenRPADict-AdminDict-RestartPCBool").show(); } + } - mGlobal.OrchestratorModelUpdate() // Cal the update orchestrator model + + /// v1.2.0 pyOpenRPA Init defs + mGlobal.pyOpenRPA.ServerJSInitDef(); // Recieve JS from server (if exist) and then call anothe url ServerData + mGlobal.pyOpenRPA.ServerDataRefreshDef(); // Init the refresh data def from server side + mGlobal.pyOpenRPA.ServerLogListRefreshDef(); // Init the refresh data def from the log window + mGlobal.pyOpenRPA.ServerLogListDoRenderTrue(); // Init button to freeze/unfreeze textare with logs + + $('.ui.dropdown').dropdown(); }); \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.xhtml b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.xhtml index 672fda6c..74e4976d 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.xhtml +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Web/Index.xhtml @@ -59,11 +59,12 @@             -

Orchestrator Web GUI

+     +

ORCHESTRATOR WEB GUI

-
+
-
-

- -
- Administration -
-

- - - -
-
- + + +