v.1.3.0 is published!

dev
robo-bo 2 years ago
parent 39bae95e0d
commit 0258e89565

@ -1,7 +1,7 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.2.14 Version: 1.3.0
Summary: First open source RPA platform for business Summary: The powerful open source RPA platform for business
Home-page: https://pyopenrpa.ru/ Home-page: https://pyopenrpa.ru/
Author: Ivan Maslov Author: Ivan Maslov
Author-email: Ivan.Maslov@pyopenrpa.ru Author-email: Ivan.Maslov@pyopenrpa.ru

@ -1,13 +1,13 @@
pyOpenRPA-1.2.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.2.14.dist-info/METADATA,sha256=msxiHoe4JlRNqXnlKGZWthHNr5JPV7OWXJzgXwzZTcc,4372 pyOpenRPA-1.3.0.dist-info/METADATA,sha256=V-qwlFCJ26LQShABSS0p5Tm9vxOXMYqrahL40zkthnI,4378
pyOpenRPA-1.2.14.dist-info/RECORD,, pyOpenRPA-1.3.0.dist-info/RECORD,,
pyOpenRPA-1.2.14.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA-1.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.2.14.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.3.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.2.14.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.3.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Agent/A2O.py,sha256=PlIZZCTnVrYF2i6DSAi_KbzZfc2gtcBPmOerrEZq68U,1718 pyOpenRPA/Agent/A2O.py,sha256=PlIZZCTnVrYF2i6DSAi_KbzZfc2gtcBPmOerrEZq68U,1718
pyOpenRPA/Agent/O2A.py,sha256=XHl5nytUoUqfPvmYWh5auYo-s0GIThNmkOA9ON-JCis,5535 pyOpenRPA/Agent/O2A.py,sha256=o-5JF-415L69-vCg0COzK79sWs4btJwOkt53pqVhu0U,6210
pyOpenRPA/Agent/Processor.py,sha256=xNZfQ_HcV-qm_x90tBLKYJqvnENiTqHSoUk2LhDfqWQ,6346 pyOpenRPA/Agent/Processor.py,sha256=xNZfQ_HcV-qm_x90tBLKYJqvnENiTqHSoUk2LhDfqWQ,6346
pyOpenRPA/Agent/__Agent__.py,sha256=gqKxqu9XEEdgLNRvAlaGqDaQR2sgn_n_Vskf8dv2cQo,12692 pyOpenRPA/Agent/__Agent__.py,sha256=rUvtEGEmlsd3ZujkQnPhL3mGaALmM2iNvfWBoF0Puc4,15167
pyOpenRPA/Agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Agent/__pycache__/A2O.cpython-37.pyc,, pyOpenRPA/Agent/__pycache__/A2O.cpython-37.pyc,,
pyOpenRPA/Agent/__pycache__/O2A.cpython-37.pyc,, pyOpenRPA/Agent/__pycache__/O2A.cpython-37.pyc,,
@ -17,18 +17,18 @@ pyOpenRPA/Agent/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Agent/readme.md,sha256=QF_Bnv204OK3t1JUEhjfICkxFmSdX6bvaRl_HI6lH9I,19 pyOpenRPA/Agent/readme.md,sha256=QF_Bnv204OK3t1JUEhjfICkxFmSdX6bvaRl_HI6lH9I,19
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85 pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/LICENSE.pdf,sha256=8L-9X_kCCt8yWvjy0E_xV-C6Im79hZnH7WcfZHRz8uM,4322139 pyOpenRPA/LICENSE.pdf,sha256=8L-9X_kCCt8yWvjy0E_xV-C6Im79hZnH7WcfZHRz8uM,4322139
pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=ymWcw6ZKg6-sSiykQK8iolhBjK2amTyQx7u8QKPnewc,37947 pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=IqVZygd8ab9X1gBfP7WImQrYqKy8snCSbThqrvdT5f0,39633
pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103 pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103
pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529 pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=nBJqwBd6y9yeE49XOn83r8Dtvb3yReujrp-frxOhNL8,16671 pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=PZzh_RUke8bIMGghCXTnEuTYICCwW71r2xXk7iTdUnU,17345
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582 pyOpenRPA/Orchestrator/Managers/Git.py,sha256=VCXXc-enJhvrAJvYc8jHK9GcGe02meMdszU0tlJDHiQ,12879
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377 pyOpenRPA/Orchestrator/Managers/Process.py,sha256=4LJNMrt61AJKI3p7SeXnUSEpA61BtqWVxaVYxYS_BaI,42221
pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71 pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71
pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Process.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Process.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Processor.py,sha256=FtNmdIsBStkLHLlOe6MDWzSmZv9m7ntlQs-NirA6OgQ,10264 pyOpenRPA/Orchestrator/Processor.py,sha256=WXA_OC8tWVU-R8dsYR6O7-griwcxn6HH27qRs3GWnoU,10368
pyOpenRPA/Orchestrator/ProcessorOld.py,sha256=Vh5zLRpWWf-vt9CCYI8nDY7oaefiufnu6Pnl4tp27pY,13749 pyOpenRPA/Orchestrator/ProcessorOld.py,sha256=Vh5zLRpWWf-vt9CCYI8nDY7oaefiufnu6Pnl4tp27pY,13749
pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531 pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=GQCB1NElDCsJ8e9CKs9ivi91BjQVBSPL4Uqt9DTFn2A,1976 pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=GQCB1NElDCsJ8e9CKs9ivi91BjQVBSPL4Uqt9DTFn2A,1976
@ -36,7 +36,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=hvuXDlmcacN6GqBuICWJcu
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657 pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405 pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405
pyOpenRPA/Orchestrator/RobotRDPActive/Recovery.py,sha256=jneD474V-ZBYnmQFxWoY_feGNMSL0lGaRK6TEfQ6gOc,2954 pyOpenRPA/Orchestrator/RobotRDPActive/Recovery.py,sha256=jneD474V-ZBYnmQFxWoY_feGNMSL0lGaRK6TEfQ6gOc,2954
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=5FX48HlIn8NKfs7q_rp3lpumWtNcwdHq7J8ygnOwU_g,12284 pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=LQexk8eb4YOa8A51XwyZdng3AzLadgHNAgJfW2OAF0E,13065
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144 pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462 pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077 pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
@ -54,7 +54,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py,sha256=YjS23qinMk_2z47MGRVSDxbvsUMImnhqLi1F4BqW2OE,602 pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py,sha256=GQt40zD9X0R4RPaa2Cnbn-17oR2gUZvRGk3T3uGdKuY,603
pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606
pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593 pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593
@ -62,9 +62,9 @@ pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=YOQgZQ97nM_XQYVRbusj_b50aqEiNBJFF3bs7wA-O6k,36240 pyOpenRPA/Orchestrator/Server.py,sha256=eYiXKvWsiBG_kfHtzdNX4Zu2xL2DjkJZXqBfqOgHAk4,38600
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=260YPXINLrora8pBBVHQSPNBkc8wdlyadsoQTQKdpAs,32590 pyOpenRPA/Orchestrator/ServerSettings.py,sha256=wZe5aEUJOWYol8WzKUQBRq9JEnXj0Z39554PAIoqvbw,34326
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=TR6WQVm-0sFoQjnV08t9K5oQOcpC7dbKOnWQS31m9dQ,21443 pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=dVL-JZpAUQP3LLXE_7IUuE7RkLTYBAA-RX4e5FZ_DU0,21499
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097 pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681 pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681
pyOpenRPA/Orchestrator/Utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Orchestrator/Utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@ -75,7 +75,7 @@ pyOpenRPA/Orchestrator/Web/Index.js,sha256=YACiZAvjr6NmFlDhQu6urkJp49BX7L8WJU9p-
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257 pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257
pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,, pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=C0gVOwB3bYRJMALXLPLdkHw0wobQBly5_G7pLWBjGcg,204085 pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=LmEhNQkdK5SEIqql0ZM9PrjKgQ4-aQOiOheX83GbqmQ,207494
pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207 pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207
pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273 pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273
pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,, pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,,
@ -263,7 +263,46 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
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/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/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/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899 pyOpenRPA/Resources/Web/orpa/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
pyOpenRPA/Resources/Web/orpa/footer.xhtml,sha256=5aNthu2jsINqpgo_BS8UDbRWhA3rlRtlQZIILv_4hKo,3190
pyOpenRPA/Resources/Web/orpa/header.xhtml,sha256=pqVM-N53bz4_DzbG4PoN7B7N7XECZWZe12qVlc68ylk,3617
pyOpenRPA/Resources/Web/orpa/logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/Resources/Web/orpa/orc.js,sha256=qlzbbewXWDFbNhNHVVvMEYQFyQbRA7zEHoeaV38fJoQ,43558
pyOpenRPA/Resources/Web/orpa/orc.xhtml,sha256=x6NdMv6HrjUt0rZsz61dJeMl3DNte1KkEULQRkGfsJg,19098
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Bold.woff2,sha256=roj8DXqWGDL4CVJ9ML05g6aGbUL2alat4j9UNoFZTbY,184912
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Italic.woff2,sha256=RGV2Xy9u3c2tNP_XyrVZ5WvA515F4ZL4XpVisHcUgdw,195704
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Regular.woff2,sha256=mDsMrzNuhUIhT8FwGaT8XgNghkuSgGyhTVXB_BwsWg8,182708
pyOpenRPA/Resources/Web/orpa/styleset/bg1.jpg,sha256=63vfRzL-rLY_hW634p8rFps-BKFUKK9O0e4zaeHFxKw,251041
pyOpenRPA/Resources/Web/orpa/styleset/bg10.jpg,sha256=ZY_Z27kqavsjccDUrqoURz71zvkk81hdYB7u8TPciwI,256648
pyOpenRPA/Resources/Web/orpa/styleset/bg2.jpg,sha256=UlHtxLzqoypCTm1d_cIO3UFDrpYFNmTfAUQr3RtADdo,249670
pyOpenRPA/Resources/Web/orpa/styleset/bg3.jpg,sha256=N5Lp18GyFzCSaDXfcPAwrtVfCW7uoNIOvRos0F-qryg,245168
pyOpenRPA/Resources/Web/orpa/styleset/bg4.jpg,sha256=nckyiY8IgPYYUcprl0kOGE7-RzFnik4uqfFZc5V7aU8,258568
pyOpenRPA/Resources/Web/orpa/styleset/bg5.jpg,sha256=9AeZLTygYTWTlyyFaHnQSkj50m7eZ6iTCb0xt8oe_xM,261562
pyOpenRPA/Resources/Web/orpa/styleset/bg6.jpg,sha256=SXF3wNssI2dEHnBOfTWjRijXWA-BMq9YXXixq8ajVNk,260686
pyOpenRPA/Resources/Web/orpa/styleset/bg7.jpg,sha256=tZ2LP0BKZCxZnxlTUCCmXUSvdReRKb0AyX6ea7hAe0k,261376
pyOpenRPA/Resources/Web/orpa/styleset/bg8.jpg,sha256=x3l1TJaepQnMkeRvkhjOp_g6tUSebqp2-AEUDM2QCkg,261288
pyOpenRPA/Resources/Web/orpa/styleset/bg9.jpg,sha256=cRfXuOGYv_DCKBGrh7-Js1NGmtdrZWgYxXW9pi8c5Wo,261559
pyOpenRPA/Resources/Web/orpa/styleset/docs.css,sha256=XmeLuUmo_tTGFSurYJPZgaBb_gD_nMZX1TCzqBbKz7k,55821
pyOpenRPA/Resources/Web/orpa/styleset/docs.css.bak,sha256=uDJOPZxwDDgBOhhy12G1hYIBvOm6nuYQCdw0BoyidII,55845
pyOpenRPA/Resources/Web/orpa/styleset/docs.js,sha256=6MvOXSzLAeQLjzUt7IkRLhOn0QE1xRYZRgQQhu6y3mQ,44749
pyOpenRPA/Resources/Web/orpa/styleset/dropdown.css,sha256=Gra8mTrxFli1BxnYTArvthaDUajJPbB2Yta5y86C1rA,37642
pyOpenRPA/Resources/Web/orpa/styleset/easing.min.js,sha256=lP963PCWRotqEmscc9mBLkieNsnZ1d9KCD4unl3ZpVU,3794
pyOpenRPA/Resources/Web/orpa/styleset/header.css,sha256=kZg2wcwEoerMGyaKa4aMoYPBbJNCmovrml4WoWpBvQc,13723
pyOpenRPA/Resources/Web/orpa/styleset/highlight.min.js,sha256=Z39RBsR8A-knGdSdh8Bs2h9uA6grKSb4OyVhkmv48uk,21964
pyOpenRPA/Resources/Web/orpa/styleset/home.css,sha256=rr3HRdvfuzkK2H46rChyyswywWEDnCpHcCQ7D_xuQRU,16245
pyOpenRPA/Resources/Web/orpa/styleset/home.js,sha256=e65zKntsXHUK0DORA6gaoTlom0fsF4p8Unh74UsA85s,8926
pyOpenRPA/Resources/Web/orpa/styleset/jquery.min.js,sha256=3ks8PR3CUGtmk_D5iITh3AdM2p1myrObe0ihFf38TA8,84349
pyOpenRPA/Resources/Web/orpa/styleset/less.min.js,sha256=lqonJQsjeXmDk-iZDpqlyAO5tzY5F93xFP-eUIdTUZM,136781
pyOpenRPA/Resources/Web/orpa/styleset/metadata.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
pyOpenRPA/Resources/Web/orpa/styleset/nan.jpg,sha256=oZRYv31pGnf65BGA3fTzQ-HV8ulj7VoT-hB4nFVG3lc,23839
pyOpenRPA/Resources/Web/orpa/styleset/ogImage.JPG,sha256=-WVra6DU8SusAWtJWR6fEEROlJE_UxlOAodO7G82E3U,242713
pyOpenRPA/Resources/Web/orpa/styleset/ogImage.PNG,sha256=7-C8f1hHBHUPi_Y6gscUK04S3qso8lywT7KGCCYSMBM,131928
pyOpenRPA/Resources/Web/orpa/styleset/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/Resources/Web/orpa/styleset/segment.css,sha256=wzmuVZPMT1Y1Ymn52U8WQLiqmo7zNvwcXOVYr6ePfts,20287
pyOpenRPA/Resources/Web/orpa/styleset/sidebar.js,sha256=fnype3guWOx0kmyP7rL2I0mkyMR1_V9u8u2_W5E_4vk,34482
pyOpenRPA/Resources/Web/orpa/styleset/transition.js,sha256=esNkWoCwl6ksZewJkNDMLKCE4nDTdJZDJW3tdE7dlAo,36070
pyOpenRPA/Resources/Web/orpa/styleset/visibility.js,sha256=ulme0GrsuqHAHXTQunq96J0mESTl6Lux8msdK1_fcm4,44174
pyOpenRPA/Resources/Web/orpa/styleset/white-image.png,sha256=D7WJFGDtAIp_OXUU6Tz4zeYm_1yHRd8u7aTu0F35Kcw,5951
pyOpenRPA/Robot/Clipboard.py,sha256=QXClSH1ccCl8KfKbMY1Wk_SynEgfDZqZ_0h-OZYn4kA,1962 pyOpenRPA/Robot/Clipboard.py,sha256=QXClSH1ccCl8KfKbMY1Wk_SynEgfDZqZ_0h-OZYn4kA,1962
pyOpenRPA/Robot/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071 pyOpenRPA/Robot/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071
pyOpenRPA/Robot/Mouse.py,sha256=R-2q5Q-nDhvvQjcQxFz8FRM9tHjhPUKdnK3KuPc_OZw,16361 pyOpenRPA/Robot/Mouse.py,sha256=R-2q5Q-nDhvvQjcQxFz8FRM9tHjhPUKdnK3KuPc_OZw,16361
@ -273,7 +312,7 @@ pyOpenRPA/Robot/Screen.py,sha256=nH80ghKw7OseNF_fVwfUrih0y9o1Ul2VPEl_WT5b598,454
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=WLy8wUVDFSUN5S7hXUjijQIH0B71c5tj-pBCVex7uFc,125314 pyOpenRPA/Robot/UIDesktop.py,sha256=WLy8wUVDFSUN5S7hXUjijQIH0B71c5tj-pBCVex7uFc,125314
pyOpenRPA/Robot/UIWeb.py,sha256=AaAuX32i8nzTlXORp-l6rCp383JCX28TmJO7iyrqF1c,32351 pyOpenRPA/Robot/UIWeb.py,sha256=c3VA8IG2ELuGaWskyFFCbJalBKdDON2sjWhvHjR-2Dk,32353
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039 pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
@ -304,7 +343,7 @@ pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347 pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912 pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038 pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038
pyOpenRPA/Studio/Studio.py,sha256=RYwjb7KKEK2EgGz4lb95IQXvKk0-QACObBxoMh2IEFE,8689 pyOpenRPA/Studio/Studio.py,sha256=6He68tum4IyMSOv9VXsH2hmvMDnnCf4CDI66L7Wpl_Q,8739
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119 pyOpenRPA/Studio/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119
pyOpenRPA/Studio/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 pyOpenRPA/Studio/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
@ -317,13 +356,13 @@ pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/CrossOS.py,sha256=smXZ_DSx1YwLt9aUor0se51sEIkUhm2BicfoxU6qVl8,2569 pyOpenRPA/Tools/CrossOS.py,sha256=6yq7cit6dgs0KCk6zknoy699r7a3gC0UrnYYe-ZrobM,3539
pyOpenRPA/Tools/Debugger.py,sha256=2slOSaPnUAwfDlyjhaqqhhchXUBgEKQImTzXagJt4Jw,535 pyOpenRPA/Tools/Debugger.py,sha256=2slOSaPnUAwfDlyjhaqqhhchXUBgEKQImTzXagJt4Jw,535
pyOpenRPA/Tools/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378 pyOpenRPA/Tools/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473 pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655 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/Server.py,sha256=idGpXDU9rPv-NZcOW1Wrku_acEqEYnhSXNtUmFTs1dU,20019
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -351,7 +390,7 @@ pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/StopSafe.py,sha256=BNTtMmvsRE1Wtri3EkwhoBi6gGOjEPRQnJSV1C03c84,2176 pyOpenRPA/Tools/StopSafe.py,sha256=BIMiW8cFyQfX3KpRHaspdbw6-FcImTilqXRC_XXzyik,2346
pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490 pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490
pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996 pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@ -362,6 +401,7 @@ pyOpenRPA/Tools/__pycache__/StopSafe.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/Template.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Template.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=ZYKWkmhslD3FNo1wNQ-nV3i7qwvmOgf85JgP1u5glgI,156 pyOpenRPA/Utils/Render.py,sha256=VCU5cCCwyCFvMmRQwq7MGllgqzeDAp_s8om3UChIoPk,6703
pyOpenRPA/Utils/__pycache__/Render.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=adiLDsNcgYHaK1h_sStFVU0UEQpYGgFRvPiLmmrtvnU,155
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -53,27 +53,27 @@ def O2A_Loop(inGSettings):
# Log full version if bytes size is less than limit . else short # Log full version if bytes size is less than limit . else short
lAgentLimitLogSizeBytesInt = 500 lAgentLimitLogSizeBytesInt = 500
if lBodyLenInt <= lAgentLimitLogSizeBytesInt: if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"ActivityItem from orchestrator: {lQueueItem}"); if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: {lQueueItem}")
else: else:
if lL: lL.info(f"ActivityItem from orchestrator: Supressed - big size. Size is {lBodyLenInt} bytes"); if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: содержимое свернуто из-за большого размера ({lBodyLenInt} байт")
else: else:
if lL: lL.debug(f"Empty response from the orchestrator - loop when refresh the connection between Orc and Agent"); if lL: lL.debug(f"Поступил пустой ответ от оркестратора - цикл попытается обновить соединение между оркестратором и агентом");
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
if time.time() - lCEPhaseFastTimeLastGoodFloat <= lCEPhaseFastDurationSecFloat: if time.time() - lCEPhaseFastTimeLastGoodFloat <= lCEPhaseFastDurationSecFloat:
if lL: lL.error(f"O2A Connection error - orchestrator is not available. Sleep for {lCEPhaseFastRetrySecFloat} s.") if lL: lL.error(f"О2А Ошибка соединения - оркестратор недоступен. Повторить попытку через {lCEPhaseFastRetrySecFloat} с.")
time.sleep(lCEPhaseFastRetrySecFloat) time.sleep(lCEPhaseFastRetrySecFloat)
else: else:
if lL: lL.error(f"O2A Connection error - orchestrator is not available. Sleep for {lCEPhaseLongRetrySecFloat} s.") if lL: lL.error(f"О2А Ошибка соединения - оркестратор недоступен. Повторить попытку через {lCEPhaseLongRetrySecFloat} с.")
time.sleep(lCEPhaseLongRetrySecFloat) time.sleep(lCEPhaseLongRetrySecFloat)
except ConnectionResetError as e: except ConnectionResetError as e:
if lL: lL.error(f"O2A Connection reset error - orchestrator is not available. Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.error(f"О2А Ошибка сброса соединения - оркестратор недоступен. Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except json.decoder.JSONDecodeError as e: except json.decoder.JSONDecodeError as e:
if lL: lL.error(f"O2A JSON decode error - See body of the recieved content from the Orchestrator: {lRequestBody}") if lL: lL.error(f"О2А Ошибка декодирования JSON - далее представлено содержимое, которое поступило на обработку: {lRequestBody}")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except requests.exceptions.Timeout as e: except requests.exceptions.Timeout as e:
if lL: lL.exception(f"O2A requests timeout error (no response for long time). Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.exception(f"О2А Ошибка соединения (превышено время ожидания). Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except Exception as e: except Exception as e:
if lL: lL.exception(f"O2A Error handler. Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.exception(f"О2А Общая ошибка. Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])

@ -3,66 +3,69 @@ from . import O2A, A2O # Data flow Orchestrator To Agent
from . import Processor # Processor Queue from . import Processor # Processor Queue
from ..Tools import Usage from ..Tools import Usage
from ..Tools import License from ..Tools import License
from subprocess import CREATE_NEW_CONSOLE # Flag to create new process in another CMD from pyOpenRPA.Tools import CrossOS
if CrossOS.IS_WINDOWS_BOOL: from subprocess import CREATE_NEW_CONSOLE # Flag to create new process in another CMD
if CrossOS.IS_LINUX_BOOL: pass
import os import os
gSettings = None gSettings = None
# Create binary file by the base64 string (safe for JSON transmition) # Create binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None): def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None):
""" """L+,W+: Создать бинарный файл на стороне Агента по полученной строке в формате base64 (формат безопасен для передачи по JSON протоколу)
Create binary file by the base64 string (safe for JSON transmition)
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "wb") lFile = open(inFilePathStr, "wb")
lFile.write(base64.b64decode(inFileDataBase64Str)) lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Binary file {inFilePathStr} has been created." lMessageStr = f"АГЕНТ: бинарный файл {inFilePathStr} создан успешно"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Append binary file by the base64 string (safe for JSON transmition) # Append binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None): def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None):
""" """L+,W+: Create binary file by the base64 string (safe for JSON transmition)
Create binary file by the base64 string (safe for JSON transmition)
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "ab") lFile = open(inFilePathStr, "ab")
lFile.write(base64.b64decode(inFileDataBase64Str)) lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Binary file {inFilePathStr} has been appended." lMessageStr = f"АГЕНТ: Данные успешно добавлены в бинарный файл {inFilePathStr}"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Create text file by the string # Create text file by the string
def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None): def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None):
""" """L+,W+:Создать текстовый файл на стороне Агента
Create text file in the agent GUI session
:param inFilePathStr: File abs path :param inFilePathStr: Абсолютный путь к создаваемому файлу
:param inFileDataStr: File data text content :param inFileDataStr: Текст, отправляемый в создаваемый файл
:param inEncodingStr: Write file encoding :param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный файл настроек
:return: :return:
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "w", encoding=inEncodingStr) lFile = open(inFilePathStr, "w", encoding=inEncodingStr)
lFile.write(inFileDataStr) lFile.write(inFileDataStr)
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Text file {inFilePathStr} has been created." lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} успешно создан"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None): def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
""" """L+,W+: Прочитать бинарный файл на стороне агента и отправить на сторону оркестратора в формате base64 (формат безопасный для передачи в формате JSON)
Read binary file and encode in base64 to transmit (safe for JSON transmition)
:param inFilePathStr: File path to read :param inFilePathStr: Абсолютный путь к читаемому файлу
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный словарь настроек Агента (необязательный)
:return: File content in string base64 format (use base64.b64decode to decode data). Return None if file is not exist :return: Содержимое бинарного файле, преобразованное в формат base64 (используй base64.b64decode для декодирования в байты). Вернет None запрашиваемый файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lFileDataBase64Str = None lFileDataBase64Str = None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
@ -70,56 +73,55 @@ def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
lFileDataBytes = lFile.read() lFileDataBytes = lFile.read()
lFile.close() lFile.close()
lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8") lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8")
lMessageStr = f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} has been read" lMessageStr = f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} прочитан успешно"
if lL: lL.debug(lMessageStr) if lL: lL.debug(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) #A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else: else:
if lL: lL.debug(f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} is not exists - return None") if lL: lL.debug(f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} не существует - отправить None")
return lFileDataBase64Str return lFileDataBase64Str
def OSFileMTimeGet(inFilePathStr: str) -> float or None: def OSFileMTimeGet(inFilePathStr: str) -> float or None:
""" """L+,W+: Read file modification time timestamp format (float)
Read file modification time timestamp format (float)
:param inFilePathStr: File path to read :param inFilePathStr: Абсолютный путь к файлу, дату которого требуется получить
:return: timestamp (float) Return None if file is not exist :return: Временной слепок (timestamp) в формате float. Вернет None, если запрашиваемый файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
global gSettings global gSettings
lL = gSettings.get("Logger", None) if type(gSettings) is dict else None lL = gSettings.get("Logger", None) if type(gSettings) is dict else None
lFileMTimeFloat = None lFileMTimeFloat = None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
lFileMTimeFloat = os.path.getmtime(inFilePathStr) lFileMTimeFloat = os.path.getmtime(inFilePathStr)
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} has been read") if lL: lL.debug(f"Функция OSFileMTimeGet: файл {inFilePathStr} прочитан успешно")
else: else:
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} is not exists - return None") if lL: lL.debug(f"Функция OSFileMTimeGet: file {inFilePathStr} не существует - вернуть None")
return lFileMTimeFloat return lFileMTimeFloat
def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None): def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None):
""" """L+,W+: Прочитать текстовый файл на стороне агента и отправить на сторону оркестратора
Read text file in the agent GUI session
:param inFilePathStr: File abs path :param inFilePathStr: Абсолютный путь к читаемому файлу
:param inEncodingStr: Read file encoding. Default utf-8 :param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный словарь настроек
:return: File text content in string format (use base64.b64decode to decode data). Return None if file is not exist :return: Строка - содержимое текстового файла. Возвращает None, если файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFileDataStr = None lFileDataStr = None
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
lFile = open(inFilePathStr, "r", encoding=inEncodingStr) lFile = open(inFilePathStr, "r", encoding=inEncodingStr)
lFileDataStr = lFile.read() lFileDataStr = lFile.read()
lFile.close() lFile.close()
lMessageStr = f"OSFileTextDataStrReceive: file {inFilePathStr} has been read" lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} прочитан успешно"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) #A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else: else:
if lL: lL.info(f"OSFileTextDataStrReceive: file {inFilePathStr} is not exists - return None") if lL: lL.info(f"АГЕНТ: Текстовый файл {inFilePathStr} не существует - вернуть None")
return lFileDataStr return lFileDataStr
# Send CMD to OS. Result return to log + Orchestrator by the A2O connection # Send CMD to OS. Result return to log + Orchestrator by the A2O connection
def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrchestratorLogsBool = True, inCMDEncodingStr = "cp1251", inCaptureBool = True): def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrchestratorLogsBool = True, inCMDEncodingStr = "cp1251", inCaptureBool = True):
""" """L-,W+: Execute CMD on the Agent daemonic process
Execute CMD on the Agent daemonic process
:param inCMDStr: command to execute on the Agent session :param inCMDStr: command to execute on the Agent session
:param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution :param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution
@ -142,10 +144,13 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inCaptureBool == True: if inCaptureBool == True:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else: else:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None, if CrossOS.IS_WINDOWS_BOOL:
creationflags=CREATE_NEW_CONSOLE) lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None,
creationflags=CREATE_NEW_CONSOLE)
if CrossOS.IS_LINUX_BOOL:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None)
lListenBool = True lListenBool = True
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been STARTED # # # # " lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия запущена # # # # "
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on! if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr])
@ -172,7 +177,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
time.sleep(2) time.sleep(2)
else: else:
lListenBool = False lListenBool = False
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been FINISHED # # # # " lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия завершена # # # # "
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on! if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
@ -181,7 +186,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inRunAsyncBool: if inRunAsyncBool:
lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool }) lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool })
lThread.start() lThread.start()
lResultStr="ActivityList has been started in async mode - no output is available here." lResultStr="Список ActivityList отправлен на исполнение в асинхронном режиме - захват текста недоступен"
else: else:
lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool) lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool)
#lCMDCode = "cmd /c " + inCMDStr #lCMDCode = "cmd /c " + inCMDStr
@ -191,11 +196,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
def ProcessWOExeUpperUserListGet(): def ProcessWOExeUpperUserListGet():
""" """L-,W+: Вернуть список процессов, запущенных под пользователем на стороне агента
Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent
:param inProcessNameWOExeList: :return: Список процессов в формате: ["NOTEPAD","..."] (без постфикса .exe и в верхнем регистре)
:return: list of the agent user process in upper case without .EXE. Example ["NOTEPAD","..."],
""" """
lUserNameStr = getpass.getuser() lUserNameStr = getpass.getuser()
@ -238,7 +241,7 @@ def Agent(inGSettings):
lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings}) lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings})
lProcessorThread.daemon = True # Run the thread in daemon mode. lProcessorThread.daemon = True # Run the thread in daemon mode.
lProcessorThread.start() # Start the thread execution. lProcessorThread.start() # Start the thread execution.
if lL: lL.info("Processor has been started (ProcessorDict)") #Logging if lL: lL.info("Модуль процессора pyOpenRPA был успешно запущен") #Logging
# Start thread to wait data from Orchestrator (O2A) # Start thread to wait data from Orchestrator (O2A)
lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings}) lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings})
@ -247,4 +250,4 @@ def Agent(inGSettings):
# Send log that Agent has been started # Send log that Agent has been started
A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Host: {inGSettings["AgentDict"]["HostNameUpperStr"]}, User: {inGSettings["AgentDict"]["UserUpperStr"]}, Agent has been started.']) A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Хост: {inGSettings["AgentDict"]["HostNameUpperStr"]}, Логин: {inGSettings["AgentDict"]["UserUpperStr"]}, Агент инициализирован успешно'])

