modulitiz-micro 2.45.1__py311-none-any.whl → 2.46.0__py311-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- modulitiz_micro/ModuloSeriale.py +70 -70
- modulitiz_micro/ModuloTarghe.py +47 -47
- modulitiz_micro/database/AbstractDatabaseService.py +13 -13
- modulitiz_micro/database/AbstractSql.py +69 -69
- modulitiz_micro/database/ModuloSqlOracle.py +19 -19
- modulitiz_micro/database/ModuloSqlServer.py +43 -43
- modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -6
- modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -114
- modulitiz_micro/database/mysql/ModuloMysql.py +163 -163
- modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -47
- modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -6
- modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -114
- modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -82
- modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -7
- modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -7
- modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -8
- modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -7
- modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -7
- modulitiz_micro/files/cache/DatabaseCache.py +91 -91
- modulitiz_micro/files/cache/decorators/cacheRam.py +26 -26
- modulitiz_micro/files/git/ModuloGit.py +28 -28
- modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -19
- modulitiz_micro/files/git/exceptions/EccezioneGit.py +7 -7
- modulitiz_micro/gestionedom/GestioneDom.py +44 -44
- modulitiz_micro/iot/ModuleIotDevice.py +62 -62
- modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -7
- modulitiz_micro/keylogger/ModuloKeylogger.py +73 -73
- modulitiz_micro/rete/ModuleAndroidTVRemote.py +107 -0
- modulitiz_micro/rete/ModuloNetworking.py +67 -72
- modulitiz_micro/rete/ModuloOpenVpn.py +15 -15
- modulitiz_micro/rete/email/EmailBean.py +5 -5
- modulitiz_micro/rete/email/ModuloEmail.py +90 -90
- modulitiz_micro/rete/http/ModuloHttp.py +119 -119
- modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -91
- modulitiz_micro/rete/http/ModuloHttpUtils.py +69 -69
- modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -5
- modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -22
- modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +84 -84
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -28
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +6 -6
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +22 -22
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -49
- modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +21 -21
- modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -7
- modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +72 -72
- modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -73
- modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -8
- modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -35
- modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -267
- modulitiz_micro/rete/ssl/ModuloSsl.py +56 -56
- modulitiz_micro/sistema/ModuloEnvVars.py +34 -34
- modulitiz_micro/sistema/ModuloSystemPipe.py +67 -67
- modulitiz_micro/social/telegram/AbstractModuloTelegram.py +53 -53
- modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -26
- modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -15
- modulitiz_micro/util/scheduler/ModuleScheduler.py +26 -26
- modulitiz_micro/weather/AbstractModuleWeather.py +31 -31
- modulitiz_micro/weather/ModuleWeather.py +62 -62
- {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/METADATA +59 -59
- modulitiz_micro-2.46.0.dist-info/RECORD +67 -0
- {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/licenses/LICENSE +21 -21
- modulitiz_micro-2.45.1.dist-info/RECORD +0 -66
- {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/WHEEL +0 -0
- {modulitiz_micro-2.45.1.dist-info → modulitiz_micro-2.46.0.dist-info}/top_level.txt +0 -0
@@ -1,72 +1,67 @@
|
|
1
|
-
import os
|
2
|
-
import
|
3
|
-
import
|
4
|
-
from
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
from modulitiz_nano.
|
10
|
-
from modulitiz_nano.
|
11
|
-
from modulitiz_nano.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
mac
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
sockObj
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
sockObj.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
outputComando
|
65
|
-
rows=
|
66
|
-
rows
|
67
|
-
|
68
|
-
if ModuloStringhe.contains(row, "%"):
|
69
|
-
regexOutput=re.search(regexPercPacketsLost,row)
|
70
|
-
if regexOutput is not None:
|
71
|
-
return int(regexOutput.group(1).strip())==0
|
72
|
-
return False
|
1
|
+
import os
|
2
|
+
import socket
|
3
|
+
from contextlib import closing
|
4
|
+
from uuid import getnode
|
5
|
+
|
6
|
+
from _socket import gaierror
|
7
|
+
|
8
|
+
from modulitiz_nano.ModuloListe import ModuloListe
|
9
|
+
from modulitiz_nano.ModuloStringhe import ModuloStringhe
|
10
|
+
from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
|
11
|
+
from modulitiz_nano.sistema.ModuloSystem import ModuloSystem
|
12
|
+
|
13
|
+
|
14
|
+
class ModuloNetworking(object):
|
15
|
+
@staticmethod
|
16
|
+
def getMacAddress()->str:
|
17
|
+
mac=("%012X" % getnode())
|
18
|
+
return mac
|
19
|
+
|
20
|
+
@staticmethod
|
21
|
+
def getLocalIp()->str|None:
|
22
|
+
"""
|
23
|
+
Returns private local IP address.
|
24
|
+
"""
|
25
|
+
sockObj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
26
|
+
sockObj.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
27
|
+
try:
|
28
|
+
# doesn't even have to be reachable
|
29
|
+
sockObj.connect(('255.255.255.255', 1))
|
30
|
+
indirizzoIp = sockObj.getsockname()[0]
|
31
|
+
except gaierror:
|
32
|
+
indirizzoIp = None
|
33
|
+
finally:
|
34
|
+
sockObj.close()
|
35
|
+
return indirizzoIp
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def isHttpPortOpen(host:str|None,port:int)->bool:
|
39
|
+
# controllo host
|
40
|
+
if host is None:
|
41
|
+
host="127.0.0.1"
|
42
|
+
# controllo porta
|
43
|
+
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
|
44
|
+
if sock.connect_ex((host, port)) == 0:
|
45
|
+
return True
|
46
|
+
return False
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
def checkPing(ipAddress:str)->bool:
|
50
|
+
# build command
|
51
|
+
cmd="ping "
|
52
|
+
textToSearch="="
|
53
|
+
if ModuloSystem.isWindows():
|
54
|
+
cmd+="-n"
|
55
|
+
textToSearch=" TTL"+textToSearch
|
56
|
+
elif os.name=='posix':
|
57
|
+
cmd+="-W 5 -c"
|
58
|
+
textToSearch=" ttl"+textToSearch
|
59
|
+
else:
|
60
|
+
raise EccezioneRuntime("Tipologia del sistema operativo non riconosciuta: "+os.name)
|
61
|
+
cmd+=" 1 "+ipAddress
|
62
|
+
# execute command
|
63
|
+
outputComando=ModuloStringhe.normalizzaEol(ModuloSystem.systemCallReturnOutput(cmd,None))
|
64
|
+
rows=outputComando.split("\n")
|
65
|
+
rows=ModuloListe.eliminaElementiVuoti(rows)
|
66
|
+
rowsMatching=[x for x in rows if ModuloStringhe.contains(x,textToSearch)]
|
67
|
+
return len(rowsMatching)==1
|
@@ -1,15 +1,15 @@
|
|
1
|
-
from modulitiz_nano.sistema.ModuloSystem import ModuloSystem
|
2
|
-
|
3
|
-
|
4
|
-
class ModuloOpenVpn(object):
|
5
|
-
def __init__(self,percorsoOpenVpn:str):
|
6
|
-
self.__percorsoOpenVpn=percorsoOpenVpn
|
7
|
-
|
8
|
-
def startVpn(self,isOpenVpnAlreadyRunning:bool,filenameOvpn:str):
|
9
|
-
"""
|
10
|
-
Send a command to start vpn to a new or already running instance of the GUI.
|
11
|
-
https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI-New#gui-help
|
12
|
-
"""
|
13
|
-
subCmd="--command connect" if isOpenVpnAlreadyRunning else "--connect"
|
14
|
-
cmd=r'start "" "{}" {} {}.ovpn'.format(self.__percorsoOpenVpn,subCmd,filenameOvpn)
|
15
|
-
ModuloSystem.systemCallWaitAndClose(cmd,False)
|
1
|
+
from modulitiz_nano.sistema.ModuloSystem import ModuloSystem
|
2
|
+
|
3
|
+
|
4
|
+
class ModuloOpenVpn(object):
|
5
|
+
def __init__(self,percorsoOpenVpn:str):
|
6
|
+
self.__percorsoOpenVpn=percorsoOpenVpn
|
7
|
+
|
8
|
+
def startVpn(self,isOpenVpnAlreadyRunning:bool,filenameOvpn:str):
|
9
|
+
"""
|
10
|
+
Send a command to start vpn to a new or already running instance of the GUI.
|
11
|
+
https://community.openvpn.net/openvpn/wiki/OpenVPN-GUI-New#gui-help
|
12
|
+
"""
|
13
|
+
subCmd="--command connect" if isOpenVpnAlreadyRunning else "--connect"
|
14
|
+
cmd=r'start "" "{}" {} {}.ovpn'.format(self.__percorsoOpenVpn,subCmd,filenameOvpn)
|
15
|
+
ModuloSystem.systemCallWaitAndClose(cmd,False)
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class EmailBean(object):
|
2
|
-
def __init__(self,diz:dict):
|
3
|
-
self.destinatario:str=diz['destinatario']
|
4
|
-
self.user:str=diz['user']
|
5
|
-
self.password:str=diz['password']
|
1
|
+
class EmailBean(object):
|
2
|
+
def __init__(self,diz:dict):
|
3
|
+
self.destinatario:str=diz['destinatario']
|
4
|
+
self.user:str=diz['user']
|
5
|
+
self.password:str=diz['password']
|
@@ -1,90 +1,90 @@
|
|
1
|
-
import smtplib
|
2
|
-
|
3
|
-
from modulitiz_nano.ModuloDate import ModuloDate
|
4
|
-
from modulitiz_nano.ModuloListe import ModuloListe
|
5
|
-
from modulitiz_nano.ModuloStringhe import ModuloStringhe
|
6
|
-
|
7
|
-
|
8
|
-
class ModuloEmail(object):
|
9
|
-
SERVER_GOOGLE_INVIO=('smtp.gmail.com',smtplib.SMTP_SSL_PORT)
|
10
|
-
SERVER_VIRGILIO_INVIO=('out.virgilio.it',smtplib.SMTP_SSL_PORT)
|
11
|
-
|
12
|
-
def __init__(self,credenzialiServer:tuple,user:str|None,password:str|None,isDebug:bool=False):
|
13
|
-
self.credenzialiServer=credenzialiServer
|
14
|
-
self.isDebug=isDebug
|
15
|
-
self.connEmail=None
|
16
|
-
self.user=user
|
17
|
-
self.password=password
|
18
|
-
self.isLogged=False
|
19
|
-
|
20
|
-
def login(self,user:str|None=None,password:str|None=None):
|
21
|
-
if self.isLogged:
|
22
|
-
return
|
23
|
-
# controllo se usare le credenziali dei parametri o quelle della classe
|
24
|
-
if user is not None:
|
25
|
-
self.user=user
|
26
|
-
if password is not None:
|
27
|
-
self.password=password
|
28
|
-
# mi collego
|
29
|
-
self.connEmail=smtplib.SMTP_SSL(*self.credenzialiServer)
|
30
|
-
if self.isDebug:
|
31
|
-
self.connEmail.set_debuglevel(1)
|
32
|
-
# se serve setto l'autenticazione
|
33
|
-
if self.user is not None and self.password is not None:
|
34
|
-
self.connEmail.login(self.user,self.password)
|
35
|
-
self.isLogged=True
|
36
|
-
|
37
|
-
def sendWithLoginAndClose(self,destinatari:str|list|tuple, oggetto:str, messaggio:str,
|
38
|
-
isHtml:bool)->dict:
|
39
|
-
# check if already logged
|
40
|
-
if not self.isLogged:
|
41
|
-
self.login(self.user,self.password)
|
42
|
-
# invio email
|
43
|
-
try:
|
44
|
-
errors=self.send(None,destinatari,oggetto,messaggio,isHtml)
|
45
|
-
except Exception as ex:
|
46
|
-
self.close()
|
47
|
-
raise ex
|
48
|
-
# chiudo la connessione
|
49
|
-
self.close()
|
50
|
-
return errors
|
51
|
-
|
52
|
-
def send(self, mittente:str|None,destinatari:str|list|tuple, oggetto:str, messaggio:str,
|
53
|
-
isHtml:bool, dataInvio=ModuloDate.now(), cc=None, ccn=None)->dict:
|
54
|
-
# controllo i parametri
|
55
|
-
dataInvio=ModuloDate.dateToString(dataInvio)
|
56
|
-
if isinstance(destinatari, str):
|
57
|
-
destinatari=[destinatari]
|
58
|
-
if mittente is None:
|
59
|
-
mittente=self.user
|
60
|
-
domain=self.user.split("@")[-1]
|
61
|
-
messageId=f"{ModuloDate.getSecs()}@{domain}"
|
62
|
-
# creo il messaggio
|
63
|
-
message=f"""Date: {dataInvio}
|
64
|
-
From: {mittente}
|
65
|
-
Subject: {oggetto}
|
66
|
-
To: {", ".join(destinatari)}
|
67
|
-
Message-ID: <{messageId}>
|
68
|
-
"""
|
69
|
-
if not ModuloListe.isEmpty(cc):
|
70
|
-
message+=("Cc: "+", ".join(cc))+"\n"
|
71
|
-
if not ModuloListe.isEmpty(ccn):
|
72
|
-
message+=("Bcc: "+", ".join(ccn))+"\n"
|
73
|
-
message+="Content-Type: text/html;\n"
|
74
|
-
# converto il messaggio in formato html
|
75
|
-
if not isHtml:
|
76
|
-
messaggio=ModuloStringhe.normalizzaEol(messaggio).replace("\n","<br/>\n")
|
77
|
-
messaggio=messaggio.encode(ModuloStringhe.CODIFICA_ASCII,"xmlcharrefreplace").decode(ModuloStringhe.CODIFICA_UTF8)
|
78
|
-
message+="\n"+messaggio
|
79
|
-
# invio la mail
|
80
|
-
try:
|
81
|
-
return self.connEmail.sendmail(mittente,destinatari,message)
|
82
|
-
except smtplib.SMTPServerDisconnected as ex:
|
83
|
-
return {"":str(ex)}
|
84
|
-
|
85
|
-
def close(self):
|
86
|
-
if self.connEmail is None:
|
87
|
-
return
|
88
|
-
self.connEmail.quit()
|
89
|
-
self.connEmail=None
|
90
|
-
self.isLogged=False
|
1
|
+
import smtplib
|
2
|
+
|
3
|
+
from modulitiz_nano.ModuloDate import ModuloDate
|
4
|
+
from modulitiz_nano.ModuloListe import ModuloListe
|
5
|
+
from modulitiz_nano.ModuloStringhe import ModuloStringhe
|
6
|
+
|
7
|
+
|
8
|
+
class ModuloEmail(object):
|
9
|
+
SERVER_GOOGLE_INVIO=('smtp.gmail.com',smtplib.SMTP_SSL_PORT)
|
10
|
+
SERVER_VIRGILIO_INVIO=('out.virgilio.it',smtplib.SMTP_SSL_PORT)
|
11
|
+
|
12
|
+
def __init__(self,credenzialiServer:tuple,user:str|None,password:str|None,isDebug:bool=False):
|
13
|
+
self.credenzialiServer=credenzialiServer
|
14
|
+
self.isDebug=isDebug
|
15
|
+
self.connEmail=None
|
16
|
+
self.user=user
|
17
|
+
self.password=password
|
18
|
+
self.isLogged=False
|
19
|
+
|
20
|
+
def login(self,user:str|None=None,password:str|None=None):
|
21
|
+
if self.isLogged:
|
22
|
+
return
|
23
|
+
# controllo se usare le credenziali dei parametri o quelle della classe
|
24
|
+
if user is not None:
|
25
|
+
self.user=user
|
26
|
+
if password is not None:
|
27
|
+
self.password=password
|
28
|
+
# mi collego
|
29
|
+
self.connEmail=smtplib.SMTP_SSL(*self.credenzialiServer)
|
30
|
+
if self.isDebug:
|
31
|
+
self.connEmail.set_debuglevel(1)
|
32
|
+
# se serve setto l'autenticazione
|
33
|
+
if self.user is not None and self.password is not None:
|
34
|
+
self.connEmail.login(self.user,self.password)
|
35
|
+
self.isLogged=True
|
36
|
+
|
37
|
+
def sendWithLoginAndClose(self,destinatari:str|list|tuple, oggetto:str, messaggio:str,
|
38
|
+
isHtml:bool)->dict:
|
39
|
+
# check if already logged
|
40
|
+
if not self.isLogged:
|
41
|
+
self.login(self.user,self.password)
|
42
|
+
# invio email
|
43
|
+
try:
|
44
|
+
errors=self.send(None,destinatari,oggetto,messaggio,isHtml)
|
45
|
+
except Exception as ex:
|
46
|
+
self.close()
|
47
|
+
raise ex
|
48
|
+
# chiudo la connessione
|
49
|
+
self.close()
|
50
|
+
return errors
|
51
|
+
|
52
|
+
def send(self, mittente:str|None,destinatari:str|list|tuple, oggetto:str, messaggio:str,
|
53
|
+
isHtml:bool, dataInvio=ModuloDate.now(), cc=None, ccn=None)->dict:
|
54
|
+
# controllo i parametri
|
55
|
+
dataInvio=ModuloDate.dateToString(dataInvio)
|
56
|
+
if isinstance(destinatari, str):
|
57
|
+
destinatari=[destinatari]
|
58
|
+
if mittente is None:
|
59
|
+
mittente=self.user
|
60
|
+
domain=self.user.split("@")[-1]
|
61
|
+
messageId=f"{ModuloDate.getSecs()}@{domain}"
|
62
|
+
# creo il messaggio
|
63
|
+
message=f"""Date: {dataInvio}
|
64
|
+
From: {mittente}
|
65
|
+
Subject: {oggetto}
|
66
|
+
To: {", ".join(destinatari)}
|
67
|
+
Message-ID: <{messageId}>
|
68
|
+
"""
|
69
|
+
if not ModuloListe.isEmpty(cc):
|
70
|
+
message+=("Cc: "+", ".join(cc))+"\n"
|
71
|
+
if not ModuloListe.isEmpty(ccn):
|
72
|
+
message+=("Bcc: "+", ".join(ccn))+"\n"
|
73
|
+
message+="Content-Type: text/html;\n"
|
74
|
+
# converto il messaggio in formato html
|
75
|
+
if not isHtml:
|
76
|
+
messaggio=ModuloStringhe.normalizzaEol(messaggio).replace("\n","<br/>\n")
|
77
|
+
messaggio=messaggio.encode(ModuloStringhe.CODIFICA_ASCII,"xmlcharrefreplace").decode(ModuloStringhe.CODIFICA_UTF8)
|
78
|
+
message+="\n"+messaggio
|
79
|
+
# invio la mail
|
80
|
+
try:
|
81
|
+
return self.connEmail.sendmail(mittente,destinatari,message)
|
82
|
+
except smtplib.SMTPServerDisconnected as ex:
|
83
|
+
return {"":str(ex)}
|
84
|
+
|
85
|
+
def close(self):
|
86
|
+
if self.connEmail is None:
|
87
|
+
return
|
88
|
+
self.connEmail.quit()
|
89
|
+
self.connEmail=None
|
90
|
+
self.isLogged=False
|
@@ -1,119 +1,119 @@
|
|
1
|
-
import gzip
|
2
|
-
import json
|
3
|
-
import logging
|
4
|
-
import ssl
|
5
|
-
import urllib
|
6
|
-
from urllib.parse import urlencode
|
7
|
-
from urllib.request import Request
|
8
|
-
|
9
|
-
import brotli
|
10
|
-
|
11
|
-
from modulitiz_nano.ModuloBase64 import ModuloBase64
|
12
|
-
from modulitiz_nano.ModuloStringhe import ModuloStringhe
|
13
|
-
from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
|
14
|
-
from modulitiz_nano.files.ModuloLogging import ModuloLogging
|
15
|
-
from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
|
16
|
-
from modulitiz_micro.rete.http.beans.HttpResponseBean import HttpResponseBean
|
17
|
-
from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
|
18
|
-
|
19
|
-
|
20
|
-
class ModuloHttp(object):
|
21
|
-
"""
|
22
|
-
Utility per gestione richieste di rete secondo il protocollo HTTP.
|
23
|
-
"""
|
24
|
-
|
25
|
-
UA_ANDROID="Mozilla/5.0 (Linux; Android 12.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36"
|
26
|
-
|
27
|
-
UA_MACOS_CHROME="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
|
28
|
-
UA_WINDOWS_CHROME="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
|
29
|
-
UA_WINDOWS_FIREFOX="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"
|
30
|
-
|
31
|
-
UAS=[UA_MACOS_CHROME,UA_WINDOWS_CHROME,UA_WINDOWS_FIREFOX]
|
32
|
-
|
33
|
-
URL_CERCA_GOOGLE="https://www.google.it/search?q="
|
34
|
-
# https://ipecho.net/plain removed because it can return either ipv4 or ipv6 depending on your ISP/Internet connection
|
35
|
-
URLS_GET_IPV4=('https://ipinfo.io/ip','https://api.ipify.org','https://ipv4.seeip.org')
|
36
|
-
|
37
|
-
REGEX_IPV4_ADDRESS=r"\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b"
|
38
|
-
|
39
|
-
STATUS_OK=200
|
40
|
-
STATUS_OK_PARTIAL_CONTENT=206
|
41
|
-
|
42
|
-
|
43
|
-
def __init__(self,url:str,logger:ModuloLogging|None,useProxy:bool=False):
|
44
|
-
logging.getLogger("urllib3").propagate=False
|
45
|
-
|
46
|
-
self.__requestObj=Request(url)
|
47
|
-
self.__logger=logger
|
48
|
-
|
49
|
-
self.setUserAgent(self.UA_WINDOWS_FIREFOX)
|
50
|
-
self.addHeader('Accept-Encoding','gzip, deflate, br') # questo serve per ridurre la dimensione della risposta
|
51
|
-
if useProxy:
|
52
|
-
self.addHeader('Origin','localhost')
|
53
|
-
self.connectionSafe=ModuloHttpConnectionSafe(self.__logger)
|
54
|
-
|
55
|
-
def doGet(self,retries:int,ignoreCerts:bool=False)->HttpResponseBean:
|
56
|
-
"""
|
57
|
-
Esegue una richiesta di tipo GET
|
58
|
-
"""
|
59
|
-
if retries==0:
|
60
|
-
return self.__getOrPost(ignoreCerts)
|
61
|
-
return self.connectionSafe.run(retries,0,self.__getOrPost,ignoreCerts)
|
62
|
-
|
63
|
-
def doPost(self, postData:dict, asJson:bool, retries:int,ignoreCerts:bool=False)->HttpResponseBean:
|
64
|
-
"""
|
65
|
-
Esegue una richiesta di tipo POST
|
66
|
-
"""
|
67
|
-
if not asJson:
|
68
|
-
postDataEncoded=urlencode(postData)
|
69
|
-
else:
|
70
|
-
postDataEncoded=json.dumps(postData)
|
71
|
-
self.addHeader("Content-Type","application/json; charset=utf-8")
|
72
|
-
postDataEncoded=postDataEncoded.encode()
|
73
|
-
self.__requestObj.data=postDataEncoded
|
74
|
-
if retries==0:
|
75
|
-
return self.__getOrPost(ignoreCerts)
|
76
|
-
return self.connectionSafe.run(retries,0,self.__getOrPost,ignoreCerts)
|
77
|
-
|
78
|
-
@catchAndRaiseHttpExceptions
|
79
|
-
def __getOrPost(self, ignoreCerts:bool)->HttpResponseBean:
|
80
|
-
# ignoro certificati
|
81
|
-
ctx=None
|
82
|
-
if ignoreCerts:
|
83
|
-
ctx=ssl.create_default_context()
|
84
|
-
ctx.check_hostname=False
|
85
|
-
ctx.verify_mode=ssl.CERT_NONE
|
86
|
-
# send request
|
87
|
-
with urllib.request.urlopen(self.__requestObj,context=ctx) as response:
|
88
|
-
responseBody=response.read()
|
89
|
-
responseHeaders=response.info()
|
90
|
-
status=response.status
|
91
|
-
# se il server manda il contenuto in formato compresso lo decomprimo
|
92
|
-
contentEncoding=responseHeaders.get('Content-Encoding')
|
93
|
-
if contentEncoding=="gzip":
|
94
|
-
responseBody=gzip.decompress(responseBody)
|
95
|
-
elif contentEncoding=="br":
|
96
|
-
responseBody=brotli.decompress(responseBody)
|
97
|
-
elif contentEncoding is not None and contentEncoding!= "deflate":
|
98
|
-
raise EccezioneRuntime("Codifica '"+contentEncoding+"' non gestita.")
|
99
|
-
return HttpResponseBean(status,responseBody,responseHeaders)
|
100
|
-
|
101
|
-
# opzioni aggiuntive
|
102
|
-
def addHeader(self,nome:str,valore):
|
103
|
-
if ModuloStringhe.isEmpty(valore):
|
104
|
-
return
|
105
|
-
self.__requestObj.add_header(nome,valore)
|
106
|
-
|
107
|
-
def setUserAgent(self,userAgent:str=None):
|
108
|
-
if ModuloStringhe.isEmpty(userAgent):
|
109
|
-
userAgent=self.UA_ANDROID
|
110
|
-
else:
|
111
|
-
userAgent=userAgent.strip()
|
112
|
-
self.addHeader('User-Agent',userAgent)
|
113
|
-
|
114
|
-
def setDownloadRange(self,inizio:int,fine:int):
|
115
|
-
self.addHeader('Range',"bytes="+str(inizio)+"-"+str(fine))
|
116
|
-
|
117
|
-
def setAuthenticationBasic(self,username:str,password:str):
|
118
|
-
authStr=ModuloBase64.codificaStr('%s:%s' % (username, password))
|
119
|
-
self.addHeader('Authorization',"Basic "+authStr)
|
1
|
+
import gzip
|
2
|
+
import json
|
3
|
+
import logging
|
4
|
+
import ssl
|
5
|
+
import urllib
|
6
|
+
from urllib.parse import urlencode
|
7
|
+
from urllib.request import Request
|
8
|
+
|
9
|
+
import brotli
|
10
|
+
|
11
|
+
from modulitiz_nano.ModuloBase64 import ModuloBase64
|
12
|
+
from modulitiz_nano.ModuloStringhe import ModuloStringhe
|
13
|
+
from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
|
14
|
+
from modulitiz_nano.files.ModuloLogging import ModuloLogging
|
15
|
+
from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
|
16
|
+
from modulitiz_micro.rete.http.beans.HttpResponseBean import HttpResponseBean
|
17
|
+
from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
|
18
|
+
|
19
|
+
|
20
|
+
class ModuloHttp(object):
|
21
|
+
"""
|
22
|
+
Utility per gestione richieste di rete secondo il protocollo HTTP.
|
23
|
+
"""
|
24
|
+
|
25
|
+
UA_ANDROID="Mozilla/5.0 (Linux; Android 12.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Mobile Safari/537.36"
|
26
|
+
|
27
|
+
UA_MACOS_CHROME="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
|
28
|
+
UA_WINDOWS_CHROME="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
|
29
|
+
UA_WINDOWS_FIREFOX="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0"
|
30
|
+
|
31
|
+
UAS=[UA_MACOS_CHROME,UA_WINDOWS_CHROME,UA_WINDOWS_FIREFOX]
|
32
|
+
|
33
|
+
URL_CERCA_GOOGLE="https://www.google.it/search?q="
|
34
|
+
# https://ipecho.net/plain removed because it can return either ipv4 or ipv6 depending on your ISP/Internet connection
|
35
|
+
URLS_GET_IPV4=('https://ipinfo.io/ip','https://api.ipify.org','https://ipv4.seeip.org')
|
36
|
+
|
37
|
+
REGEX_IPV4_ADDRESS=r"\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b"
|
38
|
+
|
39
|
+
STATUS_OK=200
|
40
|
+
STATUS_OK_PARTIAL_CONTENT=206
|
41
|
+
|
42
|
+
|
43
|
+
def __init__(self,url:str,logger:ModuloLogging|None,useProxy:bool=False):
|
44
|
+
logging.getLogger("urllib3").propagate=False
|
45
|
+
|
46
|
+
self.__requestObj=Request(url)
|
47
|
+
self.__logger=logger
|
48
|
+
|
49
|
+
self.setUserAgent(self.UA_WINDOWS_FIREFOX)
|
50
|
+
self.addHeader('Accept-Encoding','gzip, deflate, br') # questo serve per ridurre la dimensione della risposta
|
51
|
+
if useProxy:
|
52
|
+
self.addHeader('Origin','localhost')
|
53
|
+
self.connectionSafe=ModuloHttpConnectionSafe(self.__logger)
|
54
|
+
|
55
|
+
def doGet(self,retries:int,ignoreCerts:bool=False)->HttpResponseBean:
|
56
|
+
"""
|
57
|
+
Esegue una richiesta di tipo GET
|
58
|
+
"""
|
59
|
+
if retries==0:
|
60
|
+
return self.__getOrPost(ignoreCerts)
|
61
|
+
return self.connectionSafe.run(retries,0,self.__getOrPost,ignoreCerts)
|
62
|
+
|
63
|
+
def doPost(self, postData:dict, asJson:bool, retries:int,ignoreCerts:bool=False)->HttpResponseBean:
|
64
|
+
"""
|
65
|
+
Esegue una richiesta di tipo POST
|
66
|
+
"""
|
67
|
+
if not asJson:
|
68
|
+
postDataEncoded=urlencode(postData)
|
69
|
+
else:
|
70
|
+
postDataEncoded=json.dumps(postData)
|
71
|
+
self.addHeader("Content-Type","application/json; charset=utf-8")
|
72
|
+
postDataEncoded=postDataEncoded.encode()
|
73
|
+
self.__requestObj.data=postDataEncoded
|
74
|
+
if retries==0:
|
75
|
+
return self.__getOrPost(ignoreCerts)
|
76
|
+
return self.connectionSafe.run(retries,0,self.__getOrPost,ignoreCerts)
|
77
|
+
|
78
|
+
@catchAndRaiseHttpExceptions
|
79
|
+
def __getOrPost(self, ignoreCerts:bool)->HttpResponseBean:
|
80
|
+
# ignoro certificati
|
81
|
+
ctx=None
|
82
|
+
if ignoreCerts:
|
83
|
+
ctx=ssl.create_default_context()
|
84
|
+
ctx.check_hostname=False
|
85
|
+
ctx.verify_mode=ssl.CERT_NONE
|
86
|
+
# send request
|
87
|
+
with urllib.request.urlopen(self.__requestObj,context=ctx) as response:
|
88
|
+
responseBody=response.read()
|
89
|
+
responseHeaders=response.info()
|
90
|
+
status=response.status
|
91
|
+
# se il server manda il contenuto in formato compresso lo decomprimo
|
92
|
+
contentEncoding=responseHeaders.get('Content-Encoding')
|
93
|
+
if contentEncoding=="gzip":
|
94
|
+
responseBody=gzip.decompress(responseBody)
|
95
|
+
elif contentEncoding=="br":
|
96
|
+
responseBody=brotli.decompress(responseBody)
|
97
|
+
elif contentEncoding is not None and contentEncoding!= "deflate":
|
98
|
+
raise EccezioneRuntime("Codifica '"+contentEncoding+"' non gestita.")
|
99
|
+
return HttpResponseBean(status,responseBody,responseHeaders)
|
100
|
+
|
101
|
+
# opzioni aggiuntive
|
102
|
+
def addHeader(self,nome:str,valore):
|
103
|
+
if ModuloStringhe.isEmpty(valore):
|
104
|
+
return
|
105
|
+
self.__requestObj.add_header(nome,valore)
|
106
|
+
|
107
|
+
def setUserAgent(self,userAgent:str=None):
|
108
|
+
if ModuloStringhe.isEmpty(userAgent):
|
109
|
+
userAgent=self.UA_ANDROID
|
110
|
+
else:
|
111
|
+
userAgent=userAgent.strip()
|
112
|
+
self.addHeader('User-Agent',userAgent)
|
113
|
+
|
114
|
+
def setDownloadRange(self,inizio:int,fine:int):
|
115
|
+
self.addHeader('Range',"bytes="+str(inizio)+"-"+str(fine))
|
116
|
+
|
117
|
+
def setAuthenticationBasic(self,username:str,password:str):
|
118
|
+
authStr=ModuloBase64.codificaStr('%s:%s' % (username, password))
|
119
|
+
self.addHeader('Authorization',"Basic "+authStr)
|