diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/INSTALLER b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/INSTALLER similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/INSTALLER rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/INSTALLER diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA similarity index 99% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA index 6b4d8af7..81643f98 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pyOpenRPA -Version: 1.0.37 +Version: 1.0.39 Summary: First open source RPA platform for business Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Author: Ivan Maslov diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD similarity index 94% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD index c76a61a0..4f267a9d 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD @@ -1,11 +1,11 @@ -pyOpenRPA-1.0.37.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pyOpenRPA-1.0.37.dist-info/METADATA,sha256=NvEs1xItXmuAnPaTzTs5kDpr6NhwdD4_WyFwvG9UTLo,3510 -pyOpenRPA-1.0.37.dist-info/RECORD,, -pyOpenRPA-1.0.37.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 -pyOpenRPA-1.0.37.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 +pyOpenRPA-1.0.39.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pyOpenRPA-1.0.39.dist-info/METADATA,sha256=KSr_y71FFd5y4tYQHnz80Pj_96WCYKwWbW5eK0hd4KM,3510 +pyOpenRPA-1.0.39.dist-info/RECORD,, +pyOpenRPA-1.0.39.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 +pyOpenRPA-1.0.39.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436 -pyOpenRPA/Orchestrator/Processor.py,sha256=HQQyOVX-d5vPO-YULyTxVOtXtUMfvpAaSVO4xXxaKVI,9107 -pyOpenRPA/Orchestrator/Server.py,sha256=aWDecl4_UUU00YG-pOXxyL7IvN5NK3efABt92y6M2kg,22136 +pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091 +pyOpenRPA/Orchestrator/Server.py,sha256=QQK1rMZSg-pL9pJ059AoxIHHj4aFr1OWivdOEKPh9cs,22026 pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912 pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095 pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=su4tsDD_ZMbQz6Tbmqj55SM0ZZxuQw9tfPcytaB8wzs,32953 @@ -195,7 +195,7 @@ pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI, pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 -pyOpenRPA/Robot/UIDesktop.py,sha256=MWdWr0dZpk1PL1rsD91q6_8v687CSDBx1_T7IuHd3-E,77473 +pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524 pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039 @@ -235,6 +235,18 @@ pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 +pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=DZSb17fiCAYLdNVTLFJ7nTbQhk29PjzxE9OL6ydCDcI,1645 +pyOpenRPA/Tools/RobotDB/Server.py,sha256=RO4Rj5-hmrRB41XKm4CrSFtauzKj3wNq4VmgcxhseeY,19838 +pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 +pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 +pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 +pyOpenRPA/Tools/RobotDB/__pycache__/ExcelCom.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/RobotDB.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/Server.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=qU5SXwHgQU177MjqEHyOwJDLAcSVnIkKKw76iD09J1w,7275 pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=H7ciateTh-hml8z69EYZjYgqdTZGkDRtnFwuYnytrCw,3278 pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392 @@ -255,5 +267,5 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/__init__.py,sha256=32Po3gFALn9l6ft6LTFVJBkBj-1p5hP83AVcQ_FTa0s,175 +pyOpenRPA/__init__.py,sha256=iZp06tUV8Mw7GGdUcuW_faV4YaQEJa_n5BqxOl0cwx8,175 pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/WHEEL b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/WHEEL similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/WHEEL rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/WHEEL diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/top_level.txt b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/top_level.txt similarity index 100% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/top_level.txt rename to Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/top_level.txt diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py index 6089a62c..7c10775e 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py @@ -7,6 +7,7 @@ import sys import subprocess import copy import importlib +import psutil #Input arg # [ # { @@ -38,6 +39,13 @@ import importlib # # }, # { +# "Type":"ProcessStartIfTurnedOff", +# "CheckTaskName":"", #Check if current task name is not active (then start process), +# "Path":"", +# "ArgList":[] +# +# }, +# { # "Type":"ProcessStop", # "Name":"", # "FlagForce":True, @@ -71,6 +79,7 @@ def Activity(inActivity): inActivity["DateTimeUTCStringStart"] = datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f") #Alias (compatibility) lItem = inActivity + lCurrentDateTime = datetime.datetime.now() ########################################################### #Обработка запроса на отправку команды на удаленную машину ########################################################### @@ -138,11 +147,33 @@ def Activity(inActivity): #Вид активности - запуск процесса #Запись в массив отработанных активностей #Лог - mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)}) #Запустить процесс - lItemArgs=[lItem["processPath"]] - lItemArgs.extend(lItem["processArgs"]) + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) subprocess.Popen(lItemArgs,shell=True) + ##################################### + #ProcessStartIfTurnedOff + ##################################### + if lItem["Type"]=="ProcessStartIfTurnedOff": + #Check if process running + #remove .exe from Taskname if exists + lCheckTaskName = lItem["CheckTaskName"] + if len(lCheckTaskName)>4: + if lCheckTaskName[-4:].upper() != ".EXE": + lCheckTaskName = lCheckTaskName+".exe" + else: + lCheckTaskName = lCheckTaskName+".exe" + #Check if process exist + if not CheckIfProcessRunning(lCheckTaskName): + #Вид активности - запуск процесса + #Запись в массив отработанных активностей + #Лог + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)}) + #Запустить процесс + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) + subprocess.Popen(lItemArgs,shell=True) ################################# #ProcessStop ################################# @@ -150,7 +181,7 @@ def Activity(inActivity): #Вид активности - остановка процесса #часовой пояс пока не учитываем #Сформировать команду на завершение - lActivityCloseCommand='taskkill /im '+lItem["processName"] + lActivityCloseCommand='taskkill /im '+lItem["Name"] #TODO Сделать безопасную обработку,если параметра нет в конфигурации if lItem.get('FlagForce',False): lActivityCloseCommand+=" /F" @@ -158,7 +189,7 @@ def Activity(inActivity): if lItem.get('User',"")!="": lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"' #Лог - mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processName"], "activityStartDateTime":str(lCurrentDateTime)}) + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)}) #Завершить процесс os.system(lActivityCloseCommand) ################################# @@ -213,4 +244,18 @@ def ActivityListOrDict(inActivityListOrDict): return lResult if type(inActivityListOrDict)==dict: #Dict activity - return Activity(inActivityListOrDict) \ No newline at end of file + return Activity(inActivityListOrDict) + +def CheckIfProcessRunning(processName): + ''' + Check if there is any running process that contains the given name processName. + ''' + #Iterate over the all the running process + for proc in psutil.process_iter(): + try: + # Check if process name contains the given name string. + if processName.lower() in proc.name().lower(): + return True + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + return False; \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py index e5d54b87..d82eaf3a 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py @@ -425,8 +425,6 @@ class RobotDaemonServer(Thread): #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) # Logging mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") - # Запуск адреса в браузере - os.system("explorer http://127.0.0.1:8081") #httpd.serve_forever() httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) #print('Starting server, use to stop') diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py index d18da2c6..3a003c5d 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py @@ -1208,7 +1208,7 @@ def UIOSelector_Highlight(inUIOSelector): UIO_Highlight(UIOSelector_Get_UIO(inUIOSelector)) else: # Run function from other process with help of PIPE - lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool", + lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Highlight", "ArgumentList": [inUIOSelector], "ArgumentDict": {}} # Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами @@ -1233,7 +1233,7 @@ def UIOSelector_FocusHighlight(inUIOSelector): UIO_FocusHighlight(UIOSelector_Get_UIO(inUIOSelector)) else: # Run function from other process with help of PIPE - lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool", + lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_FocusHighlight", "ArgumentList": [inUIOSelector], "ArgumentDict": {}} # Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py new file mode 100644 index 00000000..41bf0ea6 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py @@ -0,0 +1,11 @@ +import win32com.client as win32 +def OpenWorkbook(xlapp, xlfile): + try: + xlwb = xlapp.Workbooks(xlfile) + except Exception as e: + try: + xlwb = xlapp.Workbooks.Open(xlfile) + except Exception as e: + print(e) + xlwb = None + return(xlwb) \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py new file mode 100644 index 00000000..ef1c8845 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py @@ -0,0 +1,41 @@ +import subprocess +import json +import datetime +import time +import codecs +import os +import signal +import sys #Get input argument +import pdb +from . import Server +import logging +import copy +#from .Settings import Settings +import importlib +from importlib import util + +#Единый глобальный словарь (За основу взять из Settings.py) +global mGlobalDict +#Call Settings function from argv[1] file +################################################ +lSubmoduleFunctionName = "Settings" +lFileFullPath = sys.argv[1] +lModuleName = (lFileFullPath.split("\\")[-1])[0:-3] +lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) +lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) +lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) +mGlobalDict = None +if lSubmoduleFunctionName in dir(lTechModuleFromSpec): + # Run SettingUpdate function in submodule + mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() +################################################# +#mGlobalDict = Settings.Settings(sys.argv[1]) +Server.mGlobalDict = mGlobalDict + +#Инициализация настроечных параметров +lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) +lDaemonStartDateTime=datetime.datetime.now() + +#Инициализация сервера +lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict) +lThreadServer.start() \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py new file mode 100644 index 00000000..92ab89a1 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py @@ -0,0 +1,395 @@ +from http.server import BaseHTTPRequestHandler, HTTPServer +from socketserver import ThreadingMixIn +import threading +import json +from threading import Thread +import importlib +import pdb +import base64 +import uuid +import datetime +import os #for path operations +from http import cookies +global mGlobalDict +from . import ServerSettings +#Authenticate function () +# return dict +# { +# "Domain": "", #Empty if Auth is not success +# "User": "" #Empty if Auth is not success +# } +def AuthenticateVerify(inRequest): + lResult={"Domain": "", "User": ""} + ###################################### + #Way 1 - try to find AuthToken + lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", "")) + inRequest.OpenRPA = {} + inRequest.OpenRPA["AuthToken"] = None + #pdb.set_trace() + if "AuthToken" in lCookies: + lCookieAuthToken = lCookies.get("AuthToken", "").value + if lCookieAuthToken: + #Find AuthToken in GlobalDict + if lCookieAuthToken in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + #Auth Token Has Been Founded + lResult["Domain"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + #Set auth token + inRequest.OpenRPA["AuthToken"] = lCookieAuthToken + #Exit earlier + return lResult + ###################################### + #Way 2 - try to logon + lHeaderAuthorization = inRequest.headers.get("Authorization", "").split(" ") + if len(lHeaderAuthorization) == 2: + llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( + ":") + lUser = llHeaderAuthorizationDecodedUserPasswordList[0] + lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] + lDomain = "" + if "\\" in lUser: + lDomain = lUser.split("\\")[0] + lUser = lUser.split("\\")[1] + #Try to logon - use processor + lLogonResult = Processor.Activity( + { + "Type": "WindowsLogon", + "Domain": lDomain, + "User": lUser, + "Password": lPassword + } + ) + #Check result + if lLogonResult["Result"]: + lResult["Domain"] = lLogonResult["Domain"] + lResult["User"] = lLogonResult["User"] + #Create token + lAuthToken=str(uuid.uuid1()) + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + #Set-cookie + inRequest.OpenRPA["AuthToken"] = lAuthToken + inRequest.OpenRPASetCookie = {} + #New engine of server + inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken + #inRequest.OpenRPAResponse["Set-Cookie"]=[]lResult["Set-Cookie"] = lAuthToken + #pdb.set_trace() + #inRequest.send_header("Set-Cookie:", f"AuthToken={lAuthToken}") + ###################################### + return lResult +def AuthenticateBlock(inRequest): + # Send response status code + inRequest.send_response(401) + # Send headers + inRequest.send_header('Content-type', 'text/html') + inRequest.send_header('WWW-Authenticate', 'Basic') # Always ask login pass + inRequest.end_headers() + # Write content as utf-8 data + inRequest.wfile.write(bytes("", "utf8")) +#Check access before execute the action +#return bool True - go execute, False - dont execute +def UserAccessCheckBefore(inMethod, inRequest): + # Help def - Get access flag from dict + #pdb.set_trace() + def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): + if "FlagAccess" in inAccessRuleItem: + return inAccessRuleItem["FlagAccess"] + elif "FlagAccessDefRequestGlobalAuthenticate" in inAccessRuleItem: + return inAccessRuleItem["FlagAccessDefRequestGlobalAuthenticate"](inRequest, inGlobalDict, + inAuthenticateDict) + ########################################## + inMethod=inMethod.upper() + #Prepare result false + lResult = False + lAuthToken = inRequest.OpenRPA["AuthToken"] + #go next if user is identified + lUserDict = None + if lAuthToken: + lUserDict = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] + #pdb.set_trace() + ######################################## + ######################################## + #Check general before rule (without User domain) + #Check rules + for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []): + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.contains(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + ######################################### + ######################################### + #Do check if lResult is false + if not lResult: + #Check access by User Domain + #Check rules to find first appicable + #Check rules + for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []): + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + #check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.contains(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + ##################################### + ##################################### + #Return lResult + return lResult +# HTTPRequestHandler class +class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): + #Tech def + #return {"headers":[],"body":"","statuscode":111} + def URLItemCheckDo(self, inURLItem, inMethod): + ############################### + #Tech sub def - do item + ################################ + def URLItemDo(inURLItem,inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + #Set status code 200 + inResponseDict["StatusCode"] = 200 + #Content-type + if "ResponseContentType" in inURLItem: + inResponseDict["Headers"]["Content-type"] = inURLItem["ResponseContentType"] + #If file path is set + if "ResponseFilePath" in inURLItem: + lFileObject = open(inURLItem["ResponseFilePath"], "rb") + # Write content as utf-8 data + inResponseDict["Body"] = lFileObject.read() + # Закрыть файловый объект + lFileObject.close() + #If function is set + if "ResponseDefRequestGlobal" in inURLItem: + inURLItem["ResponseDefRequestGlobal"](inRequest, inGlobalDict) + if "ResponseFolderPath" in inURLItem: + lRequestPath = inRequest.path + lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"") + lFilePath = 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): + lFileObject = open(lFilePath, "rb") + # Write content as utf-8 data + inResponseDict["Body"] = lFileObject.read() + inResponseDict["ContentType"]= "application/octet-stream" + # Закрыть файловый объект + lFileObject.close() + ############################################## + if inURLItem["Method"].upper() == inMethod.upper(): + # check Match type variant: BeginWith + if inURLItem["MatchType"].upper() == "BEGINWITH": + lURLPath = self.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(inURLItem["URL"].upper()): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: Contains + elif inURLItem["MatchType"].upper() == "CONTAINS": + lURLPath = self.path + lURLPath = lURLPath.upper() + if lURLPath.contains(inURLItem["URL"].upper()): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: Equal + elif inURLItem["MatchType"].upper() == "EQUAL": + if inURLItem["URL"].upper() == self.path.upper(): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: EqualCase + elif inURLItem["MatchType"].upper() == "EQUALCASE": + if inURLItem["URL"] == self.path: + URLItemDo(inURLItem, self, mGlobalDict) + return True + return False + #ResponseContentTypeFile + def SendResponseContentTypeFile(self, inContentType, inFilePath): + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type', inContentType) + #Check if var exist + if hasattr(self, "OpenRPASetCookie"): + self.send_header("Set-Cookie", f"AuthToken={self.OpenRPA['AuthToken']}") + self.end_headers() + lFileObject = open(inFilePath, "rb") + # Write content as utf-8 data + self.wfile.write(lFileObject.read()) + #Закрыть файловый объект + lFileObject.close() + # ResponseContentTypeFile + def ResponseDictSend(self): + inResponseDict = self.OpenRPAResponseDict + # Send response status code + self.send_response(inResponseDict["StatusCode"]) + # Send headers + for lItemKey, lItemValue in inResponseDict["Headers"].items(): + self.send_header(lItemKey, lItemValue) + # Send headers: Set-Cookie + for lItemKey, lItemValue in inResponseDict["SetCookies"].items(): + self.send_header("Set-Cookie", f"{lItemKey}={lItemValue}") + #Close headers section in response + self.end_headers() + # Write content as utf-8 data + self.wfile.write(inResponseDict["Body"]) + def do_GET(self): + # Prepare result dict + lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + # Logging + mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}") + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("GET", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in mGlobalDict["Server"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + else: + #Set access denied code + # Send response status code + self.send_response(403) + # Send headers + self.end_headers() + # POST + def do_POST(self): + # Prepare result dict + #pdb.set_trace() + lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("POST", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in mGlobalDict["Server"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + return + else: + #Set access denied code + # Send response status code + self.send_response(403) + # Send headers + self.end_headers() + return + #Logging + #!Turn it on to stop print in console + #def log_message(self, format, *args): + # return +class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): + """Handle requests in a separate thread.""" + def finish_request(self, request, client_address): + request.settimeout(30) + # "super" can not be used because BaseServer is not created from object + HTTPServer.finish_request(self, request, client_address) +#inGlobalDict +# "JSONConfigurationDict": +class RobotDaemonServer(Thread): + def __init__(self,name,inGlobalDict): + Thread.__init__(self) + self.name = name + # Update the global dict + ServerSettings.SettingsUpdate(mGlobalDict) + def run(self): + inServerAddress=""; + inPort = mGlobalDict["Server"]["ListenPort"]; + # Server settings + # Choose port 8080, for port 80, which is normally used for a http server, you need root access + server_address = (inServerAddress, inPort) + #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) + # Logging + mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") + #httpd.serve_forever() + httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) + #print('Starting server, use to stop') + httpd.serve_forever() diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py new file mode 100644 index 00000000..3620dd75 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py @@ -0,0 +1,168 @@ +import json +from . import ExcelCom +import os +import sqlite3 +import win32com.client +import time +import pythoncom +#Insert in DB +def SQLInsert(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + # Create result JSON + lResultJSON = {"Status": "OK", "ErrorMessage":"", "Result":[]} + #Set status code 200 + inResponseDict["StatusCode"] = 200 + try: + #Read the body + #ReadRequest + lInputJSON={} + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray=inRequest.rfile.read(lInputByteArrayLength) + #print(lInputByteArray.decode('utf8')) + #Превращение массива байт в объект + lInputJSON=json.loads(lInputByteArray.decode('utf8')) + ######################################## + conn = sqlite3.connect(inGlobalDict["SQLite"]["DBPath"]) + c = conn.cursor() + # Loop for rows + for lRowItem in lInputJSON: + lRowResult={"Status": "OK", "ErrorMessage":""} + try: + my_dict = lRowItem["RowDict"] + # Insert a row of data + columns = ', '.join(my_dict.keys()) + placeholders = ':'+', :'.join(my_dict.keys()) + query = f'INSERT INTO {lRowItem["TableName"]} (%s) VALUES (%s)' % (columns, placeholders) + c.execute(query, my_dict) + except Exception as e: + lRowResult["Status"]="ERROR" + lRowResult["ErrorMessage"]=str(e) + finally: + lResultJSON["Result"].append(lRowResult) + # Save (commit) the changes + conn.commit() + # We can also close the connection if we are done with it. + # Just be sure any changes have been committed or they will be lost. + conn.close() + except Exception as e: + lResultJSON["Status"]="ERROR" + lResultJSON["ErrorMessage"]=str(e) + finally: + ######################################## + # Send message back to client + message = json.dumps(lResultJSON) + print(message) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") +################################################ +#Export SQLite to Excel +def SQLExportXLS(inRequest,inGlobalDict): + #Step 1 - read SQLite + conn = sqlite3.connect(inGlobalDict["SQLite"]["DBPath"]) + c = conn.cursor() + # Loop for rows +# for lRowItem in lInputJSON: +# my_dict = lRowItem["RowDict"] +# # Insert a row of data +# columns = ', '.join(my_dict.keys()) +# placeholders = ':'+', :'.join(my_dict.keys()) + query = f'select * from Test' + #create data array + #row = range(0,10) + i = 0 + data_array = [] + for row in c.execute(query): + # use the cursor as an iterable + data_array.append(row) + i += 1 + # We can also close the connection if we are done with it. + # Just be sure any changes have been committed or they will be lost. + conn.close() + #step 2 - insert in XLS + pythoncom.CoInitialize() + #write the array to an excel file + #excel = win32com.client.Dispatch("Excel.Application") + excel = win32com.client.gencache.EnsureDispatch('Excel.Application') + excel.Visible = True + excel.DisplayAlerts = False + #excel.ScreenUpdating = False + #book = excel.Workbooks.Add() + #sheet = book.Worksheets(1) + #Read input JSON + lInputJSON={} + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray=inRequest.rfile.read(lInputByteArrayLength) + #print(lInputByteArray.decode('utf8')) + #Превращение массива байт в объект + lInputJSON=json.loads(lInputByteArray.decode('utf8')) + #Config + lOffsetRow = lInputJSON["OffsetRow"] + lOffsetCol = lInputJSON["OffsetCol"] + lXLSTemplatePath = lInputJSON["XLSTemplatePath"] + lXLSSheetName = lInputJSON["XLSSheetName"] + lXLSResultPath = lInputJSON["XLSResultPath"] + lXLSResultFlagSendInResponse = lInputJSON["XLSResultFlagSendInResponse"] + lXLSResultFlagDeleteAfterSend = lInputJSON["XLSResultFlagDeleteAfterSend"] + try: + #excel = win32com.client.gencache.EnsureDispatch('Excel.Application') + book = ExcelCom.OpenWorkbook(excel, lXLSTemplatePath) + sheet = book.Worksheets(lXLSSheetName) + excel.Visible = True + #single loop, writing a row to a range + #Logic + start = time.time() + row = 0 + for line in data_array: + row += 1 + sheet.Range(sheet.Cells(row+lOffsetRow,1+lOffsetCol), sheet.Cells(row+lOffsetRow, len(line)+lOffsetCol)).Value = line + if lXLSResultPath: + book.SaveAs(Filename = lXLSResultPath) + #excel.ScreenUpdating = True + except Exception as e: + print(e) + finally: + # RELEASES RESOURCES + sheet = None + book = None + excel.DisplayAlerts = True + excel.Quit() + excel = None + pythoncom.CoUninitialize() + ##################### + #Step 3 - Send file content to client + ##################### + if lXLSResultFlagSendInResponse and lXLSResultPath: + lFileObject = open(lXLSResultPath, "rb") + # Write content as utf-8 data + inRequest.OpenRPAResponseDict["Body"] = lFileObject.read() + # Закрыть файловый объект + lFileObject.close() + ##################### + #Step 4 - Delete after send + ##################### + if lXLSResultFlagDeleteAfterSend and lXLSResultPath: + if os.path.exists(lXLSResultPath): + os.remove(lXLSResultPath) +def SettingsUpdate(inGlobalConfiguration): + import os + import pyOpenRPA.Orchestrator + lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1]) + lURLList = \ + [ #List of available URLs with the orchestrator server + #{ + # "Method":"GET|POST", + # "URL": "/index", #URL of the request + # "MatchType": "", #"BeginWith|Contains|Equal|EqualCase", + # "ResponseFilePath": "", #Absolute or relative path + # "ResponseFolderPath": "", #Absolute or relative path + # "ResponseContentType": "", #HTTP Content-type + # "ResponseDefRequestGlobal": None #Function with str result + #} + #Orchestrator basic dependencies + {"Method":"POST", "URL": "/SQLInsert", "MatchType": "EqualCase", "ResponseDefRequestGlobal": SQLInsert, "ResponseContentType": "application/json"}, + {"Method":"POST", "URL": "/SQLExportXLS.xlsx", "MatchType": "EqualCase", "ResponseDefRequestGlobal": SQLExportXLS, "ResponseContentType": "application/octet-stream"} + ] + inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList + return inGlobalConfiguration \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py new file mode 100644 index 00000000..26809770 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py @@ -0,0 +1,7 @@ +r""" + +The OpenRPA package (from UnicodeLabs) + +""" +__all__ = [] +__author__ = 'Ivan Maslov ' \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py new file mode 100644 index 00000000..f23064d3 --- /dev/null +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py @@ -0,0 +1,4 @@ +import sys +lFolderPath = "\\".join(__file__.split("\\")[:-3]) +sys.path.insert(0, lFolderPath) +from pyOpenRPA.Tools.RobotDB import RobotDB \ No newline at end of file diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py index eeeef317..1100d03a 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py +++ b/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA/__init__.py @@ -3,7 +3,7 @@ r""" The OpenRPA package (from UnicodeLabs) """ -__version__ = 'v1.0.37' +__version__ = 'v1.0.39' __all__ = [] __author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/INSTALLER b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/INSTALLER similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/INSTALLER rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/INSTALLER diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA similarity index 99% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA index 6b4d8af7..81643f98 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/METADATA +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pyOpenRPA -Version: 1.0.37 +Version: 1.0.39 Summary: First open source RPA platform for business Home-page: https://gitlab.com/UnicodeLabs/OpenRPA Author: Ivan Maslov diff --git a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD similarity index 94% rename from Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD index c76a61a0..4f267a9d 100644 --- a/Resources/WPy32-3720/python-3.7.2/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/RECORD +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/RECORD @@ -1,11 +1,11 @@ -pyOpenRPA-1.0.37.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pyOpenRPA-1.0.37.dist-info/METADATA,sha256=NvEs1xItXmuAnPaTzTs5kDpr6NhwdD4_WyFwvG9UTLo,3510 -pyOpenRPA-1.0.37.dist-info/RECORD,, -pyOpenRPA-1.0.37.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 -pyOpenRPA-1.0.37.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 +pyOpenRPA-1.0.39.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pyOpenRPA-1.0.39.dist-info/METADATA,sha256=KSr_y71FFd5y4tYQHnz80Pj_96WCYKwWbW5eK0hd4KM,3510 +pyOpenRPA-1.0.39.dist-info/RECORD,, +pyOpenRPA-1.0.39.dist-info/WHEEL,sha256=qB97nP5e4MrOsXW5bIU5cUn_KSVr10EV0l-GCHG9qNs,97 +pyOpenRPA-1.0.39.dist-info/top_level.txt,sha256=RPzwQXgYBRo_m5L3ZLs6Voh8aEkMeT29Xsul1w1qE0g,10 pyOpenRPA/Orchestrator/Orchestrator.py,sha256=UKp7eqvWDM91kYLwl2mo0UB8Pw-qu8eJCsR9NEXD1aU,6436 -pyOpenRPA/Orchestrator/Processor.py,sha256=HQQyOVX-d5vPO-YULyTxVOtXtUMfvpAaSVO4xXxaKVI,9107 -pyOpenRPA/Orchestrator/Server.py,sha256=aWDecl4_UUU00YG-pOXxyL7IvN5NK3efABt92y6M2kg,22136 +pyOpenRPA/Orchestrator/Processor.py,sha256=kmGNIqe6AZMSrzCt1QlonEy58ecFeLunjo8AeRMsufU,11091 +pyOpenRPA/Orchestrator/Server.py,sha256=QQK1rMZSg-pL9pJ059AoxIHHj4aFr1OWivdOEKPh9cs,22026 pyOpenRPA/Orchestrator/ServerSettings.py,sha256=jOXJTLwg8cJx6D-rN8J4dn5RCb2nepAhCH4F9hYVUdM,4912 pyOpenRPA/Orchestrator/Timer.py,sha256=FQZ3y6G9d47Ybx7RewzePKQV77H4gCkx5SaeFVlsuhc,2095 pyOpenRPA/Orchestrator/Web/Index.xhtml,sha256=su4tsDD_ZMbQz6Tbmqj55SM0ZZxuQw9tfPcytaB8wzs,32953 @@ -195,7 +195,7 @@ pyOpenRPA/Robot/Clipboard.py,sha256=q76X8L21zJwcwdoJJNPeCEwAV30xS6ylHP1WwvtxoWI, pyOpenRPA/Robot/OrchestratorConnector.py,sha256=Fihxz-jH9M4VakXEE0SZ0Vo9tLEQk8Tcg_C4HoH45gI,20037 pyOpenRPA/Robot/SettingsTemplate.py,sha256=Rp5XPeV2I4tCS2uf4Zkqm_ERJ6pZMg4-e5_lMqGJYLk,1453 pyOpenRPA/Robot/Test.py,sha256=qXr990nXiFZX5SNv6QN9GLb_U4HZRmJnbZR2qSnwilY,2878 -pyOpenRPA/Robot/UIDesktop.py,sha256=MWdWr0dZpk1PL1rsD91q6_8v687CSDBx1_T7IuHd3-E,77473 +pyOpenRPA/Robot/UIDesktop.py,sha256=3I2bllTDvR9d10O2ltkjoKmYw34wkkDAZfPlRpwbj30,77476 pyOpenRPA/Robot/Utils/JSONNormalize.py,sha256=aIuVzuZDazhxkCOzoOjfhHVz66mp2FWdfPv5E7KWF5Y,3890 pyOpenRPA/Robot/Utils/ProcessBitness.py,sha256=WlKL-DklGaoTnchtapOTM_ydxSB4yOeo9lcG3zr2VME,4524 pyOpenRPA/Robot/Utils/ProcessCommunicator.py,sha256=8GfmLnOvAdosmt7YNT86uEV9cjhKippssCX62wOMJwM,8039 @@ -235,6 +235,18 @@ pyOpenRPA/Studio/__pycache__/Studio.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/ValueVerify.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Studio/__pycache__/__main__.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/ExcelCom.py,sha256=hp0dvXOEC7Au00ueh7pqxkdixV-PC-km7tCt-wRunYs,343 +pyOpenRPA/Tools/RobotDB/RobotDB.py,sha256=DZSb17fiCAYLdNVTLFJ7nTbQhk29PjzxE9OL6ydCDcI,1645 +pyOpenRPA/Tools/RobotDB/Server.py,sha256=RO4Rj5-hmrRB41XKm4CrSFtauzKj3wNq4VmgcxhseeY,19838 +pyOpenRPA/Tools/RobotDB/ServerSettings.py,sha256=5p9JwrpKHh68oVHIWazTajB6AOfzeapARbvGcJOFmNc,7406 +pyOpenRPA/Tools/RobotDB/__init__.py,sha256=qVH8fEPgXk54rmy-ol0PnT8GF5OlGE0a8mExwJ4tFqY,124 +pyOpenRPA/Tools/RobotDB/__main__.py,sha256=w9sXIF4r_PeWJjHJutTuH8DSYpXxpgcAN0KUOjiJ6PI,140 +pyOpenRPA/Tools/RobotDB/__pycache__/ExcelCom.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/RobotDB.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/Server.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/ServerSettings.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/__init__.cpython-37.pyc,, +pyOpenRPA/Tools/RobotDB/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/RobotRDPActive/Connector.py,sha256=qU5SXwHgQU177MjqEHyOwJDLAcSVnIkKKw76iD09J1w,7275 pyOpenRPA/Tools/RobotRDPActive/Monitor.py,sha256=H7ciateTh-hml8z69EYZjYgqdTZGkDRtnFwuYnytrCw,3278 pyOpenRPA/Tools/RobotRDPActive/Template.rdp,sha256=qPCLkjzTdYKURK7nRApkPUjRuS4K20vDPj9DIUNSSkE,2392 @@ -255,5 +267,5 @@ pyOpenRPA/Tools/RobotScreenActive/__pycache__/__init__.cpython-37.pyc,, pyOpenRPA/Tools/RobotScreenActive/__pycache__/__main__.cpython-37.pyc,, pyOpenRPA/Tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 pyOpenRPA/Tools/__pycache__/__init__.cpython-37.pyc,, -pyOpenRPA/__init__.py,sha256=32Po3gFALn9l6ft6LTFVJBkBj-1p5hP83AVcQ_FTa0s,175 +pyOpenRPA/__init__.py,sha256=iZp06tUV8Mw7GGdUcuW_faV4YaQEJa_n5BqxOl0cwx8,175 pyOpenRPA/__pycache__/__init__.cpython-37.pyc,, diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/WHEEL b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/WHEEL similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/WHEEL rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/WHEEL diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/top_level.txt b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/top_level.txt similarity index 100% rename from Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.37.dist-info/top_level.txt rename to Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA-1.0.39.dist-info/top_level.txt diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py index 6089a62c..7c10775e 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Processor.py @@ -7,6 +7,7 @@ import sys import subprocess import copy import importlib +import psutil #Input arg # [ # { @@ -38,6 +39,13 @@ import importlib # # }, # { +# "Type":"ProcessStartIfTurnedOff", +# "CheckTaskName":"", #Check if current task name is not active (then start process), +# "Path":"", +# "ArgList":[] +# +# }, +# { # "Type":"ProcessStop", # "Name":"", # "FlagForce":True, @@ -71,6 +79,7 @@ def Activity(inActivity): inActivity["DateTimeUTCStringStart"] = datetime.datetime.strftime(datetime.datetime.now(),"%Y-%m-%dT%H:%M:%S.%f") #Alias (compatibility) lItem = inActivity + lCurrentDateTime = datetime.datetime.now() ########################################################### #Обработка запроса на отправку команды на удаленную машину ########################################################### @@ -138,11 +147,33 @@ def Activity(inActivity): #Вид активности - запуск процесса #Запись в массив отработанных активностей #Лог - mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processPath"], "activityStartDateTime":str(lCurrentDateTime)}) + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)}) #Запустить процесс - lItemArgs=[lItem["processPath"]] - lItemArgs.extend(lItem["processArgs"]) + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) subprocess.Popen(lItemArgs,shell=True) + ##################################### + #ProcessStartIfTurnedOff + ##################################### + if lItem["Type"]=="ProcessStartIfTurnedOff": + #Check if process running + #remove .exe from Taskname if exists + lCheckTaskName = lItem["CheckTaskName"] + if len(lCheckTaskName)>4: + if lCheckTaskName[-4:].upper() != ".EXE": + lCheckTaskName = lCheckTaskName+".exe" + else: + lCheckTaskName = lCheckTaskName+".exe" + #Check if process exist + if not CheckIfProcessRunning(lCheckTaskName): + #Вид активности - запуск процесса + #Запись в массив отработанных активностей + #Лог + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Path"], "activityStartDateTime":str(lCurrentDateTime)}) + #Запустить процесс + lItemArgs=[lItem["Path"]] + lItemArgs.extend(lItem["ArgList"]) + subprocess.Popen(lItemArgs,shell=True) ################################# #ProcessStop ################################# @@ -150,7 +181,7 @@ def Activity(inActivity): #Вид активности - остановка процесса #часовой пояс пока не учитываем #Сформировать команду на завершение - lActivityCloseCommand='taskkill /im '+lItem["processName"] + lActivityCloseCommand='taskkill /im '+lItem["Name"] #TODO Сделать безопасную обработку,если параметра нет в конфигурации if lItem.get('FlagForce',False): lActivityCloseCommand+=" /F" @@ -158,7 +189,7 @@ def Activity(inActivity): if lItem.get('User',"")!="": lActivityCloseCommand+=f' /fi "username eq {lItem["User"]}"' #Лог - mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["activityType"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["processName"], "activityStartDateTime":str(lCurrentDateTime)}) + mGlobalDict["Processor"]["LogList"].append({"activityType":lItem["Type"], "activityDateTime":str(lActivityDateTime), "processPath":lItem["Name"], "activityStartDateTime":str(lCurrentDateTime)}) #Завершить процесс os.system(lActivityCloseCommand) ################################# @@ -213,4 +244,18 @@ def ActivityListOrDict(inActivityListOrDict): return lResult if type(inActivityListOrDict)==dict: #Dict activity - return Activity(inActivityListOrDict) \ No newline at end of file + return Activity(inActivityListOrDict) + +def CheckIfProcessRunning(processName): + ''' + Check if there is any running process that contains the given name processName. + ''' + #Iterate over the all the running process + for proc in psutil.process_iter(): + try: + # Check if process name contains the given name string. + if processName.lower() in proc.name().lower(): + return True + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + return False; \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py index e5d54b87..d82eaf3a 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Orchestrator/Server.py @@ -425,8 +425,6 @@ class RobotDaemonServer(Thread): #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) # Logging mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") - # Запуск адреса в браузере - os.system("explorer http://127.0.0.1:8081") #httpd.serve_forever() httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) #print('Starting server, use to stop') diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py index d18da2c6..3a003c5d 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Robot/UIDesktop.py @@ -1208,7 +1208,7 @@ def UIOSelector_Highlight(inUIOSelector): UIO_Highlight(UIOSelector_Get_UIO(inUIOSelector)) else: # Run function from other process with help of PIPE - lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool", + lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Highlight", "ArgumentList": [inUIOSelector], "ArgumentDict": {}} # Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами @@ -1233,7 +1233,7 @@ def UIOSelector_FocusHighlight(inUIOSelector): UIO_FocusHighlight(UIOSelector_Get_UIO(inUIOSelector)) else: # Run function from other process with help of PIPE - lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_Exist_Bool", + lPIPEResuestDict = {"ModuleName": "UIDesktop", "ActivityName": "UIOSelector_FocusHighlight", "ArgumentList": [inUIOSelector], "ArgumentDict": {}} # Отправить запрос в дочерний процесс, который отвечает за работу с Windows окнами diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py new file mode 100644 index 00000000..41bf0ea6 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ExcelCom.py @@ -0,0 +1,11 @@ +import win32com.client as win32 +def OpenWorkbook(xlapp, xlfile): + try: + xlwb = xlapp.Workbooks(xlfile) + except Exception as e: + try: + xlwb = xlapp.Workbooks.Open(xlfile) + except Exception as e: + print(e) + xlwb = None + return(xlwb) \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py new file mode 100644 index 00000000..ef1c8845 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/RobotDB.py @@ -0,0 +1,41 @@ +import subprocess +import json +import datetime +import time +import codecs +import os +import signal +import sys #Get input argument +import pdb +from . import Server +import logging +import copy +#from .Settings import Settings +import importlib +from importlib import util + +#Единый глобальный словарь (За основу взять из Settings.py) +global mGlobalDict +#Call Settings function from argv[1] file +################################################ +lSubmoduleFunctionName = "Settings" +lFileFullPath = sys.argv[1] +lModuleName = (lFileFullPath.split("\\")[-1])[0:-3] +lTechSpecification = importlib.util.spec_from_file_location(lModuleName, lFileFullPath) +lTechModuleFromSpec = importlib.util.module_from_spec(lTechSpecification) +lTechSpecificationModuleLoader = lTechSpecification.loader.exec_module(lTechModuleFromSpec) +mGlobalDict = None +if lSubmoduleFunctionName in dir(lTechModuleFromSpec): + # Run SettingUpdate function in submodule + mGlobalDict = getattr(lTechModuleFromSpec, lSubmoduleFunctionName)() +################################################# +#mGlobalDict = Settings.Settings(sys.argv[1]) +Server.mGlobalDict = mGlobalDict + +#Инициализация настроечных параметров +lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) +lDaemonStartDateTime=datetime.datetime.now() + +#Инициализация сервера +lThreadServer = Server.RobotDaemonServer("ServerThread", mGlobalDict) +lThreadServer.start() \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py new file mode 100644 index 00000000..92ab89a1 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/Server.py @@ -0,0 +1,395 @@ +from http.server import BaseHTTPRequestHandler, HTTPServer +from socketserver import ThreadingMixIn +import threading +import json +from threading import Thread +import importlib +import pdb +import base64 +import uuid +import datetime +import os #for path operations +from http import cookies +global mGlobalDict +from . import ServerSettings +#Authenticate function () +# return dict +# { +# "Domain": "", #Empty if Auth is not success +# "User": "" #Empty if Auth is not success +# } +def AuthenticateVerify(inRequest): + lResult={"Domain": "", "User": ""} + ###################################### + #Way 1 - try to find AuthToken + lCookies = cookies.SimpleCookie(inRequest.headers.get("Cookie", "")) + inRequest.OpenRPA = {} + inRequest.OpenRPA["AuthToken"] = None + #pdb.set_trace() + if "AuthToken" in lCookies: + lCookieAuthToken = lCookies.get("AuthToken", "").value + if lCookieAuthToken: + #Find AuthToken in GlobalDict + if lCookieAuthToken in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + #Auth Token Has Been Founded + lResult["Domain"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + #Set auth token + inRequest.OpenRPA["AuthToken"] = lCookieAuthToken + #Exit earlier + return lResult + ###################################### + #Way 2 - try to logon + lHeaderAuthorization = inRequest.headers.get("Authorization", "").split(" ") + if len(lHeaderAuthorization) == 2: + llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( + ":") + lUser = llHeaderAuthorizationDecodedUserPasswordList[0] + lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] + lDomain = "" + if "\\" in lUser: + lDomain = lUser.split("\\")[0] + lUser = lUser.split("\\")[1] + #Try to logon - use processor + lLogonResult = Processor.Activity( + { + "Type": "WindowsLogon", + "Domain": lDomain, + "User": lUser, + "Password": lPassword + } + ) + #Check result + if lLogonResult["Result"]: + lResult["Domain"] = lLogonResult["Domain"] + lResult["User"] = lLogonResult["User"] + #Create token + lAuthToken=str(uuid.uuid1()) + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + #Set-cookie + inRequest.OpenRPA["AuthToken"] = lAuthToken + inRequest.OpenRPASetCookie = {} + #New engine of server + inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken + #inRequest.OpenRPAResponse["Set-Cookie"]=[]lResult["Set-Cookie"] = lAuthToken + #pdb.set_trace() + #inRequest.send_header("Set-Cookie:", f"AuthToken={lAuthToken}") + ###################################### + return lResult +def AuthenticateBlock(inRequest): + # Send response status code + inRequest.send_response(401) + # Send headers + inRequest.send_header('Content-type', 'text/html') + inRequest.send_header('WWW-Authenticate', 'Basic') # Always ask login pass + inRequest.end_headers() + # Write content as utf-8 data + inRequest.wfile.write(bytes("", "utf8")) +#Check access before execute the action +#return bool True - go execute, False - dont execute +def UserAccessCheckBefore(inMethod, inRequest): + # Help def - Get access flag from dict + #pdb.set_trace() + def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): + if "FlagAccess" in inAccessRuleItem: + return inAccessRuleItem["FlagAccess"] + elif "FlagAccessDefRequestGlobalAuthenticate" in inAccessRuleItem: + return inAccessRuleItem["FlagAccessDefRequestGlobalAuthenticate"](inRequest, inGlobalDict, + inAuthenticateDict) + ########################################## + inMethod=inMethod.upper() + #Prepare result false + lResult = False + lAuthToken = inRequest.OpenRPA["AuthToken"] + #go next if user is identified + lUserDict = None + if lAuthToken: + lUserDict = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] + #pdb.set_trace() + ######################################## + ######################################## + #Check general before rule (without User domain) + #Check rules + for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []): + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.contains(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + ######################################### + ######################################### + #Do check if lResult is false + if not lResult: + #Check access by User Domain + #Check rules to find first appicable + #Check rules + for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []): + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + #check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + lURLPath = inRequest.path + lURLPath = lURLPath.upper() + if lURLPath.contains(lAccessRuleItem["URL"].upper()): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + ##################################### + ##################################### + #Return lResult + return lResult +# HTTPRequestHandler class +class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): + #Tech def + #return {"headers":[],"body":"","statuscode":111} + def URLItemCheckDo(self, inURLItem, inMethod): + ############################### + #Tech sub def - do item + ################################ + def URLItemDo(inURLItem,inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + #Set status code 200 + inResponseDict["StatusCode"] = 200 + #Content-type + if "ResponseContentType" in inURLItem: + inResponseDict["Headers"]["Content-type"] = inURLItem["ResponseContentType"] + #If file path is set + if "ResponseFilePath" in inURLItem: + lFileObject = open(inURLItem["ResponseFilePath"], "rb") + # Write content as utf-8 data + inResponseDict["Body"] = lFileObject.read() + # Закрыть файловый объект + lFileObject.close() + #If function is set + if "ResponseDefRequestGlobal" in inURLItem: + inURLItem["ResponseDefRequestGlobal"](inRequest, inGlobalDict) + if "ResponseFolderPath" in inURLItem: + lRequestPath = inRequest.path + lFilePathSecondPart = lRequestPath.replace(inURLItem["URL"],"") + lFilePath = 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): + lFileObject = open(lFilePath, "rb") + # Write content as utf-8 data + inResponseDict["Body"] = lFileObject.read() + inResponseDict["ContentType"]= "application/octet-stream" + # Закрыть файловый объект + lFileObject.close() + ############################################## + if inURLItem["Method"].upper() == inMethod.upper(): + # check Match type variant: BeginWith + if inURLItem["MatchType"].upper() == "BEGINWITH": + lURLPath = self.path + lURLPath = lURLPath.upper() + if lURLPath.startswith(inURLItem["URL"].upper()): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: Contains + elif inURLItem["MatchType"].upper() == "CONTAINS": + lURLPath = self.path + lURLPath = lURLPath.upper() + if lURLPath.contains(inURLItem["URL"].upper()): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: Equal + elif inURLItem["MatchType"].upper() == "EQUAL": + if inURLItem["URL"].upper() == self.path.upper(): + URLItemDo(inURLItem, self, mGlobalDict) + return True + # check Match type variant: EqualCase + elif inURLItem["MatchType"].upper() == "EQUALCASE": + if inURLItem["URL"] == self.path: + URLItemDo(inURLItem, self, mGlobalDict) + return True + return False + #ResponseContentTypeFile + def SendResponseContentTypeFile(self, inContentType, inFilePath): + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type', inContentType) + #Check if var exist + if hasattr(self, "OpenRPASetCookie"): + self.send_header("Set-Cookie", f"AuthToken={self.OpenRPA['AuthToken']}") + self.end_headers() + lFileObject = open(inFilePath, "rb") + # Write content as utf-8 data + self.wfile.write(lFileObject.read()) + #Закрыть файловый объект + lFileObject.close() + # ResponseContentTypeFile + def ResponseDictSend(self): + inResponseDict = self.OpenRPAResponseDict + # Send response status code + self.send_response(inResponseDict["StatusCode"]) + # Send headers + for lItemKey, lItemValue in inResponseDict["Headers"].items(): + self.send_header(lItemKey, lItemValue) + # Send headers: Set-Cookie + for lItemKey, lItemValue in inResponseDict["SetCookies"].items(): + self.send_header("Set-Cookie", f"{lItemKey}={lItemValue}") + #Close headers section in response + self.end_headers() + # Write content as utf-8 data + self.wfile.write(inResponseDict["Body"]) + def do_GET(self): + # Prepare result dict + lResponseDict = {"Headers": {}, "SetCookies": {}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + # Logging + mGlobalDict["Logger"].info(f"HTTP request /. Domain: {lAuthenticateDict['Domain']}, User: {lAuthenticateDict['User']}") + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("GET", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in mGlobalDict["Server"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + else: + #Set access denied code + # Send response status code + self.send_response(403) + # Send headers + self.end_headers() + # POST + def do_POST(self): + # Prepare result dict + #pdb.set_trace() + lResponseDict = {"Headers": {}, "SetCookies":{}, "Body": b"", "StatusCode": None} + self.OpenRPAResponseDict = lResponseDict + ##################################### + #Do authentication + #Check if authentication is turned on + ##################################### + lFlagAccessUserBlock=False + lAuthenticateDict = {"Domain": "", "User": ""} + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lAuthenticateDict = AuthenticateVerify(self) + if not lAuthenticateDict["User"]: + lFlagAccessUserBlock=True + if lFlagAccessUserBlock: + AuthenticateBlock(self) + ##################################### + else: + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("POST", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + ############################ + #New server engine (url from global dict (URLList)) + ############################ + for lURLItem in mGlobalDict["Server"]["URLList"]: + #Check if all condition are applied + lFlagURLIsApplied=False + lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") + if lFlagURLIsApplied: + self.ResponseDictSend() + return + return + else: + #Set access denied code + # Send response status code + self.send_response(403) + # Send headers + self.end_headers() + return + #Logging + #!Turn it on to stop print in console + #def log_message(self, format, *args): + # return +class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): + """Handle requests in a separate thread.""" + def finish_request(self, request, client_address): + request.settimeout(30) + # "super" can not be used because BaseServer is not created from object + HTTPServer.finish_request(self, request, client_address) +#inGlobalDict +# "JSONConfigurationDict": +class RobotDaemonServer(Thread): + def __init__(self,name,inGlobalDict): + Thread.__init__(self) + self.name = name + # Update the global dict + ServerSettings.SettingsUpdate(mGlobalDict) + def run(self): + inServerAddress=""; + inPort = mGlobalDict["Server"]["ListenPort"]; + # Server settings + # Choose port 8080, for port 80, which is normally used for a http server, you need root access + server_address = (inServerAddress, inPort) + #httpd = HTTPServer(server_address, testHTTPServer_RequestHandler) + # Logging + mGlobalDict["Logger"].info(f"Server init. Listen URL: {inServerAddress}, Listen port: {inPort}") + #httpd.serve_forever() + httpd = ThreadedHTTPServer(server_address, testHTTPServer_RequestHandler) + #print('Starting server, use to stop') + httpd.serve_forever() diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py new file mode 100644 index 00000000..3620dd75 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/ServerSettings.py @@ -0,0 +1,168 @@ +import json +from . import ExcelCom +import os +import sqlite3 +import win32com.client +import time +import pythoncom +#Insert in DB +def SQLInsert(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + # Create result JSON + lResultJSON = {"Status": "OK", "ErrorMessage":"", "Result":[]} + #Set status code 200 + inResponseDict["StatusCode"] = 200 + try: + #Read the body + #ReadRequest + lInputJSON={} + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray=inRequest.rfile.read(lInputByteArrayLength) + #print(lInputByteArray.decode('utf8')) + #Превращение массива байт в объект + lInputJSON=json.loads(lInputByteArray.decode('utf8')) + ######################################## + conn = sqlite3.connect(inGlobalDict["SQLite"]["DBPath"]) + c = conn.cursor() + # Loop for rows + for lRowItem in lInputJSON: + lRowResult={"Status": "OK", "ErrorMessage":""} + try: + my_dict = lRowItem["RowDict"] + # Insert a row of data + columns = ', '.join(my_dict.keys()) + placeholders = ':'+', :'.join(my_dict.keys()) + query = f'INSERT INTO {lRowItem["TableName"]} (%s) VALUES (%s)' % (columns, placeholders) + c.execute(query, my_dict) + except Exception as e: + lRowResult["Status"]="ERROR" + lRowResult["ErrorMessage"]=str(e) + finally: + lResultJSON["Result"].append(lRowResult) + # Save (commit) the changes + conn.commit() + # We can also close the connection if we are done with it. + # Just be sure any changes have been committed or they will be lost. + conn.close() + except Exception as e: + lResultJSON["Status"]="ERROR" + lResultJSON["ErrorMessage"]=str(e) + finally: + ######################################## + # Send message back to client + message = json.dumps(lResultJSON) + print(message) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") +################################################ +#Export SQLite to Excel +def SQLExportXLS(inRequest,inGlobalDict): + #Step 1 - read SQLite + conn = sqlite3.connect(inGlobalDict["SQLite"]["DBPath"]) + c = conn.cursor() + # Loop for rows +# for lRowItem in lInputJSON: +# my_dict = lRowItem["RowDict"] +# # Insert a row of data +# columns = ', '.join(my_dict.keys()) +# placeholders = ':'+', :'.join(my_dict.keys()) + query = f'select * from Test' + #create data array + #row = range(0,10) + i = 0 + data_array = [] + for row in c.execute(query): + # use the cursor as an iterable + data_array.append(row) + i += 1 + # We can also close the connection if we are done with it. + # Just be sure any changes have been committed or they will be lost. + conn.close() + #step 2 - insert in XLS + pythoncom.CoInitialize() + #write the array to an excel file + #excel = win32com.client.Dispatch("Excel.Application") + excel = win32com.client.gencache.EnsureDispatch('Excel.Application') + excel.Visible = True + excel.DisplayAlerts = False + #excel.ScreenUpdating = False + #book = excel.Workbooks.Add() + #sheet = book.Worksheets(1) + #Read input JSON + lInputJSON={} + if inRequest.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) + lInputByteArray=inRequest.rfile.read(lInputByteArrayLength) + #print(lInputByteArray.decode('utf8')) + #Превращение массива байт в объект + lInputJSON=json.loads(lInputByteArray.decode('utf8')) + #Config + lOffsetRow = lInputJSON["OffsetRow"] + lOffsetCol = lInputJSON["OffsetCol"] + lXLSTemplatePath = lInputJSON["XLSTemplatePath"] + lXLSSheetName = lInputJSON["XLSSheetName"] + lXLSResultPath = lInputJSON["XLSResultPath"] + lXLSResultFlagSendInResponse = lInputJSON["XLSResultFlagSendInResponse"] + lXLSResultFlagDeleteAfterSend = lInputJSON["XLSResultFlagDeleteAfterSend"] + try: + #excel = win32com.client.gencache.EnsureDispatch('Excel.Application') + book = ExcelCom.OpenWorkbook(excel, lXLSTemplatePath) + sheet = book.Worksheets(lXLSSheetName) + excel.Visible = True + #single loop, writing a row to a range + #Logic + start = time.time() + row = 0 + for line in data_array: + row += 1 + sheet.Range(sheet.Cells(row+lOffsetRow,1+lOffsetCol), sheet.Cells(row+lOffsetRow, len(line)+lOffsetCol)).Value = line + if lXLSResultPath: + book.SaveAs(Filename = lXLSResultPath) + #excel.ScreenUpdating = True + except Exception as e: + print(e) + finally: + # RELEASES RESOURCES + sheet = None + book = None + excel.DisplayAlerts = True + excel.Quit() + excel = None + pythoncom.CoUninitialize() + ##################### + #Step 3 - Send file content to client + ##################### + if lXLSResultFlagSendInResponse and lXLSResultPath: + lFileObject = open(lXLSResultPath, "rb") + # Write content as utf-8 data + inRequest.OpenRPAResponseDict["Body"] = lFileObject.read() + # Закрыть файловый объект + lFileObject.close() + ##################### + #Step 4 - Delete after send + ##################### + if lXLSResultFlagDeleteAfterSend and lXLSResultPath: + if os.path.exists(lXLSResultPath): + os.remove(lXLSResultPath) +def SettingsUpdate(inGlobalConfiguration): + import os + import pyOpenRPA.Orchestrator + lOrchestratorFolder = "\\".join(pyOpenRPA.Orchestrator.__file__.split("\\")[:-1]) + lURLList = \ + [ #List of available URLs with the orchestrator server + #{ + # "Method":"GET|POST", + # "URL": "/index", #URL of the request + # "MatchType": "", #"BeginWith|Contains|Equal|EqualCase", + # "ResponseFilePath": "", #Absolute or relative path + # "ResponseFolderPath": "", #Absolute or relative path + # "ResponseContentType": "", #HTTP Content-type + # "ResponseDefRequestGlobal": None #Function with str result + #} + #Orchestrator basic dependencies + {"Method":"POST", "URL": "/SQLInsert", "MatchType": "EqualCase", "ResponseDefRequestGlobal": SQLInsert, "ResponseContentType": "application/json"}, + {"Method":"POST", "URL": "/SQLExportXLS.xlsx", "MatchType": "EqualCase", "ResponseDefRequestGlobal": SQLExportXLS, "ResponseContentType": "application/octet-stream"} + ] + inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList + return inGlobalConfiguration \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py new file mode 100644 index 00000000..26809770 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__init__.py @@ -0,0 +1,7 @@ +r""" + +The OpenRPA package (from UnicodeLabs) + +""" +__all__ = [] +__author__ = 'Ivan Maslov ' \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py new file mode 100644 index 00000000..f23064d3 --- /dev/null +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/Tools/RobotDB/__main__.py @@ -0,0 +1,4 @@ +import sys +lFolderPath = "\\".join(__file__.split("\\")[:-3]) +sys.path.insert(0, lFolderPath) +from pyOpenRPA.Tools.RobotDB import RobotDB \ No newline at end of file diff --git a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py index eeeef317..1100d03a 100644 --- a/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py +++ b/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/pyOpenRPA/__init__.py @@ -3,7 +3,7 @@ r""" The OpenRPA package (from UnicodeLabs) """ -__version__ = 'v1.0.37' +__version__ = 'v1.0.39' __all__ = [] __author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/Sources/pyOpenRPA/__init__.py b/Sources/pyOpenRPA/__init__.py index 1ce87e12..1100d03a 100644 --- a/Sources/pyOpenRPA/__init__.py +++ b/Sources/pyOpenRPA/__init__.py @@ -3,7 +3,7 @@ r""" The OpenRPA package (from UnicodeLabs) """ -__version__ = 'v1.0.38' +__version__ = 'v1.0.39' __all__ = [] __author__ = 'Ivan Maslov ' #from .Core import Robot \ No newline at end of file diff --git a/v1.0.38- b/v1.0.38- deleted file mode 100644 index e69de29b..00000000 diff --git a/Test.txt b/v1.0.39 similarity index 100% rename from Test.txt rename to v1.0.39