dotfiles/os/wireless/apply.py
2025-05-09 00:28:33 +02:00

59 lines
1.7 KiB
Python

"""
Add the networks saved in wireless_networks to wpa_supplicant.
Does not restart it or touch its config file.
"""
import json
import pathlib
import re
import subprocess
NETWORKS_FILE = pathlib.Path("/etc/keys/wireless_networks.json")
def wpa_cli(command: list[str]) -> list[bytes]:
command.insert(0, "wpa_cli")
process = subprocess.run(command, stdout=subprocess.PIPE, check=True)
lines = process.stdout.splitlines()
while lines[0].startswith(b"Selected interface"):
lines.pop(0)
return lines
network_numbers: dict[str, int] = {}
networks_tsv = wpa_cli(["list_networks"])
networks_tsv.pop(0)
for network_line in networks_tsv:
split = network_line.split(b"\t")
number = int(split[0])
ssid_bytes = split[1]
ssid = re.sub(
rb"\\x([0-9a-f]{2})",
lambda d: int(d[1], base=16).to_bytes(),
ssid_bytes,
).decode()
network_numbers[ssid] = number
if NETWORKS_FILE.is_file():
with NETWORKS_FILE.open() as fd:
networks = json.load(fd)
for network in networks:
ssid = network["ssid"]
if ssid in network_numbers:
number = network_numbers[ssid]
else:
number = int(wpa_cli(["add_network"])[0])
number_str = str(number)
for key, value in network.items():
if isinstance(value, str):
value_str = f'"{value}"'
elif isinstance(value, list):
value_str = " ".join(value)
else:
value_str = str(value)
ret = wpa_cli(["set_network", number_str, key, value_str])
if ret[0] != b"OK":
msg = f"Couldn't set {key} for {ssid}, got {ret}"
raise RuntimeError(msg)