Retro Bulletin Board Systems on atproto. Web app and TUI. lazy mirror of alyraffauf/atbbs atbbs.xyz
forums python tui atproto bbs
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

core/utils: tighten up safety

+12 -6
+6 -2
core/models.py
··· 13 13 14 14 @classmethod 15 15 def parse(cls, uri: str) -> "AtUri": 16 - parts = uri.split("/") 17 - return cls(parts[2], parts[3], parts[4]) 16 + if not uri.startswith("at://"): 17 + raise ValueError(f"not an AT URI: {uri!r}") 18 + parts = uri[5:].split("/") 19 + if len(parts) != 3 or not all(parts): 20 + raise ValueError(f"malformed AT URI: {uri!r}") 21 + return cls(*parts) 18 22 19 23 def __str__(self) -> str: 20 24 return f"at://{self.did}/{self.collection}/{self.rkey}"
+6 -4
core/util.py
··· 4 4 5 5 6 6 def now_iso() -> str: 7 - """Current UTC timestamp in ISO format.""" 8 - return datetime.now(timezone.utc).isoformat() 7 + """Current UTC timestamp in ISO format with Z suffix (ATProto convention).""" 8 + return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") 9 9 10 10 11 11 def format_datetime_utc(value: str) -> str: ··· 22 22 23 23 def blob_url(pds: str, did: str, cid: str) -> str: 24 24 """Construct an ATProto blob fetch URL.""" 25 - return f"{pds}/xrpc/com.atproto.sync.getBlob?did={did}&cid={cid}" 25 + return f"{pds.rstrip('/')}/xrpc/com.atproto.sync.getBlob?did={did}&cid={cid}" 26 26 27 27 28 28 def attachment_cid(attachment: dict) -> str: 29 29 """Return the blob CID from a post attachment, or empty string if missing.""" 30 - return (attachment.get("file") or {}).get("ref", {}).get("$link", "") 30 + file = attachment.get("file") or {} 31 + ref = file.get("ref") or {} 32 + return ref.get("$link") or ""