91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
|
"""Download."""
|
||
|
import os
|
||
|
import gzip
|
||
|
import shutil
|
||
|
|
||
|
import aiofiles
|
||
|
import async_timeout
|
||
|
from integrationhelper import Logger
|
||
|
import backoff
|
||
|
from ..hacsbase.exceptions import HacsException
|
||
|
|
||
|
from custom_components.hacs.globals import get_hacs
|
||
|
|
||
|
|
||
|
@backoff.on_exception(backoff.expo, Exception, max_tries=5)
|
||
|
async def async_download_file(url):
|
||
|
"""
|
||
|
Download files, and return the content.
|
||
|
"""
|
||
|
hacs = get_hacs()
|
||
|
logger = Logger("hacs.download.downloader")
|
||
|
if url is None:
|
||
|
return
|
||
|
|
||
|
# There is a bug somewhere... TODO: Find that bug....
|
||
|
if "tags/" in url:
|
||
|
url = url.replace("tags/", "")
|
||
|
|
||
|
logger.debug(f"Downloading {url}")
|
||
|
|
||
|
result = None
|
||
|
|
||
|
with async_timeout.timeout(60, loop=hacs.hass.loop):
|
||
|
request = await hacs.session.get(url)
|
||
|
|
||
|
# Make sure that we got a valid result
|
||
|
if request.status == 200:
|
||
|
result = await request.read()
|
||
|
else:
|
||
|
raise HacsException(
|
||
|
"Got status code {} when trying to download {}".format(
|
||
|
request.status, url
|
||
|
)
|
||
|
)
|
||
|
|
||
|
return result
|
||
|
|
||
|
|
||
|
async def async_save_file(location, content):
|
||
|
"""Save files."""
|
||
|
logger = Logger("hacs.download.save")
|
||
|
logger.debug(f"Saving {location}")
|
||
|
mode = "w"
|
||
|
encoding = "utf-8"
|
||
|
errors = "ignore"
|
||
|
|
||
|
if not isinstance(content, str):
|
||
|
mode = "wb"
|
||
|
encoding = None
|
||
|
errors = None
|
||
|
|
||
|
try:
|
||
|
async with aiofiles.open(
|
||
|
location, mode=mode, encoding=encoding, errors=errors
|
||
|
) as outfile:
|
||
|
await outfile.write(content)
|
||
|
outfile.close()
|
||
|
|
||
|
# Create gz for .js files
|
||
|
if os.path.isfile(location):
|
||
|
if location.endswith(".js") or location.endswith(".css"):
|
||
|
with open(location, "rb") as f_in:
|
||
|
with gzip.open(location + ".gz", "wb") as f_out:
|
||
|
shutil.copyfileobj(f_in, f_out)
|
||
|
|
||
|
# Remove with 2.0
|
||
|
if "themes" in location and location.endswith(".yaml"):
|
||
|
filename = location.split("/")[-1]
|
||
|
base = location.split("/themes/")[0]
|
||
|
combined = f"{base}/themes/{filename}"
|
||
|
if os.path.exists(combined):
|
||
|
logger.info(f"Removing old theme file {combined}")
|
||
|
os.remove(combined)
|
||
|
|
||
|
except Exception as error: # pylint: disable=broad-except
|
||
|
msg = "Could not write data to {} - {}".format(location, error)
|
||
|
logger.error(msg)
|
||
|
return False
|
||
|
|
||
|
return os.path.exists(location)
|