commit 8b4f10af8c5df796723cc66ee799c06f0c84875a from: Aleksey Ryndin date: Thu Oct 03 11:59:25 2024 UTC Add: lonk page with comments commit - fafb2ce7fd7a140705547330b120fa1e68c0d961 commit + 8b4f10af8c5df796723cc66ee799c06f0c84875a blob - d110abd2c054f4b095428779a88ab0be21bcce59 blob + 8e114e9f198bf3aabe8cbe4e4dcfa5fba1edba84 --- lonk.py +++ lonk.py @@ -247,10 +247,12 @@ def _create_schema(db_con): CREATE TABLE donk ( donk_id INTEGER PRIMARY KEY, + client_id INTEGER, convoy_id INTEGER, url TEXT NOT NULL, mime TEXT, alt_text TEXT, + FOREIGN KEY (client_id) REFERENCES client (client_id), FOREIGN KEY (convoy_id) REFERENCES convoy (convoy_id) ) """ @@ -277,7 +279,7 @@ def db_connect(): return db_con -class _Collected: +class _LonkTreeItem: def __init__(self, convoy_id, convoy, honk_id, honker, url, html, date): self.convoy_id = convoy_id self.convoy = convoy @@ -286,192 +288,140 @@ class _Collected: self.url = url self.html = html self.date = date - self._donks = None - self._reason_thread = [] - self._reason_repost = [] - - def add_donk(self, donk_url, mime, alt_text): - if self._donks is None: - self._donks = [(donk_url, mime, alt_text)] - else: - self._donks.append((donk_url, mime, alt_text)) - - def end_of_donks(self): - if self._donks is None: - self._donks = [] - - def iterate_donks(self, db_con): - if self._donks is not None: - yield from self._donks - return - - res_donks = db_con.execute( - "SELECT url, mime, alt_text FROM donk WHERE convoy_id=?", - (self.convoy_id, ) - ) - while True: - donks = res_donks.fetchmany() - if not donks: - return - - yield from donks + self.donks = [] + self.reposters = [] + self.thread = [] - def add_reason_thread(self, reason): - if reason not in self._reason_thread: - self._reason_thread.append(reason) - - def add_reason_repost(self, reason): - if reason not in self._reason_repost: - self._reason_repost.append(reason) - - def format_reason(self): - repost = ", ".join(reason for reason in self._reason_repost) - thread = ", ".join(thread for thread in self._reason_thread) - rv = "" - if repost: - rv += f" (๐Ÿ” {repost})" - if thread: - rv += f" (๐Ÿงต {thread})" - return rv + def iterate_honks(self): + if self.html is not None: + handle = self.honker + if self.reposters: + handle += " (๐Ÿ” " + ", ".join(reason for reason in set(self.reposters)) + ")" + yield { + "Convoy": self.convoy, + "Handle": handle, + "ID": self.honk_id, + "XID": self.url, + "HTML": self.html, + "Date": self.date, + "Donks": [ + {"URL": donk[0], "Media": donk[1], "Desc": donk[2]} + for donk in self.donks + ] + } + child_honks = self.thread[:] + child_honks.reverse() + yield from reversed(child_honks) -def lonk(db_con, client_id, lonk_url, honk_url): +def page_lonk(db_con, client_id, lonk_url, honk_url): gethonks_answer = honk_url.do_get(action="gethonks", page="home") - lonk_page = {} - for honk in reversed(gethonks_answer.get("honks") or []): - if honk.get("RID"): - reason_fn = _Collected.add_reason_thread - reason = honk["Handle"] - else: - reason_fn = _Collected.add_reason_repost - oondle = honk.get("Oondle") - reason = honk["Handle"] if oondle else None + lonk_page = {} + for honk in (gethonks_answer.pop("honks", None) or []): convoy = honk["Convoy"] - if convoy in lonk_page: - if reason_fn and reason: - reason_fn(lonk_page[convoy], reason) - continue - row = db_con.execute( - "SELECT convoy_id, convoy, honk_id, honker, url, html, date FROM convoy WHERE client_id=? AND convoy=?", - (client_id, convoy) - ).fetchone() - if row: - lonk_page[convoy] = _Collected(*row) - if reason_fn and reason: - reason_fn(lonk_page[convoy], reason) - continue - - def _save_convoy(convoy, honker, honk): + if convoy not in lonk_page: row = db_con.execute( - """ - INSERT INTO - convoy(convoy, client_id, honk_id, honker, url, html, date) - VALUES - (?, ?, ?, ?, ?, ?, ?) - RETURNING - convoy_id - """, - (convoy, client_id, honk["ID"], honker, honk["XID"], honk["HTML"], honk["Date"]) + "SELECT convoy_id, convoy, honk_id, honker, url, html, date FROM convoy WHERE client_id=? AND convoy=?", + (client_id, convoy) ).fetchone() - convoy_id, = row - lonk_page[convoy] = _Collected( - convoy_id, convoy, honk["ID"], honker, honk["XID"], honk["HTML"], honk["Date"] - ) - - for donk in (honk.get("Donks") or []): - donk_url = honk_url.build_url(path=f'/d/{donk["XID"]}') if donk.get("XID") else donk["URL"] - mime, alt_text = donk["Media"], donk.get("Desc") or donk.get("Name") or None - db_con.execute( - "INSERT INTO donk (convoy_id, url, mime, alt_text) VALUES (?, ?, ?, ?)", - (lonk_page[convoy].convoy_id, donk_url, mime, alt_text, ) - ) - lonk_page[convoy].add_donk(donk_url, mime, alt_text) - lonk_page[convoy].end_of_donks() + if row: + lonk_page[convoy] = _LonkTreeItem(*row) + res_donks = db_con.execute( + "SELECT url, mime, alt_text FROM donk WHERE client_id=? AND convoy_id=?", + (client_id, lonk_page[convoy].convoy_id, ) + ) + while True: + donks = res_donks.fetchmany() + if not donks: + break - if honk.get("RID"): - for honk_in_convoy in honk_url.do_get(action="gethonks", page="convoy", c=convoy)["honks"]: - if not honk_in_convoy.get("RID"): - honker = honk_in_convoy.get("Oondle") or honk_in_convoy["Handle"] - _save_convoy(convoy, honker, honk_in_convoy) - if reason_fn and reason: - reason_fn(lonk_page[convoy], reason) - break - else: + for donk in donks: + donk_url, donk_mime, donk_text = donk + lonk_page[convoy].donks.append((donk_url, donk_mime, donk_text)) + + if convoy not in lonk_page: + def _save_convoy(convoy, honker, honk): row = db_con.execute( """ INSERT INTO - convoy(convoy, client_id, honk_id) + convoy(convoy, client_id, honk_id, honker, url, html, date) VALUES - (?, ?, ?) - RETURNING + (?, ?, ?, ?, ?, ?, ?) + RETURNING convoy_id """, - (convoy, client_id, honk["ID"]) + (convoy, client_id, honk["ID"], honker, honk["XID"], honk["HTML"], honk["Date"]) ).fetchone() convoy_id, = row - lonk_page[convoy] = _Collected(convoy_id, convoy, None, None, None, None, None) - else: - honker = honk.get("Oondle") or honk["Handle"] - _save_convoy(convoy, honker, honk) - if reason_fn and reason: - reason_fn(lonk_page[convoy], reason) + lonk_page[convoy] = _LonkTreeItem( + convoy_id, convoy, honk["ID"], honker, honk["XID"], honk["HTML"], honk["Date"] + ) - print("20 text/gemini\r") - print("# ๐“— onk: lonk\r") - print("\r") + for donk in (honk.get("Donks") or []): + donk_url = honk_url.build_url(path=f'/d/{donk["XID"]}') if donk.get("XID") else donk["URL"] + donk_mime, donk_text = donk["Media"], donk.get("Desc") or donk.get("Name") or None + db_con.execute( + "INSERT INTO donk (client_id, convoy_id, url, mime, alt_text) VALUES (?, ?, ?, ?, ?)", + (client_id, lonk_page[convoy].convoy_id, donk_url, donk_mime, donk_text, ) + ) + lonk_page[convoy].donks.append((donk_url, donk_mime, donk_text)) - line = f"=> {lonk_url.build('atme')} @me" - if gethonks_answer["mecount"]: - line += f' ({gethonks_answer["mecount"]})' - print(line + "\r") + if honk.get("RID"): + for honk_in_convoy in honk_url.do_get(action="gethonks", page="convoy", c=convoy)["honks"]: + if not honk_in_convoy.get("RID"): + honker = honk_in_convoy.get("Oondle") or honk_in_convoy["Handle"] + _save_convoy(convoy, honker, honk_in_convoy) + break + else: + _save_convoy(convoy, None, {"ID": None, "XID": None, "HTML": None, "Date": None}) + else: + _save_convoy(convoy, honk.get("Oondle") or honk["Handle"], honk) - line = f"=> {honk_url.build_url(path='chatter')} chatter" - if gethonks_answer["chatcount"]: - line += f' ({gethonks_answer["chatcount"]})' - print(line + "\r") - print("\r") + if honk.get("What") == "bonked": + lonk_page[convoy].reposters.append(honk["Handle"]) + if honk.get("RID"): + lonk_page[convoy].thread.append(honk) - for collected in reversed(lonk_page.values()): - if collected.honker is None: - continue + gethonks_answer["honks"] = [] + for tree_item in lonk_page.values(): + gethonks_answer["honks"] += list(tree_item.iterate_honks()) - lines = [ - f"## From {collected.honker}{collected.format_reason()} {collected.date}", - f'=> {lonk_url.build("convoy", urlencode({"c": collected.convoy}))} Convoy {collected.convoy}', - HtmlToGmi(honk_url.build_url(), lonk_url.media).feed(collected.html) - ] - for donk_url, donk_mime, donk_text in collected.iterate_donks(db_con): - lines.append(f'=> {lonk_url.media(donk_mime, donk_url)}') - if donk_text: - lines.append(donk_text) - print("\r\n".join(lines)) - print("\r") + print("20 text/gemini\r") + print("# ๐“— onk: lonk\r") + print("\r") + print_gethonks(gethonks_answer, lonk_url, honk_url) -def convoy(db_con, client_id, lonk_url, honk_url): +def page_convoy(db_con, client_id, lonk_url, honk_url): query = {pair[0]: pair[1] for pair in parse_qsl(lonk_url.query)} if "c" not in query: print("51 Not found\r") return + gethonks_answer = honk_url.do_get(action="gethonks", page="convoy", c=query["c"]) + gethonks_answer["honks"] = [ + honk + for honk in (gethonks_answer.pop("honks", None) or []) + if honk.get("What") != "bonked" + ] print("20 text/gemini\r") print(f"# ๐“— onk: convoy {query['c']}\r") print("\r") - _gethonks(gethonks_answer, lonk_url, honk_url) + print_gethonks(gethonks_answer, lonk_url, honk_url) -def atme(db_con, client_id, lonk_url, honk_url): +def page_atme(db_con, client_id, lonk_url, honk_url): gethonks_answer = honk_url.do_get(action="gethonks", page="atme") print("20 text/gemini\r") print("# ๐“— onk: @me") print("\r") - _gethonks(gethonks_answer, lonk_url, honk_url) + print_gethonks(gethonks_answer, lonk_url, honk_url) -def _gethonks(gethonks_answer, lonk_url, honk_url): +def print_gethonks(gethonks_answer, lonk_url, honk_url): line = f"=> {lonk_url.build('atme')} @me" if gethonks_answer["mecount"]: line += f' ({gethonks_answer["mecount"]})' @@ -577,11 +527,11 @@ def proxy(mime, url): def vgi(cert_hash, raw_url): lonk_url = LonkUrl(raw_url) if lonk_url.page == "lonk": - authenticated(cert_hash, lonk_url, lonk) + authenticated(cert_hash, lonk_url, page_lonk) elif lonk_url.page == "convoy": - authenticated(cert_hash, lonk_url, convoy) + authenticated(cert_hash, lonk_url, page_convoy) elif lonk_url.page == "atme": - authenticated(cert_hash, lonk_url, atme) + authenticated(cert_hash, lonk_url, page_atme) elif lonk_url.page == "ask_server": new_client_stage_1_ask_server(lonk_url) elif lonk_url.page == "ask_username":