diff --git a/README.md b/README.md index 2f7fee2..d484197 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ burgercat: burger social media +now back again! + ### self hosting: this guide assumes you have git, python3, and redis installed on your server @@ -10,10 +12,6 @@ python init_db python main ``` -### zero downtime restarts: -- launch new burgercat server -- close previous server - ### contribution guidelines: - please check that your PR does not break anything - unless absolutely nessecary, avoid adding dependecies diff --git a/config.ini b/config.ini index ff3fe97..596f2a9 100644 --- a/config.ini +++ b/config.ini @@ -3,5 +3,4 @@ PORT = 8080 SECRET_KEY = placeholder UPLOAD_FOLDER = uploads PASSWORD_REQUIREMENT = 12 -UPLOAD_LIMIT = 4 -REDIS_URL = redis://localhost \ No newline at end of file +UPLOAD_LIMIT = 12 \ No newline at end of file diff --git a/hashpass.py b/hashpass.py new file mode 100644 index 0000000..d64f4fe --- /dev/null +++ b/hashpass.py @@ -0,0 +1,4 @@ +from werkzeug.security import generate_password_hash, check_password_hash + +passwordthing = input("insert pass: ") +print(generate_password_hash(passwordthing)) \ No newline at end of file diff --git a/main b/main index bd57b71..9ec863f 100644 --- a/main +++ b/main @@ -9,15 +9,13 @@ import datetime import socket import threading import subprocess +import asyncio +from hypercorn.config import Config +from hypercorn.asyncio import serve from itertools import groupby -from waitress import serve from werkzeug.utils import secure_filename from werkzeug.security import generate_password_hash, check_password_hash -from werkzeug.middleware.proxy_fix import ProxyFix -from flask import Flask, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request -from flask_limiter import Limiter -from flask_limiter.util import get_remote_address -from flask_sse import sse +from quart import Quart, render_template, request, url_for, flash, redirect, session, make_response, send_from_directory, stream_with_context, Response, request, jsonify, websocket from apscheduler.schedulers.background import BackgroundScheduler # read config file @@ -29,23 +27,10 @@ SECRET_KEY = config["config"]["SECRET_KEY"] UPLOAD_FOLDER = config["config"]["UPLOAD_FOLDER"] UPLOAD_LIMIT = config["config"]["UPLOAD_LIMIT"] PASSWORD_REQUIREMENT = config["config"]["PASSWORD_REQUIREMENT"] -REDIS_URL = config["config"]["REDIS_URL"] -app = Flask(__name__) +app = Quart(__name__) app.config["SECRET_KEY"] = SECRET_KEY -app.config["REDIS_URL"] = REDIS_URL app.config["MAX_CONTENT_LENGTH"] = int(UPLOAD_LIMIT) * 1000 * 1000 -app.register_blueprint(sse, url_prefix="/stream") - -app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1) - -limiter = Limiter( - get_remote_address, - app = app, - default_limits = ["3 per second"], - storage_uri = "memory://", - strategy = "fixed-window" -) if SECRET_KEY == "placeholder": print("[WARNING] Secret key is not set") @@ -136,15 +121,14 @@ def get_session(id): full_hash = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip() short_hash = subprocess.check_output(["git", "rev-parse", "--short=8", "HEAD"]).decode().strip() -ALLOWED_EXTENSIONS = {"png", "apng", "jpg", "jpeg", "gif", "svg", "webp"} +ALLOWED_EXTENSIONS = {"png", "apng", "jpg", "jpeg", "gif", "svg", "webp", "jxl"} def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS - @app.route("/", methods=("GET", "POST")) -def main(): +async 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() @@ -153,22 +137,22 @@ def main(): if usersession: userCookie = get_session(usersession) user = get_user(userCookie["id"]) - return render_template("main.html", userdata=user, posts=posts, full_hash=full_hash, short_hash=short_hash) + return await render_template("main.html", userdata=user, posts=posts, full_hash=full_hash, short_hash=short_hash) else: - return render_template("main.html", posts=posts, full_hash=full_hash, short_hash=short_hash) + return await render_template("main.html", posts=posts, full_hash=full_hash, short_hash=short_hash) @app.route("/chat", methods=("GET", "POST")) -def chat(): +async def chat(): usersession = request.cookies.get("session_DO_NOT_SHARE") if usersession: userCookie = get_session(usersession) user = get_user(userCookie["id"]) - return render_template("chat.html", userdata=user) + return await render_template("chat.html", userdata=user) else: - return render_template("chat.html") + return await render_template("chat.html") @app.route("/api/chat/listrooms") -def chatlistrooms(): +async def chatlistrooms(): conn = get_db_connection() rooms = conn.execute("SELECT * FROM chatrooms ORDER BY id ASC;").fetchall() conn.close() @@ -185,8 +169,7 @@ def chatlistrooms(): return(template), 200 @app.route("/api/chat/getmessages/") -@limiter.exempt -def chatget(roomid): +async def chatget(roomid): messages = get_messages(roomid, 150) template = [] @@ -209,13 +192,14 @@ def chatget(roomid): return(template), 200 + @app.route("/api/chat/send/", methods=("GET", "POST")) -def chatsend(roomid): +async def chatsend(roomid): usersession = request.cookies.get("session_DO_NOT_SHARE") if usersession: if request.method == "POST": - data = request.get_json() + data = await request.get_json() content = data["content"] userCookie = get_session(usersession) @@ -233,7 +217,7 @@ def chatsend(roomid): "created": str(time.time()) } - sse.publish({"message": chatMessageContent}, type="publish") + #message_queue.append({"message": chatMessageContent}) conn = get_db_connection() conn.execute("INSERT INTO chatmessages (content, chatroom_id, creator, created) VALUES (?, ?, ?, ?)", @@ -245,7 +229,7 @@ def chatsend(roomid): @app.route("/@", methods=("GET", "POST")) -def user(pageusername): +async def user(pageusername): usersession = request.cookies.get("session_DO_NOT_SHARE") checkusername = check_username_taken(pageusername) @@ -255,20 +239,20 @@ def user(pageusername): if usersession: userCookie = get_session(usersession) user = get_user(userCookie["id"]) - return render_template("user.html", userdata=user, createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) + return await render_template("user.html", userdata=user, createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) else: - return render_template("user.html", createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) + return await render_template("user.html", createddate=datetime.datetime.utcfromtimestamp(int(str(pageuser["created"]).split(".")[0])).strftime("%Y-%m-%d"), pageuser=pageuser) else: return """""", 404 @app.route("/api/page/", methods=("GET", "POST")) -def apipageuser(userid): +async def apipageuser(userid): pageuser = get_user(userid) addhtml = """ - """ + """ if not pageuser == "error": return addhtml + pageuser["htmldescription"] @@ -276,7 +260,7 @@ def apipageuser(userid): return """""", 404 @app.route("/@/edit", methods=("GET", "POST")) -def edituser(pageusername): +async def edituser(pageusername): usersession = request.cookies.get("session_DO_NOT_SHARE") checkusername = check_username_taken(pageusername) @@ -288,7 +272,9 @@ def edituser(pageusername): user = get_user(userCookie["id"]) if pageuser["username"] == user["username"]: if request.method == "POST": - code = request.form["code"].replace("Content-Security-Policy", "").replace("