commit c093e3cd0479fc88566628fac9e9daf815ee2a4d from: Aleksey Ryndin date: Sun Oct 13 20:41:00 2024 UTC Fix: (!)EXPERIMENTAL(!) minimalistics db commit - 7fac138e7c03ad906cb8cf863af760311239236f commit + c093e3cd0479fc88566628fac9e9daf815ee2a4d blob - 77995b9386d798e6a40beaa9d6506da82c5d68af blob + 9a11ad497b966156c047c0fad2ef81f79b3ae680 --- lonk.py +++ lonk.py @@ -38,8 +38,8 @@ class ParagraphTag(_BaseTag): self.content = [] self.footer = [] return "\n".join([result] + footer) + "\n" if result else "" + - class LinkTag(_BaseTag): def __init__(self, href, paragraph, tag, attrs): super().__init__(tag, attrs) @@ -203,10 +203,14 @@ class HonkUrl: ) def get(self, action, answer_is_json=True, **kwargs): - query = {**{"action": action, "token": self._token}, **kwargs} - with urlopen(self.build(path="api", query=urlencode(query)), timeout=45) as response: - answer = response.read().decode("utf8") - return json_loads(answer) if answer_is_json else answer + start_time = clock_gettime(CLOCK_MONOTONIC) + try: + query = {**{"action": action, "token": self._token}, **kwargs} + with urlopen(self.build(path="api", query=urlencode(query)), timeout=45) as response: + answer = response.read().decode("utf8") + return json_loads(answer) if answer_is_json else answer + finally: + stderr.write(f"GET {action} {kwargs}|{clock_gettime(CLOCK_MONOTONIC) - start_time:.3f}sec.\n") def db_create_schema(db_con): @@ -214,47 +218,9 @@ def db_create_schema(db_con): """ CREATE TABLE client ( - client_id INTEGER PRIMARY KEY, - cert_hash TEXT UNIQUE, + cert_hash TEXT PRIMARY KEY, honk_url TEXT NOT NULL, token TEXT NOT NULL - ) - """ - ) - db_con.execute( - """ - CREATE TABLE - convoy ( - convoy_id INTEGER PRIMARY KEY, - convoy TEXT, - client_id INTEGER, - honk_id INTEGER, - handle TEXT, - oondle TEXT, - url TEXT, - html TEXT, - date TEXT, - public INTEGER, - handles TEXT, - honker_url TEXT, - oonker_url TEXT, - FOREIGN KEY (client_id) REFERENCES client (client_id), - UNIQUE (convoy, client_id) - ) - """ - ) - db_con.execute( - """ - 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) ) """ ) @@ -347,124 +313,37 @@ def print_gethonks(gethonks_answer, lonk_url, honk_url class _LonkTreeItem: - def __init__(self, convoy_id, convoy, honk_id, handle, oondle, url, html, date, public, handles, honker, oonker): - self.convoy_id = convoy_id - self.convoy = convoy - self.honk_id = honk_id - self.handle = handle - self.oondle = oondle - self.url = url - self.html = html - self.date = date - self.public = bool(public) - self.handles = handles - self.honker = honker - self.oonker = oonker - self.donks = [] + def __init__(self, honk=None): + self.honk = honk self.thread = [] def iterate_honks(self): - if self.html is not None: - yield { - "Convoy": self.convoy, - "Handle": self.handle, - "Oondle": self.oondle, - "ID": self.honk_id, - "XID": self.url, - "HTML": self.html, - "Date": self.date, - "Public": self.public, - "Handles": self.handles, - "Honker": self.honker, - "Oonker": self.oonker, - "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) + if self.honk is not None: + yield self.honk + yield from self.thread -def page_lonk(db_con, client_id, lonk_url, honk_url): +def page_lonk(lonk_url, honk_url): gethonks_answer = honk_url.get("gethonks", page="home") lonk_page = {} convoy_map = {} for honk in reversed(gethonks_answer.pop("honks", None) or []): convoy = convoy_map.get(honk["Convoy"], honk["Convoy"]) - - def _select_convoy_from_db(convoy): - row = db_con.execute( - """ - SELECT - convoy_id, convoy, honk_id, handle, oondle, url, html, date, public, handles, honker_url, oonker_url - FROM - convoy - WHERE - client_id=? AND convoy=? - """, - (client_id, convoy) - ).fetchone() - 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 - - 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: - _select_convoy_from_db(convoy) - - if convoy not in lonk_page: - def _save_convoy(convoy, honk): - is_public = 1 if honk.get("Public") else 0 - row = db_con.execute( - """ - INSERT INTO - convoy(convoy, client_id, honk_id, handle, oondle, url, html, date, public, handles, honker_url, oonker_url) - VALUES - (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - RETURNING - convoy_id, convoy, honk_id, handle, oondle, url, html, date, public, handles, honker_url, oonker_url - """, - (convoy, client_id, honk["ID"], honk["Handle"], honk.get("Oondle"), honk["XID"], honk["HTML"], honk["Date"], is_public, honk["Handles"], honk.get("Honker"), honk.get("Oonker")) - ).fetchone() - lonk_page[convoy] = _LonkTreeItem(*row) - - for donk in (honk.get("Donks") or []): - donk_url = honk_url.build(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)) - if honk.get("RID"): for honk_in_convoy in honk_url.get("gethonks", page="convoy", c=convoy)["honks"]: if honk_in_convoy["What"] == "honked": if convoy != honk_in_convoy["Convoy"]: convoy_map[convoy] = honk_in_convoy["Convoy"] convoy = honk_in_convoy["Convoy"] - if convoy not in lonk_page: - _select_convoy_from_db(convoy) if convoy not in lonk_page: - _save_convoy(convoy, honk_in_convoy) + lonk_page[convoy] = _LonkTreeItem(honk_in_convoy) break else: - _save_convoy(convoy, {"ID": None, "Handle": None, "XID": None, "HTML": None, "Date": None, "Handles": None}) + lonk_page[convoy] = _LonkTreeItem(None) else: - _save_convoy(convoy, honk) + lonk_page[convoy] = _LonkTreeItem(honk) if honk.get("RID"): lonk_page[convoy].thread.append(honk) @@ -477,7 +356,7 @@ def page_lonk(db_con, client_id, lonk_url, honk_url): print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_convoy(db_con, client_id, lonk_url, honk_url): +def page_convoy(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") @@ -488,7 +367,7 @@ def page_convoy(db_con, client_id, lonk_url, honk_url) print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_search(db_con, client_id, lonk_url, honk_url): +def page_search(lonk_url, honk_url): if not lonk_url.query: print("10 What are we looking for?\r") return @@ -499,25 +378,25 @@ def page_search(db_con, client_id, lonk_url, honk_url) print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_atme(db_con, client_id, lonk_url, honk_url): +def page_atme(lonk_url, honk_url): gethonks_answer = honk_url.get("gethonks", page="atme") print_header("@me") print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_longago(db_con, client_id, lonk_url, honk_url): +def page_longago(lonk_url, honk_url): gethonks_answer = honk_url.get("gethonks", page="longago") print_header("long ago") print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_myhonks(db_con, client_id, lonk_url, honk_url): +def page_myhonks(lonk_url, honk_url): gethonks_answer = honk_url.get("gethonks", page="myhonks") print_header("my honks") print_gethonks(gethonks_answer, lonk_url, honk_url) -def page_honker(db_con, client_id, lonk_url, honk_url): +def page_honker(lonk_url, honk_url): xid = {pair[0]: pair[1] for pair in parse_qsl(lonk_url.query)}.get("xid") if not xid: print("51 Not found\r") @@ -528,7 +407,7 @@ def page_honker(db_con, client_id, lonk_url, honk_url) print_gethonks(gethonks_answer, lonk_url, honk_url) -def bonk(db_con, client_id, lonk_url, honk_url): +def bonk(lonk_url, honk_url): what = {pair[0]: pair[1] for pair in parse_qsl(lonk_url.query)}.get("w") if not what: print("51 Not found\r") @@ -538,7 +417,7 @@ def bonk(db_con, client_id, lonk_url, honk_url): print(f'30 {lonk_url.build("myhonks")}\r') -def gethonkers(db_con, client_id, lonk_url, honk_url): +def gethonkers(lonk_url, honk_url): print_header("honkers") print_menu(lonk_url, honk_url) @@ -561,7 +440,7 @@ def gethonkers(db_con, client_id, lonk_url, honk_url): print_menu(lonk_url, honk_url) -def addhonker(db_con, client_id, lonk_url, honk_url): +def addhonker(lonk_url, honk_url): if not lonk_url.query: print("10 honker url: \r") return @@ -578,7 +457,7 @@ def addhonker(db_con, client_id, lonk_url, honk_url): print(f'> {error.fp.read().decode("utf8")}\r') -def unsubscribe(db_con, client_id, lonk_url, honk_url): +def unsubscribe(lonk_url, honk_url): honkerid = {pair[0]: pair[1] for pair in parse_qsl(lonk_url.query)}.get("honkerid") if not honkerid: print("51 Not found\r") @@ -589,7 +468,7 @@ def unsubscribe(db_con, client_id, lonk_url, honk_url) print(f'30 {lonk_url.build("gethonkers")}\r') -def subscribe(db_con, client_id, lonk_url, honk_url): +def subscribe(lonk_url, honk_url): honkerid = {pair[0]: pair[1] for pair in parse_qsl(lonk_url.query)}.get("honkerid") if not honkerid: print("51 Not found\r") @@ -600,7 +479,7 @@ def subscribe(db_con, client_id, lonk_url, honk_url): print(f'30 {lonk_url.build("gethonkers")}\r') -def newhonk(db_con, client_id, lonk_url, honk_url): +def newhonk(lonk_url, honk_url): if not lonk_url.query: print("10 let's make some noise: \r") return @@ -610,7 +489,7 @@ def newhonk(db_con, client_id, lonk_url, honk_url): print(f'30 {lonk_url.build("myhonks")}\r') -def honkback(db_con, client_id, lonk_url, honk_url): +def honkback(lonk_url, honk_url): if not lonk_url.query: handles = unquote(lonk_url.splitted_path[-3]).strip() rid = unquote(lonk_url.splitted_path[-2]) @@ -625,13 +504,13 @@ def honkback(db_con, client_id, lonk_url, honk_url): def authenticated(cert_hash, lonk_url, fn_impl): db_con = db_connect() - row = db_con.execute("SELECT client_id, honk_url, token FROM client WHERE cert_hash=?", (cert_hash, )).fetchone() + row = db_con.execute("SELECT honk_url, token FROM client WHERE cert_hash=?", (cert_hash, )).fetchone() if not row: print(f'30 {lonk_url.build("ask_server")}\r') return - client_id, honk_url, token = row + honk_url, token = row with db_con: - fn_impl(db_con, client_id, lonk_url, HonkUrl(honk_url, token)) + fn_impl(lonk_url, HonkUrl(honk_url, token)) def new_client_stage_1_ask_server(lonk_url):