v.1.3.0 is published!

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

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

@ -1,13 +1,13 @@
pyOpenRPA-1.2.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.2.14.dist-info/METADATA,sha256=msxiHoe4JlRNqXnlKGZWthHNr5JPV7OWXJzgXwzZTcc,4372
pyOpenRPA-1.2.14.dist-info/RECORD,,
pyOpenRPA-1.2.14.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.2.14.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/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.3.0.dist-info/METADATA,sha256=V-qwlFCJ26LQShABSS0p5Tm9vxOXMYqrahL40zkthnI,4378
pyOpenRPA-1.3.0.dist-info/RECORD,,
pyOpenRPA-1.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.3.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.3.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
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/__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/__pycache__/A2O.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/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
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/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=nBJqwBd6y9yeE49XOn83r8Dtvb3yReujrp-frxOhNL8,16671
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=PZzh_RUke8bIMGghCXTnEuTYICCwW71r2xXk7iTdUnU,17345
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=VCXXc-enJhvrAJvYc8jHK9GcGe02meMdszU0tlJDHiQ,12879
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=4LJNMrt61AJKI3p7SeXnUSEpA61BtqWVxaVYxYS_BaI,42221
pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71
pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Process.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/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
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/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405
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/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462
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__/__main__.cpython-37.pyc,,
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/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=YOQgZQ97nM_XQYVRbusj_b50aqEiNBJFF3bs7wA-O6k,36240
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=260YPXINLrora8pBBVHQSPNBkc8wdlyadsoQTQKdpAs,32590
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=TR6WQVm-0sFoQjnV08t9K5oQOcpC7dbKOnWQS31m9dQ,21443
pyOpenRPA/Orchestrator/Server.py,sha256=eYiXKvWsiBG_kfHtzdNX4Zu2xL2DjkJZXqBfqOgHAk4,38600
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=wZe5aEUJOWYol8WzKUQBRq9JEnXj0Z39554PAIoqvbw,34326
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=dVL-JZpAUQP3LLXE_7IUuE7RkLTYBAA-RX4e5FZ_DU0,21499
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681
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/__pycache__/Basic.cpython-37.pyc,,
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/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273
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/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/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/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071
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/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
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/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591
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/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
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/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119
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__/__init__.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/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655
pyOpenRPA/Tools/RobotDB/Server.py,sha256=rjW9Sg-j9P8pFQD66Uih-rke6-f6sCulinwi4_W-3mc,19933
pyOpenRPA/Tools/RobotDB/Server.py,sha256=idGpXDU9rPv-NZcOW1Wrku_acEqEYnhSXNtUmFTs1dU,20019
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -351,7 +390,7 @@ pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/StopSafe.py,sha256=BNTtMmvsRE1Wtri3EkwhoBi6gGOjEPRQnJSV1C03c84,2176
pyOpenRPA/Tools/StopSafe.py,sha256=BIMiW8cFyQfX3KpRHaspdbw6-FcImTilqXRC_XXzyik,2346
pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490
pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996
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__/Usage.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/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
lAgentLimitLogSizeBytesInt = 500
if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"ActivityItem from orchestrator: {lQueueItem}");
if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: {lQueueItem}")
else:
if lL: lL.info(f"ActivityItem from orchestrator: Supressed - big size. Size is {lBodyLenInt} bytes");
if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: содержимое свернуто из-за большого размера ({lBodyLenInt} байт")
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:
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)
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)
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"])
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"])
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"])
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"])

