From eeb1b733d2f2b0a8a319896aaa3da838b1068a39 Mon Sep 17 00:00:00 2001 From: nebula Date: Mon, 21 Apr 2025 03:33:01 +0000 Subject: [PATCH] strange new worlds --- README.md | 25 +++++++++++++++++-------- bink.py | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e17407c..8cbf5b7 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,24 @@ -**note**: this readme has been extensively edited since i initially posted it on tilde.town. there are no longer any ambitions to replace bbj with this project - # bink serverless microblogging for tilde.town -# object logic +## command usage + +`bink`: show post list + +buttons used to navigate the list are similar to `less`. here are the keys you can use: +* space, page down: scroll down one whole screen +* down arrow, n, j, ctrl-n: go down one line +* up arrow, p, k, ctrl-p: go up one line +* page up: go up one whole screen +* g: go to top +* G: go to bottom + +`bink pipe`: allow standard input to be the post body, eg. `echo "hello world!" | bink pipe` +`bink dump`: dumps all post data to a json object + +## object logic each system user that chooses to use bink will have a folder in their home directory called `.bink/`, which will be populated by items named after the epoch-nanoseconds time of creation. the contents of each item are plaintext, and that is the post. -from the path where the object is stored, ex. `/home/nebula/.bink/1745182221128478782`, the user who posted the item and the time it was produced can be inferred. each post object therefore has 3 pieces of data: the post body, the exact time the post was produced, and the user who posted it. the client will iterate over system files by using the `/home/**/.bink/*` glob, collecting all of the user objects without using a central server like `bbj` - -## potential flaws - -* scales poorly: client will need to implement some sort of pagination logic if many thousands of posts exist, or the program will be very slow. every file on the system must be iterated with each subsequent update. in 10 years of use, this serverless approach may become cumbersome. \ No newline at end of file +from the path where the object is stored, ex. `/home/nebula/.bink/1745182221128478782`, the user who posted the item and the time it was produced can be inferred. each post object therefore has 3 pieces of data: the post body, the exact time the post was produced, and the user who posted it. the client will iterate over system files by using the `/home/**/.bink/*` glob, collecting all of the user objects without using a central server. \ No newline at end of file diff --git a/bink.py b/bink.py index 57bf998..2aecf42 100755 --- a/bink.py +++ b/bink.py @@ -49,20 +49,37 @@ def generate_feed(before=None, count=50): blogs.append(obj) return blogs -if "dump" in argv: +if "--help" in argv or "help" in argv: + exit("see https://git.tilde.town/nebula/bink for usage instructions") +elif "dump" in argv: with open("/dev/stdout", "w") as f: json.dump(generate_feed(), f) exit() +elif "pipe" in argv: + try: + with open("/dev/stdin", "r", encoding="UTF-8") as f: + body = f.read().strip() + if body: + create_post(body) + exit() + except KeyboardInterrupt: + exit() + import urwid -class App(object): +attrmap = [ + ("bold", "default,bold", "default") +] + +class App(): def __init__(self): self.walker = urwid.SimpleListWalker([ self.post_to_widget(post) for post in generate_feed() ]) self.loop = urwid.MainLoop( - ActionBox(self.walker) + ActionBox(self.walker), + palette=attrmap ) def update(self, before=None, count=50): @@ -74,8 +91,8 @@ class App(object): time = post["time"] / 1_000_000_000 stamp = datetime.datetime.fromtimestamp(time) return urwid.Pile([ - urwid.Text([f"~{post['user']}", " @ ", stamp.strftime("%H:%M (%A, %B %d, %Y)")]), - urwid.Text(f" {post['body']}"), + urwid.Text([("bold", f"~{post['user']}"), " @ ", stamp.strftime("%H:%M (%A, %B %d, %Y)")]), + urwid.Text(post['body']), urwid.Divider() ]) @@ -101,6 +118,16 @@ class ActionBox(urwid.ListBox): elif keyl in ("q", "x"): app.loop.stop() exit() + elif keyl == " ": + super().keypress(size, "page down") + elif keyl in ("j", "n", "ctrl n"): + super().keypress(size, "down") + elif keyl in ("k", "p", "ctrl p"): + super().keypress(size, "up") + elif key == "g": + super().keypress(size, "home") + elif key == "G": + super().keypress(size, "end") return super().keypress(size, key) app = App()