@ -77,7 +77,7 @@ def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict):
} }
inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict
inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies
if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") if lL: lL.info(f"РДП сессия инициализирована. Идентификатор сессии:{lCookieSessionGUIDStr}")
return lCookieSessionGUIDStr return lCookieSessionGUIDStr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
lCreateNewSessionBool = False # Flag to create new session structure lCreateNewSessionBool = False # Flag to create new session structure
@ -108,7 +108,7 @@ def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict):
if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]:
lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]
if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key 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") if lL: lL.debug(f"Время жизни HTTP запроса истекло - удалить из отслеживаемых!")
lDoWhileBool = False # Stop the iterations lDoWhileBool = False # Stop the iterations
if lDoWhileBool: if lDoWhileBool:
TechnicalCheck() # Calculate the CP TechnicalCheck() # Calculate the CP
@ -277,7 +277,7 @@ def v1_2_0_ProcessorOld2NewActivityDict(inActivityOld):
"ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList) "ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
} }
else: else:
raise Exception(f"BackwardCompatibility up to v1.2.0, old processor: No type {inActivityOld['Type']} has been found in old processor.") raise Exception(f"Обратная совместимость до v1.2.0, старый процессор: Тип {inActivityOld['Type']} был обнаружен в старом процессоре")
return lResult # return the result return lResult # return the result
@ -295,7 +295,7 @@ def Update(inGSettings):
inGSettings["Autocleaner"] = { # Some gurbage is collecting in g settings. So you can configure autocleaner to periodically clear gSettings inGSettings["Autocleaner"] = { # Some gurbage is collecting in g settings. So you can configure autocleaner to periodically clear gSettings
"IntervalSecFloat": 7200.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 lL: lL.warning(f"Обратная совместимость (от v1.1.13 до v1.1.14): Добавить 'Autocleaner' структуру") # Log about compatibility
if "Client" not in inGSettings: # Add "Client" structure if "Client" not in inGSettings: # Add "Client" structure
inGSettings["Client"] = { # Settings about client web orchestrator inGSettings["Client"] = { # Settings about client web orchestrator
"Session":{ # Settings about web session. Session algorythms works only for special requests (URL in ServerSettings) "Session":{ # Settings about web session. Session algorythms works only for special requests (URL in ServerSettings)
@ -318,14 +318,14 @@ 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 lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Добавить структуру 'Client'") # Log about compatibility
if "Server" in inGSettings and "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 inGSettings["Server"]["RequestTimeoutSecFloat"] = 300 # Time to handle request in seconds
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility 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 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 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 if lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Преобразовать структуру 'OrchestratorStart' > 'DefSettingsUpdatePathList'") # Log about compatibility
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# v1.1.20 to v1.2.0 # v1.1.20 to v1.2.0
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@ -338,14 +338,14 @@ def Update(inGSettings):
"DumpLogList": [], # Will be filled automatically "DumpLogList": [], # Will be filled automatically
"DumpLogListHashStr": None, # 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать атрибут 'Client > DumpLog... с параметрами по умолчанию'") # Log about compatibility
if "Processor" in inGSettings: # Check if Processor exist if "Processor" in inGSettings: # Check if Processor exist
# Update Logger # Update Logger
if lL is not None: if lL is not None:
SettingsTemplate.LoggerDumpLogHandlerAdd(inLogger=lL, inGSettingsClientDict=inGSettings["Client"]) 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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Добавить веб дамп для отображения лога на веб клиенте оркестратора") # Log about compatibility
del inGSettings["Processor"] # Remove the key 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Удалить структуру старого процессора 'Processor'") # Log about compatibility
if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure
inGSettings["ProcessorDict"]={ inGSettings["ProcessorDict"]={
"ActivityList": [ # List of the activities "ActivityList": [ # List of the activities
@ -361,14 +361,14 @@ def Update(inGSettings):
"ExecuteBool": True, # Flag to execute thread processor "ExecuteBool": True, # Flag to execute thread processor
"ThreadIdInt": None # Fill thread id when processor will be inited "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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'ProcessorDict'") # Log about compatibility
if "VersionStr" not in inGSettings: # Create new ProcessorDict structure if "VersionStr" not in inGSettings: # Create new ProcessorDict structure
inGSettings["VersionStr"] = None 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'VersionStr'") # Log about compatibility
if "AgentDict" not in inGSettings: # Create new AgentDict structure if "AgentDict" not in inGSettings: # Create new AgentDict structure
inGSettings["AgentDict"]= {} inGSettings["AgentDict"]= {}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'AgentDict'") # Log about compatibility f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'AgentDict'") # Log about compatibility
# Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy # Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy
# if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: # if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())] # lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())]
@ -379,7 +379,7 @@ def Update(inGSettings):
# Check if Server is active > convert to ServerDict # Check if Server is active > convert to ServerDict
inGSettings["ServerDict"] = inGSettings["Server"] inGSettings["ServerDict"] = inGSettings["Server"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Server' -> 'ServerDict'") # Log about compatibility
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["Server"] del inGSettings["Server"]
lShowWarnBool = False lShowWarnBool = False
@ -401,7 +401,7 @@ def Update(inGSettings):
# remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate # remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate
#del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"] #del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"]
if lShowWarnBool: # Show only 1 warning per all run 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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Интегрировать структуру доступа к панелям управления в общую UAC иерархию") # Log about compatibility
# Check if ControlPanelDict is active > convert to CPDict # Check if ControlPanelDict is active > convert to CPDict
if "ControlPanelDict" in inGSettings: if "ControlPanelDict" in inGSettings:
if "CPDict" not in inGSettings: inGSettings["CPDict"]={} if "CPDict" not in inGSettings: inGSettings["CPDict"]={}
@ -409,7 +409,7 @@ def Update(inGSettings):
inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None} inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None}
# Remove old structure ControlPanel # Remove old structure ControlPanel
del inGSettings["ControlPanelDict"] del inGSettings["ControlPanelDict"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'ControlPanelDict' -> 'CPDict'") # Log about compatibility
# Check if Scheduler is active > convert to SchedulerDict # Check if Scheduler is active > convert to SchedulerDict
if "Scheduler" in inGSettings: if "Scheduler" in inGSettings:
if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]} if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]}
@ -423,27 +423,27 @@ def Update(inGSettings):
inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict)
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Scheduler' -> 'SchedulerDict' с новыми функциональными возможностями") # Log about compatibility
# # Convert to Storage to StorageDict # # Convert to Storage to StorageDict
if "Storage" in inGSettings: if "Storage" in inGSettings:
# Check if Server is active > convert to ServerDict # Check if Server is active > convert to ServerDict
inGSettings["StorageDict"] = inGSettings["Storage"] inGSettings["StorageDict"] = inGSettings["Storage"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Convert Storage to StorageDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Преобразовать 'Storage' -> 'StorageDict'") # Log about compatibility
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["Storage"] del inGSettings["Storage"]
# Add new key WarningExecutionMoreThanSecFloat in ProcessorDict # Add new key WarningExecutionMoreThanSecFloat in ProcessorDict
if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]: if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0 inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add key WarningExecutionMoreThanSecFloat in ProcessorDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключ 'WarningExecutionMoreThanSecFloat' -> 'ProcessorDict'") # Log about compatibility
# Add new key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict # Add new key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict
if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]: if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0 inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0
inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0 inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0
inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0 inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключи: 'AgentActivityLifetimeSecFloat', 'AgentConnectionLifetimeSecFloat', 'AgentLoopSleepSecFloat' -> 'ProcessorDict' > 'ServerDict'") # Log about compatibility
# Add new key RecoveryDict in ProcessorDict > RobotRDPActive # Add new key RecoveryDict in ProcessorDict > RobotRDPActive
if "RecoveryDict" not in inGSettings["RobotRDPActive"]: if "RecoveryDict" not in inGSettings["RobotRDPActive"]:
inGSettings["RobotRDPActive"]["RecoveryDict"] = { inGSettings["RobotRDPActive"]["RecoveryDict"] = {
@ -457,7 +457,7 @@ def Update(inGSettings):
} }
} }
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add new key RecoveryDict in ProcessorDict > RobotRDPActive") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключ 'RecoveryDict' -> 'ProcessorDict' > 'RobotRDPActive'") # Log about compatibility
# Add new key ServerDict > ListenDict # Add new key ServerDict > ListenDict
if "ListenDict" not in inGSettings["ServerDict"]: if "ListenDict" not in inGSettings["ServerDict"]:
lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80) lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80)
@ -471,7 +471,7 @@ def Update(inGSettings):
} }
} }
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.2 to v1.2.3): Add new key ServerDict > ListenDict. Transfer port from ServerDict > ListenPort") # Log about compatibility f"Обратная совместимость (v1.2.2 -> v1.2.3): Добавить ключ 'ServerDict' > 'ListenDict'. Изменение свойства, отвечающее за прослушиваемый порт 'ServerDict' > 'ListenPort'") # Log about compatibility
# Add new key # Add new key
#"ServerDict": { #"ServerDict": {
# "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition # "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition
@ -479,24 +479,24 @@ def Update(inGSettings):
if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]: if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000 inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkBytesSizeInt") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentFileChunkBytesSizeInt") # Log about compatibility
if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]: if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2 inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility
if "ServerThread" not in inGSettings["ServerDict"]: if "ServerThread" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["ServerThread"]= None inGSettings["ServerDict"]["ServerThread"]= None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > ServerThread") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > ServerThread") # Log about compatibility
if "AgentLimitLogSizeBytesInt" not in inGSettings["ServerDict"]: if "AgentLimitLogSizeBytesInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300 inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentLimitLogSizeBytesInt") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentLimitLogSizeBytesInt") # Log about compatibility
# Remove ControlPanelDict and CPDict > go to ServerDict > ControlPanelDict # Remove ControlPanelDict and CPDict > go to ServerDict > ControlPanelDict
if "ControlPanelDict" in inGSettings: if "ControlPanelDict" in inGSettings:
del inGSettings["ControlPanelDict"] del inGSettings["ControlPanelDict"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Remove old key: ControlPanelDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Удалить ключ ControlPanelDict") # Log about compatibility
if "CPDict" in inGSettings: if "CPDict" in inGSettings:
for lCPKeyStr in inGSettings["CPDict"]: for lCPKeyStr in inGSettings["CPDict"]:
lCPItemDict = inGSettings["CPDict"][lCPKeyStr] lCPItemDict = inGSettings["CPDict"][lCPKeyStr]
@ -505,40 +505,40 @@ def Update(inGSettings):
inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"]) inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"])
del inGSettings["CPDict"] del inGSettings["CPDict"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Remove old key: CPDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Удалить ключ: CPDict") # Log about compatibility
if "ControlPanelDict" not in inGSettings["ServerDict"]: if "ControlPanelDict" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["ControlPanelDict"]={} inGSettings["ServerDict"]["ControlPanelDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ServerDict > ControlPanelDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ServerDict > ControlPanelDict") # Log about compatibility
# ManagersProcessDict # ManagersProcessDict
if "ManagersProcessDict" not in inGSettings: if "ManagersProcessDict" not in inGSettings:
inGSettings["ManagersProcessDict"]={} inGSettings["ManagersProcessDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ManagersProcessDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ManagersProcessDict") # Log about compatibility
# Check "SchedulerDict": { "Schedule": schedule, # https://schedule.readthedocs.io/en/stable/examples.html # Check "SchedulerDict": { "Schedule": schedule, # https://schedule.readthedocs.io/en/stable/examples.html
if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None: if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None:
inGSettings["SchedulerDict"]["Schedule"] = schedule inGSettings["SchedulerDict"]["Schedule"] = schedule
if lL: lL.warning(f"Backward compatibility (v1.2.4 to v1.2.7): Create new module schedule (schedule.readthedocs.io)") # Log about compatibility if lL: lL.warning(f"Backward compatibility (v1.2.4 to v1.2.7): Подключить новый модуль расписания (см. schedule.readthedocs.io)") # Log about compatibility
# ManagersGitDict # ManagersGitDict
if "ManagersGitDict" not in inGSettings: if "ManagersGitDict" not in inGSettings:
inGSettings["ManagersGitDict"]={} inGSettings["ManagersGitDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ManagersGitDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ManagersGitDict") # Log about compatibility
# ProcessorDict > ActivityItemNowDict # ProcessorDict > ActivityItemNowDict
if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]: if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ProcessorDict > ActivityItemNowDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ProcessorDict > ActivityItemNowDict") # Log about compatibility
# # "UACBool": True # True - check user access before do this URL item # # "UACBool": True # True - check user access before do this URL item
for lURLItemDict in inGSettings["ServerDict"]["URLList"]: for lURLItemDict in inGSettings["ServerDict"]["URLList"]:
if "UACBool" not in lURLItemDict: if "UACBool" not in lURLItemDict:
lURLItemDict["UACBool"]=None lURLItemDict["UACBool"]=None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): ServerDict > URLList > item: add UACBool = None") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): ServerDict > URLList > item и UACBool = None") # Log about compatibility
# "URLIndexStr" # "URLIndexStr"
if "URLIndexStr" not in inGSettings["ServerDict"]: if "URLIndexStr" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["URLIndexStr"] = "/" inGSettings["ServerDict"]["URLIndexStr"] = "/"
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.11 to v1.2.12): ServerDict > URLIndexStr: add URLIndexStr = /") # Log about compatibility f"Обратная совместимость (v1.2.11 -> v1.2.12): ServerDict > URLIndexStr и URLIndexStr = /") # Log about compatibility

@ -84,7 +84,7 @@ class ControlPanel():
""" """
# Connect self witch pyOpenRPA via ControlPanelNameStr # Connect self witch pyOpenRPA via ControlPanelNameStr
if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]: if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]:
raise Exception(f"Another control panel with name {inControlPanelNameStr} is already exists. Please resolve the error and restart") raise Exception(f"Ошибка: Ранее уже была инициализирована панель управления с идентификатором: {inControlPanelNameStr}. Устраните ошибку и перезапустите оркестратор")
Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self
self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr) self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
@ -116,7 +116,7 @@ class ControlPanel():
self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True) self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True)
self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr) self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e: except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2") Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def RefreshHTMLJinja2StrGenerate(self, inDataDict): def RefreshHTMLJinja2StrGenerate(self, inDataDict):
""" """
@ -145,7 +145,7 @@ class ControlPanel():
self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True) self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True)
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr) self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e: except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2") Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def InitJSJinja2StrGenerate(self, inDataDict): def InitJSJinja2StrGenerate(self, inDataDict):
""" """
@ -290,7 +290,7 @@ class ControlPanel():
# Call backward compatibility HTML generator # Call backward compatibility HTML generator
lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult) lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult)
except Exception as e: except Exception as e:
if lL: lL.exception(f"Error in control panel HTMLRenderDef. CP Key {self.mControlPanelNameStr}. Exception are below") if lL: lL.exception(f"Ошибка в функции генерации HTML контента (HTMLRenderDef). Идентификатор панели управления: {self.mControlPanelNameStr}")
return lResultStr return lResultStr
@ -317,10 +317,10 @@ class ControlPanel():
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: 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:
lResultDict = lJSONResult lResultDict = lJSONResult
else: else:
if lL: lL.warning(f"JSONGenerator return bad type: {str(type(lJSONResult))}, CP Key {self.mControlPanelNameStr}") if lL: lL.warning(f"Функция генерации JSON сформировала некорректную структуру: {str(type(lJSONResult))}, идентификатор панели управления: {self.mControlPanelNameStr}")
except Exception as e: except Exception as e:
if lL: lL.exception( if lL: lL.exception(
f"Error in control panel JSONGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below") f"Ошибка при формирвоании JSON (JSONGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultDict return lResultDict
def BackwardAdapterJSDef(self,inRequest): def BackwardAdapterJSDef(self,inRequest):
@ -343,8 +343,8 @@ class ControlPanel():
if type(lJSResult) is str: if type(lJSResult) is str:
lResultStr = lJSResult # Add delimiter to some cases lResultStr = lJSResult # Add delimiter to some cases
else: else:
if lL: lL.warning(f"JSInitGenerator return bad type: {str(type(lJSResult))}, CP Key {self.mControlPanelNameStr}") if lL: lL.warning(f"Функция JSInitGenerator вернула неверный формат данных: {str(type(lJSResult))}, идентификатор панели управления {self.mControlPanelNameStr}")
except Exception as e: except Exception as e:
if lL: lL.exception( if lL: lL.exception(
f"Error in control panel JSInitGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below") f"Ошибка в функции формирования кода JavaScript (JSInitGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultStr return lResultStr

@ -34,7 +34,7 @@ class Git():
self.mAgentHostNameStr = inAgentHostNameStr self.mAgentHostNameStr = inAgentHostNameStr
self.mAgentUserNameStr = inAgentUserNameStr self.mAgentUserNameStr = inAgentUserNameStr
lGS["ManagersGitDict"][(inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), lAbsPathUpperStr)]=self lGS["ManagersGitDict"][(inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), lAbsPathUpperStr)]=self
else: raise Exception(f"Managers.Git ({inAgentHostNameStr}, {inAgentUserNameStr}, {lAbsPathUpperStr}): Can't init the Git instance because it already inited in early") else: raise Exception(f"Модуль Managers.Git ({inAgentHostNameStr}, {inAgentUserNameStr}, {lAbsPathUpperStr}): Невозможно инициализировать экземпляр класса, так как он уже был инициализирован ранее")
def ProcessConnect(self, inProcess: Process): def ProcessConnect(self, inProcess: Process):
""" """
@ -151,11 +151,11 @@ class Git():
:param inBranchRemoteStr: [description] :param inBranchRemoteStr: [description]
:type inBranchRemoteStr: str :type inBranchRemoteStr: str
""" """
Orchestrator.OrchestratorLoggerGet().debug(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet has been init") Orchestrator.OrchestratorLoggerGet().debug(f"Модуль Managers.Git ({self.mAbsPathStr}): функция self.BranchRevLastGet успешно инициализирована")
# check if the correct revision # check if the correct revision
lCMDResultStr = None lCMDResultStr = None
if self.BranchRevIsLast(inBranchLocalStr=inBranchLocalStr, inBranchRemoteStr=inBranchRemoteStr) == False: if self.BranchRevIsLast(inBranchLocalStr=inBranchLocalStr, inBranchRemoteStr=inBranchRemoteStr) == False:
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, new rev (branch: {inBranchLocalStr}) has been detected - merge (branch: {inBranchRemoteStr})") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Git ({self.mAbsPathStr}): функуция self.BranchRevLastGet, новая ревизия (ветка: {inBranchLocalStr}) была удалена - выполнить слияние (ветка на сервере: {inBranchRemoteStr})")
# Do the stop safe for the connected process # Do the stop safe for the connected process
self.ProcessListSaveStopSafe() self.ProcessListSaveStopSafe()
lBranchNameCurrentStr = self.BranchNameGet() lBranchNameCurrentStr = self.BranchNameGet()
@ -170,7 +170,7 @@ class Git():
# checkout to the source branch which was # checkout to the source branch which was
self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr) self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr)
# do the orc restart # do the orc restart
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, merge done, restart orc") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, merge done, restart orc")
Orchestrator.OrchestratorRestart() Orchestrator.OrchestratorRestart()
return lCMDResultStr return lCMDResultStr

@ -108,7 +108,7 @@ class Process():
__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict) __Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict)
if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck) if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
self.mStatusCheckIntervalSecFloat = inStatusCheckIntervalSecFloat self.mStatusCheckIntervalSecFloat = inStatusCheckIntervalSecFloat
else: raise Exception(f"Managers.Process ({inAgentHostNameStr}, {inAgentUserNameStr}, {inProcessNameWOExeStr}): Can't init the Process instance because it already inited in early (see ProcessInitSafe)") else: raise Exception(f"Модуль Managers.Process ({inAgentHostNameStr}, {inAgentUserNameStr}, {inProcessNameWOExeStr}): Невозможно инициализировать процесс, так как он был инициализирован ранее (см. ProcessInitSafe)")
def ManualStopTriggerSet(self, inMSTdTSecFloat: float, inMSTdNInt: int) -> None: def ManualStopTriggerSet(self, inMSTdTSecFloat: float, inMSTdNInt: int) -> None:
""" """
@ -145,7 +145,7 @@ class Process():
self.mStatusStr = "1_STOPPED_MANUAL" self.mStatusStr = "1_STOPPED_MANUAL"
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): ManualStopTrigger is activated. {self.mMSTdNInt} start tries in {self.mMSTdTSecFloat} sec.") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Триггер ручной остановки активирован. {self.mMSTdNInt} повторить попытку через {self.mMSTdTSecFloat} сек.")
return self.mStatusStr return self.mStatusStr
def ManualStopListClear(self) -> None: def ManualStopListClear(self) -> None:
@ -180,7 +180,7 @@ class Process():
""" """
if inIsManualBool == False: self.ManualStopTriggerNewStart() # Set the time if inIsManualBool == False: self.ManualStopTriggerNewStart() # Set the time
if self.mStatusStr is not None and (self.mStatusStr == "1_STOPPED_MANUAL" or "STOP_SAFE" in self.mStatusStr) and inIsManualBool == False: if self.mStatusStr is not None and (self.mStatusStr == "1_STOPPED_MANUAL" or "STOP_SAFE" in self.mStatusStr) and inIsManualBool == False:
lStr = f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Process will not start because of stopped manual or stop safe is now." lStr = f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Процесс не будет запущен, так как инициализирован триггер ручной остановки или активен режим безопасного отключения"
__Orchestrator__.OrchestratorLoggerGet().warning(lStr) __Orchestrator__.OrchestratorLoggerGet().warning(lStr)
return self.mStatusStr return self.mStatusStr
# Send activity item to agent - wait result # Send activity item to agent - wait result
@ -259,7 +259,7 @@ class Process():
if "SAFE" in self.mStatusStr: if "SAFE" in self.mStatusStr:
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Safe stop has been wait for {inStopSafeTimeoutSecFloat} sec. Now do the force stop.") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Алгоритм безопасной остановки ожидал завершение процесса в течение {inStopSafeTimeoutSecFloat} сек. Выполнить принудительную остановку")
self.StopForce(inIsManualBool=inIsManualBool,inMuteIgnoreBool=True) self.StopForce(inIsManualBool=inIsManualBool,inMuteIgnoreBool=True)
# Log info about process # Log info about process
# self.StatusChangeLog() status check has already log status (see above) # self.StatusChangeLog() status check has already log status (see above)
@ -350,7 +350,7 @@ class Process():
if self.mStatusStr == "2_STOP_SAFE": self.mStatusSavedStr = "0_STOPPED" if self.mStatusStr == "2_STOP_SAFE": self.mStatusSavedStr = "0_STOPPED"
elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL" elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL"
else: self.mStatusSavedStr = self.mStatusStr; lWarnSafeBool = False else: self.mStatusSavedStr = self.mStatusStr; lWarnSafeBool = False
if lWarnSafeBool==True: __Orchestrator__.OrchestratorLoggerGet().warning(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Safe status has been catched when safe > change saved status to stopped.") if lWarnSafeBool==True: __Orchestrator__.OrchestratorLoggerGet().warning(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Состояние безопасной остановки было обнаружено при попытке сохранить состояние > зафиксировать состояние как остановленное")
return self.mStatusStr return self.mStatusStr
@ -358,7 +358,7 @@ class Process():
"""Call from orchestrator when init """Call from orchestrator when init
""" """
if self.mStatusCheckIntervalSecFloat is not None: if self.mStatusCheckIntervalSecFloat is not None:
__Orchestrator__.OrchestratorLoggerGet().info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Restore schedule to StatusCheck in interval of {self.mStatusCheckIntervalSecFloat} sec.") __Orchestrator__.OrchestratorLoggerGet().info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Восстановить периодическую проверку состояния с интервалом в {self.mStatusCheckIntervalSecFloat} сек.")
__Orchestrator__.OrchestratorScheduleGet().every(self.mStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck) __Orchestrator__.OrchestratorScheduleGet().every(self.mStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
def StatusRestore(self): def StatusRestore(self):
@ -377,7 +377,7 @@ class Process():
self.StopSafe(inIsManualBool=True) self.StopSafe(inIsManualBool=True)
if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr: if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr:
self.Start(inIsManualBool=True) self.Start(inIsManualBool=True)
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Status has been restored to {self.mStatusSavedStr}") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Статус процесса был восстановлен на: {self.mStatusSavedStr}")
self.mStatusStr = self.mStatusSavedStr self.mStatusStr = self.mStatusSavedStr
self.mStatusSavedStr = None self.mStatusSavedStr = None
return self.mStatusStr return self.mStatusStr
@ -390,7 +390,7 @@ class Process():
""" """
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Status has been changed to {self.mStatusStr})") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Состояние процесса изменилось на {self.mStatusStr})")
def StatusCheck(self): def StatusCheck(self):

@ -70,7 +70,7 @@ def ActivityListExecute(inGSettings, inActivityList):
lResultList = [] # init the result list lResultList = [] # init the result list
try: try:
for lActivityItem in inActivityList: # Iterate throught the activity list 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.') if lL: lL.info(f'Процессор:: Исполнение функции def:{str(lActivityItem["Def"])}. В целях информационной безопасности параметры недоступны для просмотра')
lDef = None # Def variable lDef = None # Def variable
if callable(lActivityItem["Def"]): # CHeck if def is callable if callable(lActivityItem["Def"]): # CHeck if def is callable
lDef = lActivityItem["Def"] # Get the def lDef = lActivityItem["Def"] # Get the def
@ -79,7 +79,7 @@ def ActivityListExecute(inGSettings, inActivityList):
#gSettings #gSettings
lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None)
# # Prepare arg dict - gSettings # # 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 "" if type(lGSettingsDictKey) is str and lGSettingsDictKey != "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgGSettings is ""
lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict
# # Prepare arg list # # Prepare arg list
elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict
@ -87,7 +87,7 @@ def ActivityListExecute(inGSettings, inActivityList):
#Logger #Logger
lLoggerDictKey = lActivityItem.pop("ArgLogger",None) lLoggerDictKey = lActivityItem.pop("ArgLogger",None)
# # Prepare arg dict - Logger # # 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 "" if type(lLoggerDictKey) is str and lLoggerDictKey != "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgLogger is ""
lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict
# # Prepare arg list # # Prepare arg list
elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict

@ -62,22 +62,22 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
try: try:
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True) Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started
if lL: lL.info(f"Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}, SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging if lL: lL.info(f"Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}, Идентификатор сессии: {str(lRDPConfigurationDict['SessionHex'])}:: Сессия была инициализирована!") #Logging
# catch ConnectorExceptions.SessionWindowNotExistError # catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e: except ConnectorExceptions.SessionWindowNotExistError as e:
lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
if lL: lL.warning(f"Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}, SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist! Mark the retry") #Logging if lL: lL.warning(f"Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}, Идентификатор сессии: {str(lRDPConfigurationDict['SessionHex'])}:: Сессия не обнаружена - попытаться подключиться!") #Logging
# Recovery operations # Recovery operations
Recovery.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) Recovery.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings)
if Recovery.RetryIsTriggered(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) == True: if Recovery.RetryIsTriggered(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) == True:
if lL: lL.warning(f"!ATTENTION! Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}; RDP is not responsible for many times - run recovery mode") if lL: lL.warning(f"!ВНИМАНИЕ! Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}; сессия РДП недоступна при попытках подключения - инициализация режима восстановления")
Recovery.RetryHostClear(inHostStr=lRDPConfigurationDict['Host'],inGSettings=inGSettings) # Clear the stat about current host Recovery.RetryHostClear(inHostStr=lRDPConfigurationDict['Host'],inGSettings=inGSettings) # Clear the stat about current host
if inGSettings["RobotRDPActive"]["RecoveryDict"]["DoDict"]["OSRemotePCRestart"] == True: if inGSettings["RobotRDPActive"]["RecoveryDict"]["DoDict"]["OSRemotePCRestart"] == True:
if lL: lL.warning(f"!ATTENTION! Host: {lRDPConfigurationDict['Host']}, Send signal to restart remote PC.") if lL: lL.warning(f"!ВНИМАНИЕ! Хост: {lRDPConfigurationDict['Host']}, отправить сигнал на перезагрузку удаленной машины")
__Orchestrator__.OSRemotePCRestart(inLogger=lL,inHostStr=lRDPConfigurationDict['Host'],inForceBool=True) __Orchestrator__.OSRemotePCRestart(inLogger=lL,inHostStr=lRDPConfigurationDict['Host'],inForceBool=True)
# general exceptions # general exceptions
except Exception as e: except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging if lL: lL.exception(f"!!! ВНИМАНИЕ !!! Неопознанная ошибка. Обратитесь в тех. поддержку pyOpenRPA") #Logging
pass pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Connector.SystemRDPWarningClickOk() # Click all warning messages Connector.SystemRDPWarningClickOk() # Click all warning messages
@ -125,7 +125,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)( lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) *lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e: 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 if lL: lL.exception(f"РДП: Ошибка при обработке активности в процессоре РДП сессии - активность будет проигнорирована. Активность: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult) lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool # Check if Result is bool
@ -137,7 +137,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e: except RuntimeError as e:
# case noGUI error passed - do nothing # case noGUI error passed - do nothing
if lL: lL.warning(f"Host session has lost the GUI") #Logging if lL: lL.warning(f"Оркестратор потерял графическую сессию - повторить попытку через несколько секунд") #Logging
finally: finally:
# Wait for the next iteration # Wait for the next iteration
time.sleep(0.7) time.sleep(0.7)
@ -145,4 +145,4 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1) #Monitor.Monitor(mGSettingsRDPActiveDict, 1)
except Exception as e: except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging if lL: lL.exception(f"!!! ВНИМАНИ !!! В модуле РДП произошла критическая ошибка. Обратитесь в службу тех. поддержки pyOpenRPA") #Logging

@ -10,7 +10,7 @@ def CheckScreen(inIntervalSeconds=1):
#Send os command to create console version (base screen) #Send os command to create console version (base screen)
Screen.ConsoleScreenBase() Screen.ConsoleScreenBase()
#Delay to create console screen #Delay to create console screen
time.sleep(5) time.sleep(15)
#Delay #Delay
time.sleep(inIntervalSeconds) time.sleep(inIntervalSeconds)
return None return None

@ -24,12 +24,13 @@ import uuid
import datetime import datetime
import os #for path operations import os #for path operations
from http import cookies from http import cookies
global gSettingsDict gSettingsDict = {}
from . import ServerSettings from . import ServerSettings
from . import __Orchestrator__ from . import __Orchestrator__
import copy import copy
import mimetypes import mimetypes
mimetypes.add_type("font/woff2",".woff2") mimetypes.add_type("font/woff2",".woff2")
mimetypes.add_type("text/javascript",".js")
gCacheDict = {} gCacheDict = {}
@ -82,6 +83,7 @@ def AuthenticateVerify(inRequest):
###################################### ######################################
#Way 1 - try to find AuthToken #Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", "")) lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
global gSettingsDict
#pdb.set_trace() #pdb.set_trace()
if "AuthToken" in lCookies: if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -147,6 +149,7 @@ def AuthenticateBlock(inRequest):
def UserAccessCheckBefore(inMethod, inRequest): def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict # Help def - Get access flag from dict
#pdb.set_trace() #pdb.set_trace()
global gSettingsDict
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem: if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"] return inAccessRuleItem["FlagAccess"]
@ -261,6 +264,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to get hierarchy of the current user roles # Def to get hierarchy of the current user roles
# if return {} - all is available # if return {} - all is available
def UserRoleHierarchyGet(self): def UserRoleHierarchyGet(self):
#global gSettingsDict
lDomainUpperStr = self.OpenRPA["Domain"].upper() lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper() lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
@ -268,6 +272,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#Tech def #Tech def
#return {"headers":[],"body":"","statuscode":111} #return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False): def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False):
global gSettingsDict
############################### ###############################
#Tech sub def - do item #Tech sub def - do item
################################ ################################
@ -288,18 +293,22 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data # Write content as utf-8 data
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]] inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
else: else:
if os.path.exists(inURLItem["ResponseFilePath"]) and os.path.isfile(inURLItem["ResponseFilePath"]):
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data
gCacheDict[inURLItem["ResponseFilePath"]] = lFileObject.read()
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
# Закрыть файловый объект
lFileObject.close()
else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
else:
if os.path.exists(inURLItem["ResponseFilePath"]) and os.path.isfile(inURLItem["ResponseFilePath"]):
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb") lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data # Write content as utf-8 data
gCacheDict[inURLItem["ResponseFilePath"]] = lFileObject.read() inResponseDict["Body"] = lFileObject.read()
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
# Закрыть файловый объект # Закрыть файловый объект
lFileObject.close() lFileObject.close()
else: else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data
inResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
# detect MIME type if none # detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(inURLItem["ResponseFilePath"])[0] inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(inURLItem["ResponseFilePath"])[0]
@ -320,7 +329,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings
lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"") lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"")
lFilePathSecondPart = lFilePathSecondPart.split("?")[0] lFilePathSecondPart = lFilePathSecondPart.split("?")[0]
lFilePath = os.path.join(CrossOS.PathStr(inURLItem["ResponseFolderPath"]),lFilePathSecondPart) lFilePath = CrossOS.PathStr(os.path.join(inURLItem["ResponseFolderPath"],lFilePathSecondPart))
#print(f"File full path {lFilePath}") #print(f"File full path {lFilePath}")
#Check if file exist #Check if file exist
if os.path.exists(lFilePath) and os.path.isfile(lFilePath): if os.path.exists(lFilePath) and os.path.isfile(lFilePath):
@ -345,6 +354,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# detect MIME type if none # detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(lFilePath)[0] inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(lFilePath)[0]
else:
inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
# If No content-type # If No content-type
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= "application/octet-stream" inResponseDict["Headers"]["Content-type"]= "application/octet-stream"
@ -420,6 +431,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
def do_GET(self): def do_GET(self):
try: try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self threading.current_thread().request = self
self.OpenRPA = {} self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None self.OpenRPA["AuthToken"] = None
@ -493,33 +507,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# check if file in FileURL - File Path Mapping Dict # check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]: if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL]) self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
# Index page
elif self.path == gSettingsDict["ServerDict"]["URLIndexStr"]:
lURLItemDict = {
"Method":"GET",
"URL": gSettingsDict["ServerDict"]["URLIndexStr"],
"MatchType": "EqualCase",
"ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.xhtml"),
"ResponseContentType": "text/html"}
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItemDict, "GET")
if lFlagURLIsApplied:
self.ResponseDictSend()
return
else: else:
#Set access denied code #Set access denied code
# Send response status code # Send response status code
self.send_response(403) self.send_response(403)
# Send headers # Send headers
self.end_headers() self.end_headers()
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_GET): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Server.do_GET: Global error handler - look traceback below.") if lL: lL.exception(f"Сервер (do_GET): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
# POST # POST
def do_POST(self): def do_POST(self):
try: try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self threading.current_thread().request = self
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
self.OpenRPA = {} self.OpenRPA = {}
@ -603,7 +608,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lActivityTypeListStr += f"{lInputObject['Type']}" lActivityTypeListStr += f"{lInputObject['Type']}"
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" 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}") if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}")
# Send message back to client # Send message back to client
message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject)) message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject))
# Write content as utf-8 data # Write content as utf-8 data
@ -616,20 +621,35 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers # Send headers
self.end_headers() self.end_headers()
return return
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_POST): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Server.do_POST: Global error handler - look traceback below.") if lL: lL.exception(f"Сервер (do_POST): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
#Logging #Logging
#!Turn it on to stop print in console #!Turn it on to stop print in console
#def log_message(self, format, *args): #def log_message(self, format, *args):
# return # return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True daemon_threads = True
"""Handle requests in a separate thread.""" """Handle requests in a separate thread."""
def finish_request(self, request, client_address): def finish_request(self, request, client_address):
request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]) try:
# "super" can not be used because BaseServer is not created from object global gSettingsDict
HTTPServer.finish_request(self, request, client_address) request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
# "super" can not be used because BaseServer is not created from object
HTTPServer.finish_request(self, request, client_address)
except ConnectionResetError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (finish_request): Возникла ошибка сети - ConnectionResetError: [Errno 104] Connection reset by peer. Сервер продолжает работу")
except Exception as e:
lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Сервер (finish_request): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
#inGlobalDict #inGlobalDict
# "JSONConfigurationDict":<JSON> # "JSONConfigurationDict":<JSON>
import ssl import ssl
@ -640,6 +660,7 @@ class RobotDaemonServer(Thread):
# Update the global dict # Update the global dict
ServerSettings.SettingsUpdate(inGlobalDict) ServerSettings.SettingsUpdate(inGlobalDict)
def run(self): def run(self):
global gSettingsDict
lL = gSettingsDict.get("Logger",None) lL = gSettingsDict.get("Logger",None)
try: try:
lServerDict = gSettingsDict["ServerDict"]["ListenDict"][self.name] lServerDict = gSettingsDict["ServerDict"]["ListenDict"][self.name]
@ -660,10 +681,10 @@ class RobotDaemonServer(Thread):
httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr, keyfile=lKeyFilePathStr) httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr, keyfile=lKeyFilePathStr)
else: else:
httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr) httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr)
if lL: lL.info(f"Web Server init (with SSL). Name: {self.name}, Listen URL: {lAddressStr}, Listen port: {lPortInt}, Cert path: {lCertFilePathStr}") if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}")
else: else:
if lL: lL.info(f"Web Server init. Name: {self.name}, Listen URL: {lAddressStr}, Listen port: {lPortInt}") if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}")
#print('Starting server, use <Ctrl-C> to stop') #print('Starting server, use <Ctrl-C> to stop')
httpd.serve_forever() httpd.serve_forever()
except Exception as e: except Exception as e:
if lL: lL.exception(f"Web Server execution exception") if lL: lL.exception(f"Сервер:: Ошибка при инициализации - обратитесь в тех. поддержку pyOpenRPA")

@ -8,7 +8,7 @@ if CrossOS.IS_WINDOWS_BOOL: #CrossOS
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages) getRectAsImage, getDisplaysAsImages)
if CrossOS.IS_LINUX_BOOL: pass if CrossOS.IS_LINUX_BOOL: import pyscreeze
from http import cookies from http import cookies
import uuid # generate UUID4 import uuid # generate UUID4
@ -197,9 +197,9 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
# Get Screenshot # Get Screenshot
def SaveScreenshot(inFilePath): def SaveScreenshot(inFilePath):
# grab fullscreen # grab fullscreen
# Save the entire virtual screen as a PNG # Save the entire virtual screen as a PNsG
lScreenshot = getScreenAsImage() lScreenshot = getScreenAsImage()
lScreenshot.save('screenshot.png', format='png') lScreenshot.save('Screenshot.png', format='png')
# lScreenshot = ScreenshotSecondScreen.grab_screen() # lScreenshot = ScreenshotSecondScreen.grab_screen()
# save image file # save image file
# lScreenshot.save('screenshot.png') # lScreenshot.save('screenshot.png')
@ -211,7 +211,13 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read() inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект # Закрыть файловый объект
lFileObject.close() lFileObject.close()
else: lFileObject = b'' else:
pyscreeze._screenshot_linux(imageFilename='Screenshot.png')
lFileObject = open("Screenshot.png", "rb")
# Write content as utf-8 data
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
# Add activity item or activity list to the processor queue # Add activity item or activity list to the processor queue
# Body is Activity item or Activity List # Body is Activity item or Activity List
@ -233,7 +239,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
for lActivityItem in lInput: for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; " lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
# Separate into 2 lists - sync and async # Separate into 2 lists - sync and async
@ -259,7 +265,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
try: try:
lActivityTypeListStr = lInput['Def'] lActivityTypeListStr = lInput['Def']
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
if lInput.get("ThreadBool",False) == False: if lInput.get("ThreadBool",False) == False:
@ -288,7 +294,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
for lActivityItem in lInput: for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; " lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
# Execution # Execution
@ -301,7 +307,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
try: try:
lActivityTypeListStr = lInput['Def'] lActivityTypeListStr = lInput['Def']
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,
inOperationCodeStr=lActivityTypeListStr, inOperationCodeStr=lActivityTypeListStr,
inMessageStr="pyOpenRPA_ActivityListExecute") inMessageStr="pyOpenRPA_ActivityListExecute")
@ -432,13 +438,13 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr] lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr]
# Create item in gSettings # Create item in gSettings
inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue) inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue)
lLogStr = "x bytes" lLogStr = "x байт"
try: try:
if lActivityReturnItemValue is not None: if lActivityReturnItemValue is not None:
lLogStr = f"{len(lActivityReturnItemValue)} bytes" lLogStr = f"{len(lActivityReturnItemValue)} байт"
except Exception as e: except Exception as e:
pass pass
if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Has recieved result of the activity items from agent! ActivityItem GUID Str: {lActivityReturnItemKeyStr}; Return value len: {lLogStr}") if lL: lL.debug(f"СЕРВЕР: Функция pyOpenRPA_Agent_A2O:: Получена активность от агента! Идентификатор активности: {lActivityReturnItemKeyStr}; Длина переданной активности: {lLogStr}")
# Delete the source activity item from AgentDict # Delete the source activity item from AgentDict
if lAgentDictItemKeyTurple in inGSettings["AgentDict"]: if lAgentDictItemKeyTurple in inGSettings["AgentDict"]:
lAgentDictActivityListNew = [] lAgentDictActivityListNew = []
@ -448,11 +454,23 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lAgentDictActivityListNew.append(lActivityItem) lAgentDictActivityListNew.append(lActivityItem)
else: else:
del lActivityItem del lActivityItem
if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Source activity item request was deleted from the orchestrator. ActivityItem GUID Str: {lActivityReturnItemKeyStr}") if lL: lL.debug(f"СЕРВЕР: Функция pyOpenRPA_Agent_A2O:: Активность была удалена из процессорной очереди. Идентификатор активности: {lActivityReturnItemKeyStr}")
inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"] = lAgentDictActivityListNew inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"] = lAgentDictActivityListNew
from pyOpenRPA.Utils.Render import Render
lFileStr = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-2] + ["Resources","Web","orpa","orc.xhtml"])
gRender = Render(inTemplatePathStr=lFileStr,inTemplateRefreshBool=True)
def pyOpenRPA_Index():
# Пример использования
global gRender
lStr = gRender.Generate(inDataDict={"title":"ОРКЕСТРАТОР PYOPENRPA", "subtitle":"ПАНЕЛЬ УПРАВЛЕНИЯ"})
__Orchestrator__.WebRequestResponseSend(inResponeStr=lStr,inContentTypeStr="text/html")
def SettingsUpdate(inGlobalConfiguration): def SettingsUpdate(inGlobalConfiguration):
import os import os
import pyOpenRPA.Orchestrator import pyOpenRPA.Orchestrator
gSettingsDict = __Orchestrator__.GSettingsGet()
if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1]) if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1])
if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1]) if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1])
lURLList = \ lURLList = \
@ -467,7 +485,10 @@ def SettingsUpdate(inGlobalConfiguration):
# "ResponseDefRequestGlobal": None #Function with str result # "ResponseDefRequestGlobal": None #Function with str result
#} #}
#Orchestrator basic dependencies # Index page in server.py because of special settings #Orchestrator basic dependencies # Index page in server.py because of special settings
{"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index},
{"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\orpa\\metadata.json"), "ResponseContentType": "application/json"},
{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"}, {"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"},
{"Method":"GET", "URL": "/orpa/Resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "..\\Resources"),"UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.css", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css"), "ResponseContentType": "text/css", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.css", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css"), "ResponseContentType": "text/css", "UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/jQuery/jquery-3.1.1.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/jQuery/jquery-3.1.1.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True},
@ -494,4 +515,4 @@ def SettingsUpdate(inGlobalConfiguration):
] ]
Usage.Process(inComponentStr="Orchestrator") Usage.Process(inComponentStr="Orchestrator")
inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList
return inGlobalConfiguration return inGlobalConfiguration