@ -3,66 +3,69 @@ from . import O2A, A2O # Data flow Orchestrator To Agent
from . import Processor # Processor Queue
from ..Tools import Usage
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
gSettings = None
# Create binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Создать бинарный файл на стороне Агента по полученной строке в формате base64 (формат безопасен для передачи по JSON протоколу)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "wb")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Append binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Create binary file by the base64 string (safe for JSON transmition)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "ab")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Create text file by the string
def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None):
"""
Create text file in the agent GUI session
"""L+,W+:Создать текстовый файл на стороне Агента
:param inFilePathStr: File abs path
:param inFileDataStr: File data text content
:param inEncodingStr: Write file encoding
:param inGSettings: global settings of the Agent (singleton)
:param inFilePathStr: Абсолютный путь к создаваемому файлу
:param inFileDataStr: Текст, отправляемый в создаваемый файл
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный файл настроек
:return:
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "w", encoding=inEncodingStr)
lFile.write(inFileDataStr)
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
"""
Read binary file and encode in base64 to transmit (safe for JSON transmition)
"""L+,W+: Прочитать бинарный файл на стороне агента и отправить на сторону оркестратора в формате base64 (формат безопасный для передачи в формате JSON)
:param inFilePathStr: File path to read
:param inGSettings: global settings of the Agent (singleton)
:return: File content in string base64 format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inGSettings: Глобальный словарь настроек Агента (необязательный)
:return: Содержимое бинарного файле, преобразованное в формат base64 (используй base64.b64decode для декодирования в байты). Вернет None запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lFileDataBase64Str = None
if os.path.exists(inFilePathStr):
@ -70,56 +73,55 @@ def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
lFileDataBytes = lFile.read()
lFile.close()
lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8")
lMessageStr = f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} has been read"
lMessageStr = f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} прочитан успешно"
if lL: lL.debug(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else:
if lL: lL.debug(f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} не существует - отправить None")
return lFileDataBase64Str
def OSFileMTimeGet(inFilePathStr: str) -> float or None:
"""
Read file modification time timestamp format (float)
"""L+,W+: Read file modification time timestamp format (float)
:param inFilePathStr: File path to read
:return: timestamp (float) Return None if file is not exist
:param inFilePathStr: Абсолютный путь к файлу, дату которого требуется получить
:return: Временной слепок (timestamp) в формате float. Вернет None, если запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
global gSettings
lL = gSettings.get("Logger", None) if type(gSettings) is dict else None
lFileMTimeFloat = None
if os.path.exists(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:
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileMTimeGet: file {inFilePathStr} не существует - вернуть None")
return lFileMTimeFloat
def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None):
"""
Read text file in the agent GUI session
"""L+,W+: Прочитать текстовый файл на стороне агента и отправить на сторону оркестратора
:param inFilePathStr: File abs path
:param inEncodingStr: Read file encoding. Default utf-8
:param inGSettings: global settings of the Agent (singleton)
:return: File text content in string format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный словарь настроек
:return: Строка - содержимое текстового файла. Возвращает None, если файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFileDataStr = None
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
if os.path.exists(inFilePathStr):
lFile = open(inFilePathStr, "r", encoding=inEncodingStr)
lFileDataStr = lFile.read()
lFile.close()
lMessageStr = f"OSFileTextDataStrReceive: file {inFilePathStr} has been read"
lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} прочитан успешно"
if lL: lL.info(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else:
if lL: lL.info(f"OSFileTextDataStrReceive: file {inFilePathStr} is not exists - return None")
if lL: lL.info(f"АГЕНТ: Текстовый файл {inFilePathStr} не существует - вернуть None")
return lFileDataStr
# 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):
"""
Execute CMD on the Agent daemonic process
"""L-,W+: Execute CMD on the Agent daemonic process
:param inCMDStr: command to execute on the Agent session
: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:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else:
if CrossOS.IS_WINDOWS_BOOL:
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
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been STARTED # # # # "
lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия запущена # # # # "
if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr])
@ -172,7 +177,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
time.sleep(2)
else:
lListenBool = False
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been FINISHED # # # # "
lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия завершена # # # # "
if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
@ -181,7 +186,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inRunAsyncBool:
lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool })
lThread.start()
lResultStr="ActivityList has been started in async mode - no output is available here."
lResultStr="Список ActivityList отправлен на исполнение в асинхронном режиме - захват текста недоступен"
else:
lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool)
#lCMDCode = "cmd /c " + inCMDStr
@ -191,11 +196,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
def ProcessWOExeUpperUserListGet():
"""
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
"""L-,W+: Вернуть список процессов, запущенных под пользователем на стороне агента
:param inProcessNameWOExeList:
:return: list of the agent user process in upper case without .EXE. Example ["NOTEPAD","..."],
:return: Список процессов в формате: ["NOTEPAD","..."] (без постфикса .exe и в верхнем регистре)
"""
lUserNameStr = getpass.getuser()
@ -238,7 +241,7 @@ def Agent(inGSettings):
lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings})
lProcessorThread.daemon = True # Run the thread in daemon mode.
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)
lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings})
@ -247,4 +250,4 @@ def Agent(inGSettings):
# 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
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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
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"]:
lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]
if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key
if lL: lL.debug(f"Client request lifetime is over")
if lL: lL.debug(f"Время жизни HTTP запроса истекло - удалить из отслеживаемых!")
lDoWhileBool = False # Stop the iterations
if lDoWhileBool:
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)
}
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
@ -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
"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
inGSettings["Client"] = { # Settings about client web orchestrator
"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
inGSettings["Server"]["RequestTimeoutSecFloat"] = 300 # Time to handle request in seconds
if lL: lL.warning(
f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility
if "DefSettingsUpdatePathList" not in inGSettings["OrchestratorStart"]: # Add OrchestratorStart > "DefSettingsUpdatePathList" property
inGSettings["OrchestratorStart"]["DefSettingsUpdatePathList"] = [] # List of the .py files which should be loaded before init the algorythms
if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Преобразовать структуру 'OrchestratorStart' > 'DefSettingsUpdatePathList'") # Log about compatibility
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# v1.1.20 to v1.2.0
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@ -338,14 +338,14 @@ def Update(inGSettings):
"DumpLogList": [], # Will be filled automatically
"DumpLogListHashStr": None, # Will be filled automatically
})
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'Client > DumpLog... with default parameters'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать атрибут 'Client > DumpLog... с параметрами по умолчанию'") # Log about compatibility
if "Processor" in inGSettings: # Check if Processor exist
# Update Logger
if lL is not None:
SettingsTemplate.LoggerDumpLogHandlerAdd(inLogger=lL, inGSettingsClientDict=inGSettings["Client"])
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Add web dump log in logger as handler") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Добавить веб дамп для отображения лога на веб клиенте оркестратора") # Log about compatibility
del inGSettings["Processor"] # Remove the key
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Remove old structure 'Processor'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Удалить структуру старого процессора 'Processor'") # Log about compatibility
if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure
inGSettings["ProcessorDict"]={
"ActivityList": [ # List of the activities
@ -361,14 +361,14 @@ def Update(inGSettings):
"ExecuteBool": True, # Flag to execute thread processor
"ThreadIdInt": None # Fill thread id when processor will be inited
}
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'ProcessorDict'") # Log about compatibility
if "VersionStr" not in inGSettings: # Create new ProcessorDict structure
inGSettings["VersionStr"] = None
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'VersionStr'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'VersionStr'") # Log about compatibility
if "AgentDict" not in inGSettings: # Create new AgentDict structure
inGSettings["AgentDict"]= {}
if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'AgentDict'") # Log about compatibility
f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'AgentDict'") # Log about compatibility
# Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy
# if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())]
@ -379,7 +379,7 @@ def Update(inGSettings):
# Check if Server is active > convert to ServerDict
inGSettings["ServerDict"] = inGSettings["Server"]
if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility
f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Server' -> 'ServerDict'") # Log about compatibility
# Remove old structure Scheduler
del inGSettings["Server"]
lShowWarnBool = False
@ -401,7 +401,7 @@ def Update(inGSettings):
# remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate
#del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"]
if lShowWarnBool: # Show only 1 warning per all run
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert CP allowed list to UAC Client hierarchy (consolidated)") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Интегрировать структуру доступа к панелям управления в общую UAC иерархию") # Log about compatibility
# Check if ControlPanelDict is active > convert to CPDict
if "ControlPanelDict" in inGSettings:
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}
# Remove old structure ControlPanel
del inGSettings["ControlPanelDict"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'ControlPanelDict' -> 'CPDict'") # Log about compatibility
# Check if Scheduler is active > convert to SchedulerDict
if "Scheduler" in inGSettings:
if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]}
@ -423,27 +423,27 @@ def Update(inGSettings):
inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict)
# Remove old structure Scheduler
del inGSettings["Scheduler"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Scheduler to SchedulerDict with new features") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Scheduler' -> 'SchedulerDict' с новыми функциональными возможностями") # Log about compatibility
# # Convert to Storage to StorageDict
if "Storage" in inGSettings:
# Check if Server is active > convert to ServerDict
inGSettings["StorageDict"] = inGSettings["Storage"]
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
del inGSettings["Storage"]
# Add new key WarningExecutionMoreThanSecFloat in ProcessorDict
if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0
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
if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0
inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0
inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0
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
if "RecoveryDict" not in inGSettings["RobotRDPActive"]:
inGSettings["RobotRDPActive"]["RecoveryDict"] = {
@ -457,7 +457,7 @@ def Update(inGSettings):
}
}
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
if "ListenDict" not in inGSettings["ServerDict"]:
lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80)
@ -471,7 +471,7 @@ def Update(inGSettings):
}
}
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
#"ServerDict": {
# "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition
@ -479,24 +479,24 @@ def Update(inGSettings):
if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000
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"]:
inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2
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"]:
inGSettings["ServerDict"]["ServerThread"]= None
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"]:
inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300
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
if "ControlPanelDict" in inGSettings:
del inGSettings["ControlPanelDict"]
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:
for lCPKeyStr in inGSettings["CPDict"]:
lCPItemDict = inGSettings["CPDict"][lCPKeyStr]
@ -505,40 +505,40 @@ def Update(inGSettings):
inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"])
del inGSettings["CPDict"]
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"]:
inGSettings["ServerDict"]["ControlPanelDict"]={}
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
if "ManagersProcessDict" not in inGSettings:
inGSettings["ManagersProcessDict"]={}
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
if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None:
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
if "ManagersGitDict" not in inGSettings:
inGSettings["ManagersGitDict"]={}
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
if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None
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
for lURLItemDict in inGSettings["ServerDict"]["URLList"]:
if "UACBool" not in lURLItemDict:
lURLItemDict["UACBool"]=None
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"
if "URLIndexStr" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["URLIndexStr"] = "/"
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
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
self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
@ -116,7 +116,7 @@ class ControlPanel():
self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True)
self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def RefreshHTMLJinja2StrGenerate(self, inDataDict):
"""
@ -145,7 +145,7 @@ class ControlPanel():
self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True)
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def InitJSJinja2StrGenerate(self, inDataDict):
"""
@ -290,7 +290,7 @@ class ControlPanel():
# Call backward compatibility HTML generator
lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult)
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
@ -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:
lResultDict = lJSONResult
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:
if lL: lL.exception(
f"Error in control panel JSONGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
f"Ошибка при формирвоании JSON (JSONGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultDict
def BackwardAdapterJSDef(self,inRequest):
@ -343,8 +343,8 @@ class ControlPanel():
if type(lJSResult) is str:
lResultStr = lJSResult # Add delimiter to some cases
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:
if lL: lL.exception(
f"Error in control panel JSInitGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
f"Ошибка в функции формирования кода JavaScript (JSInitGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultStr

@ -34,7 +34,7 @@ class Git():
self.mAgentHostNameStr = inAgentHostNameStr
self.mAgentUserNameStr = inAgentUserNameStr
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):
"""
@ -151,11 +151,11 @@ class Git():
:param inBranchRemoteStr: [description]
: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
lCMDResultStr = None
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
self.ProcessListSaveStopSafe()
lBranchNameCurrentStr = self.BranchNameGet()
@ -170,7 +170,7 @@ class Git():
# checkout to the source branch which was
self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr)
# 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()
return lCMDResultStr

