Skip to content

Instantly share code, notes, and snippets.

@Gemba
Created February 9, 2024 18:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gemba/4729e3560264511ea06aadb18f439112 to your computer and use it in GitHub Desktop.
Save Gemba/4729e3560264511ea06aadb18f439112 to your computer and use it in GitHub Desktop.
Rename one property and restructure selected collections for random collection function of ES
#! /usr/bin/env python3
# Converts the settings RandomCollectionSystemsAuto,
# RandomCollectionSystemsCustom, RandomCollectionSystems to XML format
#
# Renames 'RandomCollectionMaxItems' to 'RandomCollectionMaxGames' in
# es_settings.cfg. Backup file will be created w/ extension .previous
# (c) 2024 Gemba @ GitHub
# SPDX-License-Identifier: GPL-3.0-or-later
from lxml import html
from pathlib import Path
import lxml.etree as ET
import os
import re
import shutil
import sys
HOME = os.environ.get("HOME", "/home/pi")
ES_SETTINGS_CFG = Path(f"{HOME}/.emulationstation/es_settings.cfg")
with open(ES_SETTINGS_CFG, "r") as file:
data = file.read()
doc = ET.fromstring(data, parser=ET.HTMLParser())
found = False
for c in [
"RandomCollectionMaxItems",
"RandomCollectionSystemsAuto",
"RandomCollectionSystemsCustom",
"RandomCollectionSystems",
]:
for e in doc.xpath(f"//string[@name='{c}']"):
name = e.attrib["name"]
print(f"[+] Found '{name}'")
found = True
if name == "RandomCollectionMaxItems":
new_elem = e.makeelement("int")
new_elem.attrib["name"] = "RandomCollectionMaxGames"
new_elem.attrib["value"] = e.attrib["value"]
else:
new_elem = e.makeelement("map")
new_elem.attrib["name"] = name
new_elem.attrib["type"] = "int"
# print(new_elem.attrib)
for k, v in [s.split(":") for s in e.attrib["value"].split(",")]:
inner = new_elem.makeelement("int")
inner.attrib["name"] = k
inner.attrib["value"] = v
# print(f" {inner.attrib}")
new_elem.append(inner)
e.clear() # will be <string/> only
doc.append(new_elem)
if not found:
print(
f"[-] No settings to convert found. No changes made to"
f" '{ES_SETTINGS_CFG}'"
)
sys.exit(0)
out_str = html.tostring(
doc,
pretty_print=True,
method="xml",
encoding="unicode",
include_meta_content_type=False,
doctype="",
)
# remove clutter
out_str = re.sub(r"<[/]?html>\s*", "", out_str)
out_str = re.sub(r"\s*<[/]?body>", "\n", out_str)
out_str = re.sub(r"<string/>", "", out_str)
# apply current es_settings.cfg style
out_str = re.sub(r"\s+(.+RandomCollectionMaxGames.+)", r"\n\1", out_str)
out_str = re.sub(r"\s\s<map", "<map", out_str)
out_str = re.sub(r"\s\s</map", "</map", out_str)
out_str = re.sub(r"\s\s<", "\t<", out_str)
out_str = re.sub(r"(\S)/>", r"\1 />", out_str)
bkp_file = ES_SETTINGS_CFG.parent / (ES_SETTINGS_CFG.name + ".previous")
shutil.move(ES_SETTINGS_CFG, bkp_file)
print(f"[+] Previous settings kept in '{bkp_file}'")
with open(ES_SETTINGS_CFG, "w") as of:
of.write('<?xml version="1.0"?>\n')
for line in [l for l in out_str.split("\n") if l]:
of.write(f"{line}\n")
print(f"[+] Written converted settings to '{ES_SETTINGS_CFG}'")
@Gemba
Copy link
Author

Gemba commented Feb 9, 2024

Example: Conversion is from

<string name="RandomCollectionSystemsAuto" value="all games:0,favorites:3,last played:0" />

to

<map name="RandomCollectionSystemsAuto" type="int">
        <int name="all games" value="0" />
        <int name="favorites" value="3" />
        <int name="last played" value="0" />
</map>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment