Retro Bulletin Board Systems on atproto. Web app and TUI. atbbs.xyz
python tui atproto bbs

web: re-use blessed API routes

+46 -69
+25 -6
web/routes_sysop.py
··· 4 4 5 5 from core import lexicon 6 6 from core.models import AtUri, AuthError 7 + from core.records import _pds_post, delete_record 7 8 from core.util import now_iso 8 - from web.helpers import get_user 9 - from web.routes_write import _authed_pds_post, authed_delete_record 9 + from web.helpers import get_user, session_updater 10 10 11 11 bp = Blueprint("sysop", __name__) 12 12 ··· 14 14 @bp.errorhandler(AuthError) 15 15 async def handle_auth_error(e): 16 16 return redirect("/login") 17 + 18 + 19 + async def _authed_pds_post(user: dict, endpoint: str, body: dict): 20 + """Make an authenticated POST to the user's PDS.""" 21 + return await _pds_post( 22 + current_app.http_client, user, endpoint, body, session_updater 23 + ) 17 24 18 25 19 26 async def _has_bbs(user: dict) -> bool: ··· 76 83 failed = [] 77 84 for slug in board_slugs: 78 85 try: 79 - await authed_delete_record(user, lexicon.BOARD, slug) 86 + await delete_record( 87 + current_app.http_client, user, lexicon.BOARD, slug, session_updater 88 + ) 80 89 except Exception: 81 90 failed.append(f"board/{slug}") 82 91 ··· 89 98 for ref in backlinks.records: 90 99 if ref.did == user["did"]: 91 100 try: 92 - await authed_delete_record(user, lexicon.NEWS, ref.rkey) 101 + await delete_record( 102 + current_app.http_client, 103 + user, 104 + lexicon.NEWS, 105 + ref.rkey, 106 + session_updater, 107 + ) 93 108 except Exception: 94 109 failed.append(f"news/{ref.rkey}") 95 110 except Exception: ··· 102 117 103 118 # Delete site record 104 119 try: 105 - await authed_delete_record(user, lexicon.SITE, "self") 120 + await delete_record( 121 + current_app.http_client, user, lexicon.SITE, "self", session_updater 122 + ) 106 123 except Exception: 107 124 return await error("Could not delete BBS.") 108 125 ··· 418 435 return redirect(f"/bbs/{handle}") 419 436 420 437 try: 421 - await authed_delete_record(user, lexicon.NEWS, tid) 438 + await delete_record( 439 + current_app.http_client, user, lexicon.NEWS, tid, session_updater 440 + ) 422 441 except Exception: 423 442 return await error("Could not delete news.") 424 443
+21 -63
web/routes_write.py
··· 4 4 5 5 from core import lexicon 6 6 from core.models import AtUri, AuthError 7 - from core.records import upload_blob 8 - from core.util import now_iso 7 + from core.records import create_reply_record, create_thread_record, delete_record, upload_blob 9 8 from web.helpers import get_user, session_updater 10 9 11 10 bp = Blueprint("write", __name__) ··· 14 13 @bp.errorhandler(AuthError) 15 14 async def handle_auth_error(e): 16 15 return redirect("/login") 17 - 18 - 19 - async def _authed_pds_post(user: dict, endpoint: str, body: dict): 20 - """Make an authenticated POST to the user's PDS.""" 21 - from core.records import _pds_post 22 - 23 - return await _pds_post( 24 - current_app.http_client, user, endpoint, body, session_updater 25 - ) 26 - 27 - 28 - async def authed_delete_record(user: dict, collection: str, rkey: str): 29 - """Delete a record from the user's repo.""" 30 - resp = await _authed_pds_post( 31 - user, 32 - "com.atproto.repo.deleteRecord", 33 - { 34 - "repo": user["did"], 35 - "collection": collection, 36 - "rkey": rkey, 37 - }, 38 - ) 39 - resp.raise_for_status() 40 - return resp 41 16 42 17 43 18 @bp.route("/bbs/<handle>/board/<slug>/new-thread", methods=["POST"]) ··· 90 65 message=f"Failed to upload {f.filename}.", 91 66 ), 400 92 67 93 - record = { 94 - "$type": lexicon.THREAD, 95 - "board": board_uri, 96 - "title": title, 97 - "body": body, 98 - "createdAt": now_iso(), 99 - } 100 - if attachments: 101 - record["attachments"] = attachments 102 - 103 - resp = await _authed_pds_post( 68 + resp = await create_thread_record( 69 + current_app.http_client, 104 70 user, 105 - "com.atproto.repo.createRecord", 106 - { 107 - "repo": user["did"], 108 - "collection": lexicon.THREAD, 109 - "record": record, 110 - }, 71 + board_uri, 72 + title, 73 + body, 74 + attachments=attachments or None, 75 + session_updater=session_updater, 111 76 ) 112 77 resp.raise_for_status() 113 78 ··· 150 115 message=f"Failed to upload {f.filename}.", 151 116 ), 400 152 117 153 - record = { 154 - "$type": lexicon.REPLY, 155 - "subject": thread_uri, 156 - "body": body, 157 - "createdAt": now_iso(), 158 - } 159 - if attachments: 160 - record["attachments"] = attachments 161 - if quote: 162 - record["quote"] = quote 163 - 164 - resp = await _authed_pds_post( 118 + resp = await create_reply_record( 119 + current_app.http_client, 165 120 user, 166 - "com.atproto.repo.createRecord", 167 - { 168 - "repo": user["did"], 169 - "collection": lexicon.REPLY, 170 - "record": record, 171 - }, 121 + thread_uri, 122 + body, 123 + attachments=attachments or None, 124 + quote=quote, 125 + session_updater=session_updater, 172 126 ) 173 127 resp.raise_for_status() 174 128 ··· 181 135 if not user or user["did"] != did: 182 136 return redirect(f"/bbs/{handle}/thread/{did}/{tid}") 183 137 184 - await authed_delete_record(user, lexicon.THREAD, tid) 138 + await delete_record( 139 + current_app.http_client, user, lexicon.THREAD, tid, session_updater 140 + ) 185 141 return redirect(f"/bbs/{handle}") 186 142 187 143 ··· 191 147 if not user: 192 148 return redirect(f"/bbs/{handle}/thread/{did}/{tid}") 193 149 194 - await authed_delete_record(user, lexicon.REPLY, reply_tid) 150 + await delete_record( 151 + current_app.http_client, user, lexicon.REPLY, reply_tid, session_updater 152 + ) 195 153 return redirect(f"/bbs/{handle}/thread/{did}/{tid}")