@ -108,7 +108,7 @@ class Process():
__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict)
if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
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:
"""
@ -145,7 +145,7 @@ class Process():
self.mStatusStr = "1_STOPPED_MANUAL"
# Log info about process
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
def ManualStopListClear(self) -> None:
@ -180,7 +180,7 @@ class Process():
"""
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:
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)
return self.mStatusStr
# Send activity item to agent - wait result
@ -259,7 +259,7 @@ class Process():
if "SAFE" in self.mStatusStr:
# Log info about process
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)
# Log info about process
# 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"
elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL"
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
@ -358,7 +358,7 @@ class Process():
"""Call from orchestrator when init
"""
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)
def StatusRestore(self):
@ -377,7 +377,7 @@ class Process():
self.StopSafe(inIsManualBool=True)
if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr:
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.mStatusSavedStr = None
return self.mStatusStr
@ -390,7 +390,7 @@ class Process():
"""
# Log info about process
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):

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

@ -62,22 +62,22 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
try:
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
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
except ConnectorExceptions.SessionWindowNotExistError as e:
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.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings)
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
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)
# general exceptions
except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging
if lL: lL.exception(f"!!! ВНИМАНИЕ !!! Неопознанная ошибка. Обратитесь в тех. поддержку pyOpenRPA") #Logging
pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Connector.SystemRDPWarningClickOk() # Click all warning messages
@ -125,7 +125,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e:
if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging
if lL: lL.exception(f"РДП: Ошибка при обработке активности в процессоре РДП сессии - активность будет проигнорирована. Активность: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
@ -137,7 +137,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e:
# 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:
# Wait for the next iteration
time.sleep(0.7)
@ -145,4 +145,4 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1)
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)
Screen.ConsoleScreenBase()
#Delay to create console screen
time.sleep(5)
time.sleep(15)
#Delay
time.sleep(inIntervalSeconds)
return None

@ -24,12 +24,13 @@ import uuid
import datetime
import os #for path operations
from http import cookies
global gSettingsDict
gSettingsDict = {}
from . import ServerSettings
from . import __Orchestrator__
import copy
import mimetypes
mimetypes.add_type("font/woff2",".woff2")
mimetypes.add_type("text/javascript",".js")
gCacheDict = {}
@ -82,6 +83,7 @@ def AuthenticateVerify(inRequest):
######################################
#Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
global gSettingsDict
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -147,6 +149,7 @@ def AuthenticateBlock(inRequest):
def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict
#pdb.set_trace()
global gSettingsDict
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"]
@ -261,6 +264,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to get hierarchy of the current user roles
# if return {} - all is available
def UserRoleHierarchyGet(self):
#global gSettingsDict
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
@ -268,6 +272,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#Tech def
#return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False):
global gSettingsDict
###############################
#Tech sub def - do item
################################
@ -288,18 +293,22 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
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")
# Write content as utf-8 data
inResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
# detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None:
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
lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"")
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}")
#Check if file exist
if os.path.exists(lFilePath) and os.path.isfile(lFilePath):
@ -345,6 +354,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None:
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 inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= "application/octet-stream"
@ -420,6 +431,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
@ -493,33 +507,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
# 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:
#Set access denied code
# Send response status code
self.send_response(403)
# Send 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:
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
def do_POST(self):
try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
lL = gSettingsDict["Logger"]
self.OpenRPA = {}
@ -603,7 +608,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lActivityTypeListStr += f"{lInputObject['Type']}"
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
if lL: lL.info(f"Server:: !ATTENTION! /Utils/Processor will be deprecated in future. Use /pyOpenRPA/Processor or /pyOpenRPA/ActivityListExecute. User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}")
if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}")
# Send message back to client
message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject))
# Write content as utf-8 data
@ -616,20 +621,35 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers
self.end_headers()
return
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_POST): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e:
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
#!Turn it on to stop print in console
#def log_message(self, format, *args):
# return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True
"""Handle requests in a separate thread."""
def finish_request(self, request, client_address):
try:
global gSettingsDict
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
# "JSONConfigurationDict":<JSON>
import ssl
@ -640,6 +660,7 @@ class RobotDaemonServer(Thread):
# Update the global dict
ServerSettings.SettingsUpdate(inGlobalDict)
def run(self):
global gSettingsDict
lL = gSettingsDict.get("Logger",None)
try:
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)
else:
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:
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')
httpd.serve_forever()
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,
getRectAsImage, getDisplaysAsImages)
if CrossOS.IS_LINUX_BOOL: pass
if CrossOS.IS_LINUX_BOOL: import pyscreeze
from http import cookies
import uuid # generate UUID4
@ -197,9 +197,9 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
# Get Screenshot
def SaveScreenshot(inFilePath):
# grab fullscreen
# Save the entire virtual screen as a PNG
# Save the entire virtual screen as a PNsG
lScreenshot = getScreenAsImage()
lScreenshot.save('screenshot.png', format='png')
lScreenshot.save('Screenshot.png', format='png')
# lScreenshot = ScreenshotSecondScreen.grab_screen()
# save image file
# lScreenshot.save('screenshot.png')
@ -211,7 +211,13 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
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
# Body is Activity item or Activity List
@ -233,7 +239,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr)
# Separate into 2 lists - sync and async
@ -259,7 +265,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
try:
lActivityTypeListStr = lInput['Def']
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr)
if lInput.get("ThreadBool",False) == False:
@ -288,7 +294,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute")
if lL: lL.info(lWebAuditMessageStr)
# Execution
@ -301,7 +307,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
try:
lActivityTypeListStr = lInput['Def']
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,
inOperationCodeStr=lActivityTypeListStr,
inMessageStr="pyOpenRPA_ActivityListExecute")
@ -432,13 +438,13 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr]
# Create item in gSettings
inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue)
lLogStr = "x bytes"
lLogStr = "x байт"
try:
if lActivityReturnItemValue is not None:
lLogStr = f"{len(lActivityReturnItemValue)} bytes"
lLogStr = f"{len(lActivityReturnItemValue)} байт"
except Exception as e:
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
if lAgentDictItemKeyTurple in inGSettings["AgentDict"]:
lAgentDictActivityListNew = []
@ -448,11 +454,23 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lAgentDictActivityListNew.append(lActivityItem)
else:
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
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):
import os
import pyOpenRPA.Orchestrator
gSettingsDict = __Orchestrator__.GSettingsGet()
if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1])
if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1])
lURLList = \
@ -467,7 +485,10 @@ def SettingsUpdate(inGlobalConfiguration):
# "ResponseDefRequestGlobal": None #Function with str result
#}
#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": "/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.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},

@ -1,5 +1,7 @@
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
def __Create__():
@ -340,7 +342,7 @@ def Create(inModeStr="BASIC", inLoggerLevel = None):
lL.setLevel(logging.INFO)
# create the logging file handler
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')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# 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
*******************************/

@ -154,7 +154,7 @@ def run():
server_address = (inServerAddress, inPort)
httpd = HTTPServer(server_address, testHTTPServer_RequestHandler)
# 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)}")
Usage.Process(inComponentStr="Studio")

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

@ -26,7 +26,7 @@ def Init(inLogger=None):
gIsSignalCloseBool = False # Init default
gLogger = inLogger
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.start()
#shutdown_thread.join()
@ -62,5 +62,5 @@ def _shutdown_monitor():
win32gui.PumpMessages()
gIsSignalCloseBool = True # WM_CLOSE message has come
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
"""
__version__ = 'v1.2.14'
__version__ = 'v1.3.0'
__all__ = []
__author__ = 'Ivan Maslov <ivan.maslov@pyopenrpa.ru>'
#from .Core import Robot

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

