Files
SocialPub/tools/pasture/town/state.py
T

67 lines
2.1 KiB
Python
Raw Normal View History

"""What the town keeps between commands in .state/town/ (removed with the pasture): every account it made and the
session (token, local id, actor) each one signs in with, so a second command never makes or signs in anyone again."""
import json
import os
import threading
from dialects import driver
from dialects.base import Account, Session
ROOT = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".state", "town")
_lock = threading.Lock()
def _path(name):
os.makedirs(ROOT, exist_ok=True)
return os.path.join(ROOT, name)
def load(name, default):
try:
with open(_path(name)) as f:
return json.load(f)
except (FileNotFoundError, ValueError):
return default
def save(name, value):
with _lock:
tmp = _path(name) + ".tmp"
with open(tmp, "w") as f:
json.dump(value, f, indent=1, default=str)
os.replace(tmp, _path(name))
def remember(sessions):
stored = load("sessions.json", {})
for s in sessions:
stored[f"{s.account.platform}/{s.account.username}"] = {
"account": s.account.__dict__, "token": s.token, "local_id": s.local_id, "actor_uri": s.actor_uri}
save("sessions.json", stored)
def session(platform, username):
stored = load("sessions.json", {}).get(f"{platform}/{username}")
if stored is None:
raise KeyError(f"the town has no account {username} on {platform}")
return Session(Account(**stored["account"]), stored["token"], stored["local_id"], stored["actor_uri"])
def sessions(platform=None):
out = []
for key, stored in load("sessions.json", {}).items():
if platform and not key.startswith(platform + "/"):
continue
out.append(Session(Account(**stored["account"]), stored["token"], stored["local_id"], stored["actor_uri"]))
return out
def provision(platform, accounts):
"""Sessions for `accounts`, making and signing in only those the town does not already have."""
known = {s.account.username: s for s in sessions(platform)}
missing = [a for a in accounts if a.username not in known]
if missing:
made = driver(platform).provision(missing)
remember(made)
known.update({s.account.username: s for s in made})
return [known[a.username] for a in accounts]