diff --git a/.gitignore b/.gitignore index c7626e3..1149575 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -database.db +database.db uploads \ No newline at end of file diff --git a/config.ini b/config.ini index ac2652c..24da8c8 100644 --- a/config.ini +++ b/config.ini @@ -1,7 +1,7 @@ -[config] -HOST = 0.0.0.0 -PORT = 8080 -SECRET_KEY = placeholder -UPLOAD_FOLDER = uploads -PASSWORD_REQUIREMENT = 12 +[config] +HOST = 0.0.0.0 +PORT = 8080 +SECRET_KEY = placeholder +UPLOAD_FOLDER = uploads +PASSWORD_REQUIREMENT = 12 UPLOAD_LIMIT = 4 \ No newline at end of file diff --git a/edituser b/edituser index c245e3b..3141432 100644 --- a/edituser +++ b/edituser @@ -1,21 +1,21 @@ -#!/usr/bin/python3 -import sqlite3 -import os - -userid = input("Insert ID: ") -changewhat = input("Change what value?: ") -towhat = input("What should " + changewhat + " be changed to?: ") - -def get_db_connection(): - conn = sqlite3.connect("database.db") - conn.row_factory = sqlite3.Row - return conn - -conn = get_db_connection() -conn.execute("UPDATE users SET " + changewhat + " = ?" - " WHERE id = ?", - (str(towhat), userid)) -conn.commit() -conn.close() - +#!/usr/bin/python3 +import sqlite3 +import os + +userid = input("Insert ID: ") +changewhat = input("Change what value?: ") +towhat = input("What should " + changewhat + " be changed to?: ") + +def get_db_connection(): + conn = sqlite3.connect("database.db") + conn.row_factory = sqlite3.Row + return conn + +conn = get_db_connection() +conn.execute("UPDATE users SET " + changewhat + " = ?" + " WHERE id = ?", + (str(towhat), userid)) +conn.commit() +conn.close() + print("Success!") \ No newline at end of file diff --git a/init_db b/init_db index eac9ac6..be00da1 100644 --- a/init_db +++ b/init_db @@ -1,29 +1,29 @@ -#!/usr/bin/python3 -import sqlite3 -import os - -def generatedb(): - connection = sqlite3.connect("database.db") - - with open("schema.sql") as f: - connection.executescript(f.read()) - - cur = connection.cursor() - - connection.commit() - connection.close() - - print("[INFO] Generated database") - -if not os.path.exists("database.db"): - generatedb() -else: - answer = input("Proceeding will overwrite the database. Proceed? (y/N)") - if "y" in answer.lower(): - generatedb() - elif "n" in answer.lower(): - print("Stopped") - elif ":3" in answer: - print(":3") - else: +#!/usr/bin/python3 +import sqlite3 +import os + +def generatedb(): + connection = sqlite3.connect("database.db") + + with open("schema.sql") as f: + connection.executescript(f.read()) + + cur = connection.cursor() + + connection.commit() + connection.close() + + print("[INFO] Generated database") + +if not os.path.exists("database.db"): + generatedb() +else: + answer = input("Proceeding will overwrite the database. Proceed? (y/N)") + if "y" in answer.lower(): + generatedb() + elif "n" in answer.lower(): + print("Stopped") + elif ":3" in answer: + print(":3") + else: print("Stopped") \ No newline at end of file diff --git a/main b/main index 2616d05..0f3b39b 100644 --- a/main +++ b/main @@ -1,317 +1,367 @@ -#!/usr/bin/python3 -import os -import configparser -import sqlite3 -import json -import secrets -from werkzeug.utils import secure_filename -from werkzeug.security import generate_password_hash, check_password_hash -from flask import Flask, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request - -# read config file -config = configparser.ConfigParser() -config.read("config.ini") - -HOST = config["config"]["HOST"] -PORT = config["config"]["PORT"] -SECRET_KEY = config["config"]["SECRET_KEY"] -UPLOAD_FOLDER = config["config"]["UPLOAD_FOLDER"] -UPLOAD_LIMIT = config["config"]["UPLOAD_LIMIT"] -PASSWORD_REQUIREMENT = config["config"]["PASSWORD_REQUIREMENT"] - -app = Flask(__name__) -app.config["SECRET_KEY"] = SECRET_KEY -app.config["MAX_CONTENT_LENGTH"] = int(UPLOAD_LIMIT) * 1000 * 1000 - -if SECRET_KEY == "placeholder": - print("[WARNING] Secret key is not set") - -if not os.path.exists(UPLOAD_FOLDER): - print("[WARNING] Upload folder doesn't exist, creating one") - os.mkdir(UPLOAD_FOLDER) - -if not os.path.exists("database.db"): - print("[ERROR] No database exists, please run init_db") - exit() - - -def makeStrSafe(url): - return str(urllib.parse.quote(url)).replace("%20", " ") - - -def get_db_connection(): - conn = sqlite3.connect("database.db") - conn.row_factory = sqlite3.Row - return conn - - -def get_user(id): - conn = get_db_connection() - post = conn.execute("SELECT * FROM users WHERE id = ?", - (id,)).fetchone() - conn.close() - if post is None: - return "error" - return post - - -def get_post(id): - conn = get_db_connection() - post = conn.execute("SELECT * FROM posts WHERE id = ?", - (id,)).fetchone() - conn.close() - if post is None: - return "error" - return post - - -app.jinja_env.globals.update(getUser=get_user) - - -def check_username_taken(username): - conn = get_db_connection() - post = conn.execute("SELECT * FROM users WHERE username = ?", - (username,)).fetchone() - conn.close() - if post is None: - return "error" - return post["id"] - - -def get_session(id): - conn = get_db_connection() - post = conn.execute("SELECT * FROM sessions WHERE session = ?", - (id,)).fetchone() - conn.close() - if post is None: - return "error" - return post - - -ALLOWED_EXTENSIONS = {"png", "apng", "jpg", "jpeg", "gif", "svg", "webp"} - - -def allowed_file(filename): - return '.' in filename and \ - filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS - - -@app.route("/", methods=("GET", "POST")) -def main(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - conn = get_db_connection() - posts = conn.execute( - "SELECT * FROM posts ORDER BY created DESC;").fetchall() - conn.close() - - if usersession: - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - return render_template("main.html", userdata=user, posts=posts) - else: - return render_template("main.html", posts=posts) - - -@app.route("/post", methods=("GET", "POST")) -def post(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - if request.method == "POST": - title = request.form["title"] - if title == "": - flash("Text required :3") - return redirect(request.url) - - if "file" not in request.files: - flash("No file selected :3") - return redirect(request.url) - - file = request.files["file"] - if file.filename == "": - flash("No file selected :3") - return redirect(request.url) - - if not allowed_file(file.filename): - flash("File is not an image!") - return redirect(request.url) - - filename = secure_filename(file.filename) - finalfilename = secrets.token_hex(64) + filename - - file.save(os.path.join(UPLOAD_FOLDER, finalfilename)) - imgurl = "/cdn/" + finalfilename - - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - - if not user["banned"] == "0": - flash("Your account has been banned. Reason: " + - user["banned"]) - return redirect(request.url) - - print(userCookie) - - conn = get_db_connection() - conn.execute("INSERT INTO posts (textstr, imageurl, creator) VALUES (?, ?, ?)", - (title, imgurl, userCookie["id"])) - conn.commit() - conn.close() - return redirect("/") - - else: - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - return render_template("post.html", userdata=user) - else: - flash("A burgercat account is required to post :3") - return redirect("/login") - - -@app.route("/cdn/", methods=("GET", "POST")) -def cdn(filename): - if os.path.exists(os.path.join(UPLOAD_FOLDER, filename)): - return send_from_directory(UPLOAD_FOLDER, filename) - else: - return "file doesn't exist!!" - - -@app.route("/signup", methods=("GET", "POST")) -def signup(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - return redirect("/") - if request.method == "POST": - if not check_username_taken(request.form["username"]) == "error": - flash("Username already taken :3") - return redirect(request.url) - - if not request.form["username"].isalnum(): - flash("Username must be alphanumeric :3") - return redirect(request.url) - - if not len(request.form["password"]) > int(PASSWORD_REQUIREMENT): - flash("Password must contain at least " + PASSWORD_REQUIREMENT + " characters") - return redirect(request.url) - - hashedpassword = generate_password_hash(request.form["password"]) - - conn = get_db_connection() - conn.execute("INSERT INTO users (username, password) VALUES (?, ?)", - (request.form["username"], hashedpassword)) - conn.commit() - conn.close() - - return redirect("/login") - else: - return render_template("signup.html") - - -@app.route("/login", methods=("GET", "POST")) -def login(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - return redirect("/") - if request.method == "POST": - userID = check_username_taken(request.form["username"]) - user = get_user(userID) - - if user == "error": - flash("Wrong username or password :3") - return redirect(request.url) - - if not check_password_hash(user["password"], (request.form["password"])): - flash("Wrong username or password :3") - return redirect(request.url) - - randomCharacters = secrets.token_hex(512) - - conn = get_db_connection() - conn.execute("INSERT INTO sessions (session, id) VALUES (?, ?)", - (randomCharacters, userID)) - conn.commit() - conn.close() - - resp = make_response(redirect("/")) - resp.set_cookie("session_DO_NOT_SHARE", randomCharacters) - - return resp - else: - return render_template("login.html") - - -@app.route("/settings", methods=("GET", "POST")) -def settings(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - - return render_template("settings.html", userdata=user) - else: - return redirect("/") - - -@app.route("/remove/", methods=("GET", "POST")) -def remove(postid): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - if str(user["administrator"]) == "1": - post = get_post(postid) - conn = get_db_connection() - conn.execute("DELETE FROM posts WHERE id = ?", (postid,)) - conn.commit() - conn.close() - return "Deleted post!" - else: - return "nice try" - else: - return redirect("/login") - -@app.route("/listusers", methods=("GET", "POST")) -def listusers(): - usersession = request.cookies.get("session_DO_NOT_SHARE") - if usersession: - userCookie = get_session(usersession) - user = get_user(userCookie["id"]) - if str(user["administrator"]) == "1": - thing = "" - - conn = get_db_connection() - users = conn.execute("SELECT * FROM users").fetchall() - conn.close() - for x in users: - thing = str(x["id"]) + " - " + x["username"] + "
" + thing - - return thing - else: - return "nice try" - else: - return redirect("/login") - - -@app.route("/settings/logout", methods=("GET", "POST")) -def logout(): - resp = redirect("/") - session = request.cookies.get("session_DO_NOT_SHARE") - resp.delete_cookie("session_DO_NOT_SHARE") - - return resp - - -@app.errorhandler(413) -def page_not_found(e): - return "the server decided to commit die" - - -@app.errorhandler(413) -def page_not_found(e): - return "Images can't be larger than 4MB" - - -if __name__ == "__main__": - from waitress import serve - print("[INFO] Server started") - serve(app, host=HOST, port=PORT) - print("[INFO] Server stopped") +#!/usr/bin/python3 +import os +import configparser +import sqlite3 +import time +import json +import secrets +from itertools import groupby +from werkzeug.utils import secure_filename +from werkzeug.security import generate_password_hash, check_password_hash +from flask import Flask, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request + +# read config file +config = configparser.ConfigParser() +config.read("config.ini") + +HOST = config["config"]["HOST"] +PORT = config["config"]["PORT"] +SECRET_KEY = config["config"]["SECRET_KEY"] +UPLOAD_FOLDER = config["config"]["UPLOAD_FOLDER"] +UPLOAD_LIMIT = config["config"]["UPLOAD_LIMIT"] +PASSWORD_REQUIREMENT = config["config"]["PASSWORD_REQUIREMENT"] + +app = Flask(__name__) +app.config["SECRET_KEY"] = SECRET_KEY +app.config["MAX_CONTENT_LENGTH"] = int(UPLOAD_LIMIT) * 1000 * 1000 + +if SECRET_KEY == "placeholder": + print("[WARNING] Secret key is not set") + +if not os.path.exists(UPLOAD_FOLDER): + print("[WARNING] Upload folder doesn't exist, creating") + os.mkdir(UPLOAD_FOLDER) + +if not os.path.exists("database.db"): + print("[ERROR] No database exists, please run init_db") + exit() + + +def makeStrSafe(url): + return str(urllib.parse.quote(url)).replace("%20", " ") + + +def get_db_connection(): + conn = sqlite3.connect("database.db") + conn.row_factory = sqlite3.Row + return conn + + +def get_user(id): + conn = get_db_connection() + post = conn.execute("SELECT * FROM users WHERE id = ?", + (id,)).fetchone() + conn.close() + if post is None: + return "error" + return post + + +def get_comments(id): + conn = get_db_connection() + post = conn.execute("SELECT * FROM comments WHERE post_id = ?", + (id,)).fetchall() + conn.close() + if post is None: + return "error" + return post + + +app.jinja_env.globals.update(getComments=get_comments) + +def get_post(id): + conn = get_db_connection() + post = conn.execute("SELECT * FROM posts WHERE id = ?", + (id,)).fetchone() + conn.close() + if post is None: + return "error" + return post + + +app.jinja_env.globals.update(getUser=get_user) + + +def check_username_taken(username): + conn = get_db_connection() + post = conn.execute("SELECT * FROM users WHERE username = ?", + (username,)).fetchone() + conn.close() + if post is None: + return "error" + return post["id"] + + +def get_session(id): + conn = get_db_connection() + post = conn.execute("SELECT * FROM sessions WHERE session = ?", + (id,)).fetchone() + conn.close() + if post is None: + return "error" + return post + + +ALLOWED_EXTENSIONS = {"png", "apng", "jpg", "jpeg", "gif", "svg", "webp"} + + +def allowed_file(filename): + return '.' in filename and \ + filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + + +@app.route("/", methods=("GET", "POST")) +def main(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + conn = get_db_connection() + posts = conn.execute("SELECT * FROM posts ORDER BY created DESC;").fetchall() + conn.close() + + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + return render_template("main.html", userdata=user, posts=posts) + else: + return render_template("main.html", posts=posts) + +@app.route("/post", methods=("GET", "POST")) +def post(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + if request.method == "POST": + title = request.form["title"] + if title == "": + flash("Text required :3") + return redirect(url_for("post")) + + if "file" not in request.files: + flash("No file selected :3") + return redirect(url_for("post")) + + file = request.files["file"] + if file.filename == "": + flash("No file selected :3") + return redirect(url_for("post")) + + if not allowed_file(file.filename): + flash("File is not an image!") + return redirect(url_for("post")) + + filename = secure_filename(file.filename) + finalfilename = secrets.token_hex(64) + filename + + file.save(os.path.join(UPLOAD_FOLDER, finalfilename)) + imgurl = "/cdn/" + finalfilename + + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + + if not user["banned"] == "0": + flash("Your account has been banned. Reason: " + + user["banned"]) + return redirect(url_for("post")) + + conn = get_db_connection() + conn.execute("INSERT INTO posts (textstr, imageurl, creator, created) VALUES (?, ?, ?, ?)", + (title, imgurl, userCookie["id"], str(time.time()))) + conn.commit() + conn.close() + return redirect(url_for("main")) + + else: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + return render_template("post.html", userdata=user) + else: + flash("A burgercat account is required to post :3") + return redirect(url_for("login")) + + +@app.route("/comment", methods=("GET", "POST")) +def comment(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + if request.method == "POST": + + data = request.get_json() + uid = data["id"] + title = data["title"] + + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + + if not user["banned"] == "0": + flash("Your account has been banned. Reason: " + + user["banned"]) + return redirect(url_for("comment")) + + conn = get_db_connection() + conn.execute("INSERT INTO comments (textstr, post_id, creator, created) VALUES (?, ?, ?, ?)", + (title, uid, userCookie["id"], str(time.time()))) + conn.commit() + conn.close() + + return "success" + + else: + return """""", 400 + else: + flash("A burgercat account is required to post :3") + return redirect(url_for("login")) + + +@app.route("/cdn/", methods=("GET", "POST")) +def cdn(filename): + if os.path.exists(os.path.join(UPLOAD_FOLDER, filename)): + return send_from_directory(UPLOAD_FOLDER, filename) + else: + return "file doesn't exist!!" + + +@app.route("/signup", methods=("GET", "POST")) +def signup(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + return redirect(url_for("main")) + if request.method == "POST": + if not check_username_taken(request.form["username"]) == "error": + flash("Username already taken :3") + return redirect(url_for("signup")) + + if not request.form["username"].isalnum(): + flash("Username must be alphanumeric :3") + return redirect(url_for("signup")) + + if not len(request.form["password"]) > int(PASSWORD_REQUIREMENT): + flash("Password must contain at least " + PASSWORD_REQUIREMENT + " characters") + return redirect(url_for("signup")) + + hashedpassword = generate_password_hash(request.form["password"]) + + conn = get_db_connection() + conn.execute("INSERT INTO users (username, password, created) VALUES (?, ?, ?)", + (request.form["username"], hashedpassword, str(time.time()))) + conn.commit() + conn.close() + + return redirect(url_for("login")) + else: + return render_template("signup.html") + + +@app.route("/login", methods=("GET", "POST")) +def login(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + redirect(url_for("main")) + if request.method == "POST": + userID = check_username_taken(request.form["username"]) + user = get_user(userID) + + if user == "error": + flash("Wrong username or password :3") + return redirect(url_for("login")) + + if not check_password_hash(user["password"], (request.form["password"])): + flash("Wrong username or password :3") + return redirect(url_for("login")) + + randomCharacters = secrets.token_hex(512) + + conn = get_db_connection() + conn.execute("INSERT INTO sessions (session, id) VALUES (?, ?)", + (randomCharacters, userID)) + conn.commit() + conn.close() + + resp = make_response(redirect("/")) + resp.set_cookie("session_DO_NOT_SHARE", randomCharacters) + + return resp + else: + return render_template("login.html") + + +@app.route("/settings", methods=("GET", "POST")) +def settings(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + + return render_template("settings.html", userdata=user) + else: + return redirect("/") + + +@app.route("/remove/", methods=("GET", "POST")) +def remove(postid): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + if str(user["administrator"]) == "1": + post = get_post(postid) + conn = get_db_connection() + conn.execute("DELETE FROM posts WHERE id = ?", (postid,)) + conn.commit() + conn.close() + return "Deleted post!" + else: + return "nice try" + else: + return redirect(url_for("login")) + +@app.route("/listusers", methods=("GET", "POST")) +def listusers(): + usersession = request.cookies.get("session_DO_NOT_SHARE") + if usersession: + userCookie = get_session(usersession) + user = get_user(userCookie["id"]) + if str(user["administrator"]) == "1": + thing = "" + + conn = get_db_connection() + users = conn.execute("SELECT * FROM users").fetchall() + conn.close() + for x in users: + thing = str(x["id"]) + " - " + x["username"] + "
" + thing + + return thing + else: + return """""" + else: + return redirect(url_for("login")) + + +@app.route("/settings/logout", methods=("GET", "POST")) +def logout(): + resp = redirect(url_for("main")) + session = request.cookies.get("session_DO_NOT_SHARE") + resp.delete_cookie("session_DO_NOT_SHARE") + + return resp + +@app.errorhandler(500) +def page_not_found(e): + return """""", 500 + +@app.errorhandler(400) +def page_not_found(e): + return """""", 400 + +@app.errorhandler(404) +def page_not_found(e): + return """""", 404 + +@app.errorhandler(413) +def page_not_found(e): + return "Images can't be larger than 4MB", 413 + + +if __name__ == "__main__": + from waitress import serve + print("[INFO] Server started") + serve(app, host=HOST, port=PORT) + #app.run(host=HOST, port=PORT, debug=True) + print("[INFO] Server stopped") diff --git a/readme.md b/readme.md deleted file mode 100644 index 9479a0a..0000000 --- a/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -burger social media - -self hosting: -- git clone https://codeberg.org/burger-software/burgercat -- cd burgercat -- python init_db -- python main \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 2f36f67..a7bab09 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -flask -werkzeug \ No newline at end of file +flask +werkzeug +waitress \ No newline at end of file diff --git a/schema.sql b/schema.sql index 366b1da..ba5e001 100644 --- a/schema.sql +++ b/schema.sql @@ -1,25 +1,34 @@ -DROP TABLE IF EXISTS users; -DROP TABLE IF EXISTS posts; -DROP TABLE IF EXISTS sessions; - -CREATE TABLE users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - username TEXT NOT NULL, - password TEXT NOT NULL, - banned TEXT NOT NULL DEFAULT 0, - administrator INTEGER NOT NULL DEFAULT 0 -); - -CREATE TABLE posts ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - creator TEXT NOT NULL, - imageurl TEXT NOT NULL, - textstr TEXT NOT NULL -); - -CREATE TABLE sessions ( - session TEXT PRIMARY KEY NOT NULL, - id INTEGER NOT NULL +DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS posts; +DROP TABLE IF EXISTS comments; +DROP TABLE IF EXISTS sessions; + +CREATE TABLE users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created TEXT NOT NULL, + username TEXT NOT NULL, + password TEXT NOT NULL, + banned TEXT NOT NULL DEFAULT 0, + administrator INTEGER NOT NULL DEFAULT 0 +); + +CREATE TABLE posts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + created TEXT NOT NULL, + creator TEXT NOT NULL, + imageurl TEXT NOT NULL, + textstr TEXT NOT NULL +); + +CREATE TABLE comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + post_id INTEGER NOT NULL, + created TEXT NOT NULL, + creator TEXT NOT NULL, + textstr TEXT NOT NULL +); + +CREATE TABLE sessions ( + session TEXT PRIMARY KEY NOT NULL, + id INTEGER NOT NULL ); \ No newline at end of file diff --git a/static/css/style.css b/static/css/style.css index 7ceb1bb..869b784 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1,94 +1,136 @@ -@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap"); - -body { - margin: 0; - font-family: "Inter", sans-serif; -} - -.navbar { - margin: 0; - padding: 10px; - border: solid; - border-color: grey; - border-width: 0; - border-bottom-width: 1px; - background-color: white; - width: 100%; - position: fixed; -} -.navbar .selected { - border: solid; - border-color: #f1b739; - border-width: 0; - border-bottom-width: 2px; -} - -.accountform { - margin-left: 20%; - margin-right: 20%; -} -.accountform input { - padding: 7px; - border: solid; - border-width: 1px; - border-color: grey; - width: calc(100% - 15px); - font-size: 16px; - border-radius: 8px; -} -.accountform .flash { - padding: 7px; - border: solid; - border-width: 1px; - border-color: #f1b739; - width: calc(100% - 15px); - font-size: 16px; - border-radius: 8px; -} -.accountform button { - padding: 7px; - border: solid; - border-width: 1px; - color: black; - border-color: grey; - background-color: white; - font-size: 16px; - width: 100%; - border-radius: 8px; -} - -.navbar a { - color: black; - text-decoration: none; -} - -.navbar .right { - float: right; - padding-right: 5px; -} - -.navbar .r { - padding-right: 15px; -} - -.post { - margin: 10px; - padding: 5px; - margin-bottom: 10px; - border-radius: 10px; - background-color: rgb(250, 250, 250); -} - -.post img { - min-height: 200px; - max-height: 300px; - border-radius: 10px; -} - -.post .username { - font-size: 18px; -} - -.post .date { - color: rgb(175, 175, 175); +@import url("https://fonts.googleapis.com/css2?family=Inter&display=swap"); + +body { + margin: 0; + font-family: "Inter", sans-serif; +} + +.navbar { + margin: 0; + padding: 10px; + border: solid; + border-color: grey; + border-width: 0; + border-bottom-width: 1px; + background-color: white; + width: 100%; + position: fixed; +} +.navbar .selected { + border: solid; + border-color: #f1b739; + border-width: 0; + border-bottom-width: 2px; +} +.postDiv { + padding-top: 120px; +} + +.accountform { + margin-left: 20%; + margin-right: 20%; +} +.accountform input { + padding: 7px; + border: solid; + border-width: 1px; + border-color: grey; + width: calc(100% - 15px); + font-size: 16px; + border-radius: 8px; +} +.accountform .flash { + padding: 7px; + border: solid; + border-width: 1px; + border-color: #f1b739; + width: calc(100% - 15px); + font-size: 16px; + border-radius: 8px; +} +.accountform button { + padding: 7px; + border: solid; + border-width: 1px; + color: black; + border-color: grey; + background-color: white; + font-size: 16px; + width: 100%; + border-radius: 8px; +} + +.navbar a { + color: black; + text-decoration: none; +} + +.navbar .right { + float: right; + padding-right: 5px; +} + +.navbar .r { + padding-right: 15px; +} + +.post { + margin: 10px; + padding: 5px; + margin-bottom: 10px; + border-radius: 10px; + background-color: rgb(250, 250, 250); +} + +.post img { + min-height: 200px; + max-height: 300px; + border-radius: 10px; +} + +.post button { + background-color: rgb(250, 250, 250); + border: solid; + border-color: rgb(197, 197, 197); + border-width: 1px; + border-radius: 6px; + font-size: 16px; + font-family: "Inter", sans-serif; +} +.post button:hover { + border-color: #f1b739; +} + +.post .commentdiv input { + background-color: rgb(250, 250, 250); + border: solid; + border-color: rgb(197, 197, 197); + border-width: 1px; + border-radius: 6px; + font-size: 16px; + margin-top: 5px; + font-family: "Inter", sans-serif; +} +.post hr { + color: rgb(255, 255, 255); + background-color: rgb(255, 255, 255); + border-color: rgb(255, 255, 255); +} +.post .commentsdiv { + background-color: #f5f5f5; + padding: 5px; + border-radius: 10px; + margin-bottom: 5px; +} + +.post .username { + font-size: 18px; +} + +.post .date { + color: rgb(175, 175, 175); +} + +.hidden { + display: none; } \ No newline at end of file diff --git a/static/js/main.js b/static/js/main.js new file mode 100644 index 0000000..b16b31f --- /dev/null +++ b/static/js/main.js @@ -0,0 +1,38 @@ +const posts = document.getElementsByClassName("post") +for (let i = 0; i < posts.length; i++) { + let post = posts[i] + let commentButton = post.children["commentButton"] + let commentId = post.children["commentId"] + let commentDiv = post.children["commentDiv"] + let commentBox = commentDiv.children["commentBox"] + let commentSave = commentDiv.children["commentDivSave"] + let commentCancel = commentDiv.children["commentDivCancel"] + + commentButton.addEventListener("click", (e) => { + commentDiv.classList.remove("hidden") + commentBox.value = "" + }); + commentCancel.addEventListener("click", (e) => { + commentDiv.classList.add("hidden") + }); + commentSave.addEventListener("click", (e) => { + console.log(commentId.innerHTML) + title = String(commentBox.value) + id = String(commentId.innerHTML) + + fetch("/comment", { + method: "POST", + body: JSON.stringify({ + id: id, + title: title, + }), + headers: { + "Content-Type": "application/json" + } + }) + .then((response) => response.json()) + .then((json) => console.log(json)); + + commentDiv.classList.add("hidden") + }); +} \ No newline at end of file diff --git a/templates/login.html b/templates/login.html index 0aa2860..6f5cf25 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,35 +1,35 @@ - - - - - burgercat - - - - - - - -
-
- back -

-

Log in to burgercat

- {% with messages = get_flashed_messages() %} - {% if messages %} - {% for message in messages %} -

{{ message }}

- {% endfor %} - {% endif %} - {% endwith %} - -

- -
-
- -

- Don't have an account? Sign up! -
- - + + + + + burgercat + + + + + + + +
+
+ back +

+

Log in to burgercat

+ {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} +

{{ message }}

+ {% endfor %} + {% endif %} + {% endwith %} + +

+ +
+
+ +

+ Don't have an account? Sign up! +
+ + diff --git a/templates/main.html b/templates/main.html index dedd0dc..59b1f8c 100644 --- a/templates/main.html +++ b/templates/main.html @@ -1,45 +1,98 @@ - - - - - burgercat - - - - - - - - - -





- - {% for post in posts %} -
-

{{ getUser(post["creator"])["username"] }}

-

{{ post["created"] }}

- {% if userdata %} - {% if userdata.administrator == 1 %} - Remove post -

- {% endif %} - {% endif %} - -

{{ post["textstr"] }}

-
- {% endfor %} - - - + + + + + burgercat + + + + + + + + + + + +
+ {% for post in posts %} +
+

{{ getUser(post["creator"])["username"] }}

+

+ {% if userdata %} + {% if userdata.administrator == 1 %} + Remove post +

+ {% endif %} + {% endif %} + +

{{ post["textstr"] }}

+
+ {% for comment in getComments(post["id"]) %} +

{{ getUser(comment["creator"])["username"] }}: {{ comment.textstr }}

+ {% endfor %} +
+ + + + +
+ {% endfor %} +
+ + + + \ No newline at end of file diff --git a/templates/post.html b/templates/post.html index 7126194..20e1057 100644 --- a/templates/post.html +++ b/templates/post.html @@ -1,65 +1,63 @@ - - - - - burgercat - - - - - - - - - -





-
- {% with messages = get_flashed_messages() %} - {% if messages %} - {% for message in messages %} -

{{ message }}

- {% endfor %} - {% endif %} - {% endwith %} -
-

Post

-

Image

- -
-

Text

- -

- -
-
-
-
-

Rules

-
    -
  • Please do not spam
  • -
  • Treat everyone with respect, respect each others opinions
  • -
  • Posting NSFW content is strictly prohibited, doing so will get you an instant ban
  • -
  • Discussions regarding politics and related controversial topics are disallowed
  • -
  • Advertising is not allowed
  • -
  • Do not post links
  • -
  • Do not create alt-accounts to evade bans
  • -
    - In general, just be a good person. -
-
-
- - - + + + + + burgercat + + + + + + + + + +





+
+ {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} +

{{ message }}

+ {% endfor %} + {% endif %} + {% endwith %} +
+

Post

+

Image

+ +
+

Text

+ +

+ +
+
+
+
+

Rules

+
    +
  • Please do not spam
  • +
  • Treat everyone with respect, respect each others opinions
  • +
  • Posting NSFW content is strictly prohibited, doing so will get you an instant ban
  • +
  • Discussions regarding politics and related controversial topics are disallowed
  • +
  • Advertising is not allowed
  • +
  • Do not post links
  • +
  • Do not create alt-accounts to evade bans
  • +
+
+
+ + + \ No newline at end of file diff --git a/templates/settings.html b/templates/settings.html index de994f3..7bba1ea 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -1,39 +1,38 @@ - - - - - burgercat - - - - - - - - - -





-
- {% if userdata.administrator == 1 %} - Administrator

- {% endif %} - Logged in as {{ userdata.username }}
- Your user ID is {{ userdata.id }} -

- Log out -
- - - + + + + + burgercat + + + + + + + + + +






+
+ {% if userdata.administrator == 1 %} + Administrator

+ {% endif %} + Logged in as {{ userdata.username }} +

+ Log out +
+ + + \ No newline at end of file diff --git a/templates/signup.html b/templates/signup.html index 6834bb0..4f613be 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -1,35 +1,35 @@ - - - - - burgercat - - - - - - - -
-
- back -

-

Create a burgercat account

-

Create a burgercat acccount to create posts and more!

- {% with messages = get_flashed_messages() %} - {% if messages %} - {% for message in messages %} -

{{ message }}

- {% endfor %} - {% endif %} - {% endwith %} - -

- -

- -

- Already have an account? Log in! -
- - + + + + + burgercat + + + + + + + +
+
+ back +

+

Create a burgercat account

+

Create a burgercat acccount to create posts and more!

+ {% with messages = get_flashed_messages() %} + {% if messages %} + {% for message in messages %} +

{{ message }}

+ {% endfor %} + {% endif %} + {% endwith %} + +

+ +

+ +

+ Already have an account? Log in! +
+ +