@ -1,13 +1,13 @@
pyOpenRPA-1.2.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.2.14.dist-info/METADATA,sha256=msxiHoe4JlRNqXnlKGZWthHNr5JPV7OWXJzgXwzZTcc,4372
pyOpenRPA-1.2.14.dist-info/RECORD,,
pyOpenRPA-1.2.14.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.2.14.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/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
pyOpenRPA-1.3.0.dist-info/METADATA,sha256=V-qwlFCJ26LQShABSS0p5Tm9vxOXMYqrahL40zkthnI,4378
pyOpenRPA-1.3.0.dist-info/RECORD,,
pyOpenRPA-1.3.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
pyOpenRPA-1.3.0.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97
pyOpenRPA-1.3.0.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10
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/__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/__pycache__/A2O.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/Info.md,sha256=u4Nv-PjniSF0Zlbtr6jEJX2vblK3_1zhSLNUgOdtDaA,85
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/Core.py,sha256=OHa3mSC3_wRAizqrWBVjlR6ln4-xVVvBpOSnWl6qVvY,529
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=nBJqwBd6y9yeE49XOn83r8Dtvb3yReujrp-frxOhNL8,16671
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=dgXx2UzSwiEev4ov2hBbb-5MhXVhFKWZo2lmr19QSCQ,12582
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=DYX1pBK4gaxcfmDj-1OaLNyk83D_R_7ztZyt0SHWoik,41377
pyOpenRPA/Orchestrator/Managers/ControlPanel.py,sha256=PZzh_RUke8bIMGghCXTnEuTYICCwW71r2xXk7iTdUnU,17345
pyOpenRPA/Orchestrator/Managers/Git.py,sha256=VCXXc-enJhvrAJvYc8jHK9GcGe02meMdszU0tlJDHiQ,12879
pyOpenRPA/Orchestrator/Managers/Process.py,sha256=4LJNMrt61AJKI3p7SeXnUSEpA61BtqWVxaVYxYS_BaI,42221
pyOpenRPA/Orchestrator/Managers/__init__.py,sha256=4my0XiwmI_QLRQVhOzNvWTggCosF3tb2yRxGkehOCq0,71
pyOpenRPA/Orchestrator/Managers/__pycache__/ControlPanel.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Git.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Managers/__pycache__/Process.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/RobotRDPActive/CMDStr.py,sha256=6otw1WnR2_evvQ5LGyOVh0BLk_nTdilViGub7p56fXQ,1531
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/Processor.py,sha256=bMahu6wRznmoLYsopgbNOLqufcQnEDanIepuGvXIsac,12405
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/Template.rdp,sha256=YjIxCXyIvDtZx-MPpyHPj3quT9dlUZPuuILiB21eRpU,2462
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__/__main__.cpython-37.pyc,,
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/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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__/__init__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Orchestrator/Server.py,sha256=YOQgZQ97nM_XQYVRbusj_b50aqEiNBJFF3bs7wA-O6k,36240
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=260YPXINLrora8pBBVHQSPNBkc8wdlyadsoQTQKdpAs,32590
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=TR6WQVm-0sFoQjnV08t9K5oQOcpC7dbKOnWQS31m9dQ,21443
pyOpenRPA/Orchestrator/Server.py,sha256=eYiXKvWsiBG_kfHtzdNX4Zu2xL2DjkJZXqBfqOgHAk4,38600
pyOpenRPA/Orchestrator/ServerSettings.py,sha256=wZe5aEUJOWYol8WzKUQBRq9JEnXj0Z39554PAIoqvbw,34326
pyOpenRPA/Orchestrator/SettingsTemplate.py,sha256=dVL-JZpAUQP3LLXE_7IUuE7RkLTYBAA-RX4e5FZ_DU0,21499
pyOpenRPA/Orchestrator/Timer.py,sha256=HvYtEeH2Q5WVVjgds9XaBpWRmvZgwgBXurJDdVVq_T0,2097
pyOpenRPA/Orchestrator/Utils/LoggerHandlerDumpLogList.py,sha256=hD47TiOuKR-G8IWu9lJD2kG28qlH7YZV63i3qv1N5Dk,681
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/__pycache__/Basic.cpython-37.pyc,,
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/__main__.py,sha256=czJrc7_57WiO3EPIYfPeF_LG3pZsQVmuAYgbl_YXcVU,273
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/images/flags.png,sha256=lNXH8WYTAcSm3Ekdct1VmgYgzZF6gm8N8bAju5bqnd0,28123
pyOpenRPA/Resources/Web/jQuery/jquery-3.1.1.min.js,sha256=HPMOWdIdSuVgr3FD9ZE-_MgiK8qk_MdQjrgCtfqp6U4,86713
pyOpenRPA/Resources/Web/pyOpenRPA_logo.png,sha256=7rulXo_C57xJQEaYWmAkChxXb6xbDW2zq-werzVbDbc,4899
pyOpenRPA/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/Keyboard.py,sha256=3RCogucSWPCtq7YbFKIUvJOSBvFE04P6Lo3hjCGUHi8,26071
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/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878
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/ProcessBitness.py,sha256=NvzuTxNWL_EMmdU1Isu0bUck1Iud0Kkzn8GsVCzIAAM,4591
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/ProcessCommunicator.py,sha256=HD3XASJae31_HV3OznFe8E2MgZFXnwt7YveVN82M8nU,7912
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/Web/Index.xhtml,sha256=X_fLnzxdcJ8ML9VRORpaMmQwlu1Pcr0CR2Krzt65Hes,48119
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__/__init__.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/License.py,sha256=r4z9HExUzpk2Q_6WhzgUnHlOPPHK1MLevtdlLwtZ7Hk,10378
pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343
pyOpenRPA/Tools/RobotDB/HowToUse,sha256=TUXPZAFcse-PSlKFM6jcaYuuZZEmXOSSvgeqrbmIDoc,1473
pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=qtGu8PS2atd0L8taCNpk-08Qpxp8Qz1lqwAcBkyLFLM,1655
pyOpenRPA/Tools/RobotDB/Server.py,sha256=rjW9Sg-j9P8pFQD66Uih-rke6-f6sCulinwi4_W-3mc,19933
pyOpenRPA/Tools/RobotDB/Server.py,sha256=idGpXDU9rPv-NZcOW1Wrku_acEqEYnhSXNtUmFTs1dU,20019
pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406
pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124
pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140
@ -351,7 +390,7 @@ pyOpenRPA/Tools/SafeSource/__pycache__/Crypter.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/DistrCreate.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__init__.cpython-37.pyc,,
pyOpenRPA/Tools/SafeSource/__pycache__/__main__.cpython-37.pyc,,
pyOpenRPA/Tools/StopSafe.py,sha256=BNTtMmvsRE1Wtri3EkwhoBi6gGOjEPRQnJSV1C03c84,2176
pyOpenRPA/Tools/StopSafe.py,sha256=BIMiW8cFyQfX3KpRHaspdbw6-FcImTilqXRC_XXzyik,2346
pyOpenRPA/Tools/Template.py,sha256=3COsenafs8yoRUTAPQUjR-b18TepiWjS9Rv3Jq01rw0,5490
pyOpenRPA/Tools/Usage.py,sha256=GVGpC1E6qt1FjjD-RSyn4l9koI5FNfXBIWEBHGKbdK4,2996
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__/Usage.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/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
lAgentLimitLogSizeBytesInt = 500
if lBodyLenInt <= lAgentLimitLogSizeBytesInt:
if lL: lL.info(f"ActivityItem from orchestrator: {lQueueItem}");
if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: {lQueueItem}")
else:
if lL: lL.info(f"ActivityItem from orchestrator: Supressed - big size. Size is {lBodyLenInt} bytes");
if lL: lL.info(f"Словарь ActivityItem, полученный от оркестратора: содержимое свернуто из-за большого размера ({lBodyLenInt} байт")
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:
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)
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)
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"])
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"])
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"])
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"])

