diff --git a/core/models.py b/core/models.py index 55866c4..b955fb3 100644 --- a/core/models.py +++ b/core/models.py @@ -34,6 +34,11 @@ class AtUri: return hash(str(self)) +def make_at_uri(did: str, collection: str, rkey: str) -> str: + """Build an AT URI string from its components.""" + return f"at://{did}/{collection}/{rkey}" + + # errors diff --git a/core/records.py b/core/records.py index 9717429..f07b8f7 100644 --- a/core/records.py +++ b/core/records.py @@ -10,7 +10,7 @@ import httpx from core import lexicon from core.constellation import get_board_activity, get_replies, get_root_posts from core.filters import filter_moderated -from core.models import AtUri, AuthError, BBS, Board, MiniDoc, Post, Record +from core.models import AtUri, AuthError, BBS, Board, MiniDoc, Post, Record, make_at_uri from core.slingshot import ( get_records_batch, get_records_by_uri, @@ -51,7 +51,7 @@ async def hydrate_threads( newest posts first, the first time a thread URI appears is its most recent activity — giving us bump order naturally. """ - board_uri = str(AtUri(bbs.identity.did, lexicon.BOARD, board.slug)) + board_uri = make_at_uri(bbs.identity.did, lexicon.BOARD, board.slug) max_scans = 4 # Phase 1: Scan board activity to find unique thread URIs diff --git a/core/resolver.py b/core/resolver.py index 43c0fc9..4f910d0 100644 --- a/core/resolver.py +++ b/core/resolver.py @@ -11,6 +11,7 @@ from core.models import ( BBSNotFoundError, NoBBSError, NetworkError, + make_at_uri, ) from core import lexicon from core.cache import TTLCache @@ -51,7 +52,7 @@ async def _resolve_bbs(client: httpx.AsyncClient, handle: str) -> BBS: raise NetworkError("Could not reach the network.") site_value = site_record.value - site_uri = str(AtUri(identity.did, lexicon.SITE, "self")) + site_uri = make_at_uri(identity.did, lexicon.SITE, "self") # Fetch boards and news concurrently board_uris = site_value["boards"] diff --git a/tui/screens/compose/news.py b/tui/screens/compose/news.py index cc7dd16..f751fa6 100644 --- a/tui/screens/compose/news.py +++ b/tui/screens/compose/news.py @@ -3,7 +3,7 @@ from textual.containers import Vertical from textual.widgets import Footer, Input, Static, TextArea from core import lexicon, limits -from core.models import AtUri, BBS +from core.models import BBS, make_at_uri from tui.screens.compose.base import ComposeScreen from tui.widgets.breadcrumb import Breadcrumb @@ -36,5 +36,5 @@ class ComposeNewsScreen(ComposeScreen): self.query_one("#compose-title", Input).focus() def get_post_params(self, title: str | None, body: str) -> dict: - site_uri = str(AtUri(self.bbs.identity.did, lexicon.SITE, "self")) + site_uri = make_at_uri(self.bbs.identity.did, lexicon.SITE, "self") return {"scope": site_uri, "body": body, "title": title} diff --git a/tui/screens/compose/thread.py b/tui/screens/compose/thread.py index c42cdca..4b606b6 100644 --- a/tui/screens/compose/thread.py +++ b/tui/screens/compose/thread.py @@ -3,7 +3,7 @@ from textual.containers import Vertical from textual.widgets import Footer, Input, Static, TextArea from core import lexicon, limits -from core.models import AtUri, BBS, Board +from core.models import BBS, Board, make_at_uri from tui.screens.compose.base import ComposeScreen from tui.widgets.breadcrumb import Breadcrumb @@ -40,5 +40,5 @@ class ComposeThreadScreen(ComposeScreen): self.query_one("#compose-title", Input).focus() def get_post_params(self, title: str | None, body: str) -> dict: - board_uri = str(AtUri(self.bbs.identity.did, lexicon.BOARD, self.board.slug)) + board_uri = make_at_uri(self.bbs.identity.did, lexicon.BOARD, self.board.slug) return {"scope": board_uri, "body": body, "title": title} diff --git a/tui/screens/sysop/create.py b/tui/screens/sysop/create.py index 4d09321..9fea5f3 100644 --- a/tui/screens/sysop/create.py +++ b/tui/screens/sysop/create.py @@ -5,7 +5,7 @@ from textual.screen import Screen from textual.widgets import Footer, Input from core import lexicon -from core.models import AtUri, AuthError +from core.models import AuthError, make_at_uri from core.records import put_board_record, put_site_record from core.resolver import invalidate_bbs_cache, resolve_bbs from core.util import now_iso @@ -77,7 +77,7 @@ class SysopCreateScreen(BBSFormMixin, Screen): "description": description, "intro": intro, "boards": [ - str(AtUri(session["did"], lexicon.BOARD, board["slug"])) + make_at_uri(session["did"], lexicon.BOARD, board["slug"]) for board in self._boards ], "createdAt": now, diff --git a/tui/screens/sysop/delete.py b/tui/screens/sysop/delete.py index 14ffdd2..256a41a 100644 --- a/tui/screens/sysop/delete.py +++ b/tui/screens/sysop/delete.py @@ -5,7 +5,7 @@ from textual.screen import Screen from textual.widgets import Button, Footer, Static from core import lexicon -from core.models import AtUri, BBS +from core.models import AtUri, BBS, make_at_uri from core.constellation import get_root_posts from core.records import delete_record, list_pds_records from tui.util import make_session_updater @@ -55,7 +55,7 @@ class SysopDeleteScreen(Screen): failed.append(f"board/{board.slug}") # Delete sysop's news posts (posts scoped to site) - site_uri = str(AtUri(session["did"], lexicon.SITE, "self")) + site_uri = make_at_uri(session["did"], lexicon.SITE, "self") try: backlinks = await get_root_posts(client, site_uri) for ref in backlinks.records: diff --git a/tui/screens/sysop/edit.py b/tui/screens/sysop/edit.py index ebde77c..cdb8c57 100644 --- a/tui/screens/sysop/edit.py +++ b/tui/screens/sysop/edit.py @@ -5,7 +5,7 @@ from textual.screen import Screen from textual.widgets import Footer, Input from core import lexicon -from core.models import AtUri, AuthError, BBS +from core.models import AuthError, BBS, make_at_uri from core.records import delete_record, put_board_record, put_site_record from core.resolver import invalidate_bbs_cache from core.util import now_iso @@ -107,7 +107,7 @@ class SysopEditScreen(BBSFormMixin, Screen): "description": description, "intro": intro, "boards": [ - str(AtUri(session["did"], lexicon.BOARD, board["slug"])) + make_at_uri(session["did"], lexicon.BOARD, board["slug"]) for board in self._boards ], "createdAt": self.bbs.site.created_at or now,