@ -1,5 +1,7 @@
import os, logging, datetime, sys import os, logging, datetime, sys
import schedule # https://schedule.readthedocs.io/en/stable/examples.html import schedule
from pyOpenRPA.Tools import CrossOS # https://schedule.readthedocs.io/en/stable/examples.html
# Technical def - return GSettings structure with examples # Technical def - return GSettings structure with examples
def __Create__(): def __Create__():
@ -340,7 +342,7 @@ def Create(inModeStr="BASIC", inLoggerLevel = None):
lL.setLevel(logging.INFO) lL.setLevel(logging.INFO)
# create the logging file handler # create the logging file handler
mRobotLoggerFH = logging.FileHandler( mRobotLoggerFH = logging.FileHandler(
"Reports\\" + datetime.datetime.now().strftime("%Y_%m_%d") + ".log") CrossOS.PathStr("Reports\\" + datetime.datetime.now().strftime("%Y_%m_%d") + ".log"))
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter) mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object # add handler to logger object

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@ -0,0 +1,49 @@
<div class="ui inverted vertical footer segment">
<div class="ui center aligned container">
<div class="ui stackable inverted divided equal height stackable grid">
<div class="four wide column">
<h4 class="ui inverted header">Навигатор</h4>
<div class="ui inverted link list">
<a href="https://pyopenrpa.ru/" target="_blank" class="item">Портал</a>
<a href="https://pyopenrpa.ru/wiki/guide/v1.2.14_RUS/html/index.html" target="_blank" class="item">Документация</a>
<a href="https://t.me/pyOpenRPA" target="_blank" class="item">Сообщество</a>
<a href="mailto:support@pyopenrpa.ru" target="_blank" class="item">Тех. поддержка</a>
<a href="https://pyopenrpa.ru/verification" target="_blank" class="item">Центр цифровых сертификатов</a>
</div>
</div>
<div class="four wide column">
<h4 class="ui inverted header">Интересный факт</h4>
<p><a href="https://pyopenrpa.ru" target="_blank">Портал pyOpenRPA</a> сделан на оркестраторе pyOpenRPA за 7 дней - присоединяйся к сильной стороне!</p>
</div>
<div class="eight wide column">
<h4 class="ui inverted header">Контактная информация</h4>
<span>ПРАВООБЛАДАТЕЛЬ: ООО "ОПЕН РПА", ОГРН 1227700251350</span>
<br>
<span>МСК: 125310, Россия, г. Москва, улица Муравская</span>
<br>
<span>СПБ: 197022, Россия, г. Санкт-Петербург, Аптекарский проспект, 18</span>
<br>
<span>Центр поддержки клиентов: +7 995 233 45 31 (с 9:00 до 18:00 по МСК), support@pyopenrpa.ru</span>
<br>
<span>Оказываем услуги на всей территории Российской Федерации</span>
</div>
</div>
<div class="ui inverted section divider"></div>
<div class="ui horizontal inverted small divided link list">
<a class="item" href="https://semantic-ui.com/elements/input.html" target="_blank">Справка Semantic UI</a>
<a class="item" href="https://pywinauto.readthedocs.io/en/latest/code/code.html#main-user-modules" target="_blank">Справка Pywinauto</a>
<a class="item" href="https://gitlab.com/UnicodeLabs/OpenRPA" target="_blank">Репозиторий pyOpenRPA</a>
<a class="item" href="https://pyopenrpa.ru/license/oferta.pdf" target="_blank">Оферта</a>
</div>
</div>
</div>
<script src="/orpa/Resources/Web/orpa/styleset/visibility.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/sidebar.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/transition.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/docs.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/easing.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/highlight.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/less.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/home.js"></script>

@ -0,0 +1,100 @@
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/reset.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/site.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/container.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/grid.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/header.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/image.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/menu.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/divider.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/dropdown.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/segment.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/button.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/list.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/icon.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/sidebar.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/transition.css">
<div class="pusher tag-top">
<div class="ui inverted vertical masthead center aligned segment zoomed" style="background-color:#000000; ">
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.main.menu {
margin-top: 4em;
border-radius: 0;
border: none;
box-shadow: none;
transition:
box-shadow 0.5s ease,
padding 0.5s ease
;
}
.main.menu .item img.logo {
margin-right: 1.5em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
}
.overlay .menu {
position: relative;
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);
}
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
}
</style>
<div class="ui text container tag-top">
<div class="ui middle aligned stackable grid container">
<div class="row">
<div class="four wide column">
<img src="/orpa/Resources/Web/orpa/styleset/pyOpenRPA_logo.png" width="140px;" height="140px"></img>
</div>
<div class="twelve wide column">
<h1 class="ui inverted header" style="margin-top:0px; margin-bottom:0px;">
<span class="library" style="text-transform: uppercase; letter-spacing: 5px; margin-top:0px; margin-bottom:5px; font-weight: bold;">{{title}}</span>
</h1>
<h2 style="text-transform: uppercase; letter-spacing: 5px; margin-top:0px; margin-bottom:5px;">
{{subtitle}}
</h2>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,992 @@
var mGlobal={}
mGlobal.pyOpenRPA = {}
window.onload=function() {
//document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
//Render existing data
//mGlobal.Monitor.fControlPanelRefresh_TechnicalRender()
}
$(document).ready(function() {
document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
console.log("Cookie is deleted")
// fix main menu to page on passing
$('.main.menu').visibility({
type: 'fixed'
});
$('.overlay').visibility({
type: 'fixed',
offset: 80
});
// lazy load images
$('.image').visibility({
type: 'image',
transition: 'vertical flip in',
duration: 500
});
// show dropdown on hover
$('.main.menu .ui.dropdown').dropdown({
on: 'hover'
});
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
//For data storage key
mGlobal["DataStorage"] = {}
// Clear the session cookie
String.prototype.replaceAll = function(search, replace){
return this.split(search).join(replace);
}
mGlobal.GeneralGenerateHTMLCodeHandlebars=function(inInnerTemplateSelector,inData) {
lHTMLTemplate=$(inInnerTemplateSelector)[0].innerHTML
//console.log(lHTMLTemplate)
//Компиляция
var template = Handlebars.compile(lHTMLTemplate);
//Вставка данных
var lHTMLResult = template(inData);
return lHTMLResult
}
mGlobal.GeneralGenerateHTMLCode=function(inTemplateHTMLSelector,inItemDictionary,inKeywordPrefix="::",inKeywordPostfix="::") {
///Получить заготовку
lTemplateHTMLCode=$(inTemplateHTMLSelector)[0].outerHTML
///Определить ключь экранирования специальных ключевых слов
///Выполнить циклические замены, если там есть пожходящие ключи
lResultHTMLCode=lTemplateHTMLCode
for(var lKey in inItemDictionary) {
lHTMLKey=inKeywordPrefix+lKey+inKeywordPostfix;
lResultHTMLCode=lResultHTMLCode.replaceAll(lHTMLKey,inItemDictionary[lKey])
}
///Вернуть результат
return lResultHTMLCode
}
//////////////////////////
/////Info JS module
//////////////////////////
mGlobal.Info={};
mGlobal.Info.TableActivityLogScheduleListRefresh=function() {
}
//////////////////////////
/////Controller JS module
//////////////////////////
mGlobal.Controller={};
mGlobal.Controller.CMDRunText=function(inCMDText) {
///Подготовить конфигурацию
lData = [
{"Type":"CMDStart", "Command": inCMDText}
]
///Обнулить таблицу
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3){},
dataType: "text"
});
}
mGlobal.Controller.CMDRun=function() {
///Обнулить таблицу
lCMDCode=$(".openrpa-controller-cmd-run-input")[0].value
///Подготовить конфигурацию
lData = [
{
"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: '/pyOpenRPA/ActivityListExecute',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
//lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result)
},
dataType: "text"
});
}
mGlobal.Controller.CMDRunGUILogout=function() {
///Обнулить таблицу
lCMDCode="for /f \"skip=1 tokens=2\" %s in ('query user %USERNAME%') do (tscon \\dest:console)"
//lCMDCode = lCMDCode.replace(/\\n/g, "\\n")
// .replace(/\\'/g, "\\'")
// .replace(/\\"/g, '\\"')
// .replace(/\\&/g, "\\&")
// .replace(/\\r/g, "\\r")
// .replace(/\\t/g, "\\t")
// .replace(/\\b/g, "\\b")
// .replace(/\\f/g, "\\f")
// .replace('"', "\\\"");
///Подготовить конфигурацию
lData = [
{"Type":"CMDStart", "Command": lCMDCode }
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
//lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result)
},
dataType: "text"
});
}
///Restart PC
mGlobal.Controller.PCRestart = function () {
mGlobal.Controller.OrchestratorSessionSave()
mGlobal.Controller.CMDRunText("shutdown -r")
}
///Orchestrator save session
mGlobal.Controller.OrchestratorSessionSave=function() {
///Подготовить конфигурацию
lData = [
{"Type":"OrchestratorSessionSave"}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
},
dataType: "text"
});
}
///Перезагрузить Orchestrator
mGlobal.Controller.OrchestratorRestart=function() {
///Подготовить конфигурацию
lData = [
{"Type":"OrchestratorRestart"}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
},
dataType: "text"
});
}
mGlobal.Controller.OrchestratorGITPullRestart = function() {
mGlobal.Controller.OrchestratorSessionSave() //Save current RDP list session
mGlobal.Controller.CMDRunText("timeout 3 & taskkill /f /im OpenRPA_Orchestrator.exe & timeout 2 & cd "+mGlobal.WorkingDirectoryPathStr+" & git reset --hard & git pull & pyOpenRPA.Orchestrator_x64_administrator_startup.cmd");
}
//////////////////////////
/////Monitor JS module
//////////////////////////
mGlobal.Monitor={};
mGlobal.Monitor.ScreenshotModal={};
mGlobal.Monitor.GenerateUniqueID=function(inPrefix="tempUID=") {
return inPrefix+Math.round(Math.random()*1000)+"-"+Math.round(Math.random()*10000)+"-"+Math.round(Math.random()*1000)
}
//inHostURI: http://localhost:8081
mGlobal.Monitor.ScreenshotModal.Show=function(inHostURI=" ") {
$('.ui.modal.daemon-screenshot').modal({'onHide':function (inElement) {mGlobal.Monitor.ScreenshotModal.Close();} }).modal('show');
//Функция обновления картинки
lScreenshotUpdate=function() {
lScreenshotSrc=inHostURI+"/GetScreenshot?"+mGlobal.Monitor.GenerateUniqueID()
$(".daemon-screenshot img").attr('src', lScreenshotSrc);
}
mGlobal.Monitor.ScreenshotModal.timerId=setInterval(lScreenshotUpdate,1500)
}
mGlobal.Monitor.ScreenshotModal.Close=function() {
clearInterval(mGlobal.Monitor.ScreenshotModal.timerId);
}
///Monitor
mGlobal.Monitor.DaemonList={}
mGlobal.Monitor.DaemonList.fRefreshTable=function() {
///Загрузка данных
$.ajax({
type: "GET",
url: 'Monitor/JSONDaemonListGet',
data: '',
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Сформировать HTML код новой таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-monitor-table-general",lResponseJSON)
///Очистить дерево
//mGlobal.ElementTree.fClear();
///Прогрузить новую таблицу
$(".openrpa-monitor").html(lHTMLCode)
},
dataType: "text"
});
}
////////////////////////////////
///////Control panel
///////////////////////////////
///Refresh control panel
function sleep(ms) {
ms += new Date().getTime();
while (new Date() < ms){}
}
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
mGlobal.SessionGUIDStr = uuidv4() // Generate uuid4 of the session
//console.log(uuidv4());
mGlobal.RobotRDPActive = {}
mGlobal.Monitor.fControlPanelRefresh_TechnicalRender = function()
{
lResponseJSON = mGlobal.Monitor.mDatasetLast
if (lResponseJSON!= null) {
/// 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
/// FooterButtonX1List
lItem["FooterButtonX1List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
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
}
}
)
///Прогрузить новую таблицу
$(".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 = '<div class="ui cards">'
for (var lKeyStr in lResponseJSON["CPDict"]){
lCPDict = lResponseJSON["CPDict"][lKeyStr]
/// Render HTML
if ("HTMLStr" in lCPDict) {
lHTMLCode+=lCPDict["HTMLStr"]
}
}
lHTMLCode += '</div>'
///Прогрузить новую таблицу
$(".openrpa-control-panel").html(lHTMLCode)
////////////////////////////////////////////////////
/// !RDP List ! Сформировать HTML код новой таблицы - список RDP
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON["RDPDict"])
//Присвоить ответ в mGlobal.RobotRDPActive.mResponseList
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.pyOpenRPA.ServerDataRefreshDef=function() {
try {
$.ajax({
type: "POST",
headers: {},
url: 'pyOpenRPA/ServerData',
data: mGlobal.pyOpenRPA.ServerDataHashStr,
success: function(lData,l2,l3) {
try {
var lResponseJSON=JSON.parse(lData)
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.pyOpenRPA.ServerDataRefreshDef() // recursive
},
dataType: "text",
error: function(jqXHR, textStatus, errorThrown ) {
setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive
}
});
}
catch(error) {
setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive
}
}
/////////////////////////////////////////////////////////////
/// 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("Разморозить окно логов")
$("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("Заморозить окно логов")
$("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
}
});
}
catch(error) {
setTimeout(mGlobal.pyOpenRPA.ServerLogListRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive
}
}
/////////////////////////////////////////////////////////////
mGlobal.Monitor.mDatasetLast = null
///////////////////////////////
///Processor functions
///////////////////////////////
mGlobal.Processor = {}
mGlobal.Processor.ServerValueAppend = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueAppend",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueSet",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.ServerValueOperatorPlus = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueOperator+",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.Send = function(inData) {
lData = inData
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Server= {}
mGlobal.Server.JSONGet=function(inMethod, inURL, inDataJSON, inCallback)
{
$.ajax({
type: inMethod,
url: inURL,
data: JSON.stringify(inDataJSON),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
inCallback(lResponseJSON)
},
dataType: "text"
});
}
/////////////////
///Modal
///////////////////
mGlobal.Modal={}
/////////////////////////////////////////////////////
mGlobal.Modal.TableFilter={}
mGlobal.Modal.TableFilter.Show=function(inJSON) {
//{
// "Title":"",
// "Headers":["Header1","Header2"],
// "Rows": [["Cell1","Cell2"],["Cell2-1","Cell2-2"]],
// "FilterOnKeyUp": "<JS Code>" //Fill here in function
//}
//Set js handler to Search field
inJSON["FilterOnKeyUp"]="mGlobal.Modal.TableFilter.FilterUpdate(this.value);"
///Set value
mGlobal.Modal.TableFilter.mDataJSON = inJSON
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",inJSON);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
//DO widest modal for table with scroll x
$("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["width"]="1300px"
$("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["overflow"]="scroll"
}
//Service function
mGlobal.Modal.TableFilter.FilterUpdate=function(inFilterValue) {
//Get JSON, apply filter, clone data
lDataJSON = clone(mGlobal.Modal.TableFilter.mDataJSON)
delete lDataJSON["Rows"]
lDataJSON["Rows"]=[]
//Filter code [any occurence in the row is ok for push! ]
mGlobal.Modal.TableFilter.mDataJSON["Rows"].forEach(
function(inElement) {
lFlagElementAppend = false
inElement.forEach(
function(inElement2) {
if (String(inElement2).includes(inFilterValue)) {
lFlagElementAppend = true
}
}
)
if (lFlagElementAppend) {
lDataJSON["Rows"].push(inElement)
}
}
)
//Clear Filter Title property (fixed in html)
delete lDataJSON["FilterOnKeyUp"]
delete lDataJSON["Title"]
//Search the table element [replace only table html]
lElement = $('.ui.modals.active .content table.table')[0]
lElementParentElement = lElement.parentNode
lElement.parentNode.removeChild(lElement);
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",lDataJSON);
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
/////////////////////////////////////////////////////////////
mGlobal.Modal.ListFilter={}
mGlobal.Modal.ListFilter.Show=function(inJSON) {
//{
// "Title":"",
// "List":[{"Header":"","Description":""}],
// "FilterOnKeyUp": "<JS Code>" //Fill here in function
//}
//Set js handler to Search field
inJSON["FilterOnKeyUp"]="mGlobal.Modal.ListFilter.FilterUpdate(this.value);"
///Set value
mGlobal.Modal.ListFilter.mDataJSON = inJSON
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",inJSON);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
}
//Service function
mGlobal.Modal.ListFilter.FilterUpdate=function(inFilterValue) {
//Get JSON, apply filter, clone data
lDataJSON = clone(mGlobal.Modal.ListFilter.mDataJSON)
delete lDataJSON["List"]
lDataJSON["List"]=[]
//Filter code [any occurence in the row is ok for push! ]
mGlobal.Modal.ListFilter.mDataJSON["List"].forEach(
function(inElement) {
lFlagElementAppend = false
if (String(inElement["Header"]).includes(inFilterValue)) {
lFlagElementAppend = true
}
if (String(inElement["Description"]).includes(inFilterValue)) {
lFlagElementAppend = true
}
if (lFlagElementAppend) {
lDataJSON["List"].push(inElement)
}
}
)
//Clear Filter Title property (fixed in html)
delete lDataJSON["FilterOnKeyUp"]
delete lDataJSON["Title"]
//Search the table element [replace only table html]
lElement = $('.ui.modals.active .content div.ui.inverted.segment')[0]
lElementParentElement = lElement.parentNode
lElement.parentNode.removeChild(lElement);
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",lDataJSON);
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
mGlobal.UserRoleHierarchyDict = null // Put here the user role hierarchy
// UAC Ask
mGlobal.UserRoleAsk=function(inList) {
var lResult = true; // Init flag
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;
for (var i = 0; i<lListLength; i++) {
var lItem = inList[i]; // get the item
if (typeof lKeyValue == "object") {
if (lItem in lKeyValue) { // Has key
lKeyValue = lKeyValue[lItem]; // Get the value and go to the next loop iteration
} else { // Else branch - true or false
if (Object.keys(lKeyValue).length > 0) { // false - if Dict has some elements
lResult = false; // Set the False Flag
} else {
lResult = true; // Set the true flag
}
break; // Stop the loop
}
} else { // Has element with no detalization - return true
lResult = true; // Set the flag
break; // Close the loop
}
}
return lResult; // Return the result
}
// Check user roles and update the Orchestrator UI
mGlobal.UserRoleUpdate=function() {
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(); }
if (lUACAsk(["pyOpenRPADict","AdminDict","Debugging"])) { $(".UACClient-pyOpenRPADict-AdminDict-Debugging").show(); }
}
/// v1.2.0 pyOpenRPA Init defs
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
mGlobal.pyOpenRPA.ServerJSInitDef(); // Recieve JS from server (if exist) and then call anothe url ServerData
//$('.ui.dropdown').dropdown();
////////////////////////////////////////////
// 1.2.7 Debugging
/// Execute ActivityItem
// Debugging onchange def autofill init
var lDropdownOnChange = function(inEvent){
//lValueStr = inEvent.target.value
lValueStr = inEvent
$.ajax({
type: "GET",
url: '/pyOpenRPA/Debugging/HelperDefAutofill/'+lValueStr,
data: null,
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
console.log("HelperDefAutofill:")
console.log(lResponseJSON)
//ArgDict merge
var lArgDictTargetDict = lResponseJSON["ArgDict"]
var lArgDictStr = $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value
if (lArgDictStr !="" && lArgDictStr !=null) {
lArgDictLastDict = JSON.parse(lArgDictStr)
lArgDictTargetDict = mGlobal.pyOpenRPA.DebuggingAutofillMerge(lArgDictTargetDict, lArgDictLastDict)
}
$(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value = JSON.stringify(lResponseJSON["ArgList"])
$(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value = JSON.stringify(lArgDictTargetDict)
$(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value = JSON.stringify(lResponseJSON["ArgGSettingsStr"])
$(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value = JSON.stringify(lResponseJSON["ArgLoggerStr"])
},
dataType: "text"
});
}
//$('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')[0].onchange=lDropdownOnChange
mGlobal.pyOpenRPA.DebuggingExecute=function() {
///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)
// }
///Подготовить конфигурацию
lArgListStr = $(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value
lArgDictStr = $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value
lArgGSettingsStr = $(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value
lArgLoggerStr = $(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value
lActivityItem = {
"Def":$(".mGlobal-pyOpenRPA-Debugging-Def")[0].value, // def link or def alias (look gSettings["Processor"]["AliasDefDict"])
"ArgList":(lArgListStr == "" ? [] : JSON.parse(lArgListStr)), // Args list
"ArgDict":(lArgDictStr == "" ? {} : JSON.parse(lArgDictStr)), // Args dictionary
"ArgGSettingsStr": (lArgGSettingsStr == "" ? null : lArgGSettingsStr), // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
"ArgLoggerStr": (lArgLoggerStr == "" ? null : lArgLoggerStr) // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
}
lData = [lActivityItem]
$.ajax({
type: "POST",
url: '/pyOpenRPA/ActivityListExecute',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
console.log(lResponseJSON)
$(".mGlobal-pyOpenRPA-Debugging-Output")[0].value = JSON.stringify(lResponseJSON[0])
},
dataType: "text"
});
}
mGlobal.pyOpenRPA.DebuggingAutofillMerge=function(inTargetDict, inLastDict) {
// Merge 2 dict (get values from Last dict if key exists in new dict
for (const [lKeyStr, lValue] of Object.entries(inTargetDict)) {
//Check if key exists in LastDict
if (lKeyStr in inLastDict) {
inTargetDict[lKeyStr] = inLastDict[lKeyStr]
}
}
return inTargetDict
}
// 1.2.7 Debugging toolbox init
$('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')
.dropdown({
apiSettings: {
// this url parses query server side and returns filtered results
url: '/pyOpenRPA/Debugging/HelperDefList/{query}'
},
onChange: lDropdownOnChange
})
;
});

@ -0,0 +1,499 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<!-- Yandex.Metrika counter -->
<script async="" src="https://mc.yandex.ru/metrika/tag.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88079149, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/88079149" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Оркестратор pyOpenRPA</title>
<meta name="description" content="Ведущий RPA разработчик российского программного обеспечения. RPA платформа позволяет решать любые бизнес-задачи. Комплексное решение от компании RPA pyOpenRPA. Первое открытое российское RPA решение для крупного / среднего / малого бизнеса. Доступная автоматизация для каждого.">
<meta name="keywords" content="rpa, программные роботы, автоматизация бизнес-процессов, цифровые сотрудники, виртуальные сотрудники">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/semantic.min.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/orpa/styleset/home.css">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script
src="/orpa/Resources/Web/jQuery/jquery-3.1.1.min.js"
crossorigin="anonymous"></script>
<script src="/orpa/Resources/Web/Semantic-UI-CSS-master/semantic.min.js"></script>
<script src="/orpa/Resources/Web/Handlebars/handlebars-v4.1.2.js"></script>
<script src = "/orpa/Resources/Web/orpa/orc.js"></script>
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
}
.overlay .menu {
position: relative;
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);
}
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
}
.ui.search.dropdown>input.search {
width:100%;
font-family:monospace;
font-weight: bold;
}
.ui.search.dropdown>.text {
width:100%;
font-family:monospace;
font-weight: bold;
}
</style>
</head>
<body>
{% include 'header.xhtml' %}
<div class="ui aligned stackable grid container">
<div class="row">
<div class="sixteen wide column openrpa-control-panel-general UACClient-pyOpenRPADict-CPKeyDict" style="display:none;" >
<h4 class="ui horizontal divider header" style="margin-bottom:30px;margin-top:30px;">
<i class="clipboard list icon"></i>
Роботы
</h4>
<div class="openrpa-control-panel"></div>
<script class="openrpa-hidden-control-panel" style="display:none" type="text/x-handlebars-template">
<div class="ui cards">
{% raw %}
{{#RenderRobotList}}
<div class="card">
<div class="content">
<div class="right floated mini ui ">
{{{HeaderRightText}}}
</div>
<div class="header">
{{{HeaderLeftText}}}
</div>
<div class="meta">
{{{SubheaderText}}}
</div>
<div class="description">
<ul style="padding-inline-start:16px;margin:0px">
{{#BodyKeyValueList}}
<li>{{{Key}}}: {{{Value}}}</li>
{{/BodyKeyValueList}}
</ul>
</div>
</div>
<div class="extra content">
{{{FooterText}}}
</div>
<div class="extra content">
<div class="ui two buttons">
{{#FooterButtonX2List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX2List}}
</div>
<div class="ui horizontal divider">Add. controls</div>
<div class="ui one buttons">
{{#FooterButtonX1List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX1List}}
</div>
</div>
</div>
{{/RenderRobotList}}
{% endraw %}
</div>
</script>
</div>
</div>
<div class="row">
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
{% raw %}
<table class="ui celled table">
<thead>
<tr>
<th>Machine name</th>
<th>Machihe host</th>
<th>Status</th>
<th>Actions,length: {{childs.length}}</th>
</tr>
</thead>
<tbody>
{{#ListenURLList}}
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
{{/ListenURLList}}
</tbody>
</table>
{% endraw %}
</script>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
{% raw %}
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<table class="ui celled table selectable inverted">
<thead>
<tr>
{{#Columns}}
<th>{{{this}}}</th>
{{/Columns}}
</tr>
</thead>
<tbody>
{{#Rows}}
<tr>
{{#this}}
<td>
{{{this}}}
</td>
{{/this}}
</tr>
{{/Rows}}
</tbody>
</table>
{% endraw %}
</script>
<script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{% raw %}
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<div class="ui inverted segment">
<div class="ui inverted relaxed divided list">
{{#List}}
<div class="item">
<i class="map marker icon"></i>
<div class="content">
<a class="header">{{{Header}}}</a>
<div class="description">{{{Description}}}</div>
</div>
</div>
{{/List}}
</div>
</div>
{% endraw %}
</script>
<div class="eight wide column openrpa-robotrdpactive-control-panel-general UACClient-pyOpenRPADict-RDPKeyDict" style="display:none;">
<h2 class="ui header openrpa-rdpactive-title">
<i class="desktop icon"></i>
<div class="content">
РДП сессии
</div>
</h2>
<div class="openrpa-robotrdpactive-control-panel"></div>
<script class="openrpa-hidden-robotrdpactive-control-panel" style="display:none" type="text/x-handlebars-template">
<div class="ui inverted segment" style="background: #368279">
{% raw %}
<div class="ui inverted relaxed divided list">
{{#HandlebarsList}}
<div class="item">
<div class="right floated content">
<div class="ui button" onclick="mGlobal.Processor.ServerValueAppend(['RobotRDPActive','ActivityList'],{'DefNameStr': 'RDPSessionReconnect', 'ArgList': [], 'ArgDict': {'inRDPSessionKeyStr': '{{{SessionKeyStr}}}'} })" >Переподключить</div>
</div>
<div class="right floated content">
{{#if IsIgnoredBool}}
<div class="ui button red" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],false);">Игнорировать</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],true);">Игнорировать</div>
{{/if}}
</div>
<div class="right floated content">
{{#if IsFullScreenBool}}
<div class="ui button green" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],null);">Полный экран</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],'{{{SessionKeyStr}}}');">Полный экран</div>
{{/if}}
</div>
<div class="content">
<div class="header">Session key: {{{SessionKeyStr}}}</div>
{{{SessionHexStr}}}
</div>
</div>
{{/HandlebarsList}}
</div>
{% endraw %}
</div>
</script>
</div>
<div class="eight wide column UACClient-pyOpenRPADict-AgentKeyDict" style="display:none">
<h2 class="ui header " style="">
<i class="bug icon"></i>
<div class="content">
Агент подключения
</div>
</h2>
<div class="pyOpenRPA-Agent-List"></div>
<script class="pyOpenRPA-Agent-ListTemplate" style="display:none" type="text/x-handlebars-template">
<div class="ui inverted segment" style="background: #368279">
{% raw %}
<div class="ui inverted relaxed divided list">
{{#HandlebarsList}}
<div class="item">
<div class="right floated content">
{{#if IsListenBool}}
<i class="circle icon green"></i>
Доступен
{{else}}
<i class="circle icon red"></i>
Недоступен
{{/if}}
</div>
<div class="content">
<div class="header">Хост: {{{HostnameUpperStr}}}, Пользователь: {{{UserUpperStr}}}</div>
</div>
</div>
{{/HandlebarsList}}
</div>
{% endraw %}
</div>
</script>
</div>
</div>
<div class="row openrpa-monitor">
</div>
<div class="row">
<div class="sixteen wide column" style="">
<h2 class="ui header">
<i class="settings icon"></i>
<div class="content">
Администрирование
</div>
</h2>
</div>
</div>
<div class="row">
<div class="sixteen wide column" style="">
<h4 class="ui horizontal divider header" >
<i class="clipboard list icon"></i>
Логи
</h4>
<textarea class="mGlobal-pyOpenRPA-ServerLogList UACClient-pyOpenRPADict-AdminDict-LogViewerBool" readonly="readonly" style="width:100%; display:none; resize: none; font-family:monospace; font-weight: bold;" id="textarea_id" rows="20">
</textarea>
<a class="mGlobal-pyOpenRPA-ServerLogListDoRender" onclick="" style="cursor: pointer;">Заморозить окно логов</a>
</div>
</div>
<div class="row ui">
<div class="sixteen wide column ui" style="margin-bottom:30px;">
<h4 class="ui horizontal divider header" >
<i class="settings icon"></i>
Терминал
</h4>
</div>
<div class="eight wide column ui">
<div class="ui fluid input UACClient-pyOpenRPADict-AdminDict-CMDInputBool" style="display:none;">
<input class="openrpa-controller-cmd-run-input" type="text" placeholder="Скрипт для терминала..." style="min-width:250px;">
</div>
</div>
<div class="three wide column ui">
<div class="ui button green" onclick="mGlobal.Controller.CMDRun();" style="">Выполнить</div>
</div>
<div class="five wide column ui">
<div class="ui button" onclick="mGlobal.Controller.CMDRunGUILogout();" style="">Выйти из сессии</div>
</div>
</div>
<div class="row UACClient-pyOpenRPADict-AdminDict-Debugging" style= "display:none;">
<div class="twelve wide column">
<h4 class="ui horizontal divider header" >
<i class="bug icon"></i>
Отладка - Отправить
</h4>
<div class="ui labeled input">
<div class="ui label">Def</div>
</div>
<div class="ui fluid search selection dropdown mGlobal-pyOpenRPA-Debugging-Def-Dropdown" style="margin-bottom:10px;">
<input class="mGlobal-pyOpenRPA-Debugging-Def" type="hidden" name="country" style="width:100%; font-family:monospace; font-weight: bold;">
<i class="dropdown icon"></i>
<div class="default text">Def</div>
<div class="menu">
<div class="item" data-value="eh">pyOpenRPA... sys.. os.. </div>
</div>
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgList
</div>
<input type="text" placeholder="[1,2,3]" class="mGlobal-pyOpenRPA-Debugging-ArgList" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgDict
</div>
<input type="text" placeholder="{&quot;Key1&quot;:&quot;Value1&quot;}" class="mGlobal-pyOpenRPA-Debugging-ArgDict" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgGSettingsStr
</div>
<input type="text" placeholder="inGSettings" class="mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgLoggerStr
</div>
<input type="text" placeholder="inLogger" class="mGlobal-pyOpenRPA-Debugging-ArgLoggerStr" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid button" onclick="mGlobal.pyOpenRPA.DebuggingExecute();">Выполнить</div>
</div>
<div class="four wide column">
<h4 class="ui horizontal divider header" >
<i class="bug icon"></i>
Отладка - Получить
</h4>
<p><textarea class="mGlobal-pyOpenRPA-Debugging-Output" readonly="readonly" style="width:100%; font-family:monospace; font-weight: bold;" rows="16" cols="60"></textarea></p>
</div>
</div>
<h4 class="ui horizontal divider header">
<i class="clipboard list icon"></i>
Управление
</h4>
<div class="row ui buttons">
<div class="ui animated button openrpa-control-lookmachinescreenshot green UACClient-pyOpenRPADict-AdminDict-ScreenshotViewerBool" onclick="mGlobal.Monitor.ScreenshotModal.Show();" style="display: none; margin-top: 5px;">
<div class="visible content">Смотреть экран</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-restartorchestrator orange UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorBool" onclick="mGlobal.Controller.OrchestratorRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Перезагрузить оркестратор</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-gitrestartorchestrator teal UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorGITPullBool" onclick="mGlobal.Controller.OrchestratorGITPullRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Обновить из GIT</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-restartpc red UACClient-pyOpenRPADict-AdminDict-RestartPCBool" onclick="mGlobal.Controller.PCRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Перезагрузить ОС</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
</div>
</div>
{% include 'footer.xhtml' %}
<div class="ui basic modal">
<div class="ui icon header">
</div>
<div class="content">
<p>Добро пожаловать!</p>
</div>
<div class="actions">
<div class="ui red basic cancel inverted button">
<i class="remove icon"></i>
Нет
</div>
<div class="ui green ok inverted button">
<i class="checkmark icon"></i>
Да
</div>
</div>
</div>
<div class="ui daemon-screenshot modal">
<div class="ui icon header">
</div>
<div class="content">
<img src="GetScreenshot" class="ui fluid image">
</div>
<div class="actions">
<div class="ui green ok inverted button" onclick="mGlobal.Monitor.ScreenshotModal.Close()">
<i class="checkmark icon"></i>
Закрыть
</div>
</div>
</div>
<div class="ui modal openrpa-code-list-gui-import-modal">
<i class="close icon"></i>
<div class="header">
СПисок действий
</div>
<div class="content">
<div class="description">
<div class="ui header">Вставить JSON спецификацию:</div>
<p><textarea style="width:100%" rows="6" cols="60"></textarea></p>
</div>
</div>
<div class="actions">
<div class="ui black deny button">
Отменить
</div>
<div class="ui positive right labeled icon button" onclick="mGlobal.CodeList.fActionSpecificationImportFromJSON();">
Распознать
<i class="checkmark icon"></i>
</div>
</div>
</div>
</body>
</html>

@ -0,0 +1,10 @@
/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
* Open source under the BSD License.
*
* Copyright é 2001 Robert Penner
* All rights reserved.
*
*/
jQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:"easeOutQuad",swing:function(e,f,a,h,g){return jQuery.easing[jQuery.easing.def](e,f,a,h,g)},easeInQuad:function(e,f,a,h,g){return h*(f/=g)*f+a},easeOutQuad:function(e,f,a,h,g){return -h*(f/=g)*(f-2)+a},easeInOutQuad:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f+a}return -h/2*((--f)*(f-2)-1)+a},easeInCubic:function(e,f,a,h,g){return h*(f/=g)*f*f+a},easeOutCubic:function(e,f,a,h,g){return h*((f=f/g-1)*f*f+1)+a},easeInOutCubic:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f+a}return h/2*((f-=2)*f*f+2)+a},easeInQuart:function(e,f,a,h,g){return h*(f/=g)*f*f*f+a},easeOutQuart:function(e,f,a,h,g){return -h*((f=f/g-1)*f*f*f-1)+a},easeInOutQuart:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f+a}return -h/2*((f-=2)*f*f*f-2)+a},easeInQuint:function(e,f,a,h,g){return h*(f/=g)*f*f*f*f+a},easeOutQuint:function(e,f,a,h,g){return h*((f=f/g-1)*f*f*f*f+1)+a},easeInOutQuint:function(e,f,a,h,g){if((f/=g/2)<1){return h/2*f*f*f*f*f+a}return h/2*((f-=2)*f*f*f*f+2)+a},easeInSine:function(e,f,a,h,g){return -h*Math.cos(f/g*(Math.PI/2))+h+a},easeOutSine:function(e,f,a,h,g){return h*Math.sin(f/g*(Math.PI/2))+a},easeInOutSine:function(e,f,a,h,g){return -h/2*(Math.cos(Math.PI*f/g)-1)+a},easeInExpo:function(e,f,a,h,g){return(f==0)?a:h*Math.pow(2,10*(f/g-1))+a},easeOutExpo:function(e,f,a,h,g){return(f==g)?a+h:h*(-Math.pow(2,-10*f/g)+1)+a},easeInOutExpo:function(e,f,a,h,g){if(f==0){return a}if(f==g){return a+h}if((f/=g/2)<1){return h/2*Math.pow(2,10*(f-1))+a}return h/2*(-Math.pow(2,-10*--f)+2)+a},easeInCirc:function(e,f,a,h,g){return -h*(Math.sqrt(1-(f/=g)*f)-1)+a},easeOutCirc:function(e,f,a,h,g){return h*Math.sqrt(1-(f=f/g-1)*f)+a},easeInOutCirc:function(e,f,a,h,g){if((f/=g/2)<1){return -h/2*(Math.sqrt(1-f*f)-1)+a}return h/2*(Math.sqrt(1-(f-=2)*f)+1)+a},easeInElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return -(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e},easeOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k)==1){return e+l}if(!j){j=k*0.3}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}return g*Math.pow(2,-10*h)*Math.sin((h*k-i)*(2*Math.PI)/j)+l+e},easeInOutElastic:function(f,h,e,l,k){var i=1.70158;var j=0;var g=l;if(h==0){return e}if((h/=k/2)==2){return e+l}if(!j){j=k*(0.3*1.5)}if(g<Math.abs(l)){g=l;var i=j/4}else{var i=j/(2*Math.PI)*Math.asin(l/g)}if(h<1){return -0.5*(g*Math.pow(2,10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j))+e}return g*Math.pow(2,-10*(h-=1))*Math.sin((h*k-i)*(2*Math.PI)/j)*0.5+l+e},easeInBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*(f/=h)*f*((g+1)*f-g)+a},easeOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}return i*((f=f/h-1)*f*((g+1)*f+g)+1)+a},easeInOutBack:function(e,f,a,i,h,g){if(g==undefined){g=1.70158}if((f/=h/2)<1){return i/2*(f*f*(((g*=(1.525))+1)*f-g))+a}return i/2*((f-=2)*f*(((g*=(1.525))+1)*f+g)+2)+a},easeInBounce:function(e,f,a,h,g){return h-jQuery.easing.easeOutBounce(e,g-f,0,h,g)+a},easeOutBounce:function(e,f,a,h,g){if((f/=g)<(1/2.75)){return h*(7.5625*f*f)+a}else{if(f<(2/2.75)){return h*(7.5625*(f-=(1.5/2.75))*f+0.75)+a}else{if(f<(2.5/2.75)){return h*(7.5625*(f-=(2.25/2.75))*f+0.9375)+a}else{return h*(7.5625*(f-=(2.625/2.75))*f+0.984375)+a}}}},easeInOutBounce:function(e,f,a,h,g){if(f<g/2){return jQuery.easing.easeInBounce(e,f*2,0,h,g)*0.5+a}return jQuery.easing.easeOutBounce(e,f*2-g,0,h,g)*0.5+h*0.5+a}});

@ -0,0 +1,737 @@
/*
* # Semantic UI - 2.4.2
* https://github.com/Semantic-Org/Semantic-UI
* http://www.semantic-ui.com/
*
* Copyright 2014 Contributors
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*!
* # Semantic UI - Header
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Header
*******************************/
/* Standard */
.ui.header {
border: none;
margin: calc(2rem - 0.14285714em ) 0em 1rem;
padding: 0em 0em;
font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
font-weight: bold;
line-height: 1.28571429em;
text-transform: none;
color: rgba(0, 0, 0, 0.87);
}
.ui.header:first-child {
margin-top: -0.14285714em;
}
.ui.header:last-child {
margin-bottom: 0em;
}
/*--------------
Sub Header
---------------*/
.ui.header .sub.header {
display: block;
font-weight: normal;
padding: 0em;
margin: 0em;
font-size: 1rem;
line-height: 1.2em;
color: rgba(0, 0, 0, 0.6);
}
/*--------------
Icon
---------------*/
.ui.header > .icon {
display: table-cell;
opacity: 1;
font-size: 1.5em;
padding-top: 0em;
vertical-align: middle;
}
/* With Text Node */
.ui.header .icon:only-child {
display: inline-block;
padding: 0em;
margin-right: 0.75rem;
}
/*-------------------
Image
--------------------*/
.ui.header > .image:not(.icon),
.ui.header > img {
display: inline-block;
margin-top: 0.14285714em;
width: 2.5em;
height: auto;
vertical-align: middle;
}
.ui.header > .image:not(.icon):only-child,
.ui.header > img:only-child {
margin-right: 0.75rem;
}
/*--------------
Content
---------------*/
.ui.header .content {
display: inline-block;
vertical-align: top;
}
/* After Image */
.ui.header > img + .content,
.ui.header > .image + .content {
padding-left: 0.75rem;
vertical-align: middle;
}
/* After Icon */
.ui.header > .icon + .content {
padding-left: 0.75rem;
display: table-cell;
vertical-align: middle;
}
/*--------------
Loose Coupling
---------------*/
.ui.header .ui.label {
font-size: '';
margin-left: 0.5rem;
vertical-align: middle;
}
/* Positioning */
.ui.header + p {
margin-top: 0em;
}
/*******************************
Types
*******************************/
/*--------------
Page
---------------*/
h1.ui.header {
font-size: 2rem;
}
h2.ui.header {
font-size: 1.71428571rem;
}
h3.ui.header {
font-size: 1.28571429rem;
}
h4.ui.header {
font-size: 1.07142857rem;
}
h5.ui.header {
font-size: 1rem;
}
/* Sub Header */
h1.ui.header .sub.header {
font-size: 1.14285714rem;
}
h2.ui.header .sub.header {
font-size: 1.14285714rem;
}
h3.ui.header .sub.header {
font-size: 1rem;
}
h4.ui.header .sub.header {
font-size: 1rem;
}
h5.ui.header .sub.header {
font-size: 0.92857143rem;
}
/*--------------
Content Heading
---------------*/
.ui.huge.header {
min-height: 1em;
font-size: 2em;
}
.ui.large.header {
font-size: 1.71428571em;
}
.ui.medium.header {
font-size: 1.28571429em;
}
.ui.small.header {
font-size: 1.07142857em;
}
.ui.tiny.header {
font-size: 1em;
}
/* Sub Header */
.ui.huge.header .sub.header {
font-size: 1.14285714rem;
}
.ui.large.header .sub.header {
font-size: 1.14285714rem;
}
.ui.header .sub.header {
font-size: 1rem;
}
.ui.small.header .sub.header {
font-size: 1rem;
}
.ui.tiny.header .sub.header {
font-size: 0.92857143rem;
}
/*--------------
Sub Heading
---------------*/
.ui.sub.header {
padding: 0em;
margin-bottom: 0.14285714rem;
font-weight: bold;
font-size: 0.85714286em;
text-transform: uppercase;
color: '';
}
.ui.small.sub.header {
font-size: 0.78571429em;
}
.ui.sub.header {
font-size: 0.85714286em;
}
.ui.large.sub.header {
font-size: 0.92857143em;
}
.ui.huge.sub.header {
font-size: 1em;
}
/*-------------------
Icon
--------------------*/
.ui.icon.header {
display: inline-block;
text-align: center;
margin: 2rem 0em 1rem;
}
.ui.icon.header:after {
content: '';
display: block;
height: 0px;
clear: both;
visibility: hidden;
}
.ui.icon.header:first-child {
margin-top: 0em;
}
.ui.icon.header .icon {
float: none;
display: block;
width: auto;
height: auto;
line-height: 1;
padding: 0em;
font-size: 3em;
margin: 0em auto 0.5rem;
opacity: 1;
}
.ui.icon.header .content {
display: block;
padding: 0em;
}
.ui.icon.header .circular.icon {
font-size: 2em;
}
.ui.icon.header .square.icon {
font-size: 2em;
}
.ui.block.icon.header .icon {
margin-bottom: 0em;
}
.ui.icon.header.aligned {
margin-left: auto;
margin-right: auto;
display: block;
}
/*******************************
States
*******************************/
.ui.disabled.header {
opacity: 0.45;
}
/*******************************
Variations
*******************************/
/*-------------------
Inverted
--------------------*/
.ui.inverted.header {
color: #FFFFFF;
}
.ui.inverted.header .sub.header {
color: rgba(255, 255, 255, 0.8);
}
.ui.inverted.attached.header {
background: #545454 -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(0, 0, 0, 0.05)));
background: #545454 -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
background: #545454 linear-gradient(transparent, rgba(0, 0, 0, 0.05));
-webkit-box-shadow: none;
box-shadow: none;
border-color: transparent;
}
.ui.inverted.block.header {
background: #545454 -webkit-gradient(linear, left top, left bottom, from(transparent), to(rgba(0, 0, 0, 0.05)));
background: #545454 -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.05));
background: #545454 linear-gradient(transparent, rgba(0, 0, 0, 0.05));
-webkit-box-shadow: none;
box-shadow: none;
}
.ui.inverted.block.header {
border-bottom: none;
}
/*-------------------
Colors
--------------------*/
/*--- Red ---*/
.ui.red.header {
color: #DB2828 !important;
}
a.ui.red.header:hover {
color: #d01919 !important;
}
.ui.red.dividing.header {
border-bottom: 2px solid #DB2828;
}
/* Inverted */
.ui.inverted.red.header {
color: #FF695E !important;
}
a.ui.inverted.red.header:hover {
color: #ff5144 !important;
}
/*--- Orange ---*/
.ui.orange.header {
color: #F2711C !important;
}
a.ui.orange.header:hover {
color: #f26202 !important;
}
.ui.orange.dividing.header {
border-bottom: 2px solid #F2711C;
}
/* Inverted */
.ui.inverted.orange.header {
color: #FF851B !important;
}
a.ui.inverted.orange.header:hover {
color: #ff7701 !important;
}
/*--- Olive ---*/
.ui.olive.header {
color: #B5CC18 !important;
}
a.ui.olive.header:hover {
color: #a7bd0d !important;
}
.ui.olive.dividing.header {
border-bottom: 2px solid #B5CC18;
}
/* Inverted */
.ui.inverted.olive.header {
color: #D9E778 !important;
}
a.ui.inverted.olive.header:hover {
color: #d8ea5c !important;
}
/*--- Yellow ---*/
.ui.yellow.header {
color: #FBBD08 !important;
}
a.ui.yellow.header:hover {
color: #eaae00 !important;
}
.ui.yellow.dividing.header {
border-bottom: 2px solid #FBBD08;
}
/* Inverted */
.ui.inverted.yellow.header {
color: #FFE21F !important;
}
a.ui.inverted.yellow.header:hover {
color: #ffdf05 !important;
}
/*--- Green ---*/
.ui.green.header {
color: #21BA45 !important;
}
a.ui.green.header:hover {
color: #16ab39 !important;
}
.ui.green.dividing.header {
border-bottom: 2px solid #21BA45;
}
/* Inverted */
.ui.inverted.green.header {
color: #2ECC40 !important;
}
a.ui.inverted.green.header:hover {
color: #22be34 !important;
}
/*--- Teal ---*/
.ui.teal.header {
color: #00B5AD !important;
}
a.ui.teal.header:hover {
color: #009c95 !important;
}
.ui.teal.dividing.header {
border-bottom: 2px solid #00B5AD;
}
/* Inverted */
.ui.inverted.teal.header {
color: #6DFFFF !important;
}
a.ui.inverted.teal.header:hover {
color: #54ffff !important;
}
/*--- Blue ---*/
.ui.blue.header {
color: #2185D0 !important;
}
a.ui.blue.header:hover {
color: #1678c2 !important;
}
.ui.blue.dividing.header {
border-bottom: 2px solid #2185D0;
}
/* Inverted */
.ui.inverted.blue.header {
color: #54C8FF !important;
}
a.ui.inverted.blue.header:hover {
color: #3ac0ff !important;
}
/*--- Violet ---*/
.ui.violet.header {
color: #6435C9 !important;
}
a.ui.violet.header:hover {
color: #5829bb !important;
}
.ui.violet.dividing.header {
border-bottom: 2px solid #6435C9;
}
/* Inverted */
.ui.inverted.violet.header {
color: #A291FB !important;
}
a.ui.inverted.violet.header:hover {
color: #8a73ff !important;
}
/*--- Purple ---*/
.ui.purple.header {
color: #A333C8 !important;
}
a.ui.purple.header:hover {
color: #9627ba !important;
}
.ui.purple.dividing.header {
border-bottom: 2px solid #A333C8;
}
/* Inverted */
.ui.inverted.purple.header {
color: #DC73FF !important;
}
a.ui.inverted.purple.header:hover {
color: #d65aff !important;
}
/*--- Pink ---*/
.ui.pink.header {
color: #E03997 !important;
}
a.ui.pink.header:hover {
color: #e61a8d !important;
}
.ui.pink.dividing.header {
border-bottom: 2px solid #E03997;
}
/* Inverted */
.ui.inverted.pink.header {
color: #FF8EDF !important;
}
a.ui.inverted.pink.header:hover {
color: #ff74d8 !important;
}
/*--- Brown ---*/
.ui.brown.header {
color: #A5673F !important;
}
a.ui.brown.header:hover {
color: #975b33 !important;
}
.ui.brown.dividing.header {
border-bottom: 2px solid #A5673F;
}
/* Inverted */
.ui.inverted.brown.header {
color: #D67C1C !important;
}
a.ui.inverted.brown.header:hover {
color: #c86f11 !important;
}
/*--- Grey ---*/
.ui.grey.header {
color: #767676 !important;
}
a.ui.grey.header:hover {
color: #838383 !important;
}
.ui.grey.dividing.header {
border-bottom: 2px solid #767676;
}
/* Inverted */
.ui.inverted.grey.header {
color: #DCDDDE !important;
}
a.ui.inverted.grey.header:hover {
color: #cfd0d2 !important;
}
/*-------------------
Aligned
--------------------*/
.ui.left.aligned.header {
text-align: left;
}
.ui.right.aligned.header {
text-align: right;
}
.ui.centered.header,
.ui.center.aligned.header {
text-align: center;
}
.ui.justified.header {
text-align: justify;
}
.ui.justified.header:after {
display: inline-block;
content: '';
width: 100%;
}
/*-------------------
Floated
--------------------*/
.ui.floated.header,
.ui[class*="left floated"].header {
float: left;
margin-top: 0em;
margin-right: 0.5em;
}
.ui[class*="right floated"].header {
float: right;
margin-top: 0em;
margin-left: 0.5em;
}
/*-------------------
Fitted
--------------------*/
.ui.fitted.header {
padding: 0em;
}
/*-------------------
Dividing
--------------------*/
.ui.dividing.header {
padding-bottom: 0.21428571rem;
border-bottom: 1px solid rgba(34, 36, 38, 0.15);
}
.ui.dividing.header .sub.header {
padding-bottom: 0.21428571rem;
}
.ui.dividing.header .icon {
margin-bottom: 0em;
}
.ui.inverted.dividing.header {
border-bottom-color: rgba(255, 255, 255, 0.1);
}
/*-------------------
Block
--------------------*/
.ui.block.header {
background: #F3F4F5;
padding: 0.78571429rem 1rem;
-webkit-box-shadow: none;
box-shadow: none;
border: 1px solid #D4D4D5;
border-radius: 0.28571429rem;
}
.ui.tiny.block.header {
font-size: 0.85714286rem;
}
.ui.small.block.header {
font-size: 0.92857143rem;
}
.ui.block.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: 1rem;
}
.ui.large.block.header {
font-size: 1.14285714rem;
}
.ui.huge.block.header {
font-size: 1.42857143rem;
}
/*-------------------
Attached
--------------------*/
.ui.attached.header {
background: #FFFFFF;
padding: 0.78571429rem 1rem;
margin-left: -1px;
margin-right: -1px;
-webkit-box-shadow: none;
box-shadow: none;
border: 1px solid #D4D4D5;
}
.ui.attached.block.header {
background: #F3F4F5;
}
.ui.attached:not(.top):not(.bottom).header {
margin-top: 0em;
margin-bottom: 0em;
border-top: none;
border-radius: 0em;
}
.ui.top.attached.header {
margin-bottom: 0em;
border-radius: 0.28571429rem 0.28571429rem 0em 0em;
}
.ui.bottom.attached.header {
margin-top: 0em;
border-top: none;
border-radius: 0em 0em 0.28571429rem 0.28571429rem;
}
/* Attached Sizes */
.ui.tiny.attached.header {
font-size: 0.85714286em;
}
.ui.small.attached.header {
font-size: 0.92857143em;
}
.ui.attached.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: 1em;
}
.ui.large.attached.header {
font-size: 1.14285714em;
}
.ui.huge.attached.header {
font-size: 1.42857143em;
}
/*-------------------
Sizing
--------------------*/
.ui.header:not(h1):not(h2):not(h3):not(h4):not(h5):not(h6) {
font-size: 1.28571429em;
}
/*******************************
Theme Overrides
*******************************/
/*******************************
Site Overrides
*******************************/

@ -0,0 +1,759 @@
/*******************************
Homepage
*******************************/
body.index .pusher > .page {
background-color: #FFFFFF;
}
@media only screen and (max-width: 992px) {
html {
overflow-x: visible;
-webkit-overflow-scrolling: auto;
}
}
body > .pusher {
display: block;
min-height: 0px;
flex-direction: initial;
}
body > .pusher > .full.height {
display: block;
flex: none !important;
}
/*--------------
Masthead
---------------*/
body .masthead.segment.zoomed h1 {
text-shadow: 0px 0px 4px rgba(0, 0, 0, 0);
color: rgba(255, 255, 255, 1);
}
body .masthead.zoomed:after {
opacity: 0;
}
body .masthead.zoomed {
background-color: #25282A;
}
body .masthead {
position: relative;
overflow: hidden;
text-align: center;
padding: 0em;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 0px;
border-bottom: none;
background-color: #000000;
background-position: 50% 50%;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
body .masthead:after {
position: absolute;
top: 0px;
left: 0px;
z-index: -1;
width: 100%;
height: 100%;
content: '';
background-size: cover;
opacity: 0.45;
}
body .masthead.bg1:after {
background-image: url("./bg1.jpg");
}
body .masthead.bg2:after {
background-image: url("./bg2.jpg");
}
body .masthead.bg3:after {
background-image: url("./bg3.jpg");
}
body .masthead.bg4:after {
background-image: url("./bg4.jpg");
}
body .masthead.bg5:after {
background-image: url("./bg5.jpg");
}
body .masthead.bg6:after {
background-image: url("./bg6.jpg");
}
body .masthead.bg7:after {
background-image: url("./bg7.jpg");
}
body .masthead.bg8:after {
background-image: url("./bg8.jpg");
}
body .masthead.bg9:after {
background-image: url("./bg9.jpg");
}
body .masthead.bg10:after {
background-image: url("./bg10.jpg");
}
body .masthead.bg11:after {
background-image: url("./bg1.jpg");
}
body .masthead.bg12:after {
background-image: url("./bg2.jpg");
}
body .masthead.bg13:after {
background-image: url("./bg3.jpg");
}
body .masthead.bg14:after {
background-image: url("./bg4.jpg");
}
body .masthead,
body .masthead:after {
-ms-transition:
background 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s,
opacity 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s;
-moz-transition:
background 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s,
opacity 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s;
-webkit-transition:
background 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s,
opacity 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s;
transition:
background 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s,
opacity 6s cubic-bezier(0.680, -0.550, 0.265, 1.4) 0s;
}
#example.index .masthead .container {
height: 55vh;
margin-left: auto !important;
margin-right: auto !important;
min-height: 600px;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
#example .masthead .container {
padding: 15rem 0em;
}
#example.index .following.bar iframe.github {
margin-top: 0px;
}
body.index .following.bar .menu .item {
display: block;
}
#example.index.pushed .masthead,
#example.index.pushed .following.bar {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
#example.index > .pusher > .footer {
padding-left: 0em;
}
#example.index .light.following.bar {
padding: 0em 0em;
background-color: #FFFFFF;
border-bottom: 1px solid #DDDDDD;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.04);
}
#example.index .masthead.segment .typed-cursor {
position: relative;
top: -0.05em;
left: -0.25em;
visibility: hidden;
opacity: 1;
-webkit-animation: blink 0.7s infinite;
-moz-animation: blink 0.7s infinite;
animation: blink 0.7s infinite;
-webkit-transition: opacity 0.7s ease;
-moz-transition: opacity 0.7s ease;
transition: opacity 0.7s ease;
}
#example.index .masthead.segment .typed-cursor.stop {
opacity: 0;
-moz-animation-duration: 0s;
-webkit-animation-duration: 0s;
animation-duration: 0s;
}
@keyframes blink {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
@-webkit-keyframes blink {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
@-moz-keyframes blink {
0% { opacity:1; }
50% { opacity:0; }
100% { opacity:1; }
}
#example.index .vertical.segment {
box-shadow: none;
}
#example.index .masthead.segment h1 {
font-size: 3em;
color: rgba(255, 255, 255, 1);
line-height: 1.2;
margin: 0px 0px 0px;
padding-bottom: 0px;
-moz-perspective: 500px;
-webkit-perspective: 500px;
perspective: 500px;
text-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
-moz-transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
#example.index .masthead.segment h1 .tagline {
font-size: 0.75em;
}
#example.index .masthead.segment h1 > .library {
display: block;
font-size: 1.75em;
font-weight: bold;
}
#example.index .masthead.segment h1 b {
display: inline-block;
font-weight: 500;
}
#example.index .masthead.segment h1 .text {
display: inline-block;
font-weight: 300;
margin-left: -0.4em;
}
#example.index .masthead h2 {
font-weight: normal;
margin: 0px 0 16px 0px;
font-size: 1.75em;
border-bottom: none;
line-height: 1;
}
#example.index .masthead p {
font-size: 1.5em;
margin: 1em 0em 1.5em;
padding: 0px;
}
#example.index .ui.header {
font-weight: normal;
}
#example.index .footer .ui.header {
font-weight: bold;
}
#example.index .introduction {
position: relative;
clear: both;
display: block;
text-align: center;
}
#example.index .introduction .buttons {
margin-top: 3em;
}
#example.index .advertisement {
display: none !important;
padding-left: 0;
position: absolute;
left: auto;
right: 6em;
top: 50%;
transform: translateY(-50%);
vertical-align: top;
}
#example.index .fixed.launch.button {
display: none;
top: 100px;
}
#example.index .main.menu {
top: 0px;
}
#example.index pre.console {
height: 120px;
}
/*--------------
Intro
---------------*/
#example .intro.segment h1 + p {
font-size: 22px;
}
/*--------------
Demo
---------------*/
#example .demo.row .example > .ui.label:not(.empty) {
margin-bottom: 1em;
}
#example .demo.row .ui.progress {
margin-bottom: 2.5em;
}
#example .demo.row h4 {
font-weight: bold !important;
margin: 0em 0em 1em !important;
}
#example .demo.row .example {
clear: both;
padding-top: 3em;
margin-top: 3em;
}
#example .demo.row .ui.menu,
#example .demo.row .ui.card {
width: 100%;
}
#example .demo.row .ui.card {
width: 100%;
max-width: 400px;
}
/*--------------
Features
---------------*/
#example.index .hidden.code {
visibility: hidden;
}
#example.index .demo.row .example {
clear: both;
padding-top: 1.5em;
margin-top: 1.5em;
}
#example.index .demo.row .example:first-child {
margin-top: 0;
padding-top: 0;
}
#example.index .demo.row .example:last-child {
margin-bottom: 0em;
}
/*--------------
Following
---------------*/
#example.index .following.bar {
position: fixed;
top: 0px;
z-index: 900;
left: 0%;
padding: 2em 0em;
width: 100%;
box-shadow: 0px 0px 0px 0px transparent;
border-bottom: 1px solid transparent;
transition:
padding 0.5s ease,
background 0.5s ease,
box-shadow 0.5s ease,
border 0.5s ease
;
}
#example.index .following.bar > .menu .item {
transition: all 0.5s ease;
}
#example.index.pushed .following.bar .menu .item,
#example.index.pushed .following.bar {
transition: none;
}
#example.index .following.bar .additional.item[data-site="learn"]:hover {
color: #D9499A;
}
#example.index .following.bar span.additional.item {
cursor: default;
color: rgba(0, 0, 0, 0.2);
}
#example.index .following.bar .inverted span.additional.item {
color: rgba(255, 255, 255, 0.2);
}
#example.index .following.bar .column > .menu {
margin-top: 0px;
height: 35px;
}
#example.index .following.bar .network.menu .item {
font-weight: bold;
}
#example.index .following.bar .item iframe {
margin-left: 10px;
}
#example.index .following.bar .network.menu .view-ui {
margin-right: 1em;
}
#example.index .light.following.bar .network.menu .view-ui {
color: #00B5AD;
}
#example.index .light.following.bar .inverted.network.menu .view-ui {
color: #6DFFFF;
}
#example.index .following .logo {
float: left;
width: 35px;
margin-right: 1em;
}
#example.index .following .logo .side {
width: 35px;
}
#example .masthead .version.label:after {
background-color: #000000 !important;
}
#example.index .following .version.label {
margin: 0.25em 0px 0px 1em;
}
/*--------------
Stripes
---------------*/
#example.index .stripe .grid .row {
margin: 2rem 0rem;
}
#example.index .feature.stripe .grid .row {
margin: 0rem;
}
#example.index .feature.stripe .column {
display: flex;
-ms-flex-direction: column;
-webkit-flex-direction: column;
-moz-flex-direction: column;
flex-direction: column;
}
#example.index .feature.stripe p {
-webkit-flex: 1 0 auto;
-moz-flex: 1 0 auto;
-ms-flex: 1 0 auto;
flex: 1 0 auto;
margin: 0.5em 0em 2em;
}
#example .stripe .ui.vertical.divider {
font-size: 1rem;
}
#example.index .feature.stripe .icon.header .icon.image {
width: auto;
height: 65px;
margin-bottom: 20px;
}
#example.index .stripe .icon.header .icon.image {
height: 65px;
margin-bottom: 20px;
}
#example.index .community.stripe {
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.1);
padding: 4em 0;
}
#example.index .stripe .icon.header i.icon {
font-size: 2em;
}
/* Final */
#example.index .final.stripe {
border-top: 1px solid #DDDDDD;
background-color: #F8F8F8;
}
/* Alternate */
#example .alternate.stripe {
background-color: #F2F3F5;
}
/* Inverted */
#example.index .inverted.stripe {
background-color: #1B1C1D;
}
#example.index .inverted.stripe p {
color: #FFFFFF;
}
/*--------------
Legacy?
---------------*/
/* content */
#example .solid,
#example .stripe {
background-color: #FFFFFF;
padding: 10em 0px;
border-radius: 0em;
margin: 0em;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
#example .theming.stripe {
-webkit-transform: none;
transform: none;
}
#example .stripe h1 {
font-size: 40px;
}
#example .stripe h2 {
font-size: 26px;
}
#example .stripe h3 {
font-size: 20px;
}
#example .feature.stripe {
padding: 3em 0em;
}
#example .theming.stripe .left.aligned.column {
padding-top: 8em;
}
#example .theming.stripe .hljs.code {
height: 483px;
max-height: 483px;
}
#example .theming .source.grid {
display: none !important;
margin: 2rem 2rem -4rem;
}
#example .theming .source.grid.visible {
display: block;
display: flex !important;
}
#example .theming.stripe .buttons {
vertical-align: top;
}
#example .theming.stripe .button {
margin-bottom: 0.5em;
}
#example .stripe .column > p {
font-size: 16px;
line-height: 1.6;
margin: 1em 0em;
}
#example .dark.stripe {
background-color: #333333;
background: url(/images/dark-bg.png) repeat;
color: #FFFFFF;
}
#example .stripe .column > .label {
margin-bottom: 1em;
}
#example .solid {
background-color: #FFFFFF;
-webkit-box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.1);
-moz-box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.1);
box-shadow: 0px 0px 0px 0px rgba(0, 0, 0, 0.1);
}
#example .solid .column {
color: #555555;
}
#example .solid .column p b {
color: rgba(0, 0, 0, 0.9);
}
#example .solid .column p {
color: rgba(0, 0, 0, 0.5);
}
/*--------------
Promo
---------------*/
#example.index .promo.stripe {
padding: 3em 0em;
}
/*--------------
Newsletter
---------------*/
#example.index .email.stripe {
padding: 5em 0em;
}
#example.index .email.stripe p {
margin: -0.5em 0em 1em;
}
#example.index .email.stripe .input {
width: 450px;
}
#example.index .email.stripe .submit.button {
margin-left: 1em;
}
@media only screen and (max-width : 400px) {
#example.index .advertisement {
display: none;
margin-left: -130px !important;
}
#example.index .carbonad {
width: 260px !important;
}
#example.index .masthead.segment h1 {
font-size: 1.75em !important;
}
#example.index .feature.stripe {
padding: 1em;
}
}
@media only screen and (max-width : 600px) {
#example.index .solid,
#example.index .stripe {
padding: 4em 0em;
}
#example.index .masthead.segment h1 .text {
margin-left: 0em;
}
#example.index .following.bar {
display: none;
}
#example.index .masthead:before {
display: none;
}
#example.index .following.bar .column {
text-align: center;
}
#example.index .following .logo {
float: none;
}
#example.index .codebase.stripe {
display: none;
}
#example.index .following .version.label {
vertical-align: top;
margin-top: 0em;
}
#example .masthead .container {
padding: 6rem 0rem;
}
#example.index .masthead.segment h1 {
font-size: 2.25em;
}
#example.index .email.stripe .input {
width: 100%;
}
#example.index .following .secondary.menu {
display: none;
}
#example.index .email.stripe .submit.button {
margin-top: 0.5em;
}
#example.index .stripe .icon.header .icon.image {
height: 50px;
}
#example.index .stripe {
padding: 2em 0em !important;
}
}
@media only screen and (max-width : 650px) {
#example.index .fixed.launch.button {
display: none;
}
#example .stripe h1 {
font-size: 32px;
}
}
@media only screen and (min-width : 601px) {
#example .theming .source.button {
display: none;
}
#example.index .main.menu {
display: none;
}
#example.index .fixed.launch.button {
display: none;
}
}
/* Homepage */
@media only screen and (max-width : 810px) {
#example.index .masthead.segment h1 > .library {
font-size: 1.75em;
}
#example.index .feature.stripe p {
height: auto;
min-height: 0px;
}
#example.index .container {
margin-left: 0em;
margin-right: 0em;
}
#example .solid, #example .stripe {
padding: 6em 0em;
}
#example.index .masthead .container {
margin-top: 50px;
}
#example.index .following.bar span.additional.item {
display: none;
visibility: hidden !important;
}
#example.index .following.bar .network.menu .view-ui {
margin-right: 0.75em;
}
#example.index .masthead .container {
min-height: 350px;
height: auto;
}
}
@media only screen and (max-width : 1040px) {
#example.index .following.bar .network.menu .view-ui {
margin-right: 0.5em;
}
}
@media only screen and (max-width: 1300px) {
#example.index .advertisement {
position: absolute;
top: auto;
left: 50%;
bottom: 2rem;
margin-left: -175px;
-webkit-transform: none;
-moz-transform: none;
-ms-transform: none;
transform: none;
}
#example.index .inverted.advertisement .carbonad-img {
margin-top: 0px;
}
#example.index #carbonads-container {
float: none;
}
#example.index .carbonad {
width: 340px;
}
#example.index .carbonad-text,
#example.index .carbonad-tag {
float: none;
display: block;
text-align: left;
margin-left: 160px;
width: 170px;
}
}

