config-editor/custom_components/config_editor/__init__.py

126 lines
3.8 KiB
Python
Raw Normal View History

2021-12-01 03:30:29 +01:00
import logging
import os
import voluptuous as vol
from homeassistant.components import websocket_api
from atomicwrites import AtomicWriter
DOMAIN = 'config_editor'
_LOGGER = logging.getLogger(__name__)
async def async_setup(hass, config):
websocket_api.async_register_command(hass, websocket_create)
2022-03-11 22:17:28 +01:00
hass.states.async_set(DOMAIN+".version", 4)
2021-12-01 03:30:29 +01:00
return True
@websocket_api.require_admin
@websocket_api.async_response
@websocket_api.websocket_command(
{
vol.Required("type"): DOMAIN+"/ws",
vol.Required("action"): str,
vol.Required("file"): str,
vol.Required("data"): str,
2022-01-18 03:29:33 +01:00
vol.Required("ext"): str,
2022-03-12 02:14:40 +01:00
vol.Optional("depth", default=2): int
2021-12-01 03:30:29 +01:00
}
)
async def websocket_create(hass, connection, msg):
action = msg["action"]
2022-01-18 03:29:33 +01:00
ext = msg["ext"]
2022-03-11 22:17:28 +01:00
if ext not in ["yaml","py","json","conf","js","txt","log","css","all"]:
2022-01-18 03:29:33 +01:00
ext = "yaml"
2022-03-11 22:17:28 +01:00
def extok(e):
if len(e)<2:
return False
return ( ext == 'all' or e.endswith("."+ext) )
2021-12-01 03:30:29 +01:00
2021-12-05 03:56:08 +01:00
def rec(p, q):
r = [
f for f in os.listdir(p) if os.path.isfile(os.path.join(p, f)) and
2022-03-11 22:17:28 +01:00
extok(f)
2021-12-05 03:56:08 +01:00
]
for j in r:
p = j if q == '' else os.path.join(q, j)
listyaml.append(p)
def drec(r, s):
for d in os.listdir(r):
v = os.path.join(r, d)
if os.path.isdir(v):
p = d if s == '' else os.path.join(s, d)
2022-03-12 02:14:40 +01:00
if(p.count(os.sep) < msg["depth"]) and ( ext == 'all' or p != 'custom_components' ):
2021-12-05 03:56:08 +01:00
rec(v, p)
drec(v, p)
2022-03-11 22:17:28 +01:00
yamlname = msg["file"].replace("../", "/").strip('/')
if not extok(msg["file"]):
yamlname = "temptest."+ext
fullpath = hass.config.path(yamlname)
2021-12-01 03:30:29 +01:00
if (action == 'load'):
_LOGGER.info('Loading '+fullpath)
content = ''
res = 'Loaded'
try:
with open(fullpath, encoding="utf-8") as fdesc:
content = fdesc.read()
except:
res = 'Reading Failed'
_LOGGER.exception("Reading failed: %s", fullpath)
finally:
connection.send_result(
msg["id"],
2022-01-18 03:29:33 +01:00
{'msg': res+': '+fullpath, 'file': yamlname, 'data': content, 'ext': ext}
2021-12-01 03:30:29 +01:00
)
elif (action == 'save'):
_LOGGER.info('Saving '+fullpath)
content = msg["data"]
res = "Saved"
try:
2021-12-05 03:56:08 +01:00
dirnm = os.path.dirname(fullpath)
if not os.path.isdir(dirnm):
os.makedirs(dirnm, exist_ok=True)
2022-02-04 14:53:47 +01:00
try:
2022-10-07 12:44:20 +02:00
stat_res = os.stat(fullpath)
mode = stat_res.st_mode
uid = stat_res.st_uid
gid = stat_res.st_gid
2022-02-04 14:53:47 +01:00
except:
mode = 0o666
uid = 0
gid = 0
2021-12-01 03:30:29 +01:00
with AtomicWriter(fullpath, overwrite=True).open() as fdesc:
2022-04-17 00:46:51 +02:00
fdesc.write(content)
with open(fullpath, 'a') as fdesc:
2021-12-13 20:07:02 +01:00
try:
2022-02-04 14:53:47 +01:00
os.fchmod(fdesc.fileno(), mode)
os.fchown(fdesc.fileno(), uid, gid)
2021-12-13 20:07:02 +01:00
except:
pass
2021-12-01 03:30:29 +01:00
except:
res = "Saving Failed"
_LOGGER.exception(res+": %s", fullpath)
finally:
connection.send_result(
msg["id"],
{'msg': res+': '+fullpath}
)
elif (action == 'list'):
dirnm = os.path.dirname(hass.config.path(yamlname))
2021-12-05 03:56:08 +01:00
listyaml = []
rec(dirnm, '')
2022-03-12 02:14:40 +01:00
if msg["depth"]>0:
drec(dirnm, '')
2021-12-01 03:30:29 +01:00
if (len(listyaml) < 1):
2022-01-18 03:29:33 +01:00
listyaml = ['list_error.'+ext]
2021-12-01 03:30:29 +01:00
connection.send_result(
msg["id"],
2022-01-18 03:29:33 +01:00
{'msg': str(len(listyaml))+' File(s)', 'file': listyaml, 'ext': ext}
2021-12-01 03:30:29 +01:00
)