Kokkoja as of 2026-10-10: the teacher's requests, the Session window, notices, the QR code, the license
This commit is contained in:
1 parent
95c80d04c9
commit
1d087af633
32 files changed
+4917
-890
No files matched your search
+38
-5
@@ -106,6 +106,31 @@ def load_token(directory):
|
||||
return token
|
||||
|
||||
|
||||
def remembered_relay(directory, given=""):
|
||||
"""The relay to use: the one given, which is then remembered in the
|
||||
configuration directory, or else the one remembered from last time.
|
||||
|
||||
Returns (address, remembered): the address, or None if none was given
|
||||
and none is remembered, and whether it came from memory. A relay
|
||||
address is typed once; afterwards the program is started bare (Andy,
|
||||
2026-10-08, after a start without --relay sent an invitation to a
|
||||
relay on his own computer that was not running).
|
||||
"""
|
||||
path = directory / "relay"
|
||||
if given:
|
||||
given = given.strip()
|
||||
directory.mkdir(parents=True, exist_ok=True)
|
||||
if path.exists() and path.read_text().strip() == given:
|
||||
return given, False
|
||||
write_atomically(path, (given + "\n").encode())
|
||||
return given, False
|
||||
try:
|
||||
kept = path.read_text().strip()
|
||||
except OSError:
|
||||
kept = ""
|
||||
return (kept, True) if kept else (None, False)
|
||||
|
||||
|
||||
def write_atomically(path, data):
|
||||
"""Replace a file so that it is never seen half written."""
|
||||
temporary = path.with_name("." + path.name + ".writing")
|
||||
@@ -132,7 +157,8 @@ def keep_page(notebook):
|
||||
changed = current.stat().st_mtime
|
||||
except FileNotFoundError:
|
||||
return None, False
|
||||
if b"data-stroke=" not in data and b"<image" not in data:
|
||||
# Blank: no stroke, no text block, no image.
|
||||
if not any(mark in data for mark in (b"data-stroke=", b"data-text=", b"<image")):
|
||||
return None, False
|
||||
|
||||
kept = [entry for entry in notebook.iterdir()
|
||||
@@ -459,9 +485,10 @@ def make_server(port, relay, notebooks, token, config, site=""):
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Kokkoja local program")
|
||||
parser.add_argument("--port", type=int, default=8760)
|
||||
parser.add_argument("--relay", default="ws://127.0.0.1:8770",
|
||||
help="relay used for sessions started here "
|
||||
"(default ws://127.0.0.1:8770)")
|
||||
parser.add_argument("--relay", default="",
|
||||
help="relay used for sessions started here, such as "
|
||||
"wss://kokkoja.example/relay; remembered, so it "
|
||||
"need be given only once")
|
||||
parser.add_argument("--site", default="",
|
||||
help="Kokkoja web site that invitations link to, so that "
|
||||
"guests can join with nothing installed (default: "
|
||||
@@ -478,10 +505,16 @@ def main():
|
||||
|
||||
notebooks = arguments.notebooks or default_notebooks_directory()
|
||||
config = arguments.config or config_directory()
|
||||
relay, remembered = remembered_relay(config, arguments.relay)
|
||||
if relay is None:
|
||||
parser.exit(2, "Kokkoja needs the address of a relay the first time it is started:\n"
|
||||
" python3 kokkoja.py --relay wss://kokkoja.example/relay\n"
|
||||
"Afterwards the address is remembered and python3 kokkoja.py is enough.\n")
|
||||
token = load_token(config)
|
||||
server = make_server(arguments.port, arguments.relay, notebooks, token, config, arguments.site)
|
||||
server = make_server(arguments.port, relay, notebooks, token, config, arguments.site)
|
||||
address = f"http://localhost:{arguments.port}/#token={token}"
|
||||
print(f"Kokkoja is at {address}", flush=True)
|
||||
print(f"Relay: {relay}" + (" (remembered from last time)" if remembered else ""), flush=True)
|
||||
print(f"Notebooks are in {notebooks}", flush=True)
|
||||
print("Ctrl-C to stop.", flush=True)
|
||||
if not arguments.no_browser:
|
||||
|
||||
Reference in new issue
Block a user