@ -0,0 +1,322 @@
semantic.home = {};
// ready event
semantic.home.ready = function() {
var
$themeDropdown = $('.theme.dropdown'),
$header = $('.masthead'),
$ui = $header.find('h1 b'),
$phrase = $header.find('h1 span'),
$download = $header.find('.download'),
$library = $header.find('.library'),
$cursor = $header.find('.typed-cursor'),
$version = $header.find('.version'),
$themeButton = $('.theming .source.button'),
$themeGrid = $('.theming .source.grid'),
handler
;
handler = {
getRandomInt: function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
introduction: function() {
var
background = 'bg' + handler.getRandomInt(1, 9)
;
// zoom out
$header
.addClass(background)
.removeClass('zoomed')
;
},
changeLogo: function() {
var
$logo = $('.following .logo'),
$nextSide = $logo.find('.'+ $(this).data('site') +'.side'),
directions = [
'up',
'left',
'down',
'right'
],
direction = directions[Math.floor(Math.random() * directions.length)]
;
if($nextSide.length > 0) {
clearTimeout(handler.timer);
handler.timer = setTimeout(function() {
$logo
.shape('set next side', $nextSide)
.shape('flip ' + direction)
;
}, 50);
}
},
returnLogo: function() {
var
$logo = $('.following .logo'),
$nextSide = $logo.find('.ui.side')
;
clearTimeout(handler.timer);
handler.timer = setTimeout(function() {
$logo
.shape('set next side', $nextSide)
.shape('flip over')
;
}, 500);
},
less: {
parseFile: function(content) {
var
variables = {},
lines = content.match(/^\s*(@[\s|\S]+?;)/gm),
name,
value
;
if(lines) {
$.each(lines, function(index, line) {
// clear whitespace
line = $.trim(line);
// match variables only
if(line[0] == '@') {
name = line.match(/^@(.+?):/);
value = line.match(/:\s*([\s|\S]+?;)/);
if( ($.isArray(name) && name.length >= 2) && ($.isArray(value) && value.length >= 2) ) {
name = name[1];
value = value[1];
variables[name] = value;
}
}
});
}
console.log(variables);
return variables;
},
changeTheme: function(theme) {
var
$themeDropdown = $(this),
$variableCode = $('.variable.code'),
$overrideCode = $('.override.code'),
$existingVariables = $variableCode.closest('.existing'),
$existingOverrides = $overrideCode.closest('.existing'),
variableURL = '/src/themes/{$theme}/{$type}s/{$element}.variables',
overrideURL = '/src/themes/{$theme}/{$type}s/{$element}.overrides',
urlData = {
theme : typeof(theme === 'string')
? theme.toLowerCase()
: theme,
type : $themeDropdown.data('type'),
element : $themeDropdown.data('element')
}
;
if($existingVariables.length > 0) {
$variableCode = $('<div class="ui variable code" data-type="less" data-preserve="true" />');
$variableCode
.insertAfter($existingVariables)
;
$existingVariables.remove();
console.log($variableCode);
}
if($existingOverrides.length > 0) {
$overrideCode = $('<div class="ui override code" data-type="less" data-preserve="true" />');
$overrideCode
.insertAfter($existingOverrides)
;
$existingOverrides.remove();
console.log($overrideCode);
}
$themeDropdown
.api({
on : 'now',
url : variableURL,
dataType : 'text',
urlData : urlData,
onSuccess: function(content) {
window.less.modifyVars( handler.less.parseFile(content) );
$themeDropdown
.api({
on : 'now',
url : overrideURL,
dataType : 'text',
urlData : urlData,
onSuccess: function(content) {
if( $('style.override').length > 0 ) {
$('style.override').remove();
}
$('<style>' + content + '</style>')
.addClass('override')
.appendTo('body')
;
$('.sticky').sticky('refresh');
$overrideCode.html(content);
$.proxy(semantic.handler.initializeCode, $overrideCode[0])();
}
})
;
$variableCode.html(content);
$.proxy(semantic.handler.initializeCode, $variableCode[0])();
}
})
;
}
},
showThemeButton: function(value, text) {
if(!$themeButton.transition('is visible')) {
$themeButton.transition('scale in');
}
$.proxy(handler.less.changeTheme, this)(value);
},
createDemos: function() {
$('.demo.menu .item, .demo.buttons .button')
.on('click', function() {
if(!$(this).hasClass('dropdown')) {
$(this)
.addClass('active')
.closest('.ui.menu, .ui.buttons')
.find('.item, .button')
.not($(this))
.removeClass('active')
;
}
})
;
$('.example .message .close')
.on('click', function() {
$(this).closest('.message').transition('scale out');
})
;
},
toggleTheme: function() {
$(this).toggleClass('active');
$themeGrid.toggleClass('visible');
}
};
// intro
handler.introduction();
if($(window).width() > 600) {
$('body')
.visibility({
offset : -10,
observeChanges : false,
once : false,
continuous : false,
onTopPassed: function() {
requestAnimationFrame(function() {
$('.following.bar')
.addClass('light fixed')
.find('.menu')
.removeClass('inverted')
;
$('.following .additional.item')
.transition('scale in', 750)
;
});
},
onTopPassedReverse: function() {
requestAnimationFrame(function() {
$('.following.bar')
.removeClass('light fixed')
.find('.menu')
.addClass('inverted')
.find('.additional.item')
.transition('hide')
;
});
}
})
;
}
$('.additional.item')
.popup({
delay: {
show: 200,
hide: 50
},
position: 'bottom center'
})
;
$('.email.stripe form')
.form({
fields: {
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter an e-mail'
},
{
type : 'email',
prompt : 'Please enter a valid e-mail address'
}
]
}
}
})
;
$themeDropdown
.dropdown('setting', 'transition', 'drop')
.dropdown('setting', 'duration', 350)
.dropdown('setting', 'action', 'activate')
.dropdown('setting', 'onChange', handler.showThemeButton)
;
$themeButton
.on('click', handler.toggleTheme)
;
// demos
$('.demo .checkbox')
.checkbox()
;
$('.demo .accordion')
.accordion()
;
$('.demo .dimmer')
.dimmer({
on: 'hover'
})
;
$('.demo .ui.dropdown')
.dropdown()
;
if(window.Transifex !== undefined) {
window.Transifex.live.onTranslatePage(function(countryCode){
var fullName = $('.language.dropdown .item[data-value=' + countryCode + ']').eq(0).text();
$('.language.dropdown > .text').html(fullName);
});
}
$('.ui.sidebar')
.sidebar('setting', {
transition: 'overlay'
})
;
handler.createDemos();
};
// attach ready event
$(document)
.ready(semantic.home.ready)
;

File diff suppressed because one or more lines are too long

