strange new worlds
This commit is contained in:
parent
73e488681c
commit
eeb1b733d2
25
README.md
25
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
|
# bink
|
||||||
|
|
||||||
serverless microblogging for tilde.town
|
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.
|
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`
|
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.
|
||||||
|
|
||||||
## 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.
|
|
37
bink.py
37
bink.py
@ -49,20 +49,37 @@ def generate_feed(before=None, count=50):
|
|||||||
blogs.append(obj)
|
blogs.append(obj)
|
||||||
return blogs
|
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:
|
with open("/dev/stdout", "w") as f:
|
||||||
json.dump(generate_feed(), f)
|
json.dump(generate_feed(), f)
|
||||||
exit()
|
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
|
import urwid
|
||||||
|
|
||||||
class App(object):
|
attrmap = [
|
||||||
|
("bold", "default,bold", "default")
|
||||||
|
]
|
||||||
|
|
||||||
|
class App():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.walker = urwid.SimpleListWalker([
|
self.walker = urwid.SimpleListWalker([
|
||||||
self.post_to_widget(post) for post in generate_feed()
|
self.post_to_widget(post) for post in generate_feed()
|
||||||
])
|
])
|
||||||
self.loop = urwid.MainLoop(
|
self.loop = urwid.MainLoop(
|
||||||
ActionBox(self.walker)
|
ActionBox(self.walker),
|
||||||
|
palette=attrmap
|
||||||
)
|
)
|
||||||
|
|
||||||
def update(self, before=None, count=50):
|
def update(self, before=None, count=50):
|
||||||
@ -74,8 +91,8 @@ class App(object):
|
|||||||
time = post["time"] / 1_000_000_000
|
time = post["time"] / 1_000_000_000
|
||||||
stamp = datetime.datetime.fromtimestamp(time)
|
stamp = datetime.datetime.fromtimestamp(time)
|
||||||
return urwid.Pile([
|
return urwid.Pile([
|
||||||
urwid.Text([f"~{post['user']}", " @ ", stamp.strftime("%H:%M (%A, %B %d, %Y)")]),
|
urwid.Text([("bold", f"~{post['user']}"), " @ ", stamp.strftime("%H:%M (%A, %B %d, %Y)")]),
|
||||||
urwid.Text(f" {post['body']}"),
|
urwid.Text(post['body']),
|
||||||
urwid.Divider()
|
urwid.Divider()
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -101,6 +118,16 @@ class ActionBox(urwid.ListBox):
|
|||||||
elif keyl in ("q", "x"):
|
elif keyl in ("q", "x"):
|
||||||
app.loop.stop()
|
app.loop.stop()
|
||||||
exit()
|
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)
|
return super().keypress(size, key)
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user