@ -3,66 +3,69 @@ from . import O2A, A2O # Data flow Orchestrator To Agent
from . import Processor # Processor Queue
from ..Tools import Usage
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
gSettings = None
# Create binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrCreate(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Создать бинарный файл на стороне Агента по полученной строке в формате base64 (формат безопасен для передачи по JSON протоколу)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "wb")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Append binary file by the base64 string (safe for JSON transmition)
def OSFileBinaryDataBase64StrAppend(inFilePathStr, inFileDataBase64Str,inGSettings = None):
"""
Create binary file by the base64 string (safe for JSON transmition)
"""L+,W+: Create binary file by the base64 string (safe for JSON transmition)
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "ab")
lFile.write(base64.b64decode(inFileDataBase64Str))
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
# Create text file by the string
def OSFileTextDataStrCreate(inFilePathStr, inFileDataStr, inEncodingStr = "utf-8",inGSettings = None):
"""
Create text file in the agent GUI session
"""L+,W+:Создать текстовый файл на стороне Агента
:param inFilePathStr: File abs path
:param inFileDataStr: File data text content
:param inEncodingStr: Write file encoding
:param inGSettings: global settings of the Agent (singleton)
:param inFilePathStr: Абсолютный путь к создаваемому файлу
:param inFileDataStr: Текст, отправляемый в создаваемый файл
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный файл настроек
:return:
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFile = open(inFilePathStr, "w", encoding=inEncodingStr)
lFile.write(inFileDataStr)
lFile.close()
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)
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
"""
Read binary file and encode in base64 to transmit (safe for JSON transmition)
"""L+,W+: Прочитать бинарный файл на стороне агента и отправить на сторону оркестратора в формате base64 (формат безопасный для передачи в формате JSON)
:param inFilePathStr: File path to read
:param inGSettings: global settings of the Agent (singleton)
:return: File content in string base64 format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inGSettings: Глобальный словарь настроек Агента (необязательный)
:return: Содержимое бинарного файле, преобразованное в формат base64 (используй base64.b64decode для декодирования в байты). Вернет None запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
lFileDataBase64Str = None
if os.path.exists(inFilePathStr):
@ -70,56 +73,55 @@ def OSFileBinaryDataBase64StrReceive(inFilePathStr, inGSettings=None):
lFileDataBytes = lFile.read()
lFile.close()
lFileDataBase64Str = base64.b64encode(lFileDataBytes).decode("utf-8")
lMessageStr = f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} has been read"
lMessageStr = f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} прочитан успешно"
if lL: lL.debug(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else:
if lL: lL.debug(f"OSFileBinaryDataBase64StrReceive: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileBinaryDataBase64StrReceive: файл {inFilePathStr} не существует - отправить None")
return lFileDataBase64Str
def OSFileMTimeGet(inFilePathStr: str) -> float or None:
"""
Read file modification time timestamp format (float)
"""L+,W+: Read file modification time timestamp format (float)
:param inFilePathStr: File path to read
:return: timestamp (float) Return None if file is not exist
:param inFilePathStr: Абсолютный путь к файлу, дату которого требуется получить
:return: Временной слепок (timestamp) в формате float. Вернет None, если запрашиваемый файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
global gSettings
lL = gSettings.get("Logger", None) if type(gSettings) is dict else None
lFileMTimeFloat = None
if os.path.exists(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:
if lL: lL.debug(f"OSFileMTimeGet: file {inFilePathStr} is not exists - return None")
if lL: lL.debug(f"Функция OSFileMTimeGet: file {inFilePathStr} не существует - вернуть None")
return lFileMTimeFloat
def OSFileTextDataStrReceive(inFilePathStr, inEncodingStr="utf-8", inGSettings=None):
"""
Read text file in the agent GUI session
"""L+,W+: Прочитать текстовый файл на стороне агента и отправить на сторону оркестратора
:param inFilePathStr: File abs path
:param inEncodingStr: Read file encoding. Default utf-8
:param inGSettings: global settings of the Agent (singleton)
:return: File text content in string format (use base64.b64decode to decode data). Return None if file is not exist
:param inFilePathStr: Абсолютный путь к читаемому файлу
:param inEncodingStr: Кодировка создаваемого файла. По-умолчанию 'utf-8'
:param inGSettings: Глобальный словарь настроек
:return: Строка - содержимое текстового файла. Возвращает None, если файл не существует
"""
inFilePathStr = CrossOS.PathStr(inPathStr=inFilePathStr)
lFileDataStr = None
lL = inGSettings.get("Logger", None) if type(inGSettings) is dict else None
if os.path.exists(inFilePathStr):
lFile = open(inFilePathStr, "r", encoding=inEncodingStr)
lFileDataStr = lFile.read()
lFile.close()
lMessageStr = f"OSFileTextDataStrReceive: file {inFilePathStr} has been read"
lMessageStr = f"АГЕНТ: Текстовый файл {inFilePathStr} прочитан успешно"
if lL: lL.info(lMessageStr)
#A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
else:
if lL: lL.info(f"OSFileTextDataStrReceive: file {inFilePathStr} is not exists - return None")
if lL: lL.info(f"АГЕНТ: Текстовый файл {inFilePathStr} не существует - вернуть None")
return lFileDataStr
# 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):
"""
Execute CMD on the Agent daemonic process
"""L-,W+: Execute CMD on the Agent daemonic process
:param inCMDStr: command to execute on the Agent session
: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:
lCMDProcess = subprocess.Popen(f'cmd /c {inCMDStr}', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
else:
if CrossOS.IS_WINDOWS_BOOL:
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
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been STARTED # # # # "
lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия запущена # # # # "
if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings,inLogList=[lMessageStr])
@ -172,7 +177,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
time.sleep(2)
else:
lListenBool = False
lMessageStr = f"{lOSCMDKeyStr}: # # # # AGENT CMD Process has been FINISHED # # # # "
lMessageStr = f"{lOSCMDKeyStr}: # # # # АГЕНТ: Терминальная сессия завершена # # # # "
if lL: lL.info(lMessageStr)
if inSendOutputToOrchestratorLogsBool == True: # Capturing can be turned on!
A2O.LogListSend(inGSettings=inGSettings, inLogList=[lMessageStr])
@ -181,7 +186,7 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
if inRunAsyncBool:
lThread = threading.Thread(target=_CMDRunAndListenLogs, kwargs={"inCMDStr":inCMDStr, "inGSettings":inGSettings, "inSendOutputToOrchestratorLogsBool":inSendOutputToOrchestratorLogsBool, "inCMDEncodingStr":inCMDEncodingStr, "inCaptureBool": inCaptureBool })
lThread.start()
lResultStr="ActivityList has been started in async mode - no output is available here."
lResultStr="Список ActivityList отправлен на исполнение в асинхронном режиме - захват текста недоступен"
else:
lResultStr = _CMDRunAndListenLogs(inCMDStr=inCMDStr, inGSettings=inGSettings, inSendOutputToOrchestratorLogsBool = inSendOutputToOrchestratorLogsBool, inCMDEncodingStr = inCMDEncodingStr, inCaptureBool=inCaptureBool)
#lCMDCode = "cmd /c " + inCMDStr
@ -191,11 +196,9 @@ def OSCMD(inCMDStr, inRunAsyncBool=True, inGSettings = None, inSendOutputToOrche
def ProcessWOExeUpperUserListGet():
"""
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
"""L-,W+: Вернуть список процессов, запущенных под пользователем на стороне агента
:param inProcessNameWOExeList:
:return: list of the agent user process in upper case without .EXE. Example ["NOTEPAD","..."],
:return: Список процессов в формате: ["NOTEPAD","..."] (без постфикса .exe и в верхнем регистре)
"""
lUserNameStr = getpass.getuser()
@ -238,7 +241,7 @@ def Agent(inGSettings):
lProcessorThread = threading.Thread(target= Processor.ProcessorRunSync, kwargs={"inGSettings":inGSettings})
lProcessorThread.daemon = True # Run the thread in daemon mode.
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)
lO2AThread = threading.Thread(target=O2A.O2A_Loop, kwargs={"inGSettings":inGSettings})
@ -247,4 +250,4 @@ def Agent(inGSettings):
# 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
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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
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"]:
lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]
if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key
if lL: lL.debug(f"Client request lifetime is over")
if lL: lL.debug(f"Время жизни HTTP запроса истекло - удалить из отслеживаемых!")
lDoWhileBool = False # Stop the iterations
if lDoWhileBool:
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)
}
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
@ -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
"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
inGSettings["Client"] = { # Settings about client web orchestrator
"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
inGSettings["Server"]["RequestTimeoutSecFloat"] = 300 # Time to handle request in seconds
if lL: lL.warning(
f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'Server' > 'RequestTimeoutSecFloat' property") # Log about compatibility
if "DefSettingsUpdatePathList" not in inGSettings["OrchestratorStart"]: # Add OrchestratorStart > "DefSettingsUpdatePathList" property
inGSettings["OrchestratorStart"]["DefSettingsUpdatePathList"] = [] # List of the .py files which should be loaded before init the algorythms
if lL: lL.warning(f"Backward compatibility (v1.1.13 to v1.1.14): Add default 'OrchestratorStart' > 'DefSettingsUpdatePathList' property list") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.13 -> v1.1.14): Преобразовать структуру 'OrchestratorStart' > 'DefSettingsUpdatePathList'") # Log about compatibility
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# v1.1.20 to v1.2.0
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@ -338,14 +338,14 @@ def Update(inGSettings):
"DumpLogList": [], # Will be filled automatically
"DumpLogListHashStr": None, # Will be filled automatically
})
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'Client > DumpLog... with default parameters'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать атрибут 'Client > DumpLog... с параметрами по умолчанию'") # Log about compatibility
if "Processor" in inGSettings: # Check if Processor exist
# Update Logger
if lL is not None:
SettingsTemplate.LoggerDumpLogHandlerAdd(inLogger=lL, inGSettingsClientDict=inGSettings["Client"])
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Add web dump log in logger as handler") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Добавить веб дамп для отображения лога на веб клиенте оркестратора") # Log about compatibility
del inGSettings["Processor"] # Remove the key
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Remove old structure 'Processor'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Удалить структуру старого процессора 'Processor'") # Log about compatibility
if "ProcessorDict" not in inGSettings: # Create new ProcessorDict structure
inGSettings["ProcessorDict"]={
"ActivityList": [ # List of the activities
@ -361,14 +361,14 @@ def Update(inGSettings):
"ExecuteBool": True, # Flag to execute thread processor
"ThreadIdInt": None # Fill thread id when processor will be inited
}
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new structure 'ProcessorDict'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'ProcessorDict'") # Log about compatibility
if "VersionStr" not in inGSettings: # Create new ProcessorDict structure
inGSettings["VersionStr"] = None
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'VersionStr'") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'VersionStr'") # Log about compatibility
if "AgentDict" not in inGSettings: # Create new AgentDict structure
inGSettings["AgentDict"]= {}
if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Create new attribute 'AgentDict'") # Log about compatibility
f"Обратная совместимость (v1.1.20 -> v1.2.0): Создать новую структуру 'AgentDict'") # Log about compatibility
# Alg to convert UAC ControlPanelAllawedList to UACClient hierarchy
# if inGSettings["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True:
# lUserRights = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(), inRequest.OpenRPA["User"].upper())]
@ -379,7 +379,7 @@ def Update(inGSettings):
# Check if Server is active > convert to ServerDict
inGSettings["ServerDict"] = inGSettings["Server"]
if lL: lL.warning(
f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility
f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Server' -> 'ServerDict'") # Log about compatibility
# Remove old structure Scheduler
del inGSettings["Server"]
lShowWarnBool = False
@ -401,7 +401,7 @@ def Update(inGSettings):
# remove "ControlPanelKeyAllowedList" - will be removed in __Orchestrator__.UACUpdate
#del inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lItemKeyTurple]["ControlPanelKeyAllowedList"]
if lShowWarnBool: # Show only 1 warning per all run
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert CP allowed list to UAC Client hierarchy (consolidated)") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Интегрировать структуру доступа к панелям управления в общую UAC иерархию") # Log about compatibility
# Check if ControlPanelDict is active > convert to CPDict
if "ControlPanelDict" in inGSettings:
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}
# Remove old structure ControlPanel
del inGSettings["ControlPanelDict"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert ControlPanelDict to CPDict") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'ControlPanelDict' -> 'CPDict'") # Log about compatibility
# Check if Scheduler is active > convert to SchedulerDict
if "Scheduler" in inGSettings:
if "SchedulerDict" not in inGSettings: inGSettings["SchedulerDict"]={ "CheckIntervalSecFloat": 5.0, "ActivityTimeList":[]}
@ -423,27 +423,27 @@ def Update(inGSettings):
inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict)
# Remove old structure Scheduler
del inGSettings["Scheduler"]
if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Scheduler to SchedulerDict with new features") # Log about compatibility
if lL: lL.warning(f"Обратная совместимость (v1.1.20 -> v1.2.0): Преобразовать 'Scheduler' -> 'SchedulerDict' с новыми функциональными возможностями") # Log about compatibility
# # Convert to Storage to StorageDict
if "Storage" in inGSettings:
# Check if Server is active > convert to ServerDict
inGSettings["StorageDict"] = inGSettings["Storage"]
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
del inGSettings["Storage"]
# Add new key WarningExecutionMoreThanSecFloat in ProcessorDict
if "WarningExecutionMoreThanSecFloat" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["WarningExecutionMoreThanSecFloat"] = 60.0
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
if "AgentActivityLifetimeSecFloat" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentActivityLifetimeSecFloat"] = 1200.0
inGSettings["ServerDict"]["AgentConnectionLifetimeSecFloat"] = 300.0
inGSettings["ServerDict"]["AgentLoopSleepSecFloat"] = 2.0
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
if "RecoveryDict" not in inGSettings["RobotRDPActive"]:
inGSettings["RobotRDPActive"]["RecoveryDict"] = {
@ -457,7 +457,7 @@ def Update(inGSettings):
}
}
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
if "ListenDict" not in inGSettings["ServerDict"]:
lPortInt = inGSettings.get("ServerDict",{}).get("ListenPort",80)
@ -471,7 +471,7 @@ def Update(inGSettings):
}
}
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
#"ServerDict": {
# "AgentFileChunkBytesSizeInt": 50000000, # size of the each chunk for the agent transmition
@ -479,24 +479,24 @@ def Update(inGSettings):
if "AgentFileChunkBytesSizeInt" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["AgentFileChunkBytesSizeInt"]= 50000000
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"]:
inGSettings["ServerDict"]["AgentFileChunkCheckIntervalSecFloat"]= 0.2
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"]:
inGSettings["ServerDict"]["ServerThread"]= None
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"]:
inGSettings["ServerDict"]["AgentLimitLogSizeBytesInt"] = 300
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
if "ControlPanelDict" in inGSettings:
del inGSettings["ControlPanelDict"]
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:
for lCPKeyStr in inGSettings["CPDict"]:
lCPItemDict = inGSettings["CPDict"][lCPKeyStr]
@ -505,40 +505,40 @@ def Update(inGSettings):
inJSInitGeneratorDef=lCPItemDict["JSInitGeneratorDef"])
del inGSettings["CPDict"]
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"]:
inGSettings["ServerDict"]["ControlPanelDict"]={}
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
if "ManagersProcessDict" not in inGSettings:
inGSettings["ManagersProcessDict"]={}
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
if inGSettings.get("SchedulerDict",{}).get("Schedule",None) is None:
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
if "ManagersGitDict" not in inGSettings:
inGSettings["ManagersGitDict"]={}
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
if "ActivityItemNowDict" not in inGSettings["ProcessorDict"]:
inGSettings["ProcessorDict"]["ActivityItemNowDict"]=None
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
for lURLItemDict in inGSettings["ServerDict"]["URLList"]:
if "UACBool" not in lURLItemDict:
lURLItemDict["UACBool"]=None
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"
if "URLIndexStr" not in inGSettings["ServerDict"]:
inGSettings["ServerDict"]["URLIndexStr"] = "/"
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
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
self.RefreshHTMLJinja2TemplatePathSet(inJinja2TemplatePathStr = inRefreshHTMLJinja2TemplatePathStr)
self.mJinja2TemplateRefreshBool = inJinja2TemplateRefreshBool
@ -116,7 +116,7 @@ class ControlPanel():
self.mRefreshHTMLJinja2Env = jinja2.Environment(loader=self.mRefreshHTMLJinja2Loader, trim_blocks=True)
self.mRefreshHTMLJinja2Template = self.mRefreshHTMLJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def RefreshHTMLJinja2StrGenerate(self, inDataDict):
"""
@ -145,7 +145,7 @@ class ControlPanel():
self.mInitJSJinja2Env = jinja2.Environment(loader=self.mInitJSJinja2Loader, trim_blocks=True)
self.mInitJSJinja2Template = self.mInitJSJinja2Env.get_template(lTemplateFileNameStr)
except Exception as e:
Orchestrator.OrchestratorLoggerGet().exception("EXCEPTION WHEN INIT Jinja2")
Orchestrator.OrchestratorLoggerGet().exception("Ошибка при инициализации Jinja2")
def InitJSJinja2StrGenerate(self, inDataDict):
"""
@ -290,7 +290,7 @@ class ControlPanel():
# Call backward compatibility HTML generator
lResultStr = Basic.HTMLControlPanelBC(inCPDict=lHTMLResult)
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
@ -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:
lResultDict = lJSONResult
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:
if lL: lL.exception(
f"Error in control panel JSONGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
f"Ошибка при формирвоании JSON (JSONGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultDict
def BackwardAdapterJSDef(self,inRequest):
@ -343,8 +343,8 @@ class ControlPanel():
if type(lJSResult) is str:
lResultStr = lJSResult # Add delimiter to some cases
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:
if lL: lL.exception(
f"Error in control panel JSInitGeneratorDef. CP Key {self.mControlPanelNameStr}. Exception are below")
f"Ошибка в функции формирования кода JavaScript (JSInitGeneratorDef). Идентификатор панели управления {self.mControlPanelNameStr}")
return lResultStr