@ -0,0 +1,889 @@
/*
* # Semantic UI - 2.4.2
* https://github.com/Semantic-Org/Semantic-UI
* http://www.semantic-ui.com/
*
* Copyright 2014 Contributors
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*!
* # Semantic UI - Segment
* http://github.com/semantic-org/semantic-ui/
*
*
* Released under the MIT license
* http://opensource.org/licenses/MIT
*
*/
/*******************************
Segment
*******************************/
.ui.segment {
position: relative;
background: #FFFFFF;
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
margin: 1rem 0em;
padding: 1em 1em;
border-radius: 0.28571429rem;
border: 1px solid rgba(34, 36, 38, 0.15);
}
.ui.segment:first-child {
margin-top: 0em;
}
.ui.segment:last-child {
margin-bottom: 0em;
}
/* Vertical */
.ui.vertical.segment {
margin: 0em;
padding-left: 0em;
padding-right: 0em;
background: none transparent;
border-radius: 0px;
-webkit-box-shadow: none;
box-shadow: none;
border: none;
border-bottom: 1px solid rgba(34, 36, 38, 0.15);
}
.ui.vertical.segment:last-child {
border-bottom: none;
}
/*-------------------
Loose Coupling
--------------------*/
/* Header */
.ui.inverted.segment > .ui.header {
color: #FFFFFF;
}
/* Label */
.ui[class*="bottom attached"].segment > [class*="top attached"].label {
border-top-left-radius: 0em;
border-top-right-radius: 0em;
}
.ui[class*="top attached"].segment > [class*="bottom attached"].label {
border-bottom-left-radius: 0em;
border-bottom-right-radius: 0em;
}
.ui.attached.segment:not(.top):not(.bottom) > [class*="top attached"].label {
border-top-left-radius: 0em;
border-top-right-radius: 0em;
}
.ui.attached.segment:not(.top):not(.bottom) > [class*="bottom attached"].label {
border-bottom-left-radius: 0em;
border-bottom-right-radius: 0em;
}
/* Grid */
.ui.page.grid.segment,
.ui.grid > .row > .ui.segment.column,
.ui.grid > .ui.segment.column {
padding-top: 2em;
padding-bottom: 2em;
}
.ui.grid.segment {
margin: 1rem 0em;
border-radius: 0.28571429rem;
}
/* Table */
.ui.basic.table.segment {
background: #FFFFFF;
border: 1px solid rgba(34, 36, 38, 0.15);
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
}
.ui[class*="very basic"].table.segment {
padding: 1em 1em;
}
/*******************************
Types
*******************************/
/*-------------------
Placeholder
--------------------*/
.ui.placeholder.segment {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: stretch;
-ms-flex-align: stretch;
align-items: stretch;
max-width: initial;
-webkit-animation: none;
animation: none;
overflow: visible;
padding: 1em 1em;
min-height: 18rem;
background: #F9FAFB;
border-color: rgba(34, 36, 38, 0.15);
-webkit-box-shadow: 0px 2px 25px 0 rgba(34, 36, 38, 0.05) inset;
box-shadow: 0px 2px 25px 0 rgba(34, 36, 38, 0.05) inset;
}
.ui.placeholder.segment .button,
.ui.placeholder.segment textarea {
display: block;
}
.ui.placeholder.segment .field,
.ui.placeholder.segment textarea,
.ui.placeholder.segment > .ui.input,
.ui.placeholder.segment .button {
max-width: 15rem;
margin-left: auto;
margin-right: auto;
}
.ui.placeholder.segment .column .button,
.ui.placeholder.segment .column .field,
.ui.placeholder.segment .column textarea,
.ui.placeholder.segment .column > .ui.input {
max-width: 15rem;
margin-left: auto;
margin-right: auto;
}
.ui.placeholder.segment > .inline {
-ms-flex-item-align: center;
align-self: center;
}
.ui.placeholder.segment > .inline > .button {
display: inline-block;
width: auto;
margin: 0px 0.35714286rem 0px 0px;
}
.ui.placeholder.segment > .inline > .button:last-child {
margin-right: 0px;
}
/*-------------------
Piled
--------------------*/
.ui.piled.segments,
.ui.piled.segment {
margin: 3em 0em;
-webkit-box-shadow: '';
box-shadow: '';
z-index: auto;
}
.ui.piled.segment:first-child {
margin-top: 0em;
}
.ui.piled.segment:last-child {
margin-bottom: 0em;
}
.ui.piled.segments:after,
.ui.piled.segments:before,
.ui.piled.segment:after,
.ui.piled.segment:before {
background-color: #FFFFFF;
visibility: visible;
content: '';
display: block;
height: 100%;
left: 0px;
position: absolute;
width: 100%;
border: 1px solid rgba(34, 36, 38, 0.15);
-webkit-box-shadow: '';
box-shadow: '';
}
.ui.piled.segments:before,
.ui.piled.segment:before {
-webkit-transform: rotate(-1.2deg);
transform: rotate(-1.2deg);
top: 0;
z-index: -2;
}
.ui.piled.segments:after,
.ui.piled.segment:after {
-webkit-transform: rotate(1.2deg);
transform: rotate(1.2deg);
top: 0;
z-index: -1;
}
/* Piled Attached */
.ui[class*="top attached"].piled.segment {
margin-top: 3em;
margin-bottom: 0em;
}
.ui.piled.segment[class*="top attached"]:first-child {
margin-top: 0em;
}
.ui.piled.segment[class*="bottom attached"] {
margin-top: 0em;
margin-bottom: 3em;
}
.ui.piled.segment[class*="bottom attached"]:last-child {
margin-bottom: 0em;
}
/*-------------------
Stacked
--------------------*/
.ui.stacked.segment {
padding-bottom: 1.4em;
}
.ui.stacked.segments:before,
.ui.stacked.segments:after,
.ui.stacked.segment:before,
.ui.stacked.segment:after {
content: '';
position: absolute;
bottom: -3px;
left: 0%;
border-top: 1px solid rgba(34, 36, 38, 0.15);
background: rgba(0, 0, 0, 0.03);
width: 100%;
height: 6px;
visibility: visible;
}
.ui.stacked.segments:before,
.ui.stacked.segment:before {
display: none;
}
/* Add additional page */
.ui.tall.stacked.segments:before,
.ui.tall.stacked.segment:before {
display: block;
bottom: 0px;
}
/* Inverted */
.ui.stacked.inverted.segments:before,
.ui.stacked.inverted.segments:after,
.ui.stacked.inverted.segment:before,
.ui.stacked.inverted.segment:after {
background-color: rgba(0, 0, 0, 0.03);
border-top: 1px solid rgba(34, 36, 38, 0.35);
}
/*-------------------
Padded
--------------------*/
.ui.padded.segment {
padding: 1.5em;
}
.ui[class*="very padded"].segment {
padding: 3em;
}
/* Padded vertical */
.ui.padded.segment.vertical.segment,
.ui[class*="very padded"].vertical.segment {
padding-left: 0px;
padding-right: 0px;
}
/*-------------------
Compact
--------------------*/
.ui.compact.segment {
display: table;
}
/* Compact Group */
.ui.compact.segments {
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
}
.ui.compact.segments .segment,
.ui.segments .compact.segment {
display: block;
-webkit-box-flex: 0;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
}
/*-------------------
Circular
--------------------*/
.ui.circular.segment {
display: table-cell;
padding: 2em;
text-align: center;
vertical-align: middle;
border-radius: 500em;
}
/*-------------------
Raised
--------------------*/
.ui.raised.segments,
.ui.raised.segment {
-webkit-box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15);
box-shadow: 0px 2px 4px 0px rgba(34, 36, 38, 0.12), 0px 2px 10px 0px rgba(34, 36, 38, 0.15);
}
/*******************************
Groups
*******************************/
/* Group */
.ui.segments {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
position: relative;
margin: 1rem 0em;
border: 1px solid rgba(34, 36, 38, 0.15);
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
border-radius: 0.28571429rem;
}
.ui.segments:first-child {
margin-top: 0em;
}
.ui.segments:last-child {
margin-bottom: 0em;
}
/* Nested Segment */
.ui.segments > .segment {
top: 0px;
bottom: 0px;
border-radius: 0px;
margin: 0em;
width: auto;
-webkit-box-shadow: none;
box-shadow: none;
border: none;
border-top: 1px solid rgba(34, 36, 38, 0.15);
}
.ui.segments:not(.horizontal) > .segment:first-child {
border-top: none;
margin-top: 0em;
bottom: 0px;
margin-bottom: 0em;
top: 0px;
border-radius: 0.28571429rem 0.28571429rem 0em 0em;
}
/* Bottom */
.ui.segments:not(.horizontal) > .segment:last-child {
top: 0px;
bottom: 0px;
margin-top: 0em;
margin-bottom: 0em;
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none;
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none;
border-radius: 0em 0em 0.28571429rem 0.28571429rem;
}
/* Only */
.ui.segments:not(.horizontal) > .segment:only-child {
border-radius: 0.28571429rem;
}
/* Nested Group */
.ui.segments > .ui.segments {
border-top: 1px solid rgba(34, 36, 38, 0.15);
margin: 1rem 1rem;
}
.ui.segments > .segments:first-child {
border-top: none;
}
.ui.segments > .segment + .segments:not(.horizontal) {
margin-top: 0em;
}
/* Horizontal Group */
.ui.horizontal.segments {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
background-color: transparent;
border-radius: 0px;
padding: 0em;
background-color: #FFFFFF;
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15);
margin: 1rem 0em;
border-radius: 0.28571429rem;
border: 1px solid rgba(34, 36, 38, 0.15);
}
/* Nested Horizontal Group */
.ui.segments > .horizontal.segments {
margin: 0em;
background-color: transparent;
border-radius: 0px;
border: none;
-webkit-box-shadow: none;
box-shadow: none;
border-top: 1px solid rgba(34, 36, 38, 0.15);
}
/* Horizontal Segment */
.ui.horizontal.segments > .segment {
-webkit-box-flex: 1;
flex: 1 1 auto;
-ms-flex: 1 1 0px;
/* Solves #2550 MS Flex */
margin: 0em;
min-width: 0px;
background-color: transparent;
border-radius: 0px;
border: none;
-webkit-box-shadow: none;
box-shadow: none;
border-left: 1px solid rgba(34, 36, 38, 0.15);
}
/* Border Fixes */
.ui.segments > .horizontal.segments:first-child {
border-top: none;
}
.ui.horizontal.segments > .segment:first-child {
border-left: none;
}
/*******************************
States
*******************************/
/*--------------
Disabled
---------------*/
.ui.disabled.segment {
opacity: 0.45;
color: rgba(40, 40, 40, 0.3);
}
/*--------------
Loading
---------------*/
.ui.loading.segment {
position: relative;
cursor: default;
pointer-events: none;
text-shadow: none !important;
color: transparent !important;
-webkit-transition: all 0s linear;
transition: all 0s linear;
}
.ui.loading.segment:before {
position: absolute;
content: '';
top: 0%;
left: 0%;
background: rgba(255, 255, 255, 0.8);
width: 100%;
height: 100%;
border-radius: 0.28571429rem;
z-index: 100;
}
.ui.loading.segment:after {
position: absolute;
content: '';
top: 50%;
left: 50%;
margin: -1.5em 0em 0em -1.5em;
width: 3em;
height: 3em;
-webkit-animation: segment-spin 0.6s linear;
animation: segment-spin 0.6s linear;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
border-radius: 500rem;
border-color: #767676 rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1);
border-style: solid;
border-width: 0.2em;
-webkit-box-shadow: 0px 0px 0px 1px transparent;
box-shadow: 0px 0px 0px 1px transparent;
visibility: visible;
z-index: 101;
}
@-webkit-keyframes segment-spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes segment-spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/*******************************
Variations
*******************************/
/*-------------------
Basic
--------------------*/
.ui.basic.segment {
background: none transparent;
-webkit-box-shadow: none;
box-shadow: none;
border: none;
border-radius: 0px;
}
/*-------------------
Clearing
--------------------*/
.ui.clearing.segment:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
/*-------------------
Colors
--------------------*/
/* Red */
.ui.red.segment:not(.inverted) {
border-top: 2px solid #DB2828 !important;
}
.ui.inverted.red.segment {
background-color: #DB2828 !important;
color: #FFFFFF !important;
}
/* Orange */
.ui.orange.segment:not(.inverted) {
border-top: 2px solid #F2711C !important;
}
.ui.inverted.orange.segment {
background-color: #F2711C !important;
color: #FFFFFF !important;
}
/* Yellow */
.ui.yellow.segment:not(.inverted) {
border-top: 2px solid #FBBD08 !important;
}
.ui.inverted.yellow.segment {
background-color: #FBBD08 !important;
color: #FFFFFF !important;
}
/* Olive */
.ui.olive.segment:not(.inverted) {
border-top: 2px solid #B5CC18 !important;
}
.ui.inverted.olive.segment {
background-color: #B5CC18 !important;
color: #FFFFFF !important;
}
/* Green */
.ui.green.segment:not(.inverted) {
border-top: 2px solid #21BA45 !important;
}
.ui.inverted.green.segment {
background-color: #21BA45 !important;
color: #FFFFFF !important;
}
/* Teal */
.ui.teal.segment:not(.inverted) {
border-top: 2px solid #00B5AD !important;
}
.ui.inverted.teal.segment {
background-color: #00B5AD !important;
color: #FFFFFF !important;
}
/* Blue */
.ui.blue.segment:not(.inverted) {
border-top: 2px solid #2185D0 !important;
}
.ui.inverted.blue.segment {
background-color: #2185D0 !important;
color: #FFFFFF !important;
}
/* Violet */
.ui.violet.segment:not(.inverted) {
border-top: 2px solid #6435C9 !important;
}
.ui.inverted.violet.segment {
background-color: #6435C9 !important;
color: #FFFFFF !important;
}
/* Purple */
.ui.purple.segment:not(.inverted) {
border-top: 2px solid #A333C8 !important;
}
.ui.inverted.purple.segment {
background-color: #A333C8 !important;
color: #FFFFFF !important;
}
/* Pink */
.ui.pink.segment:not(.inverted) {
border-top: 2px solid #E03997 !important;
}
.ui.inverted.pink.segment {
background-color: #E03997 !important;
color: #FFFFFF !important;
}
/* Brown */
.ui.brown.segment:not(.inverted) {
border-top: 2px solid #A5673F !important;
}
.ui.inverted.brown.segment {
background-color: #A5673F !important;
color: #FFFFFF !important;
}
/* Grey */
.ui.grey.segment:not(.inverted) {
border-top: 2px solid #767676 !important;
}
.ui.inverted.grey.segment {
background-color: #767676 !important;
color: #FFFFFF !important;
}
/* Black */
.ui.black.segment:not(.inverted) {
border-top: 2px solid #1B1C1D !important;
}
.ui.inverted.black.segment {
background-color: #1B1C1D !important;
color: #FFFFFF !important;
}
/*-------------------
Aligned
--------------------*/
.ui[class*="left aligned"].segment {
text-align: left;
}
.ui[class*="right aligned"].segment {
text-align: right;
}
.ui[class*="center aligned"].segment {
text-align: center;
}
/*-------------------
Floated
--------------------*/
.ui.floated.segment,
.ui[class*="left floated"].segment {
float: left;
margin-right: 1em;
}
.ui[class*="right floated"].segment {
float: right;
margin-left: 1em;
}
/*-------------------
Inverted
--------------------*/
.ui.inverted.segment {
border: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.ui.inverted.segment,
.ui.primary.inverted.segment {
background: #1B1C1D;
color: rgba(255, 255, 255, 0.9);
}
/* Nested */
.ui.inverted.segment .segment {
color: rgba(0, 0, 0, 0.87);
}
.ui.inverted.segment .inverted.segment {
color: rgba(255, 255, 255, 0.9);
}
/* Attached */
.ui.inverted.attached.segment {
border-color: #555555;
}
/*-------------------
Emphasis
--------------------*/
/* Secondary */
.ui.secondary.segment {
background: #F3F4F5;
color: rgba(0, 0, 0, 0.6);
}
.ui.secondary.inverted.segment {
background: #4c4f52 -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0.2)), to(rgba(255, 255, 255, 0.2)));
background: #4c4f52 -webkit-linear-gradient(rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%);
background: #4c4f52 linear-gradient(rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%);
color: rgba(255, 255, 255, 0.8);
}
/* Tertiary */
.ui.tertiary.segment {
background: #DCDDDE;
color: rgba(0, 0, 0, 0.6);
}
.ui.tertiary.inverted.segment {
background: #717579 -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0.35)), to(rgba(255, 255, 255, 0.35)));
background: #717579 -webkit-linear-gradient(rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.35) 100%);
background: #717579 linear-gradient(rgba(255, 255, 255, 0.35) 0%, rgba(255, 255, 255, 0.35) 100%);
color: rgba(255, 255, 255, 0.8);
}
/*-------------------
Attached
--------------------*/
/* Middle */
.ui.attached.segment {
top: 0px;
bottom: 0px;
border-radius: 0px;
margin: 0em -1px;
width: calc(100% - (-1px * 2));
max-width: calc(100% - (-1px * 2));
-webkit-box-shadow: none;
box-shadow: none;
border: 1px solid #D4D4D5;
}
.ui.attached:not(.message) + .ui.attached.segment:not(.top) {
border-top: none;
}
/* Top */
.ui[class*="top attached"].segment {
bottom: 0px;
margin-bottom: 0em;
top: 0px;
margin-top: 1rem;
border-radius: 0.28571429rem 0.28571429rem 0em 0em;
}
.ui.segment[class*="top attached"]:first-child {
margin-top: 0em;
}
/* Bottom */
.ui.segment[class*="bottom attached"] {
bottom: 0px;
margin-top: 0em;
top: 0px;
margin-bottom: 1rem;
-webkit-box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none;
box-shadow: 0px 1px 2px 0 rgba(34, 36, 38, 0.15), none;
border-radius: 0em 0em 0.28571429rem 0.28571429rem;
}
.ui.segment[class*="bottom attached"]:last-child {
margin-bottom: 0em;
}
/*-------------------
Size
--------------------*/
.ui.mini.segments .segment,
.ui.mini.segment {
font-size: 0.78571429rem;
}
.ui.tiny.segments .segment,
.ui.tiny.segment {
font-size: 0.85714286rem;
}
.ui.small.segments .segment,
.ui.small.segment {
font-size: 0.92857143rem;
}
.ui.segments .segment,
.ui.segment {
font-size: 1rem;
}
.ui.large.segments .segment,
.ui.large.segment {
font-size: 1.14285714rem;
}
.ui.big.segments .segment,
.ui.big.segment {
font-size: 1.28571429rem;
}
.ui.huge.segments .segment,
.ui.huge.segment {
font-size: 1.42857143rem;
}
.ui.massive.segments .segment,
.ui.massive.segment {
font-size: 1.71428571rem;
}
/*******************************
Theme Overrides
*******************************/
/*******************************
Site Overrides
*******************************/

@ -23,7 +23,7 @@ def BrowserChromeStart(inDriverExePathStr:str = None, inChromeExePathStr:str = N
from pyOpenRPA.Robot import UIWeb from pyOpenRPA.Robot import UIWeb
UIWeb.BrowserChromeStart() UIWeb.BrowserChromeStart()
UIWeb.BrowserClose() UIWeb.BrowserClose()
:param inDriverExePathStr: Путь до компонента webdriver.exe, по умолчанию None (путь до webdriver.exe, который расположен в репозитории pyOpenRPA) :param inDriverExePathStr: Путь до компонента webdriver.exe, по умолчанию None (путь до webdriver.exe, который расположен в репозитории pyOpenRPA)
:type inDriverExePathStr: str, опционально :type inDriverExePathStr: str, опционально
:param inChromeExePathStr:Путь до компонента chrome.exe, по умолчанию None (путь до chrome.exe, который расположен в репозитории pyOpenRPA) :param inChromeExePathStr:Путь до компонента chrome.exe, по умолчанию None (путь до chrome.exe, который расположен в репозитории pyOpenRPA)

@ -154,7 +154,7 @@ def run():
server_address = (inServerAddress, inPort) server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# Logging # Logging
gSettingsDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") gSettingsDict["Logger"].info(f"Сервер:: Прослушиваемый URL: {inServerAddress}, Прослушиваемый порт: {inPort}")
# Запуск адреса в браузере # Запуск адреса в браузере
os.system(f"explorer http://127.0.0.1:{str(inPort)}") os.system(f"explorer http://127.0.0.1:{str(inPort)}")
Usage.Process(inComponentStr="Studio") Usage.Process(inComponentStr="Studio")

@ -51,4 +51,26 @@ def PathSplitList(inPathStr:str) -> list:
:rtype: list :rtype: list
""" """
inPathStr = inPathStr.replace("\\","/") inPathStr = inPathStr.replace("\\","/")
return inPathStr.split("/") return inPathStr.split("/")
def PathJoinList(inList: list) ->str:
"""Слияние элементов списка в строку. Учитывает специфику формирования путей в разных ОС (Windows, Linux)
Для Windows ОС: path\\to\\file
Для Linux ОС: path/to/file
.. code-block:: python
from pyOpenRPA.Tools import CrossOS
lPathStr = CrossOS.PathJoinList(inList = ['path', 'to', 'file'] )
# WINDOWS: lPathStr == 'path\\to\\file'
# LINUX: lPathStr == 'path/to/file'
:param inList: Строка, которую обработать в зависимости от ОС, на которой происходит выполнение
:type inList: str
:return: Массив элементов пути. Пример: ['path', 'to', 'file']
:rtype: list
"""
if IS_LINUX_BOOL: return "/".join(inList)
elif IS_WINDOWS_BOOL: return "\\".join(inList)

@ -285,7 +285,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
if not lAuthenticateDict["User"]: if not lAuthenticateDict["User"]:
lFlagAccessUserBlock=True lFlagAccessUserBlock=True
# Logging # Logging
gSettingsDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}") gSettingsDict["Logger"].info(f"HTTP запросот пользователя: Домен: {lAuthenticateDict['Domain']}, Логин: {lAuthenticateDict['User']}")
if lFlagAccessUserBlock: if lFlagAccessUserBlock:
AuthenticateBlock(self) AuthenticateBlock(self)
##################################### #####################################
@ -389,7 +389,7 @@ class RobotDaemonServer(Thread):
server_address = (inServerAddress, inPort) server_address = (inServerAddress, inPort)
#httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# Logging # Logging
gSettingsDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") gSettingsDict["Logger"].info(f"Сервер:: Слушает сетевую карту: {inServerAddress}, Слушает порт: {inPort}")
#httpd.serve_forever() #httpd.serve_forever()
httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler)
#print('Starting server, use <Ctrl-C> to stop') #print('Starting server, use <Ctrl-C> to stop')

@ -26,7 +26,7 @@ def Init(inLogger=None):
gIsSignalCloseBool = False # Init default gIsSignalCloseBool = False # Init default
gLogger = inLogger gLogger = inLogger
import threading import threading
if gLogger: gLogger.info(f"StopSafe: Init termination catch thread") if gLogger: gLogger.info(f"Безопасная остановка: получен сигнал безопасной остановки")
shutdown_thread = threading.Thread(target=_shutdown_monitor) shutdown_thread = threading.Thread(target=_shutdown_monitor)
shutdown_thread.start() shutdown_thread.start()
#shutdown_thread.join() #shutdown_thread.join()
@ -62,5 +62,5 @@ def _shutdown_monitor():
win32gui.PumpMessages() win32gui.PumpMessages()
gIsSignalCloseBool = True # WM_CLOSE message has come gIsSignalCloseBool = True # WM_CLOSE message has come
if gLogger: if gLogger:
gLogger.info(f"StopSafe: Program has catch VM_CLOSE signal - do safe exit") gLogger.info(f"Безопасная остановка: Получен сигнал безопасной остановки (VM_CLOSE) - выполнить остановку")

@ -0,0 +1,139 @@
import jinja2
from pyOpenRPA.Tools import CrossOS
class Render():
"""L+,W+: Класс генерации текста по шаблонам Jinja2
.. code-block:: python
# Пример использования
from pyOpenRPA.Utils.Render import Render
lRender = Render(inTemplatePathStr="test.txt", inTemplateRefreshBool = True)
lRender.Generate()
.. code-block:: html
Hello my control panel!
You can use any def from Orchestrator module here in Jinja2 HTML template:
Example: OrchestratorModule.OSCMD(inCMDStr="notepad")
{{MathModule.pi}} # Обратиться к переменной
{% if UserInfoDict['UserNameUpperStr']=="ND" %}
YES - IT IS ND
{% endif %}
{% include 'test2.txt' %} # Добавить содержимого другого файла. Подняться выше нельзя через ..
"""
# Jinja2 consolidated
mTemplateRefreshBool = None
mDataDict = None
# RefreshHTML block
mTemplatePathStr = None
mTemplateFileNameStr = None
mLoader = None
mEnv = None
mTemplate = None
mLogger = None
def __init__(self, inTemplatePathStr = None, inTemplateRefreshBool = False, inLogger = None):
"""L+,W+: Инициализация объекта генерации текста из шаблона Jinja2
.. code-block:: python
# Пример использования
from pyOpenRPA.Utils.Render import Render
lRender = Render(inTemplatePathStr="test.txt", inTemplateRefreshBool = True)
:param inTemplatePathStr: Путь к шаблону в формате Jinja2
:type inTemplatePathStr: str
:param inTemplateRefreshBool: True - читать шаблон Jinja2 при каждом выхове функции Generate()
:type inTemplateRefreshBool: bool
:param inLogger: Экземпляр логгера
:type inLogger: logging.Logger
:return: self
:rtype: pyOpenRPA.Utils.Render.Render
"""
self.mLogger = inLogger
self.TemplatePathSet(inTemplatePathStr = inTemplatePathStr)
self.mTemplateRefreshBool = inTemplateRefreshBool
def DataSet(self, inDataDict):
"""L+,W+: Установить словарь данных, передаваемый в шаблонизатор. Функция полезна для фиксации тех данных, которые не изменяются при каждом вызове функции Generate. Если такие данные изменяются каждый раз, то передавать их можно через функцию Generate
.. code-block:: python
# Пример использования
from pyOpenRPA.Utils.Render import Render
lRender = Render(inTemplatePathStr="test.txt", inTemplateRefreshBool = True)
lRender.DataSet(inDataDict={"key1":"value1"})
lRender.Generate()
:param inDataDict: Словарь данных, который отправляется в шаблон Jinja2 при генерации
:type inDataDict: str
:return: None
"""
self.mDataDict = inDataDict
def TemplatePathSet(self, inTemplatePathStr, inLogger = None):
"""L+,W+: Установить шаблон формата Jinja2, из которого формировать готовый текст
.. code-block:: python
# Пример использования
from pyOpenRPA.Utils.Render import Render
lRender = Render(inTemplatePathStr="test.txt")
lRender.TemplatePathSet(inDataDict={"key1":"value1"})
lRender.Generate()
:param inTemplatePathStr: Путь к шаблону в формате Jinja2
:type inTemplatePathStr: str
:param inLogger: Экземпляр логгера
:type inLogger: logging.Logger
:return:
"""
try:
if inTemplatePathStr is not None:
lSystemLoaderPathStr = "/".join(CrossOS.PathSplitList(inPathStr=inTemplatePathStr)[0:-1])
lTemplateFileNameStr = CrossOS.PathSplitList(inPathStr=inTemplatePathStr)[-1]
self.mTemplateFileNameStr = lTemplateFileNameStr
self.mLoader = jinja2.FileSystemLoader(lSystemLoaderPathStr)
self.mEnv = jinja2.Environment(loader=self.mLoader, trim_blocks=True)
self.mTemplate = self.mEnv.get_template(lTemplateFileNameStr)
except Exception as e:
self._LogException(inStr = "ОШИБКА ПРИ УСТАНОВКЕ ШАБЛОНА JINJA2", inLogger = inLogger, inException=e)
def Generate(self, inDataDict=None, inLogger = None) -> str:
"""L+,W+: Сформировать текст из шаблона Jinja2. Pass the context inDataDict
.. code-block:: python
# Пример использования
from pyOpenRPA.Utils.Render import Render
lRender = Render(inTemplatePathStr="test.txt", inTemplateRefreshBool = True)
lRender.Generate()
:param inDataDict: Словарь для передачи в шаблонизатор
:type inDataDict: dict
:param inLogger: Экземпляр логгера
:type inLogger: logging.Logger
:return: Текст, сформированный шаблонизатором Jinja2
:rtype: str
"""
try:
if self.mTemplateRefreshBool == True:
self.mTemplate = self.mEnv.get_template(self.mTemplateFileNameStr)
if self.mDataDict is not None: lDataDict = self.mDataDict
elif inDataDict is not None: lDataDict = inDataDict
else: lDataDict = {}
if self.mDataDict is not None and inDataDict is not None: lDataDict.update(inDataDict)
lStr = self.mTemplate.render(**lDataDict) # Render the template into str
return lStr
except Exception as e:
self._LogException(inStr="ОШИБКА ПРИ ГЕНЕРАЦИИ ТЕКСТА ИЗ ШАБЛОНА JINJA2", inLogger=inLogger)
# LOGGING HANDLERS
def _LogException(self, inStr, inLogger = None, inException = None):
if inLogger is not None: inLogger.exception(inStr)
elif self.mLogger is not None: self.mLogger.exception(inStr)
else: raise inException

