New Addon

Google BK
This commit is contained in:
2023-04-23 18:17:03 +07:00
parent 1c7fd2b476
commit 702d080a1e
248 changed files with 72745 additions and 0 deletions
@@ -0,0 +1,113 @@
from aiohttp import ClientSession, ContentTypeError, ClientConnectorError, ClientTimeout, ClientResponse
from aiohttp.client_exceptions import ServerTimeoutError, ServerDisconnectedError, ClientOSError
from backup.exceptions import GoogleUnexpectedError, GoogleInternalError, GoogleRateLimitError, GoogleCredentialsExpired, CredRefreshGoogleError, DriveQuotaExceeded, GoogleDrivePermissionDenied, GoogleDnsFailure, GoogleCantConnect, GoogleTimeoutError
from backup.util import Resolver
from backup.logger import getLogger
from backup.config import Config, Setting
from injector import singleton, inject
from dns.exception import DNSException
RATE_LIMIT_EXCEEDED = [403]
TOO_MANY_REQUESTS = [429]
INTERNAL_ERROR = [500, 503]
PERMISSION_DENIED = [401]
REQUEST_TIMEOUT = [408]
logger = getLogger(__name__)
@singleton
class DriveRequester():
@inject
def __init__(self, config: Config, session: ClientSession, resolver: Resolver):
self.session = session
self.resolver = resolver
self.config = config
async def request(self, method, url, headers={}, json=None, data=None) -> ClientResponse:
try:
response = await self.session.request(method, url, headers=headers, json=json, timeout=self.buildTimeout(), data=data)
if response.status < 400:
return response
await self.raiseForKnownErrors(response)
if response.status in PERMISSION_DENIED:
response.release()
raise GoogleCredentialsExpired()
elif response.status in INTERNAL_ERROR:
response.release()
raise GoogleInternalError()
elif response.status in RATE_LIMIT_EXCEEDED or response.status in TOO_MANY_REQUESTS:
response.release()
raise GoogleRateLimitError()
elif response.status in REQUEST_TIMEOUT:
response.release()
raise GoogleTimeoutError()
response.raise_for_status()
return response
except ClientConnectorError as e:
logger.debug(
"Ran into trouble reaching Google Drive's servers. We'll use alternate DNS servers on the next attempt.")
self.resolver.toggle()
if "Cannot connect to host" in str(e) or "Connection reset by peer" in str(e):
raise GoogleCantConnect()
if e.os_error.errno == -2:
# -2 means dns lookup failed.
raise GoogleDnsFailure()
elif str(e.os_error) == "Domain name not found":
raise GoogleDnsFailure()
elif e.os_error.errno in [99, 111, 10061, 104]:
# 111 means connection refused
# Can't connect
raise GoogleCantConnect()
elif "Could not contact DNS serve" in str(e.os_error):
# Wish there was a better way to identify this exception
raise GoogleDnsFailure()
raise
except ClientOSError as e:
if e.errno == 1:
raise GoogleUnexpectedError()
raise
except ServerTimeoutError:
raise GoogleTimeoutError()
except ServerDisconnectedError:
raise GoogleUnexpectedError()
except DNSException:
logger.debug(
"Ran into trouble resolving Google Drive's servers. We'll use normal DNS servers on the next attempt.")
self.resolver.toggle()
raise GoogleDnsFailure()
def buildTimeout(self):
return ClientTimeout(
sock_connect=self.config.get(
Setting.GOOGLE_DRIVE_TIMEOUT_SECONDS),
sock_read=self.config.get(Setting.GOOGLE_DRIVE_TIMEOUT_SECONDS))
async def raiseForKnownErrors(self, response):
try:
message = await response.json()
except ContentTypeError:
return
except ValueError:
# parsing json failed, just give up
return
except TypeError:
# Same
return
if "error" not in message:
return
error_obj = message["error"]
if isinstance(error_obj, str):
if error_obj == "expired":
raise GoogleCredentialsExpired()
else:
raise CredRefreshGoogleError(error_obj)
if "errors" not in error_obj:
return
for error in error_obj["errors"]:
if "reason" not in error:
continue
if error["reason"] == "storageQuotaExceeded":
raise DriveQuotaExceeded()
elif error["reason"] in ["forbidden", "insufficientFilePermissions"]:
raise GoogleDrivePermissionDenied()