initial commit
This commit is contained in:
commit
38e8972b99
|
|
@ -0,0 +1 @@
|
||||||
|
__pycache__/
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
# HSWro's NomadNet page
|
||||||
|
|
||||||
|
Made entirely for fun of making it.
|
||||||
|
|
||||||
|
Requires Redis/Valkey running on localhost on its default port.
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import hswro
|
||||||
|
from os import environ
|
||||||
|
from redis import Redis
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
from uuid import uuid4
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
CHAT_NAME = "chat_test"
|
||||||
|
|
||||||
|
toast: Optional[str] = None
|
||||||
|
l = hswro.get_login_info()
|
||||||
|
|
||||||
|
r = Redis(host='localhost', port=6379, db=0)
|
||||||
|
|
||||||
|
msg_to_post = environ.get('field_message', None)
|
||||||
|
|
||||||
|
if msg_to_post is not None and msg_to_post.strip() != "" and l[0] is not None:
|
||||||
|
msg_to_post = hswro.sanitize_input(msg_to_post[0:255].strip())
|
||||||
|
r.rpush(CHAT_NAME, str(json.dumps({
|
||||||
|
"when": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
"who": l[0],
|
||||||
|
"msg": msg_to_post,
|
||||||
|
"id": uuid4().hex
|
||||||
|
})))
|
||||||
|
r.ltrim(CHAT_NAME, -20, -1)
|
||||||
|
|
||||||
|
#print(environ)
|
||||||
|
msg_to_del = environ.get('var_delete', None)
|
||||||
|
if msg_to_del is not None and hswro.is_admin():
|
||||||
|
for msg in r.lrange(CHAT_NAME, 0, -1):
|
||||||
|
m = json.loads(msg.decode('utf-8'))
|
||||||
|
if m['id'] == msg_to_del:
|
||||||
|
toast = f"\nDeleted a post by {m['who']}"
|
||||||
|
r.lrem(CHAT_NAME, 0, msg)
|
||||||
|
break
|
||||||
|
|
||||||
|
hswro.header("Shoutbox")
|
||||||
|
if toast is not None:
|
||||||
|
print(f"`c{toast}")
|
||||||
|
print("`l")
|
||||||
|
|
||||||
|
if l[0] is not None:
|
||||||
|
print(f"{l[0]}: `BFFF`F222`<message`>{hswro.BGCOLOR} [`[Send`:/page/chat.mu`*]]")
|
||||||
|
|
||||||
|
for msg in reversed(r.lrange(CHAT_NAME, 0, -1)):
|
||||||
|
m = json.loads(msg.decode('utf-8'))
|
||||||
|
delbtn = ""
|
||||||
|
if hswro.is_admin():
|
||||||
|
delbtn = f"`B400`FAAA`!`[DEL`:/page/chat.mu`delete={m['id']}]`!"
|
||||||
|
print(f"{delbtn}`BCCC`F333{m['when']}`BAAA`F444{'<'+m['who']+'>':>16}`B333`FCCC{m['msg']}")
|
||||||
|
hswro.reset_colors()
|
||||||
|
hswro.footer()
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from os import environ
|
||||||
|
from typing import Optional, Tuple
|
||||||
|
from datetime import datetime
|
||||||
|
from redis import Redis
|
||||||
|
from hashlib import sha256
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
s = datetime.now()
|
||||||
|
NO_REMOTE_IDENTITY_MSG = """User identity hash not available.
|
||||||
|
In MeshChat: use the fingerprint button in the top right to send the identification information.
|
||||||
|
In NomadNet: Save node, click on it, go to <Info> and select "Identify when connecting"."""
|
||||||
|
|
||||||
|
FORBIDDEN_INPUT = [
|
||||||
|
"[",
|
||||||
|
"`",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
|
||||||
|
ADMIN_IDENTITIES = [
|
||||||
|
"e6c72573bb91d48338dbcc57d0223b81",
|
||||||
|
"70c9608c9a0f4ae895f7fab406554e1c"
|
||||||
|
]
|
||||||
|
BGCOLOR = "`F333`BDDD"
|
||||||
|
|
||||||
|
def is_admin() -> bool:
|
||||||
|
remote_identity = environ.get("remote_identity", None)
|
||||||
|
if remote_identity is None:
|
||||||
|
return False
|
||||||
|
return remote_identity in ADMIN_IDENTITIES
|
||||||
|
|
||||||
|
def sanitize_input(text: str) -> str:
|
||||||
|
return reduce(lambda a, b: a.replace(b, ""), FORBIDDEN_INPUT, text)
|
||||||
|
|
||||||
|
def check_password(password: str) -> bool:
|
||||||
|
expected = '34a77e61000b2ba1f56201332ef64d93f9cdc60e63ab48bc255102586ef7e592'
|
||||||
|
gotten = sha256(f"hswrosalt{password}".encode('utf-8'), usedforsecurity=True).hexdigest()
|
||||||
|
return expected == gotten
|
||||||
|
|
||||||
|
def check_name(username: str) -> bool:
|
||||||
|
if len(username) >= 16:
|
||||||
|
return False
|
||||||
|
return all(map(lambda c: c.isalnum(), username))
|
||||||
|
|
||||||
|
def get_login_info() -> Tuple[Optional[str], Optional[str]]:
|
||||||
|
"""Returns [login_name, error]"""
|
||||||
|
remote_identity = environ.get("remote_identity", None)
|
||||||
|
if remote_identity is None:
|
||||||
|
return (None, NO_REMOTE_IDENTITY_MSG)
|
||||||
|
r = Redis(host='localhost', port=6379, db=0)
|
||||||
|
login = r.get(f'login_info_{remote_identity}')
|
||||||
|
if login is None:
|
||||||
|
return (None, None)
|
||||||
|
return (login.decode('utf-8'), None)
|
||||||
|
|
||||||
|
def login(username: str) -> Optional[str]:
|
||||||
|
"""Returns err"""
|
||||||
|
remote_identity = environ.get("remote_identity", None)
|
||||||
|
if remote_identity is None:
|
||||||
|
return NO_REMOTE_IDENTITY_MSG
|
||||||
|
if not check_name(username):
|
||||||
|
return "Username should only contain alphanumeric characters and have at most 16 characters."
|
||||||
|
r = Redis(host='localhost', port=6379, db=0)
|
||||||
|
r.set(f'login_info_{remote_identity}', username)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def logout():
|
||||||
|
remote_identity = environ.get("remote_identity", None)
|
||||||
|
if remote_identity is None:
|
||||||
|
return
|
||||||
|
r = Redis(host='localhost', port=6379, db=0)
|
||||||
|
r.delete(f'login_info_{remote_identity}')
|
||||||
|
|
||||||
|
|
||||||
|
def login_button() -> str:
|
||||||
|
l = get_login_info()
|
||||||
|
if l[0] is None:
|
||||||
|
return "[`[Identify`:/page/login.mu`]]"
|
||||||
|
else:
|
||||||
|
return f"Welcome, {l[0]} | [`[Forget`:/page/logout.mu`]]"
|
||||||
|
|
||||||
|
def header(title: Optional[str] = None):
|
||||||
|
if title is None:
|
||||||
|
title = ""
|
||||||
|
else:
|
||||||
|
title = ": `i" + title
|
||||||
|
print(f"""`F000`BFB1
|
||||||
|
`c
|
||||||
|
-*abc
|
||||||
|
`r {login_button()}
|
||||||
|
`l `!Hackerspace`!Wrocław{title}
|
||||||
|
`a
|
||||||
|
|
||||||
|
-_
|
||||||
|
`a
|
||||||
|
``
|
||||||
|
`FEEE`B333
|
||||||
|
`c
|
||||||
|
|
||||||
|
`l `[Home`:/page/index.mu]` | `[Status`:/page/status.mu]` | `[Shoutbox`:/page/chat.mu]`
|
||||||
|
|
||||||
|
`a
|
||||||
|
``
|
||||||
|
{BGCOLOR}
|
||||||
|
""")
|
||||||
|
|
||||||
|
def reset_colors() -> str:
|
||||||
|
print(BGCOLOR)
|
||||||
|
|
||||||
|
def footer():
|
||||||
|
print(f"{BGCOLOR}`r Rendered in: {(datetime.now()-s).total_seconds()}s")
|
||||||
|
print(f"{datetime.now()}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import hswro
|
||||||
|
|
||||||
|
hswro.header()
|
||||||
|
print("Nothing to see here... yet")
|
||||||
|
hswro.footer()
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import hswro
|
||||||
|
from os import environ
|
||||||
|
|
||||||
|
def login_form():
|
||||||
|
print("`c `!Login:`")
|
||||||
|
print("Username: `<16|username`>")
|
||||||
|
print("Password: `<!16|pass`>")
|
||||||
|
print("[`[Submit`:/page/login.mu`*]]")
|
||||||
|
|
||||||
|
l = hswro.get_login_info()
|
||||||
|
form_login = environ.get('field_username', None)
|
||||||
|
form_pass = environ.get('field_pass', None)
|
||||||
|
|
||||||
|
hswro.header()
|
||||||
|
if l[1] is not None:
|
||||||
|
print(f"`c`!Warning:`! {l[1]}")
|
||||||
|
if form_pass is not None and not hswro.check_password(form_pass):
|
||||||
|
print(f"`c`!Incorrect password.`!")
|
||||||
|
if hswro.check_password(form_pass) and form_login is not None:
|
||||||
|
e = hswro.login(form_login)
|
||||||
|
if e is not None:
|
||||||
|
print(f"`c`!Error:`! {e}")
|
||||||
|
if l[0] is None:
|
||||||
|
login_form()
|
||||||
|
else:
|
||||||
|
print(f"Welcome, {l[0]}.")
|
||||||
|
#print("`l\n\n\n\n\n")
|
||||||
|
#print(environ)
|
||||||
|
hswro.footer()
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import hswro
|
||||||
|
from os import environ
|
||||||
|
|
||||||
|
hswro.logout()
|
||||||
|
|
||||||
|
hswro.header()
|
||||||
|
print("`cYou have been logged out.")
|
||||||
|
hswro.footer()
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import hswro
|
||||||
|
|
||||||
|
def sizeof_fmt(num, suffix="B"):
|
||||||
|
for unit in ("", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"):
|
||||||
|
if abs(num) < 1024.0:
|
||||||
|
return f"{num:3.1f}{unit}{suffix}"
|
||||||
|
num /= 1024.0
|
||||||
|
return f"{num:.1f}Yi{suffix}"
|
||||||
|
|
||||||
|
|
||||||
|
status_raw = subprocess.run(["/home/reticulum/venv/bin/rnstatus", "-j"], capture_output=True)
|
||||||
|
status = json.loads(status_raw.stdout)
|
||||||
|
|
||||||
|
hswro.header("Node Status")
|
||||||
|
print("> Interfaces")
|
||||||
|
|
||||||
|
for i in status['interfaces']:
|
||||||
|
print(">> ", i['short_name'])
|
||||||
|
print("`!Clients:`! ", i['clients'])
|
||||||
|
print("`!Current RX:`! ", i['rxs'])
|
||||||
|
print("`!Current TX:`! ", i['txs'])
|
||||||
|
print("`!Total RX:`! ", sizeof_fmt(i['rxb']))
|
||||||
|
print("`!Total TX:`! ", sizeof_fmt(i['txb']))
|
||||||
|
|
||||||
|
hswro.footer()
|
||||||
Loading…
Reference in New Issue