@ -3,7 +3,7 @@ r"""
The pyOpenRPA package The pyOpenRPA package
""" """
__version__ = 'v1.2.14' __version__ = 'v1.3.0'
__all__ = [] __all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@pyopenrpa.ru>' __author__ = 'Ivan Maslov <ivan.maslov@pyopenrpa.ru>'
#from .Core import Robot #from .Core import Robot

@ -1,7 +1,7 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: pyOpenRPA Name: pyOpenRPA
Version: 1.2.14 Version: 1.3.0
Summary: First open source RPA platform for business Summary: The powerful open source RPA platform for business
Home-page: https://pyopenrpa.ru/ Home-page: https://pyopenrpa.ru/
Author: Ivan Maslov Author: Ivan Maslov
Author-email: Ivan.Maslov@pyopenrpa.ru Author-email: Ivan.Maslov@pyopenrpa.ru

@ -1,13 +1,13 @@
pyOpenRPA-1.2.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 pyOpenRPA-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.2.14.dist-info/METADATA,sha256=msxiHoe4JlRNqXnlKGZWthHNr5JPV7OWXJzgXwzZTcc,4372 pyOpenRPA-1.3.0.dist-info/METADATA,sha256=V-qwlFCJ26LQShABSS0p5Tm9vxOXMYqrahL40zkthnI,4378
pyOpenRPA-1.2.14.dist-info/RECORD,, pyOpenRPA-1.3.0.dist-info/RECORD,,
pyOpenRPA-1.2.14.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA-1.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.2.14.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 pyOpenRPA-1.3.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.2.14.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA-1.3.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
pyOpenRPA/Agent/A2O.py,sha256=PlIZZCTnVrYF2i6DSAi_KbzZfc2gtcBPmOerrEZq68U,1718 pyOpenRPA/Agent/A2O.py,sha256=PlIZZCTnVrYF2i6DSAi_KbzZfc2gtcBPmOerrEZq68U,1718
pyOpenRPA/Agent/O2A.py,sha256=XHl5nytUoUqfPvmYWh5auYo-s0GIThNmkOA9ON-JCis,5535 pyOpenRPA/Agent/O2A.py,sha256=o-5JF-415L69-vCg0COzK79sWs4btJwOkt53pqVhu0U,6210
pyOpenRPA/Agent/Processor.py,sha256=xNZfQ_HcV-qm_x90tBLKYJqvnENiTqHSoUk2LhDfqWQ,6346 pyOpenRPA/Agent/Processor.py,sha256=xNZfQ_HcV-qm_x90tBLKYJqvnENiTqHSoUk2LhDfqWQ,6346
pyOpenRPA/Agent/__Agent__.py,sha256=gqKxqu9XEEdgLNRvAlaGqDaQR2sgn_n_Vskf8dv2cQo,12692 pyOpenRPA/Agent/__Agent__.py,sha256=rUvtEGEmlsd3ZujkQnPhL3mGaALmM2iNvfWBoF0Puc4,15167
pyOpenRPA/Agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Agent/__pycache__/A2O.cpython-37.pyc,, pyOpenRPA/Agent/__pycache__/A2O.cpython-37.pyc,,
pyOpenRPA/Agent/__pycache__/O2A.cpython-37.pyc,, pyOpenRPA/Agent/__pycache__/O2A.cpython-37.pyc,,
@ -17,18 +17,18 @@ pyOpenRPA/Agent/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Agent/readme.md,sha256=QF_Bnv204OK3t1JUEhjfICkxFmSdX6bvaRl_HI6lH9I,19 pyOpenRPA/Agent/readme.md,sha256=QF_Bnv204OK3t1JUEhjfICkxFmSdX6bvaRl_HI6lH9I,19
pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85 pyOpenRPA/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
pyOpenRPA/LICENSE.pdf,sha256=8L-9X_kCCt8yWvjy0E_xV-C6Im79hZnH7WcfZHRz8uM,4322139 pyOpenRPA/LICENSE.pdf,sha256=8L-9X_kCCt8yWvjy0E_xV-C6Im79hZnH7WcfZHRz8uM,4322139
pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=ymWcw6ZKg6-sSiykQK8iolhBjK2amTyQx7u8QKPnewc,37947 pyOpenRPA/Orchestrator/BackwardCompatibility.py,sha256=IqVZygd8ab9X1gBfP7WImQrYqKy8snCSbThqrvdT5f0,39633
pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103 pyOpenRPA/Orchestrator/ControlPanel.py,sha256=OzS8HjG__8OZgqhajr8L8owyugXPuSLWHLtXuKdEP78,103
pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529 pyOpenRPA/Orchestrator/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=nBJqwBd6y9yeE49XOn83r8Dtvb3yReujrp-frxOhNL8,16671 pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=PZzh_RUke8bIMGghCXTnEuTYICCwW71r2xXk7iTdUnU,17345
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582 pyOpenRPA/Orchestrator/Managers/Git.py,sha256=VCXXc-enJhvrAJvYc8jHK9GcGe02meMdszU0tlJDHiQ,12879
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377 pyOpenRPA/Orchestrator/Managers/Process.py,sha256=4LJNMrt61AJKI3p7SeXnUSEpA61BtqWVxaVYxYS_BaI,42221
pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71 pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71
pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Process.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/Process.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/Managers/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Processor.py,sha256=FtNmdIsBStkLHLlOe6MDWzSmZv9m7ntlQs-NirA6OgQ,10264 pyOpenRPA/Orchestrator/Processor.py,sha256=WXA_OC8tWVU-R8dsYR6O7-griwcxn6HH27qRs3GWnoU,10368
pyOpenRPA/Orchestrator/ProcessorOld.py,sha256=Vh5zLRpWWf-vt9CCYI8nDY7oaefiufnu6Pnl4tp27pY,13749 pyOpenRPA/Orchestrator/ProcessorOld.py,sha256=Vh5zLRpWWf-vt9CCYI8nDY7oaefiufnu6Pnl4tp27pY,13749
pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531 pyOpenRPA/Orchestrator/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=GQCB1NElDCsJ8e9CKs9ivi91BjQVBSPL4Uqt9DTFn2A,1976 pyOpenRPA/Orchestrator/RobotRDPActive/Clipboard.py,sha256=GQCB1NElDCsJ8e9CKs9ivi91BjQVBSPL4Uqt9DTFn2A,1976
@ -36,7 +36,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/Connector.py,sha256=hvuXDlmcacN6GqBuICWJcu
pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657 pyOpenRPA/Orchestrator/RobotRDPActive/ConnectorExceptions.py,sha256=wwH9JOoMFFxDKQ7IyNyh1OkFkZ23o1cD8Jm3n31ycII,657
pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405 pyOpenRPA/Orchestrator/RobotRDPActive/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405
pyOpenRPA/Orchestrator/RobotRDPActive/Recovery.py,sha256=jneD474V-ZBYnmQFxWoY_feGNMSL0lGaRK6TEfQ6gOc,2954 pyOpenRPA/Orchestrator/RobotRDPActive/Recovery.py,sha256=jneD474V-ZBYnmQFxWoY_feGNMSL0lGaRK6TEfQ6gOc,2954
pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=5FX48HlIn8NKfs7q_rp3lpumWtNcwdHq7J8ygnOwU_g,12284 pyOpenRPA/Orchestrator/RobotRDPActive/RobotRDPActive.py,sha256=LQexk8eb4YOa8A51XwyZdng3AzLadgHNAgJfW2OAF0E,13065
pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144 pyOpenRPA/Orchestrator/RobotRDPActive/Scheduler.py,sha256=21N0ilFzWI1mj3X5S9tPMgwvG7BviuBxfTuqBY85Hy4,9144
pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462 pyOpenRPA/Orchestrator/RobotRDPActive/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462
pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077 pyOpenRPA/Orchestrator/RobotRDPActive/Timer.py,sha256=y8--fUvg10qEFomecl_cmdWpdGjarZBlFpMbs_GvzoQ,1077
@ -54,7 +54,7 @@ pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/Timer.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotRDPActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114 pyOpenRPA/Orchestrator/RobotScreenActive/ConsoleStart.bat,sha256=_HNadUKHOYI5y6foG3srh8wjSzhX33xaKNylFtDjOJk,114
pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py,sha256=YjS23qinMk_2z47MGRVSDxbvsUMImnhqLi1F4BqW2OE,602 pyOpenRPA/Orchestrator/RobotScreenActive/Monitor.py,sha256=GQt40zD9X0R4RPaa2Cnbn-17oR2gUZvRGk3T3uGdKuY,603
pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606 pyOpenRPA/Orchestrator/RobotScreenActive/Screen.py,sha256=VnYcvCVymrD35l2J4ln_tlVn7CilZhxE4Ggw9P-OhIw,606
pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Orchestrator/RobotScreenActive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593 pyOpenRPA/Orchestrator/RobotScreenActive/__main__.py,sha256=JASxDDVKWUU7DAbDkRrGTrPk-P7LZchTZFh8usp6b4U,593
@ -62,9 +62,9 @@ pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Monitor.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/Screen.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=YOQgZQ97nM_XQYVRbusj_b50aqEiNBJFF3bs7wA-O6k,36240 pyOpenRPA/Orchestrator/Server.py,sha256=eYiXKvWsiBG_kfHtzdNX4Zu2xL2DjkJZXqBfqOgHAk4,38600
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=260YPXINLrora8pBBVHQSPNBkc8wdlyadsoQTQKdpAs,32590 pyOpenRPA/Orchestrator/ServerSettings.py,sha256=wZe5aEUJOWYol8WzKUQBRq9JEnXj0Z39554PAIoqvbw,34326
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=TR6WQVm-0sFoQjnV08t9K5oQOcpC7dbKOnWQS31m9dQ,21443 pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=dVL-JZpAUQP3LLXE_7IUuE7RkLTYBAA-RX4e5FZ_DU0,21499
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097 pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681 pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681
pyOpenRPA/Orchestrator/Utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Orchestrator/Utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@ -75,7 +75,7 @@ pyOpenRPA/Orchestrator/Web/Index.js,sha256=YACiZAvjr6NmFlDhQu6urkJp49BX7L8WJU9p-
pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257 pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=5JUAs5rEiU0XtHM9QO6EdNMBGt-W6QOVGY7xJ_HLPFM,19257
pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,, pyOpenRPA/Orchestrator/Web/__pycache__/Basic.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 pyOpenRPA/Orchestrator/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=C0gVOwB3bYRJMALXLPLdkHw0wobQBly5_G7pLWBjGcg,204085 pyOpenRPA/Orchestrator/__Orchestrator__.py,sha256=LmEhNQkdK5SEIqql0ZM9PrjKgQ4-aQOiOheX83GbqmQ,207494
pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207 pyOpenRPA/Orchestrator/__init__.py,sha256=nJhjYtBXKOUNX_yNu1rRFk5y9cDz6AFiL0M6KgX_utQ,207
pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273 pyOpenRPA/Orchestrator/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273
pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,, pyOpenRPA/Orchestrator/__pycache__/BackwardCompatibility.cpython-37.pyc,,
@ -263,7 +263,46 @@ pyOpenRPA/Resources/Web/Semantic-UI-CSS-master/themes/default/assets/fonts/outli
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/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/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/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899 pyOpenRPA/Resources/Web/orpa/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
pyOpenRPA/Resources/Web/orpa/footer.xhtml,sha256=5aNthu2jsINqpgo_BS8UDbRWhA3rlRtlQZIILv_4hKo,3190
pyOpenRPA/Resources/Web/orpa/header.xhtml,sha256=pqVM-N53bz4_DzbG4PoN7B7N7XECZWZe12qVlc68ylk,3617
pyOpenRPA/Resources/Web/orpa/logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/Resources/Web/orpa/orc.js,sha256=qlzbbewXWDFbNhNHVVvMEYQFyQbRA7zEHoeaV38fJoQ,43558
pyOpenRPA/Resources/Web/orpa/orc.xhtml,sha256=x6NdMv6HrjUt0rZsz61dJeMl3DNte1KkEULQRkGfsJg,19098
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Bold.woff2,sha256=roj8DXqWGDL4CVJ9ML05g6aGbUL2alat4j9UNoFZTbY,184912
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Italic.woff2,sha256=RGV2Xy9u3c2tNP_XyrVZ5WvA515F4ZL4XpVisHcUgdw,195704
pyOpenRPA/Resources/Web/orpa/styleset/Lato-Regular.woff2,sha256=mDsMrzNuhUIhT8FwGaT8XgNghkuSgGyhTVXB_BwsWg8,182708
pyOpenRPA/Resources/Web/orpa/styleset/bg1.jpg,sha256=63vfRzL-rLY_hW634p8rFps-BKFUKK9O0e4zaeHFxKw,251041
pyOpenRPA/Resources/Web/orpa/styleset/bg10.jpg,sha256=ZY_Z27kqavsjccDUrqoURz71zvkk81hdYB7u8TPciwI,256648
pyOpenRPA/Resources/Web/orpa/styleset/bg2.jpg,sha256=UlHtxLzqoypCTm1d_cIO3UFDrpYFNmTfAUQr3RtADdo,249670
pyOpenRPA/Resources/Web/orpa/styleset/bg3.jpg,sha256=N5Lp18GyFzCSaDXfcPAwrtVfCW7uoNIOvRos0F-qryg,245168
pyOpenRPA/Resources/Web/orpa/styleset/bg4.jpg,sha256=nckyiY8IgPYYUcprl0kOGE7-RzFnik4uqfFZc5V7aU8,258568
pyOpenRPA/Resources/Web/orpa/styleset/bg5.jpg,sha256=9AeZLTygYTWTlyyFaHnQSkj50m7eZ6iTCb0xt8oe_xM,261562
pyOpenRPA/Resources/Web/orpa/styleset/bg6.jpg,sha256=SXF3wNssI2dEHnBOfTWjRijXWA-BMq9YXXixq8ajVNk,260686
pyOpenRPA/Resources/Web/orpa/styleset/bg7.jpg,sha256=tZ2LP0BKZCxZnxlTUCCmXUSvdReRKb0AyX6ea7hAe0k,261376
pyOpenRPA/Resources/Web/orpa/styleset/bg8.jpg,sha256=x3l1TJaepQnMkeRvkhjOp_g6tUSebqp2-AEUDM2QCkg,261288
pyOpenRPA/Resources/Web/orpa/styleset/bg9.jpg,sha256=cRfXuOGYv_DCKBGrh7-Js1NGmtdrZWgYxXW9pi8c5Wo,261559
pyOpenRPA/Resources/Web/orpa/styleset/docs.css,sha256=XmeLuUmo_tTGFSurYJPZgaBb_gD_nMZX1TCzqBbKz7k,55821
pyOpenRPA/Resources/Web/orpa/styleset/docs.css.bak,sha256=uDJOPZxwDDgBOhhy12G1hYIBvOm6nuYQCdw0BoyidII,55845
pyOpenRPA/Resources/Web/orpa/styleset/docs.js,sha256=6MvOXSzLAeQLjzUt7IkRLhOn0QE1xRYZRgQQhu6y3mQ,44749
pyOpenRPA/Resources/Web/orpa/styleset/dropdown.css,sha256=Gra8mTrxFli1BxnYTArvthaDUajJPbB2Yta5y86C1rA,37642
pyOpenRPA/Resources/Web/orpa/styleset/easing.min.js,sha256=lP963PCWRotqEmscc9mBLkieNsnZ1d9KCD4unl3ZpVU,3794
pyOpenRPA/Resources/Web/orpa/styleset/header.css,sha256=kZg2wcwEoerMGyaKa4aMoYPBbJNCmovrml4WoWpBvQc,13723
pyOpenRPA/Resources/Web/orpa/styleset/highlight.min.js,sha256=Z39RBsR8A-knGdSdh8Bs2h9uA6grKSb4OyVhkmv48uk,21964
pyOpenRPA/Resources/Web/orpa/styleset/home.css,sha256=rr3HRdvfuzkK2H46rChyyswywWEDnCpHcCQ7D_xuQRU,16245
pyOpenRPA/Resources/Web/orpa/styleset/home.js,sha256=e65zKntsXHUK0DORA6gaoTlom0fsF4p8Unh74UsA85s,8926
pyOpenRPA/Resources/Web/orpa/styleset/jquery.min.js,sha256=3ks8PR3CUGtmk_D5iITh3AdM2p1myrObe0ihFf38TA8,84349
pyOpenRPA/Resources/Web/orpa/styleset/less.min.js,sha256=lqonJQsjeXmDk-iZDpqlyAO5tzY5F93xFP-eUIdTUZM,136781
pyOpenRPA/Resources/Web/orpa/styleset/metadata.json,sha256=RBNvo1WzZ4oRRq0W9-hknpT7T8If536DEMBg9hyq_4o,2
pyOpenRPA/Resources/Web/orpa/styleset/nan.jpg,sha256=oZRYv31pGnf65BGA3fTzQ-HV8ulj7VoT-hB4nFVG3lc,23839
pyOpenRPA/Resources/Web/orpa/styleset/ogImage.JPG,sha256=-WVra6DU8SusAWtJWR6fEEROlJE_UxlOAodO7G82E3U,242713
pyOpenRPA/Resources/Web/orpa/styleset/ogImage.PNG,sha256=7-C8f1hHBHUPi_Y6gscUK04S3qso8lywT7KGCCYSMBM,131928
pyOpenRPA/Resources/Web/orpa/styleset/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/Resources/Web/orpa/styleset/segment.css,sha256=wzmuVZPMT1Y1Ymn52U8WQLiqmo7zNvwcXOVYr6ePfts,20287
pyOpenRPA/Resources/Web/orpa/styleset/sidebar.js,sha256=fnype3guWOx0kmyP7rL2I0mkyMR1_V9u8u2_W5E_4vk,34482
pyOpenRPA/Resources/Web/orpa/styleset/transition.js,sha256=esNkWoCwl6ksZewJkNDMLKCE4nDTdJZDJW3tdE7dlAo,36070
pyOpenRPA/Resources/Web/orpa/styleset/visibility.js,sha256=ulme0GrsuqHAHXTQunq96J0mESTl6Lux8msdK1_fcm4,44174
pyOpenRPA/Resources/Web/orpa/styleset/white-image.png,sha256=D7WJFGDtAIp_OXUU6Tz4zeYm_1yHRd8u7aTu0F35Kcw,5951
pyOpenRPA/Robot/Clipboard.py,sha256=QXClSH1ccCl8KfKbMY1Wk_SynEgfDZqZ_0h-OZYn4kA,1962 pyOpenRPA/Robot/Clipboard.py,sha256=QXClSH1ccCl8KfKbMY1Wk_SynEgfDZqZ_0h-OZYn4kA,1962
pyOpenRPA/Robot/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071 pyOpenRPA/Robot/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071
pyOpenRPA/Robot/Mouse.py,sha256=R-2q5Q-nDhvvQjcQxFz8FRM9tHjhPUKdnK3KuPc_OZw,16361 pyOpenRPA/Robot/Mouse.py,sha256=R-2q5Q-nDhvvQjcQxFz8FRM9tHjhPUKdnK3KuPc_OZw,16361
@ -273,7 +312,7 @@ pyOpenRPA/Robot/Screen.py,sha256=nH80ghKw7OseNF_fVwfUrih0y9o1Ul2VPEl_WT5b598,454
pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453
pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
pyOpenRPA/Robot/UIDesktop.py,sha256=WLy8wUVDFSUN5S7hXUjijQIH0B71c5tj-pBCVex7uFc,125314 pyOpenRPA/Robot/UIDesktop.py,sha256=WLy8wUVDFSUN5S7hXUjijQIH0B71c5tj-pBCVex7uFc,125314
pyOpenRPA/Robot/UIWeb.py,sha256=AaAuX32i8nzTlXORp-l6rCp383JCX28TmJO7iyrqF1c,32351 pyOpenRPA/Robot/UIWeb.py,sha256=c3VA8IG2ELuGaWskyFFCbJalBKdDON2sjWhvHjR-2Dk,32353
pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890
pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591
pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039 pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039
@ -304,7 +343,7 @@ pyOpenRPA/Robot/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347 pyOpenRPA/Studio/JSONNormalize.py,sha256=g0Z8G2wojCgTAdZtyRiCfe0_FHSeAi72Va7R7mk27gg,3347
pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912 pyOpenRPA/Studio/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038 pyOpenRPA/Studio/RobotConnector.py,sha256=CYO0dQoqfs44SYD_VZ_TJh3WFu_DXigHBLHj4GJ2Icc,5038
pyOpenRPA/Studio/Studio.py,sha256=RYwjb7KKEK2EgGz4lb95IQXvKk0-QACObBxoMh2IEFE,8689 pyOpenRPA/Studio/Studio.py,sha256=6He68tum4IyMSOv9VXsH2hmvMDnnCf4CDI66L7Wpl_Q,8739
pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777 pyOpenRPA/Studio/ValueVerify.py,sha256=ObskxU4fOMoCGw74_nzYt6-a5jjrAckb3sdBLYyhYxY,777
pyOpenRPA/Studio/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119 pyOpenRPA/Studio/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119
pyOpenRPA/Studio/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922 pyOpenRPA/Studio/Web/favicon.ico,sha256=6S8XwSQ_3FXPpaX6zYkf8uUewVXO9bHnrrDHEoWrEgw,112922
@ -317,13 +356,13 @@ pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/CrossOS.py,sha256=smXZ_DSx1YwLt9aUor0se51sEIkUhm2BicfoxU6qVl8,2569 pyOpenRPA/Tools/CrossOS.py,sha256=6yq7cit6dgs0KCk6zknoy699r7a3gC0UrnYYe-ZrobM,3539
pyOpenRPA/Tools/Debugger.py,sha256=2slOSaPnUAwfDlyjhaqqhhchXUBgEKQImTzXagJt4Jw,535 pyOpenRPA/Tools/Debugger.py,sha256=2slOSaPnUAwfDlyjhaqqhhchXUBgEKQImTzXagJt4Jw,535
pyOpenRPA/Tools/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378 pyOpenRPA/Tools/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473 pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655 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/Server.py,sha256=idGpXDU9rPv-NZcOW1Wrku_acEqEYnhSXNtUmFTs1dU,20019
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -351,7 +390,7 @@ pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/StopSafe.py,sha256=BNTtMmvsRE1Wtri3EkwhoBi6gGOjEPRQnJSV1C03c84,2176 pyOpenRPA/Tools/StopSafe.py,sha256=BIMiW8cFyQfX3KpRHaspdbw6-FcImTilqXRC_XXzyik,2346
pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490 pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490
pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996 pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996
pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@ -362,6 +401,7 @@ pyOpenRPA/Tools/__pycache__/StopSafe.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/Template.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Template.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/Usage.cpython-37.pyc,,
pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=ZYKWkmhslD3FNo1wNQ-nV3i7qwvmOgf85JgP1u5glgI,156 pyOpenRPA/Utils/Render.py,sha256=VCU5cCCwyCFvMmRQwq7MGllgqzeDAp_s8om3UChIoPk,6703
pyOpenRPA/Utils/__pycache__/Render.cpython-37.pyc,,
pyOpenRPA/__init__.py,sha256=adiLDsNcgYHaK1h_sStFVU0UEQpYGgFRvPiLmmrtvnU,155
pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/test.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

@ -53,27 +53,27 @@ def O2A_Loop(inGSettings):
# Log full version if bytes size is less than limit . else short # Log full version if bytes size is less than limit . else short
lAgentLimitLogSizeBytesInt = 500 lAgentLimitLogSizeBytesInt = 500
if lBodyLenInt <= lAgentLimitLogSizeBytesInt: if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"ActivityItem from orchestrator: {lQueueItem}"); if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: {lQueueItem}")
else: else:
if lL: lL.info(f"ActivityItem from orchestrator: Supressed - big size. Size is {lBodyLenInt} bytes"); if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: содержимое свернуто из-за большого размера ({lBodyLenInt} байт")
else: else:
if lL: lL.debug(f"Empty response from the orchestrator - loop when refresh the connection between Orc and Agent"); if lL: lL.debug(f"Поступил пустой ответ от оркестратора - цикл попытается обновить соединение между оркестратором и агентом");
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
if time.time() - lCEPhaseFastTimeLastGoodFloat <= lCEPhaseFastDurationSecFloat: if time.time() - lCEPhaseFastTimeLastGoodFloat <= lCEPhaseFastDurationSecFloat:
if lL: lL.error(f"O2A Connection error - orchestrator is not available. Sleep for {lCEPhaseFastRetrySecFloat} s.") if lL: lL.error(f"О2А Ошибка соединения - оркестратор недоступен. Повторить попытку через {lCEPhaseFastRetrySecFloat} с.")
time.sleep(lCEPhaseFastRetrySecFloat) time.sleep(lCEPhaseFastRetrySecFloat)
else: else:
if lL: lL.error(f"O2A Connection error - orchestrator is not available. Sleep for {lCEPhaseLongRetrySecFloat} s.") if lL: lL.error(f"О2А Ошибка соединения - оркестратор недоступен. Повторить попытку через {lCEPhaseLongRetrySecFloat} с.")
time.sleep(lCEPhaseLongRetrySecFloat) time.sleep(lCEPhaseLongRetrySecFloat)
except ConnectionResetError as e: except ConnectionResetError as e:
if lL: lL.error(f"O2A Connection reset error - orchestrator is not available. Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.error(f"О2А Ошибка сброса соединения - оркестратор недоступен. Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except json.decoder.JSONDecodeError as e: except json.decoder.JSONDecodeError as e:
if lL: lL.error(f"O2A JSON decode error - See body of the recieved content from the Orchestrator: {lRequestBody}") if lL: lL.error(f"О2А Ошибка декодирования JSON - далее представлено содержимое, которое поступило на обработку: {lRequestBody}")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except requests.exceptions.Timeout as e: except requests.exceptions.Timeout as e:
if lL: lL.exception(f"O2A requests timeout error (no response for long time). Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.exception(f"О2А Ошибка соединения (превышено время ожидания). Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])
except Exception as e: except Exception as e:
if lL: lL.exception(f"O2A Error handler. Sleep for {inGSettings['O2ADict']['RetryTimeoutSecFloat']} s.") if lL: lL.exception(f"О2А Общая ошибка. Повторить попытку через {inGSettings['O2ADict']['RetryTimeoutSecFloat']} с.")
time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"]) time.sleep(inGSettings["O2ADict"]["RetryTimeoutSecFloat"])

@ -3,66 +3,69 @@ from . import O2A, A2O # Data flow Orchestrator To Agent
from . import Processor # Processor Queue from . import Processor # Processor Queue
from ..Tools import Usage from ..Tools import Usage
from ..Tools import License from ..Tools import License
from subprocess import CREATE_NEW_CONSOLE # Flag to create new process in another CMD from pyOpenRPA.Tools import CrossOS
if CrossOS.IS_WINDOWS_BOOL: from subprocess import CREATE_NEW_CONSOLE # Flag to create new process in another CMD
if CrossOS.IS_LINUX_BOOL: pass
import os import os
gSettings = None gSettings = None
# Create binary file by the base64 string (safe for JSON transmition) # Create binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None): def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None):
""" """L+,W+: Создать бинарный файл на стороне Агента по полученной строке в формате base64 (формат безопасен для передачи по JSON протоколу)
Create binary file by the base64 string (safe for JSON transmition)
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "wb") lFile = open(inFilePathStr, "wb")
lFile.write(base64.b64decode(inFileDataBase64Str)) lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Binary file {inFilePathStr} has been created." lMessageStr = f"АГЕНТ: бинарный файл {inFilePathStr} создан успешно"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Append binary file by the base64 string (safe for JSON transmition) # Append binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None): def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None):
""" """L+,W+: Create binary file by the base64 string (safe for JSON transmition)
Create binary file by the base64 string (safe for JSON transmition)
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "ab") lFile = open(inFilePathStr, "ab")
lFile.write(base64.b64decode(inFileDataBase64Str)) lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Binary file {inFilePathStr} has been appended." lMessageStr = f"АГЕНТ: Данные успешно добавлены в бинарный файл {inFilePathStr}"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Create text file by the string # Create text file by the string
def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None): def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None):
""" """L+,W+:Создать текстовый файл на стороне Агента
Create text file in the agent GUI session
:param inFilePathStr: File abs path :param inFilePathStr: Абсолютный путь к создаваемому файлу
:param inFileDataStr: File data text content :param inFileDataStr: Текст, отправляемый в создаваемый файл
:param inEncodingStr: Write file encoding :param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный файл настроек
:return: :return:
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "w", encoding=inEncodingStr) lFile = open(inFilePathStr, "w", encoding=inEncodingStr)
lFile.write(inFileDataStr) lFile.write(inFileDataStr)
lFile.close() lFile.close()
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lMessageStr = f"AGENT Text file {inFilePathStr} has been created." lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} успешно создан"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None): def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
""" """L+,W+: Прочитать бинарный файл на стороне агента и отправить на сторону оркестратора в формате base64 (формат безопасный для передачи в формате JSON)
Read binary file and encode in base64 to transmit (safe for JSON transmition)
:param inFilePathStr: File path to read :param inFilePathStr: Абсолютный путь к читаемому файлу
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный словарь настроек Агента (необязательный)
:return: File content in string base64 format (use base64.b64decode to decode data). Return None if file is not exist :return: Содержимое бинарного файле, преобразованное в формат base64 (используй base64.b64decode для декодирования в байты). Вернет None запрашиваемый файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lFileDataBase64Str = None lFileDataBase64Str = None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
@ -70,56 +73,55 @@ def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
lFileDataBytes = lFile.read() lFileDataBytes = lFile.read()
lFile.close() lFile.close()
lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8") lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8")
lMessageStr = f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} has been read" lMessageStr = f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} прочитан успешно"
if lL: lL.debug(lMessageStr) if lL: lL.debug(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) #A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else: else:
if lL: lL.debug(f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} is not exists - return None") if lL: lL.debug(f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} не существует - отправить None")
return lFileDataBase64Str return lFileDataBase64Str
def OSFileMTimeGet(inFilePathStr: str) -> float or None: def OSFileMTimeGet(inFilePathStr: str) -> float or None:
""" """L+,W+: Read file modification time timestamp format (float)
Read file modification time timestamp format (float)
:param inFilePathStr: File path to read :param inFilePathStr: Абсолютный путь к файлу, дату которого требуется получить
:return: timestamp (float) Return None if file is not exist :return: Временной слепок (timestamp) в формате float. Вернет None, если запрашиваемый файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
global gSettings global gSettings
lL = gSettings.get("Logger", None) if type(gSettings) is dict else None lL = gSettings.get("Logger", None) if type(gSettings) is dict else None
lFileMTimeFloat = None lFileMTimeFloat = None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
lFileMTimeFloat = os.path.getmtime(inFilePathStr) lFileMTimeFloat = os.path.getmtime(inFilePathStr)
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} has been read") if lL: lL.debug(f"Функция OSFileMTimeGet: файл {inFilePathStr} прочитан успешно")
else: else:
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} is not exists - return None") if lL: lL.debug(f"Функция OSFileMTimeGet: file {inFilePathStr} не существует - вернуть None")
return lFileMTimeFloat return lFileMTimeFloat
def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None): def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None):
""" """L+,W+: Прочитать текстовый файл на стороне агента и отправить на сторону оркестратора
Read text file in the agent GUI session
:param inFilePathStr: File abs path :param inFilePathStr: Абсолютный путь к читаемому файлу
:param inEncodingStr: Read file encoding. Default utf-8 :param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: global settings of the Agent (singleton) :param inGSettings: Глобальный словарь настроек
:return: File text content in string format (use base64.b64decode to decode data). Return None if file is not exist :return: Строка - содержимое текстового файла. Возвращает None, если файл не существует
""" """
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFileDataStr = None lFileDataStr = None
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
if os.path.exists(inFilePathStr): if os.path.exists(inFilePathStr):
lFile = open(inFilePathStr, "r", encoding=inEncodingStr) lFile = open(inFilePathStr, "r", encoding=inEncodingStr)
lFileDataStr = lFile.read() lFileDataStr = lFile.read()
lFile.close() lFile.close()
lMessageStr = f"OSFileTextDataStrReceive: file {inFilePathStr} has been read" lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} прочитан успешно"
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) #A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else: else:
if lL: lL.info(f"OSFileTextDataStrReceive: file {inFilePathStr} is not exists - return None") if lL: lL.info(f"АГЕНТ: Текстовый файл {inFilePathStr} не существует - вернуть None")
return lFileDataStr return lFileDataStr
# Send CMD to OS. Result return to log + Orchestrator by the A2O connection # Send CMD to OS. Result return to log + Orchestrator by the A2O connection
def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrchestratorLogsBool = True, inCMDEncodingStr = "cp1251", inCaptureBool = True): def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrchestratorLogsBool = True, inCMDEncodingStr = "cp1251", inCaptureBool = True):
""" """L-,W+: Execute CMD on the Agent daemonic process
Execute CMD on the Agent daemonic process
:param inCMDStr: command to execute on the Agent session :param inCMDStr: command to execute on the Agent session
:param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution :param inRunAsyncBool: True - Agent processor don't wait execution; False - Agent processor wait cmd execution
@ -142,10 +144,13 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inCaptureBool == True: if inCaptureBool == True:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT) lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else: else:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None, if CrossOS.IS_WINDOWS_BOOL:
creationflags=CREATE_NEW_CONSOLE) lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None,
creationflags=CREATE_NEW_CONSOLE)
if CrossOS.IS_LINUX_BOOL:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=None, stderr=None)
lListenBool = True lListenBool = True
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been STARTED # # # # " lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия запущена # # # # "
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on! if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr])
@ -172,7 +177,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
time.sleep(2) time.sleep(2)
else: else:
lListenBool = False lListenBool = False
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been FINISHED # # # # " lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия завершена # # # # "
if lL: lL.info(lMessageStr) if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on! if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr]) A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
@ -181,7 +186,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inRunAsyncBool: if inRunAsyncBool:
lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool }) lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool })
lThread.start() lThread.start()
lResultStr="ActivityList has been started in async mode - no output is available here." lResultStr="Список ActivityList отправлен на исполнение в асинхронном режиме - захват текста недоступен"
else: else:
lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool) lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool)
#lCMDCode = "cmd /c " + inCMDStr #lCMDCode = "cmd /c " + inCMDStr
@ -191,11 +196,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
def ProcessWOExeUpperUserListGet(): def ProcessWOExeUpperUserListGet():
""" """L-,W+: Вернуть список процессов, запущенных под пользователем на стороне агента
Return the process list only for the current user (where Agent is running) without .EXE in upper case. Can use in ActivityItem from Orchestrator to Agent
:param inProcessNameWOExeList: :return: Список процессов в формате: ["NOTEPAD","..."] (без постфикса .exe и в верхнем регистре)
:return: list of the agent user process in upper case without .EXE. Example ["NOTEPAD","..."],
""" """
lUserNameStr = getpass.getuser() lUserNameStr = getpass.getuser()
@ -238,7 +241,7 @@ def Agent(inGSettings):
lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings}) lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings})
lProcessorThread.daemon = True # Run the thread in daemon mode. lProcessorThread.daemon = True # Run the thread in daemon mode.
lProcessorThread.start() # Start the thread execution. lProcessorThread.start() # Start the thread execution.
if lL: lL.info("Processor has been started (ProcessorDict)") #Logging if lL: lL.info("Модуль процессора pyOpenRPA был успешно запущен") #Logging
# Start thread to wait data from Orchestrator (O2A) # Start thread to wait data from Orchestrator (O2A)
lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings}) lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings})
@ -247,4 +250,4 @@ def Agent(inGSettings):
# Send log that Agent has been started # Send log that Agent has been started
A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Host: {inGSettings["AgentDict"]["HostNameUpperStr"]}, User: {inGSettings["AgentDict"]["UserUpperStr"]}, Agent has been started.']) A2O.LogListSend(inGSettings=inGSettings, inLogList=[f'Хост: {inGSettings["AgentDict"]["HostNameUpperStr"]}, Логин: {inGSettings["AgentDict"]["UserUpperStr"]}, Агент инициализирован успешно'])

@ -77,7 +77,7 @@ def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict):
} }
inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict
inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies
if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") if lL: lL.info(f"РДП сессия инициализирована. Идентификатор сессии:{lCookieSessionGUIDStr}")
return lCookieSessionGUIDStr return lCookieSessionGUIDStr
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
lCreateNewSessionBool = False # Flag to create new session structure lCreateNewSessionBool = False # Flag to create new session structure
@ -108,7 +108,7 @@ def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict):
if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]:
lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]
if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key 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") if lL: lL.debug(f"Время жизни HTTP запроса истекло - удалить из отслеживаемых!")
lDoWhileBool = False # Stop the iterations lDoWhileBool = False # Stop the iterations
if lDoWhileBool: if lDoWhileBool:
TechnicalCheck() # Calculate the CP TechnicalCheck() # Calculate the CP
@ -277,7 +277,7 @@ def v1_2_0_ProcessorOld2NewActivityDict(inActivityOld):
"ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList) "ArgLogger": "inLogger" # Name of GSettings attribute: str (ArgDict) or index (for ArgList)
} }
else: else:
raise Exception(f"BackwardCompatibility up to v1.2.0, old processor: No type {inActivityOld['Type']} has been found in old processor.") raise Exception(f"Обратная совместимость до v1.2.0, старый процессор: Тип {inActivityOld['Type']} был обнаружен в старом процессоре")
return lResult # return the result return lResult # return the result
@ -295,7 +295,7 @@ def Update(inGSettings):
inGSettings["Autocleaner"] = { # Some gurbage is collecting in g settings. So you can configure autocleaner to periodically clear gSettings inGSettings["Autocleaner"] = { # Some gurbage is collecting in g settings. So you can configure autocleaner to periodically clear gSettings
"IntervalSecFloat": 7200.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 lL: lL.warning(f"Обратная совместимость (от v1.1.13 до v1.1.14): Добавить 'Autocleaner' структуру") # Log about compatibility
if "Client" not in inGSettings: # Add "Client" structure if "Client" not in inGSettings: # Add "Client" structure
inGSettings["Client"] = { # Settings about client web orchestrator inGSettings["Client"] = { # Settings about client web orchestrator
"Session":{ # Settings about web session. Session algorythms works only for special requests (URL in ServerSettings) "Session":{ # Settings about web session. Session algorythms works only for special requests (URL in ServerSettings)
@ -318,14 +318,14 @@ 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 lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Добавить структуру 'Client'") # Log about compatibility
if "Server" in inGSettings and "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 inGSettings["Server"]["RequestTimeoutSecFloat"] = 300 # Time to handle request in seconds
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility 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 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 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 if lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Преобразовать структуру 'OrchestratorStart' > 'DefSettingsUpdatePathList'") # Log about compatibility
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# v1.1.20 to v1.2.0 # v1.1.20 to v1.2.0
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@ -338,14 +338,14 @@ def Update(inGSettings):
"DumpLogList": [], # Will be filled automatically "DumpLogList": [], # Will be filled automatically
"DumpLogListHashStr": None, # 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать атрибут 'Client > DumpLog... с параметрами по умолчанию'") # Log about compatibility
if "Processor" in inGSettings: # Check if Processor exist if "Processor" in inGSettings: # Check if Processor exist
# Update Logger # Update Logger
if lL is not None: if lL is not None:
SettingsTemplate.LoggerDumpLogHandlerAdd(inLogger=lL, inGSettingsClientDict=inGSettings["Client"]) 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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Добавить веб дамп для отображения лога на веб клиенте оркестратора") # Log about compatibility
del inGSettings["Processor"] # Remove the key 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Удалить структуру старого процессора 'Processor'") # Log about compatibility
if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure
inGSettings["ProcessorDict"]={ inGSettings["ProcessorDict"]={
"ActivityList": [ # List of the activities "ActivityList": [ # List of the activities
@ -361,14 +361,14 @@ def Update(inGSettings):
"ExecuteBool": True, # Flag to execute thread processor "ExecuteBool": True, # Flag to execute thread processor
"ThreadIdInt": None # Fill thread id when processor will be inited "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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'ProcessorDict'") # Log about compatibility
if "VersionStr" not in inGSettings: # Create new ProcessorDict structure if "VersionStr" not in inGSettings: # Create new ProcessorDict structure
inGSettings["VersionStr"] = None 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 lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'VersionStr'") # Log about compatibility
if "AgentDict" not in inGSettings: # Create new AgentDict structure if "AgentDict" not in inGSettings: # Create new AgentDict structure
inGSettings["AgentDict"]= {} inGSettings["AgentDict"]= {}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'AgentDict'") # Log about compatibility f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'AgentDict'") # Log about compatibility
# Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy # Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy
# if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: # if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())] # lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())]
@ -379,7 +379,7 @@ def Update(inGSettings):
# Check if Server is active > convert to ServerDict # Check if Server is active > convert to ServerDict
inGSettings["ServerDict"] = inGSettings["Server"] inGSettings["ServerDict"] = inGSettings["Server"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Server' -> 'ServerDict'") # Log about compatibility
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["Server"] del inGSettings["Server"]
lShowWarnBool = False lShowWarnBool = False
@ -401,7 +401,7 @@ def Update(inGSettings):
# remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate # remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate
#del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"] #del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"]
if lShowWarnBool: # Show only 1 warning per all run 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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Интегрировать структуру доступа к панелям управления в общую UAC иерархию") # Log about compatibility
# Check if ControlPanelDict is active > convert to CPDict # Check if ControlPanelDict is active > convert to CPDict
if "ControlPanelDict" in inGSettings: if "ControlPanelDict" in inGSettings:
if "CPDict" not in inGSettings: inGSettings["CPDict"]={} if "CPDict" not in inGSettings: inGSettings["CPDict"]={}
@ -409,7 +409,7 @@ def Update(inGSettings):
inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None} inGSettings["CPDict"][lItemDict["KeyStr"]]={"HTMLRenderDef":lItemDict["RenderFunction"], "JSONGeneratorDef":None, "JSInitGeneratorDef":None}
# Remove old structure ControlPanel # Remove old structure ControlPanel
del inGSettings["ControlPanelDict"] del inGSettings["ControlPanelDict"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'ControlPanelDict' -> 'CPDict'") # Log about compatibility
# Check if Scheduler is active > convert to SchedulerDict # Check if Scheduler is active > convert to SchedulerDict
if "Scheduler" in inGSettings: if "Scheduler" in inGSettings:
if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]} if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]}
@ -423,27 +423,27 @@ def Update(inGSettings):
inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict)
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["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 if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Scheduler' -> 'SchedulerDict' с новыми функциональными возможностями") # Log about compatibility
# # Convert to Storage to StorageDict # # Convert to Storage to StorageDict
if "Storage" in inGSettings: if "Storage" in inGSettings:
# Check if Server is active > convert to ServerDict # Check if Server is active > convert to ServerDict
inGSettings["StorageDict"] = inGSettings["Storage"] inGSettings["StorageDict"] = inGSettings["Storage"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Convert Storage to StorageDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Преобразовать 'Storage' -> 'StorageDict'") # Log about compatibility
# Remove old structure Scheduler # Remove old structure Scheduler
del inGSettings["Storage"] del inGSettings["Storage"]
# Add new key WarningExecutionMoreThanSecFloat in ProcessorDict # Add new key WarningExecutionMoreThanSecFloat in ProcessorDict
if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]: if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0 inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add key WarningExecutionMoreThanSecFloat in ProcessorDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключ 'WarningExecutionMoreThanSecFloat' -> 'ProcessorDict'") # Log about compatibility
# Add new key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict # Add new key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict
if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]: if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0 inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0
inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0 inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0
inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0 inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add key AgentActivityLifetimeSecFloat, AgentConnectionLifetimeSecFloat, AgentLoopSleepSecFloat in ProcessorDict > ServerDict") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключи: 'AgentActivityLifetimeSecFloat', 'AgentConnectionLifetimeSecFloat', 'AgentLoopSleepSecFloat' -> 'ProcessorDict' > 'ServerDict'") # Log about compatibility
# Add new key RecoveryDict in ProcessorDict > RobotRDPActive # Add new key RecoveryDict in ProcessorDict > RobotRDPActive
if "RecoveryDict" not in inGSettings["RobotRDPActive"]: if "RecoveryDict" not in inGSettings["RobotRDPActive"]:
inGSettings["RobotRDPActive"]["RecoveryDict"] = { inGSettings["RobotRDPActive"]["RecoveryDict"] = {
@ -457,7 +457,7 @@ def Update(inGSettings):
} }
} }
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.1 to v1.2.2): Add new key RecoveryDict in ProcessorDict > RobotRDPActive") # Log about compatibility f"Обратная совместимость (v1.2.1 -> v1.2.2): Добавить ключ 'RecoveryDict' -> 'ProcessorDict' > 'RobotRDPActive'") # Log about compatibility
# Add new key ServerDict > ListenDict # Add new key ServerDict > ListenDict
if "ListenDict" not in inGSettings["ServerDict"]: if "ListenDict" not in inGSettings["ServerDict"]:
lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80) lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80)
@ -471,7 +471,7 @@ def Update(inGSettings):
} }
} }
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.2 to v1.2.3): Add new key ServerDict > ListenDict. Transfer port from ServerDict > ListenPort") # Log about compatibility f"Обратная совместимость (v1.2.2 -> v1.2.3): Добавить ключ 'ServerDict' > 'ListenDict'. Изменение свойства, отвечающее за прослушиваемый порт 'ServerDict' > 'ListenPort'") # Log about compatibility
# Add new key # Add new key
#"ServerDict": { #"ServerDict": {
# "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition # "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition
@ -479,24 +479,24 @@ def Update(inGSettings):
if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]: if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000 inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkBytesSizeInt") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentFileChunkBytesSizeInt") # Log about compatibility
if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]: if "AgentFileChunkCheckIntervalSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2 inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentFileChunkCheckIntervalSecFloat") # Log about compatibility
if "ServerThread" not in inGSettings["ServerDict"]: if "ServerThread" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["ServerThread"]= None inGSettings["ServerDict"]["ServerThread"]= None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > ServerThread") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > ServerThread") # Log about compatibility
if "AgentLimitLogSizeBytesInt" not in inGSettings["ServerDict"]: if "AgentLimitLogSizeBytesInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300 inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.3 to v1.2.4): Add new key ServerDict > AgentLimitLogSizeBytesInt") # Log about compatibility f"Обратная совместимость (v1.2.3 -> v1.2.4): Добавить ключ ServerDict > AgentLimitLogSizeBytesInt") # Log about compatibility
# Remove ControlPanelDict and CPDict > go to ServerDict > ControlPanelDict # Remove ControlPanelDict and CPDict > go to ServerDict > ControlPanelDict
if "ControlPanelDict" in inGSettings: if "ControlPanelDict" in inGSettings:
del inGSettings["ControlPanelDict"] del inGSettings["ControlPanelDict"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Remove old key: ControlPanelDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Удалить ключ ControlPanelDict") # Log about compatibility
if "CPDict" in inGSettings: if "CPDict" in inGSettings:
for lCPKeyStr in inGSettings["CPDict"]: for lCPKeyStr in inGSettings["CPDict"]:
lCPItemDict = inGSettings["CPDict"][lCPKeyStr] lCPItemDict = inGSettings["CPDict"][lCPKeyStr]
@ -505,40 +505,40 @@ def Update(inGSettings):
inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"]) inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"])
del inGSettings["CPDict"] del inGSettings["CPDict"]
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Remove old key: CPDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Удалить ключ: CPDict") # Log about compatibility
if "ControlPanelDict" not in inGSettings["ServerDict"]: if "ControlPanelDict" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["ControlPanelDict"]={} inGSettings["ServerDict"]["ControlPanelDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ServerDict > ControlPanelDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ServerDict > ControlPanelDict") # Log about compatibility
# ManagersProcessDict # ManagersProcessDict
if "ManagersProcessDict" not in inGSettings: if "ManagersProcessDict" not in inGSettings:
inGSettings["ManagersProcessDict"]={} inGSettings["ManagersProcessDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ManagersProcessDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ManagersProcessDict") # Log about compatibility
# Check "SchedulerDict": { "Schedule": schedule, # https://schedule.readthedocs.io/en/stable/examples.html # Check "SchedulerDict": { "Schedule": schedule, # https://schedule.readthedocs.io/en/stable/examples.html
if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None: if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None:
inGSettings["SchedulerDict"]["Schedule"] = schedule inGSettings["SchedulerDict"]["Schedule"] = schedule
if lL: lL.warning(f"Backward compatibility (v1.2.4 to v1.2.7): Create new module schedule (schedule.readthedocs.io)") # Log about compatibility if lL: lL.warning(f"Backward compatibility (v1.2.4 to v1.2.7): Подключить новый модуль расписания (см. schedule.readthedocs.io)") # Log about compatibility
# ManagersGitDict # ManagersGitDict
if "ManagersGitDict" not in inGSettings: if "ManagersGitDict" not in inGSettings:
inGSettings["ManagersGitDict"]={} inGSettings["ManagersGitDict"]={}
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ManagersGitDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ManagersGitDict") # Log about compatibility
# ProcessorDict > ActivityItemNowDict # ProcessorDict > ActivityItemNowDict
if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]: if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): Create new key: ProcessorDict > ActivityItemNowDict") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): Добавить ключ: ProcessorDict > ActivityItemNowDict") # Log about compatibility
# # "UACBool": True # True - check user access before do this URL item # # "UACBool": True # True - check user access before do this URL item
for lURLItemDict in inGSettings["ServerDict"]["URLList"]: for lURLItemDict in inGSettings["ServerDict"]["URLList"]:
if "UACBool" not in lURLItemDict: if "UACBool" not in lURLItemDict:
lURLItemDict["UACBool"]=None lURLItemDict["UACBool"]=None
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.4 to v1.2.7): ServerDict > URLList > item: add UACBool = None") # Log about compatibility f"Обратная совместимость (v1.2.4 -> v1.2.7): ServerDict > URLList > item и UACBool = None") # Log about compatibility
# "URLIndexStr" # "URLIndexStr"
if "URLIndexStr" not in inGSettings["ServerDict"]: if "URLIndexStr" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["URLIndexStr"] = "/" inGSettings["ServerDict"]["URLIndexStr"] = "/"
if lL: lL.warning( if lL: lL.warning(
f"Backward compatibility (v1.2.11 to v1.2.12): ServerDict > URLIndexStr: add URLIndexStr = /") # Log about compatibility f"Обратная совместимость (v1.2.11 -> v1.2.12): ServerDict > URLIndexStr и URLIndexStr = /") # Log about compatibility

@ -84,7 +84,7 @@ class ControlPanel():
""" """
# Connect self witch pyOpenRPA via ControlPanelNameStr # Connect self witch pyOpenRPA via ControlPanelNameStr
if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]: if inControlPanelNameStr in Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"]:
raise Exception(f"Another control panel with name {inControlPanelNameStr} is already exists. Please resolve the error and restart") raise Exception(f"Ошибка: Ранее уже была инициализирована панель управления с идентификатором: {inControlPanelNameStr}. Устраните ошибку и перезапустите оркестратор")
Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self Orchestrator.GSettingsGet()["ServerDict"]["ControlPanelDict"][inControlPanelNameStr] = self
self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr) self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
@ -116,7 +116,7 @@ class ControlPanel():
self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True) self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True)
self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr) self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e: except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2") Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def RefreshHTMLJinja2StrGenerate(self, inDataDict): def RefreshHTMLJinja2StrGenerate(self, inDataDict):
""" """
@ -145,7 +145,7 @@ class ControlPanel():
self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True) self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True)
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr) self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e: except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2") Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def InitJSJinja2StrGenerate(self, inDataDict): def InitJSJinja2StrGenerate(self, inDataDict):
""" """
@ -290,7 +290,7 @@ class ControlPanel():
# Call backward compatibility HTML generator # Call backward compatibility HTML generator
lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult) lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult)
except Exception as e: except Exception as e:
if lL: lL.exception(f"Error in control panel HTMLRenderDef. CP Key {self.mControlPanelNameStr}. Exception are below") if lL: lL.exception(f"Ошибка в функции генерации HTML контента (HTMLRenderDef). Идентификатор панели управления: {self.mControlPanelNameStr}")
return lResultStr return lResultStr
@ -317,10 +317,10 @@ class ControlPanel():
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: 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:
lResultDict = lJSONResult lResultDict = lJSONResult
else: else:
if lL: lL.warning(f"JSONGenerator return bad type: {str(type(lJSONResult))}, CP Key {self.mControlPanelNameStr}") if lL: lL.warning(f"Функция генерации JSON сформировала некорректную структуру: {str(type(lJSONResult))}, идентификатор панели управления: {self.mControlPanelNameStr}")
except Exception as e: except Exception as e:
if lL: lL.exception( if lL: lL.exception(
f"Error in control panel JSONGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below") f"Ошибка при формирвоании JSON (JSONGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultDict return lResultDict
def BackwardAdapterJSDef(self,inRequest): def BackwardAdapterJSDef(self,inRequest):
@ -343,8 +343,8 @@ class ControlPanel():
if type(lJSResult) is str: if type(lJSResult) is str:
lResultStr = lJSResult # Add delimiter to some cases lResultStr = lJSResult # Add delimiter to some cases
else: else:
if lL: lL.warning(f"JSInitGenerator return bad type: {str(type(lJSResult))}, CP Key {self.mControlPanelNameStr}") if lL: lL.warning(f"Функция JSInitGenerator вернула неверный формат данных: {str(type(lJSResult))}, идентификатор панели управления {self.mControlPanelNameStr}")
except Exception as e: except Exception as e:
if lL: lL.exception( if lL: lL.exception(
f"Error in control panel JSInitGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below") f"Ошибка в функции формирования кода JavaScript (JSInitGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultStr return lResultStr

@ -34,7 +34,7 @@ class Git():
self.mAgentHostNameStr = inAgentHostNameStr self.mAgentHostNameStr = inAgentHostNameStr
self.mAgentUserNameStr = inAgentUserNameStr self.mAgentUserNameStr = inAgentUserNameStr
lGS["ManagersGitDict"][(inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), lAbsPathUpperStr)]=self lGS["ManagersGitDict"][(inAgentHostNameStr.upper(), inAgentUserNameStr.upper(), lAbsPathUpperStr)]=self
else: raise Exception(f"Managers.Git ({inAgentHostNameStr}, {inAgentUserNameStr}, {lAbsPathUpperStr}): Can't init the Git instance because it already inited in early") else: raise Exception(f"Модуль Managers.Git ({inAgentHostNameStr}, {inAgentUserNameStr}, {lAbsPathUpperStr}): Невозможно инициализировать экземпляр класса, так как он уже был инициализирован ранее")
def ProcessConnect(self, inProcess: Process): def ProcessConnect(self, inProcess: Process):
""" """
@ -151,11 +151,11 @@ class Git():
:param inBranchRemoteStr: [description] :param inBranchRemoteStr: [description]
:type inBranchRemoteStr: str :type inBranchRemoteStr: str
""" """
Orchestrator.OrchestratorLoggerGet().debug(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet has been init") Orchestrator.OrchestratorLoggerGet().debug(f"Модуль Managers.Git ({self.mAbsPathStr}): функция self.BranchRevLastGet успешно инициализирована")
# check if the correct revision # check if the correct revision
lCMDResultStr = None lCMDResultStr = None
if self.BranchRevIsLast(inBranchLocalStr=inBranchLocalStr, inBranchRemoteStr=inBranchRemoteStr) == False: if self.BranchRevIsLast(inBranchLocalStr=inBranchLocalStr, inBranchRemoteStr=inBranchRemoteStr) == False:
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, new rev (branch: {inBranchLocalStr}) has been detected - merge (branch: {inBranchRemoteStr})") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Git ({self.mAbsPathStr}): функуция self.BranchRevLastGet, новая ревизия (ветка: {inBranchLocalStr}) была удалена - выполнить слияние (ветка на сервере: {inBranchRemoteStr})")
# Do the stop safe for the connected process # Do the stop safe for the connected process
self.ProcessListSaveStopSafe() self.ProcessListSaveStopSafe()
lBranchNameCurrentStr = self.BranchNameGet() lBranchNameCurrentStr = self.BranchNameGet()
@ -170,7 +170,7 @@ class Git():
# checkout to the source branch which was # checkout to the source branch which was
self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr) self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr)
# do the orc restart # do the orc restart
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, merge done, restart orc") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Git ({self.mAbsPathStr}): self.BranchRevLastGet, merge done, restart orc")
Orchestrator.OrchestratorRestart() Orchestrator.OrchestratorRestart()
return lCMDResultStr return lCMDResultStr

@ -108,7 +108,7 @@ class Process():
__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict) __Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict)
if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck) if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
self.mStatusCheckIntervalSecFloat = inStatusCheckIntervalSecFloat self.mStatusCheckIntervalSecFloat = inStatusCheckIntervalSecFloat
else: raise Exception(f"Managers.Process ({inAgentHostNameStr}, {inAgentUserNameStr}, {inProcessNameWOExeStr}): Can't init the Process instance because it already inited in early (see ProcessInitSafe)") else: raise Exception(f"Модуль Managers.Process ({inAgentHostNameStr}, {inAgentUserNameStr}, {inProcessNameWOExeStr}): Невозможно инициализировать процесс, так как он был инициализирован ранее (см. ProcessInitSafe)")
def ManualStopTriggerSet(self, inMSTdTSecFloat: float, inMSTdNInt: int) -> None: def ManualStopTriggerSet(self, inMSTdTSecFloat: float, inMSTdNInt: int) -> None:
""" """
@ -145,7 +145,7 @@ class Process():
self.mStatusStr = "1_STOPPED_MANUAL" self.mStatusStr = "1_STOPPED_MANUAL"
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): ManualStopTrigger is activated. {self.mMSTdNInt} start tries in {self.mMSTdTSecFloat} sec.") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Триггер ручной остановки активирован. {self.mMSTdNInt} повторить попытку через {self.mMSTdTSecFloat} сек.")
return self.mStatusStr return self.mStatusStr
def ManualStopListClear(self) -> None: def ManualStopListClear(self) -> None:
@ -180,7 +180,7 @@ class Process():
""" """
if inIsManualBool == False: self.ManualStopTriggerNewStart() # Set the time if inIsManualBool == False: self.ManualStopTriggerNewStart() # Set the time
if self.mStatusStr is not None and (self.mStatusStr == "1_STOPPED_MANUAL" or "STOP_SAFE" in self.mStatusStr) and inIsManualBool == False: if self.mStatusStr is not None and (self.mStatusStr == "1_STOPPED_MANUAL" or "STOP_SAFE" in self.mStatusStr) and inIsManualBool == False:
lStr = f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Process will not start because of stopped manual or stop safe is now." lStr = f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Процесс не будет запущен, так как инициализирован триггер ручной остановки или активен режим безопасного отключения"
__Orchestrator__.OrchestratorLoggerGet().warning(lStr) __Orchestrator__.OrchestratorLoggerGet().warning(lStr)
return self.mStatusStr return self.mStatusStr
# Send activity item to agent - wait result # Send activity item to agent - wait result
@ -259,7 +259,7 @@ class Process():
if "SAFE" in self.mStatusStr: if "SAFE" in self.mStatusStr:
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Safe stop has been wait for {inStopSafeTimeoutSecFloat} sec. Now do the force stop.") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Алгоритм безопасной остановки ожидал завершение процесса в течение {inStopSafeTimeoutSecFloat} сек. Выполнить принудительную остановку")
self.StopForce(inIsManualBool=inIsManualBool,inMuteIgnoreBool=True) self.StopForce(inIsManualBool=inIsManualBool,inMuteIgnoreBool=True)
# Log info about process # Log info about process
# self.StatusChangeLog() status check has already log status (see above) # self.StatusChangeLog() status check has already log status (see above)
@ -350,7 +350,7 @@ class Process():
if self.mStatusStr == "2_STOP_SAFE": self.mStatusSavedStr = "0_STOPPED" if self.mStatusStr == "2_STOP_SAFE": self.mStatusSavedStr = "0_STOPPED"
elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL" elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL"
else: self.mStatusSavedStr = self.mStatusStr; lWarnSafeBool = False else: self.mStatusSavedStr = self.mStatusStr; lWarnSafeBool = False
if lWarnSafeBool==True: __Orchestrator__.OrchestratorLoggerGet().warning(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Safe status has been catched when safe > change saved status to stopped.") if lWarnSafeBool==True: __Orchestrator__.OrchestratorLoggerGet().warning(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Состояние безопасной остановки было обнаружено при попытке сохранить состояние > зафиксировать состояние как остановленное")
return self.mStatusStr return self.mStatusStr
@ -358,7 +358,7 @@ class Process():
"""Call from orchestrator when init """Call from orchestrator when init
""" """
if self.mStatusCheckIntervalSecFloat is not None: if self.mStatusCheckIntervalSecFloat is not None:
__Orchestrator__.OrchestratorLoggerGet().info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Restore schedule to StatusCheck in interval of {self.mStatusCheckIntervalSecFloat} sec.") __Orchestrator__.OrchestratorLoggerGet().info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Восстановить периодическую проверку состояния с интервалом в {self.mStatusCheckIntervalSecFloat} сек.")
__Orchestrator__.OrchestratorScheduleGet().every(self.mStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck) __Orchestrator__.OrchestratorScheduleGet().every(self.mStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
def StatusRestore(self): def StatusRestore(self):
@ -377,7 +377,7 @@ class Process():
self.StopSafe(inIsManualBool=True) self.StopSafe(inIsManualBool=True)
if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr: if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr:
self.Start(inIsManualBool=True) self.Start(inIsManualBool=True)
Orchestrator.OrchestratorLoggerGet().info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Status has been restored to {self.mStatusSavedStr}") Orchestrator.OrchestratorLoggerGet().info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Статус процесса был восстановлен на: {self.mStatusSavedStr}")
self.mStatusStr = self.mStatusSavedStr self.mStatusStr = self.mStatusSavedStr
self.mStatusSavedStr = None self.mStatusSavedStr = None
return self.mStatusStr return self.mStatusStr
@ -390,7 +390,7 @@ class Process():
""" """
# Log info about process # Log info about process
lL = __Orchestrator__.OrchestratorLoggerGet() lL = __Orchestrator__.OrchestratorLoggerGet()
lL.info(f"Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Status has been changed to {self.mStatusStr})") lL.info(f"Модуль Managers.Process ({self.mAgentHostNameStr}, {self.mAgentUserNameStr}, {self.mProcessNameWOExeStr}): Состояние процесса изменилось на {self.mStatusStr})")
def StatusCheck(self): def StatusCheck(self):

@ -70,7 +70,7 @@ def ActivityListExecute(inGSettings, inActivityList):
lResultList = [] # init the result list lResultList = [] # init the result list
try: try:
for lActivityItem in inActivityList: # Iterate throught the activity list 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.') if lL: lL.info(f'Процессор:: Исполнение функции def:{str(lActivityItem["Def"])}. В целях информационной безопасности параметры недоступны для просмотра')
lDef = None # Def variable lDef = None # Def variable
if callable(lActivityItem["Def"]): # CHeck if def is callable if callable(lActivityItem["Def"]): # CHeck if def is callable
lDef = lActivityItem["Def"] # Get the def lDef = lActivityItem["Def"] # Get the def
@ -79,7 +79,7 @@ def ActivityListExecute(inGSettings, inActivityList):
#gSettings #gSettings
lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None) lGSettingsDictKey = lActivityItem.pop("ArgGSettings",None)
# # Prepare arg dict - gSettings # # 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 "" if type(lGSettingsDictKey) is str and lGSettingsDictKey != "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgGSettings is ""
lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict lActivityItem["ArgDict"][lGSettingsDictKey] = inGSettings # Set the gSettings in dict
# # Prepare arg list # # Prepare arg list
elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict elif type(lGSettingsDictKey) is int: # check if gSetting key is in ArgDict
@ -87,7 +87,7 @@ def ActivityListExecute(inGSettings, inActivityList):
#Logger #Logger
lLoggerDictKey = lActivityItem.pop("ArgLogger",None) lLoggerDictKey = lActivityItem.pop("ArgLogger",None)
# # Prepare arg dict - Logger # # 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 "" if type(lLoggerDictKey) is str and lLoggerDictKey != "": # check if gSetting key is in ArgDict 13.02.2021 - Fix when ArgLogger is ""
lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict lActivityItem["ArgDict"][lLoggerDictKey] = lL # Set the lLogger in dict
# # Prepare arg list # # Prepare arg list
elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict elif type(lLoggerDictKey) is int: # check if gSetting key is in ArgDict

@ -62,22 +62,22 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
try: try:
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True) Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started lRDPConfigurationDict["SessionIsWindowExistBool"] = True # Flag that session is started
if lL: lL.info(f"Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}, SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session has been initialized!") #Logging if lL: lL.info(f"Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}, Идентификатор сессии: {str(lRDPConfigurationDict['SessionHex'])}:: Сессия была инициализирована!") #Logging
# catch ConnectorExceptions.SessionWindowNotExistError # catch ConnectorExceptions.SessionWindowNotExistError
except ConnectorExceptions.SessionWindowNotExistError as e: except ConnectorExceptions.SessionWindowNotExistError as e:
lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected lRDPConfigurationDict["SessionIsWindowExistBool"] = False # Set flag that session is disconnected
if lL: lL.warning(f"Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}, SessionHex: {str(lRDPConfigurationDict['SessionHex'])}:: Session is not exist! Mark the retry") #Logging if lL: lL.warning(f"Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}, Идентификатор сессии: {str(lRDPConfigurationDict['SessionHex'])}:: Сессия не обнаружена - попытаться подключиться!") #Logging
# Recovery operations # Recovery operations
Recovery.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) Recovery.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings)
if Recovery.RetryIsTriggered(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) == True: if Recovery.RetryIsTriggered(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings) == True:
if lL: lL.warning(f"!ATTENTION! Host: {lRDPConfigurationDict['Host']}, Login: {lRDPConfigurationDict['Login']}; RDP is not responsible for many times - run recovery mode") if lL: lL.warning(f"!ВНИМАНИЕ! Хост: {lRDPConfigurationDict['Host']}, Логин: {lRDPConfigurationDict['Login']}; сессия РДП недоступна при попытках подключения - инициализация режима восстановления")
Recovery.RetryHostClear(inHostStr=lRDPConfigurationDict['Host'],inGSettings=inGSettings) # Clear the stat about current host Recovery.RetryHostClear(inHostStr=lRDPConfigurationDict['Host'],inGSettings=inGSettings) # Clear the stat about current host
if inGSettings["RobotRDPActive"]["RecoveryDict"]["DoDict"]["OSRemotePCRestart"] == True: if inGSettings["RobotRDPActive"]["RecoveryDict"]["DoDict"]["OSRemotePCRestart"] == True:
if lL: lL.warning(f"!ATTENTION! Host: {lRDPConfigurationDict['Host']}, Send signal to restart remote PC.") if lL: lL.warning(f"!ВНИМАНИЕ! Хост: {lRDPConfigurationDict['Host']}, отправить сигнал на перезагрузку удаленной машины")
__Orchestrator__.OSRemotePCRestart(inLogger=lL,inHostStr=lRDPConfigurationDict['Host'],inForceBool=True) __Orchestrator__.OSRemotePCRestart(inLogger=lL,inHostStr=lRDPConfigurationDict['Host'],inForceBool=True)
# general exceptions # general exceptions
except Exception as e: except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging if lL: lL.exception(f"!!! ВНИМАНИЕ !!! Неопознанная ошибка. Обратитесь в тех. поддержку pyOpenRPA") #Logging
pass pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Connector.SystemRDPWarningClickOk() # Click all warning messages Connector.SystemRDPWarningClickOk() # Click all warning messages
@ -125,7 +125,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)( lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"]) *lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e: 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 if lL: lL.exception(f"РДП: Ошибка при обработке активности в процессоре РДП сессии - активность будет проигнорирована. Активность: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult) lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool # Check if Result is bool
@ -137,7 +137,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e: except RuntimeError as e:
# case noGUI error passed - do nothing # case noGUI error passed - do nothing
if lL: lL.warning(f"Host session has lost the GUI") #Logging if lL: lL.warning(f"Оркестратор потерял графическую сессию - повторить попытку через несколько секунд") #Logging
finally: finally:
# Wait for the next iteration # Wait for the next iteration
time.sleep(0.7) time.sleep(0.7)
@ -145,4 +145,4 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1) #Monitor.Monitor(mGSettingsRDPActiveDict, 1)
except Exception as e: except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Global error handler - look at code") #Logging if lL: lL.exception(f"!!! ВНИМАНИ !!! В модуле РДП произошла критическая ошибка. Обратитесь в службу тех. поддержки pyOpenRPA") #Logging

@ -10,7 +10,7 @@ def CheckScreen(inIntervalSeconds=1):
#Send os command to create console version (base screen) #Send os command to create console version (base screen)
Screen.ConsoleScreenBase() Screen.ConsoleScreenBase()
#Delay to create console screen #Delay to create console screen
time.sleep(5) time.sleep(15)
#Delay #Delay
time.sleep(inIntervalSeconds) time.sleep(inIntervalSeconds)
return None return None

@ -24,12 +24,13 @@ import uuid
import datetime import datetime
import os #for path operations import os #for path operations
from http import cookies from http import cookies
global gSettingsDict gSettingsDict = {}
from . import ServerSettings from . import ServerSettings
from . import __Orchestrator__ from . import __Orchestrator__
import copy import copy
import mimetypes import mimetypes
mimetypes.add_type("font/woff2",".woff2") mimetypes.add_type("font/woff2",".woff2")
mimetypes.add_type("text/javascript",".js")
gCacheDict = {} gCacheDict = {}
@ -82,6 +83,7 @@ def AuthenticateVerify(inRequest):
###################################### ######################################
#Way 1 - try to find AuthToken #Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", "")) lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
global gSettingsDict
#pdb.set_trace() #pdb.set_trace()
if "AuthToken" in lCookies: if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -147,6 +149,7 @@ def AuthenticateBlock(inRequest):
def UserAccessCheckBefore(inMethod, inRequest): def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict # Help def - Get access flag from dict
#pdb.set_trace() #pdb.set_trace()
global gSettingsDict
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem: if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"] return inAccessRuleItem["FlagAccess"]
@ -261,6 +264,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to get hierarchy of the current user roles # Def to get hierarchy of the current user roles
# if return {} - all is available # if return {} - all is available
def UserRoleHierarchyGet(self): def UserRoleHierarchyGet(self):
#global gSettingsDict
lDomainUpperStr = self.OpenRPA["Domain"].upper() lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper() lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
@ -268,6 +272,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#Tech def #Tech def
#return {"headers":[],"body":"","statuscode":111} #return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False): def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False):
global gSettingsDict
############################### ###############################
#Tech sub def - do item #Tech sub def - do item
################################ ################################
@ -288,18 +293,22 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data # Write content as utf-8 data
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]] inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
else: else:
if os.path.exists(inURLItem["ResponseFilePath"]) and os.path.isfile(inURLItem["ResponseFilePath"]):
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data
gCacheDict[inURLItem["ResponseFilePath"]] = lFileObject.read()
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
# Закрыть файловый объект
lFileObject.close()
else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
else:
if os.path.exists(inURLItem["ResponseFilePath"]) and os.path.isfile(inURLItem["ResponseFilePath"]):
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb") lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data # Write content as utf-8 data
gCacheDict[inURLItem["ResponseFilePath"]] = lFileObject.read() inResponseDict["Body"] = lFileObject.read()
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
# Закрыть файловый объект # Закрыть файловый объект
lFileObject.close() lFileObject.close()
else: else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
lFileObject = open(CrossOS.PathStr(inURLItem["ResponseFilePath"]), "rb")
# Write content as utf-8 data
inResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
# detect MIME type if none # detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(inURLItem["ResponseFilePath"])[0] inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(inURLItem["ResponseFilePath"])[0]
@ -320,7 +329,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings
lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"") lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"")
lFilePathSecondPart = lFilePathSecondPart.split("?")[0] lFilePathSecondPart = lFilePathSecondPart.split("?")[0]
lFilePath = os.path.join(CrossOS.PathStr(inURLItem["ResponseFolderPath"]),lFilePathSecondPart) lFilePath = CrossOS.PathStr(os.path.join(inURLItem["ResponseFolderPath"],lFilePathSecondPart))
#print(f"File full path {lFilePath}") #print(f"File full path {lFilePath}")
#Check if file exist #Check if file exist
if os.path.exists(lFilePath) and os.path.isfile(lFilePath): if os.path.exists(lFilePath) and os.path.isfile(lFilePath):
@ -345,6 +354,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# detect MIME type if none # detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(lFilePath)[0] inResponseDict["Headers"]["Content-type"]= mimetypes.guess_type(lFilePath)[0]
else:
inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
# If No content-type # If No content-type
if inResponseDict["Headers"]["Content-type"] is None: if inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= "application/octet-stream" inResponseDict["Headers"]["Content-type"]= "application/octet-stream"
@ -420,6 +431,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
def do_GET(self): def do_GET(self):
try: try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self threading.current_thread().request = self
self.OpenRPA = {} self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None self.OpenRPA["AuthToken"] = None
@ -493,33 +507,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# check if file in FileURL - File Path Mapping Dict # check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]: if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL]) self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
# Index page
elif self.path == gSettingsDict["ServerDict"]["URLIndexStr"]:
lURLItemDict = {
"Method":"GET",
"URL": gSettingsDict["ServerDict"]["URLIndexStr"],
"MatchType": "EqualCase",
"ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.xhtml"),
"ResponseContentType": "text/html"}
#Check if all condition are applied
lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItemDict, "GET")
if lFlagURLIsApplied:
self.ResponseDictSend()
return
else: else:
#Set access denied code #Set access denied code
# Send response status code # Send response status code
self.send_response(403) self.send_response(403)
# Send headers # Send headers
self.end_headers() self.end_headers()
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_GET): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Server.do_GET: Global error handler - look traceback below.") if lL: lL.exception(f"Сервер (do_GET): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
# POST # POST
def do_POST(self): def do_POST(self):
try: try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self threading.current_thread().request = self
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
self.OpenRPA = {} self.OpenRPA = {}
@ -603,7 +608,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lActivityTypeListStr += f"{lInputObject['Type']}" lActivityTypeListStr += f"{lInputObject['Type']}"
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" 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}") if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}")
# Send message back to client # Send message back to client
message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject)) message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject))
# Write content as utf-8 data # Write content as utf-8 data
@ -616,20 +621,35 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers # Send headers
self.end_headers() self.end_headers()
return return
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_POST): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Server.do_POST: Global error handler - look traceback below.") if lL: lL.exception(f"Сервер (do_POST): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
#Logging #Logging
#!Turn it on to stop print in console #!Turn it on to stop print in console
#def log_message(self, format, *args): #def log_message(self, format, *args):
# return # return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True daemon_threads = True
"""Handle requests in a separate thread.""" """Handle requests in a separate thread."""
def finish_request(self, request, client_address): def finish_request(self, request, client_address):
request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]) try:
# "super" can not be used because BaseServer is not created from object global gSettingsDict
HTTPServer.finish_request(self, request, client_address) request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
# "super" can not be used because BaseServer is not created from object
HTTPServer.finish_request(self, request, client_address)
except ConnectionResetError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (finish_request): Возникла ошибка сети - ConnectionResetError: [Errno 104] Connection reset by peer. Сервер продолжает работу")
except Exception as e:
lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Сервер (finish_request): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
#inGlobalDict #inGlobalDict
# "JSONConfigurationDict":<JSON> # "JSONConfigurationDict":<JSON>
import ssl import ssl
@ -640,6 +660,7 @@ class RobotDaemonServer(Thread):
# Update the global dict # Update the global dict
ServerSettings.SettingsUpdate(inGlobalDict) ServerSettings.SettingsUpdate(inGlobalDict)
def run(self): def run(self):
global gSettingsDict
lL = gSettingsDict.get("Logger",None) lL = gSettingsDict.get("Logger",None)
try: try:
lServerDict = gSettingsDict["ServerDict"]["ListenDict"][self.name] lServerDict = gSettingsDict["ServerDict"]["ListenDict"][self.name]
@ -660,10 +681,10 @@ class RobotDaemonServer(Thread):
httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr, keyfile=lKeyFilePathStr) httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr, keyfile=lKeyFilePathStr)
else: else:
httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr) httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=lCertFilePathStr)
if lL: lL.info(f"Web Server init (with SSL). Name: {self.name}, Listen URL: {lAddressStr}, Listen port: {lPortInt}, Cert path: {lCertFilePathStr}") if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}")
else: else:
if lL: lL.info(f"Web Server init. Name: {self.name}, Listen URL: {lAddressStr}, Listen port: {lPortInt}") if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}")
#print('Starting server, use <Ctrl-C> to stop') #print('Starting server, use <Ctrl-C> to stop')
httpd.serve_forever() httpd.serve_forever()
except Exception as e: except Exception as e:
if lL: lL.exception(f"Web Server execution exception") if lL: lL.exception(f"Сервер:: Ошибка при инициализации - обратитесь в тех. поддержку pyOpenRPA")

@ -8,7 +8,7 @@ if CrossOS.IS_WINDOWS_BOOL: #CrossOS
getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage, getDisplayRects, saveScreenToBmp, saveRectToBmp, getScreenAsImage,
getRectAsImage, getDisplaysAsImages) getRectAsImage, getDisplaysAsImages)
if CrossOS.IS_LINUX_BOOL: pass if CrossOS.IS_LINUX_BOOL: import pyscreeze
from http import cookies from http import cookies
import uuid # generate UUID4 import uuid # generate UUID4
@ -197,9 +197,9 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
# Get Screenshot # Get Screenshot
def SaveScreenshot(inFilePath): def SaveScreenshot(inFilePath):
# grab fullscreen # grab fullscreen
# Save the entire virtual screen as a PNG # Save the entire virtual screen as a PNsG
lScreenshot = getScreenAsImage() lScreenshot = getScreenAsImage()
lScreenshot.save('screenshot.png', format='png') lScreenshot.save('Screenshot.png', format='png')
# lScreenshot = ScreenshotSecondScreen.grab_screen() # lScreenshot = ScreenshotSecondScreen.grab_screen()
# save image file # save image file
# lScreenshot.save('screenshot.png') # lScreenshot.save('screenshot.png')
@ -211,7 +211,13 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read() inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект # Закрыть файловый объект
lFileObject.close() lFileObject.close()
else: lFileObject = b'' else:
pyscreeze._screenshot_linux(imageFilename='Screenshot.png')
lFileObject = open("Screenshot.png", "rb")
# Write content as utf-8 data
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
# Add activity item or activity list to the processor queue # Add activity item or activity list to the processor queue
# Body is Activity item or Activity List # Body is Activity item or Activity List
@ -233,7 +239,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
for lActivityItem in lInput: for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; " lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
# Separate into 2 lists - sync and async # Separate into 2 lists - sync and async
@ -259,7 +265,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
try: try:
lActivityTypeListStr = lInput['Def'] lActivityTypeListStr = lInput['Def']
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
if lInput.get("ThreadBool",False) == False: if lInput.get("ThreadBool",False) == False:
@ -288,7 +294,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
for lActivityItem in lInput: for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; " lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute") lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute")
if lL: lL.info(lWebAuditMessageStr) if lL: lL.info(lWebAuditMessageStr)
# Execution # Execution
@ -301,7 +307,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
try: try:
lActivityTypeListStr = lInput['Def'] lActivityTypeListStr = lInput['Def']
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,
inOperationCodeStr=lActivityTypeListStr, inOperationCodeStr=lActivityTypeListStr,
inMessageStr="pyOpenRPA_ActivityListExecute") inMessageStr="pyOpenRPA_ActivityListExecute")
@ -432,13 +438,13 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr] lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr]
# Create item in gSettings # Create item in gSettings
inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue) inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue)
lLogStr = "x bytes" lLogStr = "x байт"
try: try:
if lActivityReturnItemValue is not None: if lActivityReturnItemValue is not None:
lLogStr = f"{len(lActivityReturnItemValue)} bytes" lLogStr = f"{len(lActivityReturnItemValue)} байт"
except Exception as e: except Exception as e:
pass pass
if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Has recieved result of the activity items from agent! ActivityItem GUID Str: {lActivityReturnItemKeyStr}; Return value len: {lLogStr}") if lL: lL.debug(f"СЕРВЕР: Функция pyOpenRPA_Agent_A2O:: Получена активность от агента! Идентификатор активности: {lActivityReturnItemKeyStr}; Длина переданной активности: {lLogStr}")
# Delete the source activity item from AgentDict # Delete the source activity item from AgentDict
if lAgentDictItemKeyTurple in inGSettings["AgentDict"]: if lAgentDictItemKeyTurple in inGSettings["AgentDict"]:
lAgentDictActivityListNew = [] lAgentDictActivityListNew = []
@ -448,11 +454,23 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lAgentDictActivityListNew.append(lActivityItem) lAgentDictActivityListNew.append(lActivityItem)
else: else:
del lActivityItem del lActivityItem
if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Source activity item request was deleted from the orchestrator. ActivityItem GUID Str: {lActivityReturnItemKeyStr}") if lL: lL.debug(f"СЕРВЕР: Функция pyOpenRPA_Agent_A2O:: Активность была удалена из процессорной очереди. Идентификатор активности: {lActivityReturnItemKeyStr}")
inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"] = lAgentDictActivityListNew inGSettings["AgentDict"][lAgentDictItemKeyTurple]["ActivityList"] = lAgentDictActivityListNew
from pyOpenRPA.Utils.Render import Render
lFileStr = CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-2] + ["Resources","Web","orpa","orc.xhtml"])
gRender = Render(inTemplatePathStr=lFileStr,inTemplateRefreshBool=True)
def pyOpenRPA_Index():
# Пример использования
global gRender
lStr = gRender.Generate(inDataDict={"title":"ОРКЕСТРАТОР PYOPENRPA", "subtitle":"ПАНЕЛЬ УПРАВЛЕНИЯ"})
__Orchestrator__.WebRequestResponseSend(inResponeStr=lStr,inContentTypeStr="text/html")
def SettingsUpdate(inGlobalConfiguration): def SettingsUpdate(inGlobalConfiguration):
import os import os
import pyOpenRPA.Orchestrator import pyOpenRPA.Orchestrator
gSettingsDict = __Orchestrator__.GSettingsGet()
if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1]) if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1])
if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1]) if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1])
lURLList = \ lURLList = \
@ -467,7 +485,10 @@ def SettingsUpdate(inGlobalConfiguration):
# "ResponseDefRequestGlobal": None #Function with str result # "ResponseDefRequestGlobal": None #Function with str result
#} #}
#Orchestrator basic dependencies # Index page in server.py because of special settings #Orchestrator basic dependencies # Index page in server.py because of special settings
{"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index},
{"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\orpa\\metadata.json"), "ResponseContentType": "application/json"},
{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"}, {"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"},
{"Method":"GET", "URL": "/orpa/Resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "..\\Resources"),"UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.css", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css"), "ResponseContentType": "text/css", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.css", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css"), "ResponseContentType": "text/css", "UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/semantic.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/3rdParty/jQuery/jquery-3.1.1.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/3rdParty/jQuery/jquery-3.1.1.min.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js"), "ResponseContentType": "application/javascript", "UACBool":False, "UseCacheBool": True},
@ -494,4 +515,4 @@ def SettingsUpdate(inGlobalConfiguration):
] ]
Usage.Process(inComponentStr="Orchestrator") Usage.Process(inComponentStr="Orchestrator")
inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList
return inGlobalConfiguration return inGlobalConfiguration

@ -1,5 +1,7 @@
import os, logging, datetime, sys import os, logging, datetime, sys
import schedule # https://schedule.readthedocs.io/en/stable/examples.html import schedule
from pyOpenRPA.Tools import CrossOS # https://schedule.readthedocs.io/en/stable/examples.html
# Technical def - return GSettings structure with examples # Technical def - return GSettings structure with examples
def __Create__(): def __Create__():
@ -340,7 +342,7 @@ def Create(inModeStr="BASIC", inLoggerLevel = None):
lL.setLevel(logging.INFO) lL.setLevel(logging.INFO)
# create the logging file handler # create the logging file handler
mRobotLoggerFH = logging.FileHandler( mRobotLoggerFH = logging.FileHandler(
"Reports\\" + datetime.datetime.now().strftime("%Y_%m_%d") + ".log") CrossOS.PathStr("Reports\\" + datetime.datetime.now().strftime("%Y_%m_%d") + ".log"))
mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') mRobotLoggerFormatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter) mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# add handler to logger object # add handler to logger object

@ -0,0 +1,49 @@
<div class="ui inverted vertical footer segment">
<div class="ui center aligned container">
<div class="ui stackable inverted divided equal height stackable grid">
<div class="four wide column">
<h4 class="ui inverted header">Навигатор</h4>
<div class="ui inverted link list">
<a href="https://pyopenrpa.ru/" target="_blank" class="item">Портал</a>
<a href="https://pyopenrpa.ru/wiki/guide/v1.2.14_RUS/html/index.html" target="_blank" class="item">Документация</a>
<a href="https://t.me/pyOpenRPA" target="_blank" class="item">Сообщество</a>
<a href="mailto:support@pyopenrpa.ru" target="_blank" class="item">Тех. поддержка</a>
<a href="https://pyopenrpa.ru/verification" target="_blank" class="item">Центр цифровых сертификатов</a>
</div>
</div>
<div class="four wide column">
<h4 class="ui inverted header">Интересный факт</h4>
<p><a href="https://pyopenrpa.ru" target="_blank">Портал pyOpenRPA</a> сделан на оркестраторе pyOpenRPA за 7 дней - присоединяйся к сильной стороне!</p>
</div>
<div class="eight wide column">
<h4 class="ui inverted header">Контактная информация</h4>
<span>ПРАВООБЛАДАТЕЛЬ: ООО "ОПЕН РПА", ОГРН 1227700251350</span>
<br>
<span>МСК: 125310, Россия, г. Москва, улица Муравская</span>
<br>
<span>СПБ: 197022, Россия, г. Санкт-Петербург, Аптекарский проспект, 18</span>
<br>
<span>Центр поддержки клиентов: +7 995 233 45 31 (с 9:00 до 18:00 по МСК), support@pyopenrpa.ru</span>
<br>
<span>Оказываем услуги на всей территории Российской Федерации</span>
</div>
</div>
<div class="ui inverted section divider"></div>
<div class="ui horizontal inverted small divided link list">
<a class="item" href="https://semantic-ui.com/elements/input.html" target="_blank">Справка Semantic UI</a>
<a class="item" href="https://pywinauto.readthedocs.io/en/latest/code/code.html#main-user-modules" target="_blank">Справка Pywinauto</a>
<a class="item" href="https://gitlab.com/UnicodeLabs/OpenRPA" target="_blank">Репозиторий pyOpenRPA</a>
<a class="item" href="https://pyopenrpa.ru/license/oferta.pdf" target="_blank">Оферта</a>
</div>
</div>
</div>
<script src="/orpa/Resources/Web/orpa/styleset/visibility.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/sidebar.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/transition.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/docs.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/easing.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/highlight.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/less.min.js"></script>
<script src="/orpa/Resources/Web/orpa/styleset/home.js"></script>

@ -0,0 +1,100 @@
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/reset.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/site.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/container.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/grid.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/header.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/image.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/menu.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/divider.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/dropdown.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/segment.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/button.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/list.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/icon.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/sidebar.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/components/transition.css">
<div class="pusher tag-top">
<div class="ui inverted vertical masthead center aligned segment zoomed" style="background-color:#000000; ">
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.main.menu {
margin-top: 4em;
border-radius: 0;
border: none;
box-shadow: none;
transition:
box-shadow 0.5s ease,
padding 0.5s ease
;
}
.main.menu .item img.logo {
margin-right: 1.5em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
}
.overlay .menu {
position: relative;
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);
}
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
}
</style>
<div class="ui text container tag-top">
<div class="ui middle aligned stackable grid container">
<div class="row">
<div class="four wide column">
<img src="/orpa/Resources/Web/orpa/styleset/pyOpenRPA_logo.png" width="140px;" height="140px"></img>
</div>
<div class="twelve wide column">
<h1 class="ui inverted header" style="margin-top:0px; margin-bottom:0px;">
<span class="library" style="text-transform: uppercase; letter-spacing: 5px; margin-top:0px; margin-bottom:5px; font-weight: bold;">{{title}}</span>
</h1>
<h2 style="text-transform: uppercase; letter-spacing: 5px; margin-top:0px; margin-bottom:5px;">
{{subtitle}}
</h2>
</div>
</div>
</div>
</div>
</div>
</div>

@ -0,0 +1,992 @@
var mGlobal={}
mGlobal.pyOpenRPA = {}
window.onload=function() {
//document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
//Render existing data
//mGlobal.Monitor.fControlPanelRefresh_TechnicalRender()
}
$(document).ready(function() {
document.cookie = "SessionGUIDStr=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
console.log("Cookie is deleted")
// fix main menu to page on passing
$('.main.menu').visibility({
type: 'fixed'
});
$('.overlay').visibility({
type: 'fixed',
offset: 80
});
// lazy load images
$('.image').visibility({
type: 'image',
transition: 'vertical flip in',
duration: 500
});
// show dropdown on hover
$('.main.menu .ui.dropdown').dropdown({
on: 'hover'
});
function clone(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = clone(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
//For data storage key
mGlobal["DataStorage"] = {}
// Clear the session cookie
String.prototype.replaceAll = function(search, replace){
return this.split(search).join(replace);
}
mGlobal.GeneralGenerateHTMLCodeHandlebars=function(inInnerTemplateSelector,inData) {
lHTMLTemplate=$(inInnerTemplateSelector)[0].innerHTML
//console.log(lHTMLTemplate)
//Компиляция
var template = Handlebars.compile(lHTMLTemplate);
//Вставка данных
var lHTMLResult = template(inData);
return lHTMLResult
}
mGlobal.GeneralGenerateHTMLCode=function(inTemplateHTMLSelector,inItemDictionary,inKeywordPrefix="::",inKeywordPostfix="::") {
///Получить заготовку
lTemplateHTMLCode=$(inTemplateHTMLSelector)[0].outerHTML
///Определить ключь экранирования специальных ключевых слов
///Выполнить циклические замены, если там есть пожходящие ключи
lResultHTMLCode=lTemplateHTMLCode
for(var lKey in inItemDictionary) {
lHTMLKey=inKeywordPrefix+lKey+inKeywordPostfix;
lResultHTMLCode=lResultHTMLCode.replaceAll(lHTMLKey,inItemDictionary[lKey])
}
///Вернуть результат
return lResultHTMLCode
}
//////////////////////////
/////Info JS module
//////////////////////////
mGlobal.Info={};
mGlobal.Info.TableActivityLogScheduleListRefresh=function() {
}
//////////////////////////
/////Controller JS module
//////////////////////////
mGlobal.Controller={};
mGlobal.Controller.CMDRunText=function(inCMDText) {
///Подготовить конфигурацию
lData = [
{"Type":"CMDStart", "Command": inCMDText}
]
///Обнулить таблицу
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3){},
dataType: "text"
});
}
mGlobal.Controller.CMDRun=function() {
///Обнулить таблицу
lCMDCode=$(".openrpa-controller-cmd-run-input")[0].value
///Подготовить конфигурацию
lData = [
{
"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: '/pyOpenRPA/ActivityListExecute',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
//lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result)
},
dataType: "text"
});
}
mGlobal.Controller.CMDRunGUILogout=function() {
///Обнулить таблицу
lCMDCode="for /f \"skip=1 tokens=2\" %s in ('query user %USERNAME%') do (tscon \\dest:console)"
//lCMDCode = lCMDCode.replace(/\\n/g, "\\n")
// .replace(/\\'/g, "\\'")
// .replace(/\\"/g, '\\"')
// .replace(/\\&/g, "\\&")
// .replace(/\\r/g, "\\r")
// .replace(/\\t/g, "\\t")
// .replace(/\\b/g, "\\b")
// .replace(/\\f/g, "\\f")
// .replace('"', "\\\"");
///Подготовить конфигурацию
lData = [
{"Type":"CMDStart", "Command": lCMDCode }
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Отправить запрос на формирование таблицы
//lHTMLCode=console.log("CMDRun result: "+lResponseJSON[0].result)
},
dataType: "text"
});
}
///Restart PC
mGlobal.Controller.PCRestart = function () {
mGlobal.Controller.OrchestratorSessionSave()
mGlobal.Controller.CMDRunText("shutdown -r")
}
///Orchestrator save session
mGlobal.Controller.OrchestratorSessionSave=function() {
///Подготовить конфигурацию
lData = [
{"Type":"OrchestratorSessionSave"}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
},
dataType: "text"
});
}
///Перезагрузить Orchestrator
mGlobal.Controller.OrchestratorRestart=function() {
///Подготовить конфигурацию
lData = [
{"Type":"OrchestratorRestart"}
]
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
},
dataType: "text"
});
}
mGlobal.Controller.OrchestratorGITPullRestart = function() {
mGlobal.Controller.OrchestratorSessionSave() //Save current RDP list session
mGlobal.Controller.CMDRunText("timeout 3 & taskkill /f /im OpenRPA_Orchestrator.exe & timeout 2 & cd "+mGlobal.WorkingDirectoryPathStr+" & git reset --hard & git pull & pyOpenRPA.Orchestrator_x64_administrator_startup.cmd");
}
//////////////////////////
/////Monitor JS module
//////////////////////////
mGlobal.Monitor={};
mGlobal.Monitor.ScreenshotModal={};
mGlobal.Monitor.GenerateUniqueID=function(inPrefix="tempUID=") {
return inPrefix+Math.round(Math.random()*1000)+"-"+Math.round(Math.random()*10000)+"-"+Math.round(Math.random()*1000)
}
//inHostURI: http://localhost:8081
mGlobal.Monitor.ScreenshotModal.Show=function(inHostURI=" ") {
$('.ui.modal.daemon-screenshot').modal({'onHide':function (inElement) {mGlobal.Monitor.ScreenshotModal.Close();} }).modal('show');
//Функция обновления картинки
lScreenshotUpdate=function() {
lScreenshotSrc=inHostURI+"/GetScreenshot?"+mGlobal.Monitor.GenerateUniqueID()
$(".daemon-screenshot img").attr('src', lScreenshotSrc);
}
mGlobal.Monitor.ScreenshotModal.timerId=setInterval(lScreenshotUpdate,1500)
}
mGlobal.Monitor.ScreenshotModal.Close=function() {
clearInterval(mGlobal.Monitor.ScreenshotModal.timerId);
}
///Monitor
mGlobal.Monitor.DaemonList={}
mGlobal.Monitor.DaemonList.fRefreshTable=function() {
///Загрузка данных
$.ajax({
type: "GET",
url: 'Monitor/JSONDaemonListGet',
data: '',
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///Сформировать HTML код новой таблицы
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-monitor-table-general",lResponseJSON)
///Очистить дерево
//mGlobal.ElementTree.fClear();
///Прогрузить новую таблицу
$(".openrpa-monitor").html(lHTMLCode)
},
dataType: "text"
});
}
////////////////////////////////
///////Control panel
///////////////////////////////
///Refresh control panel
function sleep(ms) {
ms += new Date().getTime();
while (new Date() < ms){}
}
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
mGlobal.SessionGUIDStr = uuidv4() // Generate uuid4 of the session
//console.log(uuidv4());
mGlobal.RobotRDPActive = {}
mGlobal.Monitor.fControlPanelRefresh_TechnicalRender = function()
{
lResponseJSON = mGlobal.Monitor.mDatasetLast
if (lResponseJSON!= null) {
/// 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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
lItem["OnClick"] = lOnClickEscaped;
}
}
);
/// FooterButtonX1List
lItem["FooterButtonX1List"].forEach(
function(lItem2){
if ('OnClick' in lItem) {
lOnClickEscaped = lItem["OnClick"];
lOnClickEscaped = lOnClickEscaped.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
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
}
}
)
///Прогрузить новую таблицу
$(".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 = '<div class="ui cards">'
for (var lKeyStr in lResponseJSON["CPDict"]){
lCPDict = lResponseJSON["CPDict"][lKeyStr]
/// Render HTML
if ("HTMLStr" in lCPDict) {
lHTMLCode+=lCPDict["HTMLStr"]
}
}
lHTMLCode += '</div>'
///Прогрузить новую таблицу
$(".openrpa-control-panel").html(lHTMLCode)
////////////////////////////////////////////////////
/// !RDP List ! Сформировать HTML код новой таблицы - список RDP
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-hidden-robotrdpactive-control-panel",lResponseJSON["RDPDict"])
//Присвоить ответ в mGlobal.RobotRDPActive.mResponseList
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.pyOpenRPA.ServerDataRefreshDef=function() {
try {
$.ajax({
type: "POST",
headers: {},
url: 'pyOpenRPA/ServerData',
data: mGlobal.pyOpenRPA.ServerDataHashStr,
success: function(lData,l2,l3) {
try {
var lResponseJSON=JSON.parse(lData)
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.pyOpenRPA.ServerDataRefreshDef() // recursive
},
dataType: "text",
error: function(jqXHR, textStatus, errorThrown ) {
setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive
}
});
}
catch(error) {
setTimeout(mGlobal.pyOpenRPA.ServerDataRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerDataRefreshDef() // recursive
}
}
/////////////////////////////////////////////////////////////
/// 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("Разморозить окно логов")
$("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("Заморозить окно логов")
$("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
}
});
}
catch(error) {
setTimeout(mGlobal.pyOpenRPA.ServerLogListRefreshDef,3000)
//sleep(3000)
//mGlobal.pyOpenRPA.ServerLogListRefreshDef() // recursive
}
}
/////////////////////////////////////////////////////////////
mGlobal.Monitor.mDatasetLast = null
///////////////////////////////
///Processor functions
///////////////////////////////
mGlobal.Processor = {}
mGlobal.Processor.ServerValueAppend = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueAppend",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.ServerValueSet = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueSet",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.ServerValueOperatorPlus = function(inKeyList,inValue) {
lData = [
{
"Type":"GlobalDictKeyListValueOperator+",
"KeyList": inKeyList,
"Value": inValue
}
]
///Обнулить таблицу
$('.ui.modal.basic .content').html("");
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Processor.Send = function(inData) {
lData = inData
$.ajax({
type: "POST",
url: 'Utils/Processor',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
///TODO Show error if exist error
},
dataType: "text"
});
}
mGlobal.Server= {}
mGlobal.Server.JSONGet=function(inMethod, inURL, inDataJSON, inCallback)
{
$.ajax({
type: inMethod,
url: inURL,
data: JSON.stringify(inDataJSON),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
inCallback(lResponseJSON)
},
dataType: "text"
});
}
/////////////////
///Modal
///////////////////
mGlobal.Modal={}
/////////////////////////////////////////////////////
mGlobal.Modal.TableFilter={}
mGlobal.Modal.TableFilter.Show=function(inJSON) {
//{
// "Title":"",
// "Headers":["Header1","Header2"],
// "Rows": [["Cell1","Cell2"],["Cell2-1","Cell2-2"]],
// "FilterOnKeyUp": "<JS Code>" //Fill here in function
//}
//Set js handler to Search field
inJSON["FilterOnKeyUp"]="mGlobal.Modal.TableFilter.FilterUpdate(this.value);"
///Set value
mGlobal.Modal.TableFilter.mDataJSON = inJSON
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",inJSON);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
//DO widest modal for table with scroll x
$("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["width"]="1300px"
$("div.ui.basic.modal.transition.visible.active.scrolling")[0].style["overflow"]="scroll"
}
//Service function
mGlobal.Modal.TableFilter.FilterUpdate=function(inFilterValue) {
//Get JSON, apply filter, clone data
lDataJSON = clone(mGlobal.Modal.TableFilter.mDataJSON)
delete lDataJSON["Rows"]
lDataJSON["Rows"]=[]
//Filter code [any occurence in the row is ok for push! ]
mGlobal.Modal.TableFilter.mDataJSON["Rows"].forEach(
function(inElement) {
lFlagElementAppend = false
inElement.forEach(
function(inElement2) {
if (String(inElement2).includes(inFilterValue)) {
lFlagElementAppend = true
}
}
)
if (lFlagElementAppend) {
lDataJSON["Rows"].push(inElement)
}
}
)
//Clear Filter Title property (fixed in html)
delete lDataJSON["FilterOnKeyUp"]
delete lDataJSON["Title"]
//Search the table element [replace only table html]
lElement = $('.ui.modals.active .content table.table')[0]
lElementParentElement = lElement.parentNode
lElement.parentNode.removeChild(lElement);
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-table-filter",lDataJSON);
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
/////////////////////////////////////////////////////////////
mGlobal.Modal.ListFilter={}
mGlobal.Modal.ListFilter.Show=function(inJSON) {
//{
// "Title":"",
// "List":[{"Header":"","Description":""}],
// "FilterOnKeyUp": "<JS Code>" //Fill here in function
//}
//Set js handler to Search field
inJSON["FilterOnKeyUp"]="mGlobal.Modal.ListFilter.FilterUpdate(this.value);"
///Set value
mGlobal.Modal.ListFilter.mDataJSON = inJSON
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",inJSON);
///Установить HTML код
$('.ui.modal.basic .content').html(lHTMLCode);
$('.ui.modal.basic').modal('show');
}
//Service function
mGlobal.Modal.ListFilter.FilterUpdate=function(inFilterValue) {
//Get JSON, apply filter, clone data
lDataJSON = clone(mGlobal.Modal.ListFilter.mDataJSON)
delete lDataJSON["List"]
lDataJSON["List"]=[]
//Filter code [any occurence in the row is ok for push! ]
mGlobal.Modal.ListFilter.mDataJSON["List"].forEach(
function(inElement) {
lFlagElementAppend = false
if (String(inElement["Header"]).includes(inFilterValue)) {
lFlagElementAppend = true
}
if (String(inElement["Description"]).includes(inFilterValue)) {
lFlagElementAppend = true
}
if (lFlagElementAppend) {
lDataJSON["List"].push(inElement)
}
}
)
//Clear Filter Title property (fixed in html)
delete lDataJSON["FilterOnKeyUp"]
delete lDataJSON["Title"]
//Search the table element [replace only table html]
lElement = $('.ui.modals.active .content div.ui.inverted.segment')[0]
lElementParentElement = lElement.parentNode
lElement.parentNode.removeChild(lElement);
//Render HTML
lHTMLCode=mGlobal.GeneralGenerateHTMLCodeHandlebars(".openrpa-handlebar-template-list-filter",lDataJSON);
///Установить HTML код
lElementParentElement.insertAdjacentHTML("beforeend",lHTMLCode);
}
mGlobal.UserRoleHierarchyDict = null // Put here the user role hierarchy
// UAC Ask
mGlobal.UserRoleAsk=function(inList) {
var lResult = true; // Init flag
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;
for (var i = 0; i<lListLength; i++) {
var lItem = inList[i]; // get the item
if (typeof lKeyValue == "object") {
if (lItem in lKeyValue) { // Has key
lKeyValue = lKeyValue[lItem]; // Get the value and go to the next loop iteration
} else { // Else branch - true or false
if (Object.keys(lKeyValue).length > 0) { // false - if Dict has some elements
lResult = false; // Set the False Flag
} else {
lResult = true; // Set the true flag
}
break; // Stop the loop
}
} else { // Has element with no detalization - return true
lResult = true; // Set the flag
break; // Close the loop
}
}
return lResult; // Return the result
}
// Check user roles and update the Orchestrator UI
mGlobal.UserRoleUpdate=function() {
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(); }
if (lUACAsk(["pyOpenRPADict","AdminDict","Debugging"])) { $(".UACClient-pyOpenRPADict-AdminDict-Debugging").show(); }
}
/// v1.2.0 pyOpenRPA Init defs
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
mGlobal.pyOpenRPA.ServerJSInitDef(); // Recieve JS from server (if exist) and then call anothe url ServerData
//$('.ui.dropdown').dropdown();
////////////////////////////////////////////
// 1.2.7 Debugging
/// Execute ActivityItem
// Debugging onchange def autofill init
var lDropdownOnChange = function(inEvent){
//lValueStr = inEvent.target.value
lValueStr = inEvent
$.ajax({
type: "GET",
url: '/pyOpenRPA/Debugging/HelperDefAutofill/'+lValueStr,
data: null,
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
console.log("HelperDefAutofill:")
console.log(lResponseJSON)
//ArgDict merge
var lArgDictTargetDict = lResponseJSON["ArgDict"]
var lArgDictStr = $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value
if (lArgDictStr !="" && lArgDictStr !=null) {
lArgDictLastDict = JSON.parse(lArgDictStr)
lArgDictTargetDict = mGlobal.pyOpenRPA.DebuggingAutofillMerge(lArgDictTargetDict, lArgDictLastDict)
}
$(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value = JSON.stringify(lResponseJSON["ArgList"])
$(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value = JSON.stringify(lArgDictTargetDict)
$(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value = JSON.stringify(lResponseJSON["ArgGSettingsStr"])
$(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value = JSON.stringify(lResponseJSON["ArgLoggerStr"])
},
dataType: "text"
});
}
//$('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')[0].onchange=lDropdownOnChange
mGlobal.pyOpenRPA.DebuggingExecute=function() {
///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)
// }
///Подготовить конфигурацию
lArgListStr = $(".mGlobal-pyOpenRPA-Debugging-ArgList")[0].value
lArgDictStr = $(".mGlobal-pyOpenRPA-Debugging-ArgDict")[0].value
lArgGSettingsStr = $(".mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr")[0].value
lArgLoggerStr = $(".mGlobal-pyOpenRPA-Debugging-ArgLoggerStr")[0].value
lActivityItem = {
"Def":$(".mGlobal-pyOpenRPA-Debugging-Def")[0].value, // def link or def alias (look gSettings["Processor"]["AliasDefDict"])
"ArgList":(lArgListStr == "" ? [] : JSON.parse(lArgListStr)), // Args list
"ArgDict":(lArgDictStr == "" ? {} : JSON.parse(lArgDictStr)), // Args dictionary
"ArgGSettingsStr": (lArgGSettingsStr == "" ? null : lArgGSettingsStr), // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
"ArgLoggerStr": (lArgLoggerStr == "" ? null : lArgLoggerStr) // Name of GSettings attribute: str (ArgDict) or index (for ArgList)
}
lData = [lActivityItem]
$.ajax({
type: "POST",
url: '/pyOpenRPA/ActivityListExecute',
data: JSON.stringify(lData),
success:
function(lData,l2,l3)
{
var lResponseJSON=JSON.parse(lData)
console.log(lResponseJSON)
$(".mGlobal-pyOpenRPA-Debugging-Output")[0].value = JSON.stringify(lResponseJSON[0])
},
dataType: "text"
});
}
mGlobal.pyOpenRPA.DebuggingAutofillMerge=function(inTargetDict, inLastDict) {
// Merge 2 dict (get values from Last dict if key exists in new dict
for (const [lKeyStr, lValue] of Object.entries(inTargetDict)) {
//Check if key exists in LastDict
if (lKeyStr in inLastDict) {
inTargetDict[lKeyStr] = inLastDict[lKeyStr]
}
}
return inTargetDict
}
// 1.2.7 Debugging toolbox init
$('.ui.dropdown.mGlobal-pyOpenRPA-Debugging-Def-Dropdown')
.dropdown({
apiSettings: {
// this url parses query server side and returns filtered results
url: '/pyOpenRPA/Debugging/HelperDefList/{query}'
},
onChange: lDropdownOnChange
})
;
});

@ -0,0 +1,499 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<!-- Yandex.Metrika counter -->
<script async="" src="https://mc.yandex.ru/metrika/tag.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88079149, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/88079149" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Оркестратор pyOpenRPA</title>
<meta name="description" content="Ведущий RPA разработчик российского программного обеспечения. RPA платформа позволяет решать любые бизнес-задачи. Комплексное решение от компании RPA pyOpenRPA. Первое открытое российское RPA решение для крупного / среднего / малого бизнеса. Доступная автоматизация для каждого.">
<meta name="keywords" content="rpa, программные роботы, автоматизация бизнес-процессов, цифровые сотрудники, виртуальные сотрудники">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/Semantic-UI-CSS-master/semantic.min.css">
<link rel="stylesheet" type="text/css" href="/orpa/Resources/Web/orpa/styleset/home.css">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script
src="/orpa/Resources/Web/jQuery/jquery-3.1.1.min.js"
crossorigin="anonymous"></script>
<script src="/orpa/Resources/Web/Semantic-UI-CSS-master/semantic.min.js"></script>
<script src="/orpa/Resources/Web/Handlebars/handlebars-v4.1.2.js"></script>
<script src = "/orpa/Resources/Web/orpa/orc.js"></script>
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
}
.overlay .menu {
position: relative;
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);
}
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 5em 0em 0em;
padding: 5em 0em;
}
.ui.search.dropdown>input.search {
width:100%;
font-family:monospace;
font-weight: bold;
}
.ui.search.dropdown>.text {
width:100%;
font-family:monospace;
font-weight: bold;
}
</style>
</head>
<body>
{% include 'header.xhtml' %}
<div class="ui aligned stackable grid container">
<div class="row">
<div class="sixteen wide column openrpa-control-panel-general UACClient-pyOpenRPADict-CPKeyDict" style="display:none;" >
<h4 class="ui horizontal divider header" style="margin-bottom:30px;margin-top:30px;">
<i class="clipboard list icon"></i>
Роботы
</h4>
<div class="openrpa-control-panel"></div>
<script class="openrpa-hidden-control-panel" style="display:none" type="text/x-handlebars-template">
<div class="ui cards">
{% raw %}
{{#RenderRobotList}}
<div class="card">
<div class="content">
<div class="right floated mini ui ">
{{{HeaderRightText}}}
</div>
<div class="header">
{{{HeaderLeftText}}}
</div>
<div class="meta">
{{{SubheaderText}}}
</div>
<div class="description">
<ul style="padding-inline-start:16px;margin:0px">
{{#BodyKeyValueList}}
<li>{{{Key}}}: {{{Value}}}</li>
{{/BodyKeyValueList}}
</ul>
</div>
</div>
<div class="extra content">
{{{FooterText}}}
</div>
<div class="extra content">
<div class="ui two buttons">
{{#FooterButtonX2List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX2List}}
</div>
<div class="ui horizontal divider">Add. controls</div>
<div class="ui one buttons">
{{#FooterButtonX1List}}
<div class="ui basic {{Color}} button" onclick="{{OnClick}}">{{{Text}}}</div>
{{/FooterButtonX1List}}
</div>
</div>
</div>
{{/RenderRobotList}}
{% endraw %}
</div>
</script>
</div>
</div>
<div class="row">
<script class="openrpa-hidden-monitor-table-general" style="display:none" type="text/x-handlebars-template">
{% raw %}
<table class="ui celled table">
<thead>
<tr>
<th>Machine name</th>
<th>Machihe host</th>
<th>Status</th>
<th>Actions,length: {{childs.length}}</th>
</tr>
</thead>
<tbody>
{{#ListenURLList}}
<tr><td>{{Description}}</td><td>{{URL}}</td><td class="negative">None</td></tr>
{{/ListenURLList}}
</tbody>
</table>
{% endraw %}
</script>
<script class="openrpa-handlebar-template-table-filter" style="display:none" type="text/x-handlebars-template">
{% raw %}
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<table class="ui celled table selectable inverted">
<thead>
<tr>
{{#Columns}}
<th>{{{this}}}</th>
{{/Columns}}
</tr>
</thead>
<tbody>
{{#Rows}}
<tr>
{{#this}}
<td>
{{{this}}}
</td>
{{/this}}
</tr>
{{/Rows}}
</tbody>
</table>
{% endraw %}
</script>
<script class="openrpa-handlebar-template-list-filter" style="display:none" type="text/x-handlebars-template">
{% raw %}
{{#if Title}}
<h1>{{{Title}}}</h1>
{{/if}}
{{#if FilterOnKeyUp}}
<div class="ui icon input search" style="width:500px;">
<input type="text" onkeyup="{{#if FilterOnKeyUp}}{{{FilterOnKeyUp}}}{{/if}}" placeholder="Search...">
<i class="inverted circular search link icon"></i>
</div>
{{/if}}
<div class="ui inverted segment">
<div class="ui inverted relaxed divided list">
{{#List}}
<div class="item">
<i class="map marker icon"></i>
<div class="content">
<a class="header">{{{Header}}}</a>
<div class="description">{{{Description}}}</div>
</div>
</div>
{{/List}}
</div>
</div>
{% endraw %}
</script>
<div class="eight wide column openrpa-robotrdpactive-control-panel-general UACClient-pyOpenRPADict-RDPKeyDict" style="display:none;">
<h2 class="ui header openrpa-rdpactive-title">
<i class="desktop icon"></i>
<div class="content">
РДП сессии
</div>
</h2>
<div class="openrpa-robotrdpactive-control-panel"></div>
<script class="openrpa-hidden-robotrdpactive-control-panel" style="display:none" type="text/x-handlebars-template">
<div class="ui inverted segment" style="background: #368279">
{% raw %}
<div class="ui inverted relaxed divided list">
{{#HandlebarsList}}
<div class="item">
<div class="right floated content">
<div class="ui button" onclick="mGlobal.Processor.ServerValueAppend(['RobotRDPActive','ActivityList'],{'DefNameStr': 'RDPSessionReconnect', 'ArgList': [], 'ArgDict': {'inRDPSessionKeyStr': '{{{SessionKeyStr}}}'} })" >Переподключить</div>
</div>
<div class="right floated content">
{{#if IsIgnoredBool}}
<div class="ui button red" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],false);">Игнорировать</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','RDPList','{{{SessionKeyStr}}}','SessionIsIgnoredBool'],true);">Игнорировать</div>
{{/if}}
</div>
<div class="right floated content">
{{#if IsFullScreenBool}}
<div class="ui button green" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],null);">Полный экран</div>
{{else}}
<div class="ui button" onclick="mGlobal.Processor.ServerValueSet(['RobotRDPActive','FullScreenRDPSessionKeyStr'],'{{{SessionKeyStr}}}');">Полный экран</div>
{{/if}}
</div>
<div class="content">
<div class="header">Session key: {{{SessionKeyStr}}}</div>
{{{SessionHexStr}}}
</div>
</div>
{{/HandlebarsList}}
</div>
{% endraw %}
</div>
</script>
</div>
<div class="eight wide column UACClient-pyOpenRPADict-AgentKeyDict" style="display:none">
<h2 class="ui header " style="">
<i class="bug icon"></i>
<div class="content">
Агент подключения
</div>
</h2>
<div class="pyOpenRPA-Agent-List"></div>
<script class="pyOpenRPA-Agent-ListTemplate" style="display:none" type="text/x-handlebars-template">
<div class="ui inverted segment" style="background: #368279">
{% raw %}
<div class="ui inverted relaxed divided list">
{{#HandlebarsList}}
<div class="item">
<div class="right floated content">
{{#if IsListenBool}}
<i class="circle icon green"></i>
Доступен
{{else}}
<i class="circle icon red"></i>
Недоступен
{{/if}}
</div>
<div class="content">
<div class="header">Хост: {{{HostnameUpperStr}}}, Пользователь: {{{UserUpperStr}}}</div>
</div>
</div>
{{/HandlebarsList}}
</div>
{% endraw %}
</div>
</script>
</div>
</div>
<div class="row openrpa-monitor">
</div>
<div class="row">
<div class="sixteen wide column" style="">
<h2 class="ui header">
<i class="settings icon"></i>
<div class="content">
Администрирование
</div>
</h2>
</div>
</div>
<div class="row">
<div class="sixteen wide column" style="">
<h4 class="ui horizontal divider header" >
<i class="clipboard list icon"></i>
Логи
</h4>
<textarea class="mGlobal-pyOpenRPA-ServerLogList UACClient-pyOpenRPADict-AdminDict-LogViewerBool" readonly="readonly" style="width:100%; display:none; resize: none; font-family:monospace; font-weight: bold;" id="textarea_id" rows="20">
</textarea>
<a class="mGlobal-pyOpenRPA-ServerLogListDoRender" onclick="" style="cursor: pointer;">Заморозить окно логов</a>
</div>
</div>
<div class="row ui">
<div class="sixteen wide column ui" style="margin-bottom:30px;">
<h4 class="ui horizontal divider header" >
<i class="settings icon"></i>
Терминал
</h4>
</div>
<div class="eight wide column ui">
<div class="ui fluid input UACClient-pyOpenRPADict-AdminDict-CMDInputBool" style="display:none;">
<input class="openrpa-controller-cmd-run-input" type="text" placeholder="Скрипт для терминала..." style="min-width:250px;">
</div>
</div>
<div class="three wide column ui">
<div class="ui button green" onclick="mGlobal.Controller.CMDRun();" style="">Выполнить</div>
</div>
<div class="five wide column ui">
<div class="ui button" onclick="mGlobal.Controller.CMDRunGUILogout();" style="">Выйти из сессии</div>
</div>
</div>
<div class="row UACClient-pyOpenRPADict-AdminDict-Debugging" style= "display:none;">
<div class="twelve wide column">
<h4 class="ui horizontal divider header" >
<i class="bug icon"></i>
Отладка - Отправить
</h4>
<div class="ui labeled input">
<div class="ui label">Def</div>
</div>
<div class="ui fluid search selection dropdown mGlobal-pyOpenRPA-Debugging-Def-Dropdown" style="margin-bottom:10px;">
<input class="mGlobal-pyOpenRPA-Debugging-Def" type="hidden" name="country" style="width:100%; font-family:monospace; font-weight: bold;">
<i class="dropdown icon"></i>
<div class="default text">Def</div>
<div class="menu">
<div class="item" data-value="eh">pyOpenRPA... sys.. os.. </div>
</div>
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgList
</div>
<input type="text" placeholder="[1,2,3]" class="mGlobal-pyOpenRPA-Debugging-ArgList" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgDict
</div>
<input type="text" placeholder="{&quot;Key1&quot;:&quot;Value1&quot;}" class="mGlobal-pyOpenRPA-Debugging-ArgDict" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgGSettingsStr
</div>
<input type="text" placeholder="inGSettings" class="mGlobal-pyOpenRPA-Debugging-ArgGSettingsStr" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid labeled input" style="margin-bottom:10px;">
<div class="ui label">
ArgLoggerStr
</div>
<input type="text" placeholder="inLogger" class="mGlobal-pyOpenRPA-Debugging-ArgLoggerStr" style="width:100%; font-family:monospace; font-weight: bold;">
</div>
<div class="ui fluid button" onclick="mGlobal.pyOpenRPA.DebuggingExecute();">Выполнить</div>
</div>
<div class="four wide column">
<h4 class="ui horizontal divider header" >
<i class="bug icon"></i>
Отладка - Получить
</h4>
<p><textarea class="mGlobal-pyOpenRPA-Debugging-Output" readonly="readonly" style="width:100%; font-family:monospace; font-weight: bold;" rows="16" cols="60"></textarea></p>
</div>
</div>
<h4 class="ui horizontal divider header">
<i class="clipboard list icon"></i>
Управление
</h4>
<div class="row ui buttons">
<div class="ui animated button openrpa-control-lookmachinescreenshot green UACClient-pyOpenRPADict-AdminDict-ScreenshotViewerBool" onclick="mGlobal.Monitor.ScreenshotModal.Show();" style="display: none; margin-top: 5px;">
<div class="visible content">Смотреть экран</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-restartorchestrator orange UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorBool" onclick="mGlobal.Controller.OrchestratorRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Перезагрузить оркестратор</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-gitrestartorchestrator teal UACClient-pyOpenRPADict-AdminDict-RestartOrchestratorGITPullBool" onclick="mGlobal.Controller.OrchestratorGITPullRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Обновить из GIT</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
<div class="ui animated button openrpa-control-restartpc red UACClient-pyOpenRPADict-AdminDict-RestartPCBool" onclick="mGlobal.Controller.PCRestart();" style="display: none; margin-top: 5px;">
<div class="visible content">Перезагрузить ОС</div>
<div class="hidden content">
<i class="right arrow icon"></i>
</div>
</div>
</div>
</div>
{% include 'footer.xhtml' %}
<div class="ui basic modal">
<div class="ui icon header">
</div>
<div class="content">
<p>Добро пожаловать!</p>
</div>
<div class="actions">
<div class="ui red basic cancel inverted button">
<i class="remove icon"></i>
Нет
</div>
<div class="ui green ok inverted button">
<i class="checkmark icon"></i>
Да
</div>
</div>
</div>
<div class="ui daemon-screenshot modal">
<div class="ui icon header">
</div>
<div class="content">
<img src="GetScreenshot" class="ui fluid image">
</div>
<div class="actions">
<div class="ui green ok inverted button" onclick="mGlobal.Monitor.ScreenshotModal.Close()">
<i class="checkmark icon"></i>
Закрыть
</div>
</div>
</div>
<div class="ui modal openrpa-code-list-gui-import-modal">
<i class="close icon"></i>
<div class="header">
СПисок действий
</div>
<div class="content">
<div class="description">
<div class="ui header">Вставить JSON спецификацию:</div>
<p><textarea style="width:100%" rows="6" cols="60"></textarea></p>
</div>
</div>
<div class="actions">
<div class="ui black deny button">
Отменить
</div>
<div class="ui positive right labeled icon button" onclick="mGlobal.CodeList.fActionSpecificationImportFromJSON();">
Распознать
<i class="checkmark icon"></i>
</div>
</div>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save