@ -34,7 +34,7 @@ class Git():
self.mAgentHostNameStr = inAgentHostNameStr
self.mAgentUserNameStr = inAgentUserNameStr
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):
"""
@ -151,11 +151,11 @@ class Git():
:param inBranchRemoteStr: [description]
: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
lCMDResultStr = None
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
self.ProcessListSaveStopSafe()
lBranchNameCurrentStr = self.BranchNameGet()
@ -170,7 +170,7 @@ class Git():
# checkout to the source branch which was
self.BranchCheckout(inBranchNameStr=lBranchNameCurrentStr)
# 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()
return lCMDResultStr

@ -108,7 +108,7 @@ class Process():
__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityDict)
if inStatusCheckIntervalSecFloat is not None: __Orchestrator__.OrchestratorScheduleGet().every(inStatusCheckIntervalSecFloat).seconds.do(Orchestrator.OrchestratorThreadStart,self.StatusCheck)
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:
"""
@ -145,7 +145,7 @@ class Process():
self.mStatusStr = "1_STOPPED_MANUAL"
# Log info about process
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
def ManualStopListClear(self) -> None:
@ -180,7 +180,7 @@ class Process():
"""
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:
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)
return self.mStatusStr
# Send activity item to agent - wait result
@ -259,7 +259,7 @@ class Process():
if "SAFE" in self.mStatusStr:
# Log info about process
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)
# Log info about process
# 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"
elif self.mStatusStr == "3_STOP_SAFE_MANUAL": self.mStatusSavedStr = "1_STOPPED_MANUAL"
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
@ -358,7 +358,7 @@ class Process():
"""Call from orchestrator when init
"""
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)
def StatusRestore(self):
@ -377,7 +377,7 @@ class Process():
self.StopSafe(inIsManualBool=True)
if "STARTED" in self.mStatusSavedStr and "STARTED" not in self.mStatusStr:
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.mStatusSavedStr = None
return self.mStatusStr
@ -390,7 +390,7 @@ class Process():
"""
# Log info about process
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):

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

