This commit is contained in:
Glitchy 2025-06-06 14:20:05 +00:00
parent ec90d4a8d7
commit c3a1ce74af
4 changed files with 88 additions and 6 deletions

3
.gitignore vendored
View file

@ -1,7 +1,10 @@
users.txt
access.log
.venv
venv
env
.env
notes
log.log
__pycache__
error.log

48
app.py
View file

@ -108,7 +108,53 @@ def api(note):
def serve_note(note):
if not get_user():
return redirect(url_for("login"))
return render_template("note.html", note=note)
return render_template("note.html", note=note, username=get_user())
@app.route("/public/<username>")
@app.route("/board")
def serve_note_nologin(username: str = ""):
return render_template("note.html", note=username, username=get_user())
@app.route("/publicapi/<username>", methods=["GET", "POST"])
def public_board(username):
user = get_user()
path = os.path.join(DATA_DIR, username.replace("/", "_"), "__public.txt")
if request.method == "GET":
if not os.path.exists(path):
return "", 200
with open(path, "r", encoding="utf-8") as f:
return f.read(), 200
if request.method == "POST":
if user != username:
return "Forbidden", 403
data = request.get_json()
if not data or "content" not in data:
return "Bad request", 400
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w", encoding="utf-8") as f:
f.write(data["content"])
return jsonify({"status": "saved"})
@app.route("/boardapi", methods=["GET", "POST"])
def shared_board():
path = os.path.join(DATA_DIR, "__shared_board.txt")
if request.method == "GET":
if not os.path.exists(path):
return "", 200
with open(path, "r", encoding="utf-8") as f:
return f.read(), 200
if request.method == "POST":
data = request.get_json()
if not data or "content" not in data:
return "Bad request", 400
with open(path, "w", encoding="utf-8") as f:
f.write(data["content"])
return jsonify({"status": "saved"})
@app.route("/")
def serve_root():

View file

@ -1,31 +1,63 @@
const textarea = document.getElementById("editor");
const status = document.getElementById("status");
const error = document.getElementById("error");
const currentUser = document.getElementById("username").innerHTML;
const path = window.location.pathname;
fetch("/api/" + noteName)
// === ROUTE PARSING ===
let mode = "private";
let fetchUrl = "";
let editable = true;
let last = "";
if (path.startsWith("/public/")) {
const username = path.split("/")[2];
fetchUrl = "/publicapi/" + username;
editable = (currentUser === username);
mode = "public";
} else if (path === "/board") {
fetchUrl = "/boardapi";
mode = "shared";
editable = true;
} else if (path.startsWith("/n/") || path.startsWith("/notes/")) {
const note = path.split("/").pop();
fetchUrl = "/api/" + note;
editable = true;
} else {
error.textContent = "Unsupported path: " + path;
textarea.disabled = true;
throw new Error("Unknown path: " + path);
}
if (!editable) textarea.disabled = true;
// === FETCH INITIAL CONTENT ===
fetch(fetchUrl)
.then(res => {
if (!res.ok) throw new Error("Failed to load note. Status: " + res.status);
if (!res.ok) throw new Error("Failed to load. Status: " + res.status);
return res.text();
})
.then(text => {
textarea.value = text;
last = text;
status.textContent = "Loaded";
})
.catch(err => {
error.textContent = "Error loading note: " + err.message;
error.textContent = "Error loading content: " + err.message;
status.textContent = "Load failed";
});
// === AUTOSAVE LOGIC ===
let timeout;
let last = "";
textarea.addEventListener("input", () => {
if (!editable) return;
status.textContent = "Typing...";
clearTimeout(timeout);
timeout = setTimeout(() => {
const text = textarea.value;
if (text !== last) {
fetch("/api/" + noteName, {
fetch(fetchUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: text })

View file

@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<div id="username" style="display: none;">{{ username }}</div>
<title> {{ note }} </title>
<style>
textarea { width: 100%; height: 90vh; font-family: monospace; font-size: 1em; }