git init m8

This commit is contained in:
i-am-called-glitchy 2025-06-03 12:00:58 +00:00
commit a5c4ffe3e9
5 changed files with 272 additions and 0 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
users.txt
.venv
venv
env
.env
notes

37
static/note.js Normal file
View file

@ -0,0 +1,37 @@
const textarea = document.getElementById("editor");
const status = document.getElementById("status");
fetch("/api/" + noteName)
.then(res => res.ok ? res.text() : "")
.then(text => {
textarea.value = text;
status.textContent = "Loaded";
});
let timeout;
let last = "";
textarea.addEventListener("input", () => {
status.textContent = "Typing...";
clearTimeout(timeout);
timeout = setTimeout(() => {
const text = textarea.value;
if (text !== last) {
fetch("/api/" + noteName, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: text })
}).then(res => {
if (res.ok) {
last = text;
status.textContent = "Saved";
} else {
status.textContent = "Save failed";
}
});
} else {
status.textContent = "No changes";
}
}, 500);
});

20
templates/note.html Normal file
View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> {{ note }} </title>
<style>
textarea { width: 100%; height: 90vh; font-family: monospace; font-size: 1em; }
#status { font-size: 0.9em; color: gray; }
</style>
</head>
<body>
<textarea id="editor" placeholder="Type here!"></textarea>
<div id="status">Loading...</div>
<script>
const noteName = "{{ note|e }}";
</script>
<script src="{{ url_for('static', filename='note.js') }}"></script>
</body>
</html>

69
test.html Normal file
View file

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Autosave Textbox</title>
<style>
textarea {
width: 100%;
height: 300px;
font-family: monospace;
font-size: 1em;
}
#status {
font-size: 0.9em;
color: gray;
}
</style>
</head>
<body>
<h1>Autosave Textbox</h1>
<textarea id="editor" placeholder="Start typing..."></textarea>
<div id="status">Idle</div>
<script>
const textarea = document.getElementById("editor");
const status = document.getElementById("status");
let timeoutId;
let lastSentValue = "";
textarea.addEventListener("input", () => {
status.textContent = "Typing...";
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
const content = textarea.value;
if (content !== lastSentValue) {
saveContent(content);
} else {
status.textContent = "No changes";
}
}, 400);
});
function saveContent(text) {
status.textContent = "Saving...";
fetch("https://your-api-endpoint.example.com/save", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ content: text })
})
.then(response => {
if (!response.ok) throw new Error("Network response was not ok");
lastSentValue = text;
status.textContent = "Saved";
})
.catch(error => {
status.textContent = "Save failed";
console.error("Autosave failed:", error);
});
}
</script>
</body>
</html>

140
testflask.py Normal file
View file

@ -0,0 +1,140 @@
from flask import Flask, request, session, redirect, url_for, render_template, jsonify
from werkzeug.security import generate_password_hash, check_password_hash
from cryptography.fernet import Fernet
import os
import hashlib
import base64
import dotenv
dotenv.load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv("SECRET")
USERS_FILE = "users.txt"
DATA_DIR = "notes"
os.makedirs(DATA_DIR, exist_ok=True)
# === UTILS ===
def get_user():
return session.get("user")
def get_note_path(user, note):
safe_user = user.replace("/", "_")
safe_note = note.replace("/", "_")
user_dir = os.path.join(DATA_DIR, safe_user)
os.makedirs(user_dir, exist_ok=True)
return os.path.join(user_dir, safe_note + ".txt")
def get_key_for_user(user, password):
salt = b"fixed_salt" # You can store a per-user salt in USERS_FILE if needed
key = hashlib.pbkdf2_hmac("sha256", password.encode(), salt + user.encode(), 100_000)
return base64.urlsafe_b64encode(key[:32])
# === ROUTES ===
@app.route("/api/<note>", methods=["GET", "POST"])
def api(note):
user = get_user()
key = session.get("key")
if not user or not key:
return "Unauthorized", 401
fernet = Fernet(key.encode())
path = get_note_path(user, note)
if request.method == "GET":
if not os.path.exists(path):
return "", 200
with open(path, "rb") as f:
try:
return fernet.decrypt(f.read()).decode(), 200
except Exception:
return "Corrupted note or invalid key", 500
if request.method == "POST":
data = request.get_json()
if not data or "content" not in data:
return "Bad request", 400
ciphertext = fernet.encrypt(data["content"].encode())
with open(path, "wb") as f:
f.write(ciphertext)
return jsonify({"status": "saved"})
@app.route("/n/<note>")
@app.route("/notes/<note>")
def serve_note(note):
if not get_user():
return redirect(url_for("login"))
return render_template("note.html", note=note)
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
if not username or not password:
return "Missing fields", 400
with open(USERS_FILE, "a+") as f:
f.seek(0)
for line in f:
if line.strip().split(":")[0] == username:
return "User already exists", 400
hashed_pw = generate_password_hash(password)
f.write(f"{username}:{hashed_pw}\n")
session["user"] = username
session["key"] = get_key_for_user(username, password).decode()
return redirect(url_for("serve_note", note="home"))
return '''
<form method="post">
Username: <input name="username"><br>
Password: <input name="password" type="password"><br>
<input type="submit" value="Register">
</form>
<p>Already have an account? <a href="/login">Login here</a>.</p>
'''
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username")
password = request.form.get("password")
with open(USERS_FILE, "r") as f:
for line in f:
user, stored_hash = line.strip().split(":", 1)
if user == username and check_password_hash(stored_hash, password):
session["user"] = username
session["key"] = get_key_for_user(username, password).decode()
return redirect(url_for("serve_note", note="home"))
return "Invalid login", 401
return '''
<form method="post">
Username: <input name="username"><br>
Password: <input name="password" type="password"><br>
<input type="submit" value="Login">
</form>
<p>Don't have an account? <a href="/register">Register here</a>.</p>
'''
@app.route("/logout")
def logout():
session.pop("user", None)
session.pop("key", None)
return redirect(url_for("login"))
if __name__ == "__main__":
app.run(debug=True)