@ -62,22 +62,22 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
try:
Connector.Session(lRDPConfigurationDict, inScreenSize550x350Bool = True)
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
except ConnectorExceptions.SessionWindowNotExistError as e:
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.RetryMark(inRDPSessionKeyStr=lRDPSessionKeyStr,inGSettings=inGSettings)
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
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)
# general exceptions
except Exception as e:
if lL: lL.exception(f"!!! ATTENTION !!! Unrecognized error") #Logging
if lL: lL.exception(f"!!! ВНИМАНИЕ !!! Неопознанная ошибка. Обратитесь в тех. поддержку pyOpenRPA") #Logging
pass
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Connector.SystemRDPWarningClickOk() # Click all warning messages
@ -125,7 +125,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
lActivityItemResult = getattr(Processor, lSubmoduleFunctionName)(
*lActivityItem["ArgList"], **lActivityItem["ArgDict"])
except Exception as e:
if lL: lL.exception(f"RDP::main: Exception when run def in processor.py - activity will be ignored. Activity item: {lActivityItem}") #Logging
if lL: lL.exception(f"РДП: Ошибка при обработке активности в процессоре РДП сессии - активность будет проигнорирована. Активность: {lActivityItem}") #Logging
lActivityItemResult = True # True - clear from repeat list
lActivityItemResultType = type(lActivityItemResult)
# Check if Result is bool
@ -137,7 +137,7 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
except RuntimeError as e:
# 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:
# Wait for the next iteration
time.sleep(0.7)
@ -145,4 +145,4 @@ def RobotRDPActive(inGSettings, inThreadControlDict):
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#Monitor.Monitor(mGSettingsRDPActiveDict, 1)
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)
Screen.ConsoleScreenBase()
#Delay to create console screen
time.sleep(5)
time.sleep(15)
#Delay
time.sleep(inIntervalSeconds)
return None

