modulitiz-micro 2.45.0__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.
Files changed (64) hide show
  1. modulitiz_micro/ModuloSeriale.py +70 -70
  2. modulitiz_micro/ModuloTarghe.py +47 -47
  3. modulitiz_micro/database/AbstractDatabaseService.py +13 -13
  4. modulitiz_micro/database/AbstractSql.py +69 -69
  5. modulitiz_micro/database/ModuloSqlOracle.py +19 -19
  6. modulitiz_micro/database/ModuloSqlServer.py +43 -43
  7. modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -6
  8. modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -114
  9. modulitiz_micro/database/mysql/ModuloMysql.py +163 -163
  10. modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -47
  11. modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -6
  12. modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -114
  13. modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -82
  14. modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -7
  15. modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -7
  16. modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -8
  17. modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -7
  18. modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -7
  19. modulitiz_micro/files/cache/DatabaseCache.py +91 -91
  20. modulitiz_micro/files/cache/decorators/cacheRam.py +26 -26
  21. modulitiz_micro/files/git/ModuloGit.py +28 -28
  22. modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -19
  23. modulitiz_micro/files/git/exceptions/EccezioneGit.py +7 -7
  24. modulitiz_micro/gestionedom/GestioneDom.py +44 -44
  25. modulitiz_micro/iot/ModuleIotDevice.py +62 -62
  26. modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -7
  27. modulitiz_micro/keylogger/ModuloKeylogger.py +73 -73
  28. modulitiz_micro/rete/ModuleAndroidTVRemote.py +107 -0
  29. modulitiz_micro/rete/ModuloNetworking.py +67 -72
  30. modulitiz_micro/rete/ModuloOpenVpn.py +15 -15
  31. modulitiz_micro/rete/email/EmailBean.py +5 -5
  32. modulitiz_micro/rete/email/ModuloEmail.py +90 -90
  33. modulitiz_micro/rete/http/ModuloHttp.py +119 -119
  34. modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -91
  35. modulitiz_micro/rete/http/ModuloHttpUtils.py +69 -69
  36. modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -5
  37. modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -22
  38. modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +84 -84
  39. modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -28
  40. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +6 -6
  41. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +22 -22
  42. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -49
  43. modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +21 -21
  44. modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -7
  45. modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +72 -72
  46. modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -73
  47. modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -8
  48. modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -35
  49. modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -267
  50. modulitiz_micro/rete/ssl/ModuloSsl.py +56 -56
  51. modulitiz_micro/sistema/ModuloEnvVars.py +34 -34
  52. modulitiz_micro/sistema/ModuloSystemPipe.py +67 -67
  53. modulitiz_micro/social/telegram/AbstractModuloTelegram.py +53 -53
  54. modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -26
  55. modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -15
  56. modulitiz_micro/util/scheduler/ModuleScheduler.py +26 -26
  57. modulitiz_micro/weather/AbstractModuleWeather.py +31 -31
  58. modulitiz_micro/weather/ModuleWeather.py +62 -62
  59. {modulitiz_micro-2.45.0.dist-info → modulitiz_micro-2.46.0.dist-info}/METADATA +59 -59
  60. modulitiz_micro-2.46.0.dist-info/RECORD +67 -0
  61. {modulitiz_micro-2.45.0.dist-info → modulitiz_micro-2.46.0.dist-info}/licenses/LICENSE +21 -21
  62. modulitiz_micro-2.45.0.dist-info/RECORD +0 -66
  63. {modulitiz_micro-2.45.0.dist-info → modulitiz_micro-2.46.0.dist-info}/WHEEL +0 -0
  64. {modulitiz_micro-2.45.0.dist-info → modulitiz_micro-2.46.0.dist-info}/top_level.txt +0 -0
@@ -1,72 +1,67 @@
1
- import os
2
- import re
3
- import socket
4
- from contextlib import closing
5
- from uuid import getnode
6
-
7
- from _socket import gaierror
8
-
9
- from modulitiz_nano.ModuloListe import ModuloListe
10
- from modulitiz_nano.ModuloStringhe import ModuloStringhe
11
- from modulitiz_nano.eccezioni.EccezioneRuntime import EccezioneRuntime
12
- from modulitiz_nano.sistema.ModuloSystem import ModuloSystem
13
-
14
-
15
- class ModuloNetworking(object):
16
- @staticmethod
17
- def getMacAddress()->str:
18
- mac=("%012X" % getnode())
19
- return mac
20
-
21
- @staticmethod
22
- def getLocalIp()->str|None:
23
- """
24
- Returns private local IP address.
25
- """
26
- sockObj = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
27
- sockObj.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
28
- try:
29
- # doesn't even have to be reachable
30
- sockObj.connect(('255.255.255.255', 1))
31
- indirizzoIp = sockObj.getsockname()[0]
32
- except gaierror:
33
- indirizzoIp = None
34
- finally:
35
- sockObj.close()
36
- return indirizzoIp
37
-
38
- @staticmethod
39
- def isHttpPortOpen(host:str|None,port:int)->bool:
40
- # controllo host
41
- if host is None:
42
- host="127.0.0.1"
43
- # controllo porta
44
- with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
45
- if sock.connect_ex((host, port)) == 0:
46
- return True
47
- return False
48
-
49
- @staticmethod
50
- def checkPing(ipAddress:str)->bool:
51
- # build command
52
- cmd="ping "
53
- regexPercPacketsLost=r"(\d{1,3})\% "
54
- if ModuloSystem.isWindows():
55
- cmd+="-n"
56
- regexPercPacketsLost=r"\("+regexPercPacketsLost
57
- elif os.name=='posix':
58
- cmd+="-W 5 -c"
59
- regexPercPacketsLost=r", "+regexPercPacketsLost
60
- else:
61
- raise EccezioneRuntime("Tipologia del sistema operativo non riconosciuta: "+os.name)
62
- cmd+=" 1 "+ipAddress
63
- # execute command
64
- outputComando=ModuloStringhe.normalizzaEol(ModuloSystem.systemCallReturnOutput(cmd,None))
65
- rows=outputComando.split("\n")
66
- rows=ModuloListe.eliminaElementiVuoti(rows)
67
- for row in rows:
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)