38 lines
1.5 KiB
Python
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')
|