@ -24,12 +24,13 @@ import uuid
import datetime
import os #for path operations
from http import cookies
global gSettingsDict
gSettingsDict = {}
from . import ServerSettings
from . import __Orchestrator__
import copy
import mimetypes
mimetypes.add_type("font/woff2",".woff2")
mimetypes.add_type("text/javascript",".js")
gCacheDict = {}
@ -82,6 +83,7 @@ def AuthenticateVerify(inRequest):
######################################
#Way 1 - try to find AuthToken
lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", ""))
global gSettingsDict
#pdb.set_trace()
if "AuthToken" in lCookies:
lCookieAuthToken = lCookies.get("AuthToken", "").value
@ -147,6 +149,7 @@ def AuthenticateBlock(inRequest):
def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict
#pdb.set_trace()
global gSettingsDict
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"]
@ -261,6 +264,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Def to get hierarchy of the current user roles
# if return {} - all is available
def UserRoleHierarchyGet(self):
#global gSettingsDict
lDomainUpperStr = self.OpenRPA["Domain"].upper()
lUserUpperStr = self.OpenRPA["User"].upper()
return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
@ -268,6 +272,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
#Tech def
#return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False):
global gSettingsDict
###############################
#Tech sub def - do item
################################
@ -288,18 +293,22 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Write content as utf-8 data
inResponseDict["Body"] = gCacheDict[inURLItem["ResponseFilePath"]]
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")
# Write content as utf-8 data
inResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
lFileObject.close()
else: inResponseDict["Headers"]["Content-type"]= "application/x-empty"; inResponseDict["StatusCode"] = 204 # NOCONTENT
# detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None:
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
lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"")
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}")
#Check if file exist
if os.path.exists(lFilePath) and os.path.isfile(lFilePath):
@ -345,6 +354,8 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# detect MIME type if none
if inResponseDict["Headers"]["Content-type"] is None:
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 inResponseDict["Headers"]["Content-type"] is None:
inResponseDict["Headers"]["Content-type"]= "application/octet-stream"
@ -420,6 +431,9 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
@ -493,33 +507,24 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
# 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:
#Set access denied code
# Send response status code
self.send_response(403)
# Send 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:
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
def do_POST(self):
try:
global gSettingsDict
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
lL = gSettingsDict["Logger"]
self.OpenRPA = {}
@ -603,7 +608,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
lActivityTypeListStr += f"{lInputObject['Type']}"
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
if lL: lL.info(f"Server:: !ATTENTION! /Utils/Processor will be deprecated in future. Use /pyOpenRPA/Processor or /pyOpenRPA/ActivityListExecute. User activity from web. Domain: {self.OpenRPA['Domain']}, Username: {self.OpenRPA['User']}, ActivityType: {lActivityTypeListStr}")
if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}")
# Send message back to client
message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject))
# Write content as utf-8 data
@ -616,20 +621,35 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler):
# Send headers
self.end_headers()
return
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_POST): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e:
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
#!Turn it on to stop print in console
#def log_message(self, format, *args):
# return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True
"""Handle requests in a separate thread."""
def finish_request(self, request, client_address):
try:
global gSettingsDict
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
# "JSONConfigurationDict":<JSON>
import ssl
@ -640,6 +660,7 @@ class RobotDaemonServer(Thread):
# Update the global dict
ServerSettings.SettingsUpdate(inGlobalDict)
def run(self):
global gSettingsDict
lL = gSettingsDict.get("Logger",None)
try:
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)
else:
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:
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')
httpd.serve_forever()
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,
getRectAsImage, getDisplaysAsImages)
if CrossOS.IS_LINUX_BOOL: pass
if CrossOS.IS_LINUX_BOOL: import pyscreeze
from http import cookies
import uuid # generate UUID4
@ -197,9 +197,9 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
# Get Screenshot
def SaveScreenshot(inFilePath):
# grab fullscreen
# Save the entire virtual screen as a PNG
# Save the entire virtual screen as a PNsG
lScreenshot = getScreenAsImage()
lScreenshot.save('screenshot.png', format='png')
lScreenshot.save('Screenshot.png', format='png')
# lScreenshot = ScreenshotSecondScreen.grab_screen()
# save image file
# lScreenshot.save('screenshot.png')
@ -211,7 +211,13 @@ def pyOpenRPA_Screenshot(inRequest,inGlobalDict):
inRequest.OpenRPAResponseDict["Body"] = lFileObject.read()
# Закрыть файловый объект
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
# Body is Activity item or Activity List
@ -233,7 +239,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr)
# Separate into 2 lists - sync and async
@ -259,7 +265,7 @@ def pyOpenRPA_Processor(inRequest, inGSettings):
try:
lActivityTypeListStr = lInput['Def']
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor")
if lL: lL.info(lWebAuditMessageStr)
if lInput.get("ThreadBool",False) == False:
@ -288,7 +294,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
for lActivityItem in lInput:
lActivityTypeListStr += f"{lActivityItem['Def']}; "
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute")
if lL: lL.info(lWebAuditMessageStr)
# Execution
@ -301,7 +307,7 @@ def pyOpenRPA_ActivityListExecute(inRequest, inGSettings):
try:
lActivityTypeListStr = lInput['Def']
except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read"
lActivityTypeListStr = "Ошибка чтения типа активности"
lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,
inOperationCodeStr=lActivityTypeListStr,
inMessageStr="pyOpenRPA_ActivityListExecute")
@ -432,13 +438,13 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr]
# Create item in gSettings
inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue)
lLogStr = "x bytes"
lLogStr = "x байт"
try:
if lActivityReturnItemValue is not None:
lLogStr = f"{len(lActivityReturnItemValue)} bytes"
lLogStr = f"{len(lActivityReturnItemValue)} байт"
except Exception as e:
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
if lAgentDictItemKeyTurple in inGSettings["AgentDict"]:
lAgentDictActivityListNew = []
@ -448,11 +454,23 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings):
lAgentDictActivityListNew.append(lActivityItem)
else:
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
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):
import os
import pyOpenRPA.Orchestrator
gSettingsDict = __Orchestrator__.GSettingsGet()
if CrossOS.IS_WINDOWS_BOOL: lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1])
if CrossOS.IS_LINUX_BOOL: lOrchestratorFolder = "/".join(pyOpenRPA.Orchestrator.__file__.split("/")[:-1])
lURLList = \
@ -467,7 +485,10 @@ def SettingsUpdate(inGlobalConfiguration):
# "ResponseDefRequestGlobal": None #Function with str result
#}
#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": "/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.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},

@ -1,5 +1,7 @@
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
def __Create__():
@ -340,7 +342,7 @@ def Create(inModeStr="BASIC", inLoggerLevel = None):
lL.setLevel(logging.INFO)
# create the logging file handler
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')
mRobotLoggerFH.setFormatter(mRobotLoggerFormatter)
# 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