ocado-grocy/ocado_grocy/product_metadata.py
2026-09-19 11:32:53 +01:00

38 lines
1.5 KiB
Python

"""Read imported metadata even when Grocy's sanitizer removes the pre tag."""
import json
from html import escape
from lxml import html
def read_metadata(description):
try:
text = html.fromstring(description or '<p></p>').text_content()
except (html.etree.ParserError, ValueError):
return {}
for index, character in enumerate(text):
if character == '{':
try:
value, _ = json.JSONDecoder().raw_decode(text[index:])
if isinstance(value, dict) and 'Ocado product ID' in value:
return value
except ValueError:
pass
return {}
def replace_metadata(description, metadata):
tree = html.fragment_fromstring(description, create_parent='div')
for node in tree.iter():
for attr in ('text', 'tail'):
text = getattr(node, attr) or ''
for index, character in enumerate(text):
if character != '{':
continue
try:
old, end = json.JSONDecoder().raw_decode(text[index:])
except ValueError:
continue
if isinstance(old, dict) and 'Ocado product ID' in old:
setattr(node, attr, text[:index] + json.dumps(metadata, ensure_ascii=False, indent=2) + text[index + end:])
return escape(tree.text or '') + ''.join(html.tostring(child, encoding='unicode') for child in tree)
raise ValueError('Cannot safely locate imported metadata in description')