added file uploads and commented the config file a bit

This commit is contained in:
Your Name 2023-08-03 02:50:07 -05:00
parent 9c8bae6327
commit 611d41a8a8
18 changed files with 97 additions and 28 deletions

View file

@ -1 +1 @@
{"title": "aesdgd fgdfgsd fgdfdgdfhgsfsdfsdfsdhfjskjhfkjshfkjshjfkshfkhdfgjdhfjjkgsdhfkjghdfgjj hsfafsghjf gshdf gfhsghasf shafg aa aa a gdshjsha", "date": "08-01-2023-3", "importance": "a", "categories": ["a"], "description": "aeae", "author": "test", "editors": []}
{"title": "A Standard Post With A Standard Title And A Normal Stock Image Background", "date": "08-01-2023-3", "importance": "a", "categories": ["a"], "description": "aeae", "author": "test", "editors": []}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 372 KiB

View file

@ -0,0 +1 @@
{"title": "This is a test title for the gradient", "date": "08-02-2023-2", "importance": "a", "categories": ["a"], "description": "aaa", "author": "test", "editors": []}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 KiB

View file

@ -0,0 +1 @@
aaa

View file

@ -1,20 +1,21 @@
# This is just a simple python script that gets imported when the program starts, make sure to follow proper python syntax and dont delete any variables or youll fuck up the server
# This is just a simple python script that gets imported when the program starts, make sure to follow proper python syntax and dont delete or make any new variables or youll fuck up the server.
CONF_SITE_NAME = "Blogging Framework"
CONF_MAX_CATEGORIES_PER_POST = 10
CONF_MAX_CATEGORY_NAME_LENGTH = 20
CONF_MAX_TITLE_LENGTH = 800
CONF_MAX_IMPORTANCE_NAME_LENGTH = 15
CONF_MAX_DESCRIPTION_LENGTH = 200
CONF_SITE_NAME = "Blogging Framework" # set this to your site name, gets used in the page title and such
CONF_MAX_CATEGORIES_PER_POST = 10 # this and the following line are important to understand, having a long category length and high category count will increase the size of those categories on the page exponentially because they multiply eachother
CONF_MAX_CATEGORY_NAME_LENGTH = 20
CONF_MAX_TITLE_LENGTH = 80
CONF_MAX_IMPORTANCE_NAME_LENGTH = 15 # shouldnt be too long to prevent formatting issues
CONF_MAX_DESCRIPTION_LENGTH = 200 # shouldnt be too long to prevent formatting issues
CONF_STAY_LOGGED_IN_DURATION = 60 * 60 # 1 hour - resets on refresh
CONF_TOTAL_STAY_LOGGED_IN_DURATION = 60 * 60 * 24 * 3 # 3 days - if the user has been logged in for longer than this amount of time, they will be logged out no matter what unless keepalive keeps the user logged in
CONF_ENABLE_LOGIN_KEEPALIVE = True # login keepalive allows the max total stay logged in duration to be extended by 120 seconds every 110 seconds. this happens automatically on the post editor page to ensure a logout does not occur while a post is being edited before it can be saved
CONF_DEBUG_ENABLE = True
CONF_HOST = "127.0.0.1"
CONF_DEBUG_ENABLE = True # turn this on in production for free vbux, totally wont allow remote code execution on your server :)
CONF_HOST = "127.0.0.1" # if the unix socket is disabled the server will listen on this interface
CONF_USE_SOCKET = False
CONF_UNIX_SOCKET = "./socket.sock"
CONF_UNIX_SOCKET_PERMS = "777"
CONF_PORT = 8080
CONF_URL_PREFIX = ""
CONF_OG_IMG_FONT = "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BlackIt.otf"
CONF_OG_IMG_FONT_SIZE = 50
CONF_UNIX_SOCKET_PERMS = "777" # please restrict this, i have it set 777 for debugging and because im lazy, it should never be this in production
CONF_PORT = 8080 # port to listen on
CONF_URL_PREFIX = "" # if behind a reverse proxy at say example.com/blog, set this to "blog", otherwise leave it be
CONF_OG_IMG_FONT = "/usr/share/fonts/adobe-source-code-pro/SourceCodePro-BlackIt.otf" # path to the font for the og:image
CONF_OG_IMG_FONT_SIZE = 50 # font size for the og:image when text is overlaid on the banner image, if you have really long titles then make this smaller but otherwise just keep it as is
CONF_ALLOWED_FILETYPES = [".png", ".jpg", ".jpeg", ".pdf", ".zip", ".tar.gz"] # highly advise against adding executables, not really for user safety, but because inevitably some asshole will get them to run on the server

View file

@ -1 +1 @@
{"categories": {"announcements": ["07-31-2023-2", "07-31-2023-3"], "information": ["07-30-2023-1"], "service updates": [], "a": ["08-01-2023-3"]}, "urgencies": {"urgent": ["07-31-2023-0", "07-31-2023-2", "07-31-2023-3"], "important": [], "unimportant": ["07-30-2023-1"], "other_importanc": [], "a": ["08-01-2023-0", "08-01-2023-3"], "": []}, "featured": "08-01-2023-3"}
{"categories": {"announcements": ["07-31-2023-2", "07-31-2023-3"], "information": ["07-30-2023-1"], "service updates": [], "a": ["08-02-2023-2", "08-01-2023-3"]}, "urgencies": {"urgent": ["07-31-2023-0", "07-31-2023-2", "07-31-2023-3"], "important": [], "unimportant": ["07-30-2023-1"], "other_importanc": [], "a": ["08-01-2023-0", "08-02-2023-0", "08-02-2023-2", "08-01-2023-3"], "": []}, "featured": "08-02-2023-2"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1 @@
HOME.PNG

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

59
main.py
View file

@ -3,8 +3,8 @@
# use http://www.patorjk.com/software/taag to make labels
from flask import Flask, render_template, abort, send_from_directory, session, redirect, request, flash, make_response, url_for
from misc_functions import read_cached, get_post_content, get_post_info, limit_content_length, get_gradient_2d, get_gradient_3d, random_gradient, crop_scale_image, break_text
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
from misc_functions import read_cached, get_post_content, get_post_info, limit_content_length, get_gradient_2d, get_gradient_3d, random_gradient, crop_scale_image, break_text, random_word
from PIL import Image, ImageDraw, ImageFont, ImageEnhance, ImageFilter
import numpy as np
import json, hashlib, os, time, shutil, base64, random
@ -15,6 +15,8 @@ abspath = os.path.abspath(__file__)
dname = os.path.dirname(abspath)
os.chdir(dname)
PIL_SUPPORTED_FILETYPES = supported_extensions = {ex for ex, f in Image.registered_extensions().items() if f in Image.OPEN}
app = Flask(__name__)
@ -61,6 +63,12 @@ def viewpost(postname):
def serve_image(postname, imgname):
return send_from_directory("blogs", f"{postname}/images/{imgname}")
#
# OTHER FILE HANDLER
#
@app.route("/fileuploads/<container>/<filename>")
def serve_file(container, filename):
return send_from_directory("fileuploads", f"{container}/{filename}")
#
# PLAINTEXT VIEWER
#
@app.route("/posts/<postname>/plaintext", methods=["GET"])
@ -136,6 +144,33 @@ def admin(page=None, argument=None):
else:
abort(422)
#
# Image Upload Page
#
elif page == "fileupload":
if request.method == "GET":
return render_template("fileupload.html", filelinks = []) # dont worry, jijja2 automatically sanitises the stuff in imglinks
elif request.method == "POST":
file = request.files["file"]
if file == '':
abort(400)
fileext = os.path.splitext(file.filename)[1]
if fileext.lower() not in CONF_ALLOWED_FILETYPES:
abort(400)
filelinks = json.loads(request.form["filelinks"]) if request.form["filelinks"] else {}
used_names = os.listdir("fileuploads")
while True:
rand_name = random_word(25)
if rand_name not in used_names: break
os.makedirs(f"fileuploads/{rand_name}")
file.save(f"fileuploads/{rand_name}/file{fileext}")
with open(f"fileuploads/{rand_name}/name.txt", "w") as name: name.write(file.filename)
if fileext.lower() in PIL_SUPPORTED_FILETYPES:
thumbnail = Image.open(f"fileuploads/{rand_name}/file{fileext}")
thumbnail.thumbnail((256, 256))
thumbnail.save(f"fileuploads/{rand_name}/thumbnail.png")
filelinks[f"{rand_name}/file{fileext}"] = {"filename":file.filename, "thumbnail":f"{rand_name}/thumbnail.png"}
return render_template("fileupload.html", filelinks = filelinks, linksjson=json.dumps(filelinks))
#
# NEW POST OR EDIT POST
#
elif page in ["new", "edit"]:
@ -181,7 +216,7 @@ def admin(page=None, argument=None):
for category in db["categories"]: # remove the post from its category in the DB
try: db["categories"][category].pop(db["categories"][category].index(name))
except ValueError: pass
for urgency in db["urgencies"]: # remove the post from its category in the DB
for urgency in db["urgencies"]: # remove the post from its urgency in the DB
try: db["urgencies"][urgency].pop(db["urgencies"][urgency].index(name))
except ValueError: pass
@ -270,14 +305,18 @@ def admin(page=None, argument=None):
ogimg = False
if og:
ogimg = crop_scale_image(og.stream, 1200, 630)
elif page == "edit": # if we are editing, regenerate the og-image
if not banner:
banner_temp = f"blogs/{name}/images/banner.png"
else:
else:
if banner:
banner.seek(0)
banner_temp = banner.stream
ogimg = crop_scale_image(banner_temp, 1200, 630)
og_temp = banner.stream
elif os.path.exists(f"blogs/{name}/images/og-noedits.png"):
og_temp = f"blogs/{name}/images/og-noedits.png"
else: # this should only happen with the gradient banners
og_temp = f"blogs/{name}/images/banner.png"
ogimg = crop_scale_image(og_temp, 1200, 630)
ogimg.save(f"blogs/{name}/images/og-noedits.png")
ogimg = ImageEnhance.Brightness(ogimg).enhance(0.3)
ogimg = ogimg.filter(ImageFilter.GaussianBlur(radius=5))
draw = ImageDraw.Draw(ogimg)
font = ImageFont.truetype(CONF_OG_IMG_FONT, CONF_OG_IMG_FONT_SIZE)
text_broken = list(break_text(title, font, 1200))
@ -299,7 +338,7 @@ def admin(page=None, argument=None):
# TODO: make a cool page that shows confetti or something idk
return "Post made sucessfully!"
except: # deletes the post folder if something goes wrong, because an incomplete post folder causes errors
except SyntaxError: # deletes the post folder if something goes wrong, because an incomplete post folder causes errors
# the or is a failsafe because im paranoid that if name isnt made for some reason itll delete the entire directory
if page != "edit": shutil.rmtree(f"blogs/{name or 'SOMETHING HAS GONE TERRIBLY WRONG'}")
abort(500)

View file

@ -97,6 +97,7 @@ def random_gradient(width, height):
"""Generates a random gradient at the specified resolution"""
import numpy as np
from PIL import Image
import random
array = get_gradient_3d(width, height,\
(random.randint(0, 255),\
random.randint(0, 255),\
@ -116,9 +117,9 @@ def crop_scale_image(inputimg, width, height):
imgwidth, imgheight = img.size
if imgwidth / imgheight < width / height:
img = img.crop((0,\
(imgwidth-(imgwidth*(height/width)))/2,\
(imgheight-(imgwidth*(height/width)))/2,\
imgwidth,\
((imgwidth-(imgwidth*(height/width)))/2) + (imgwidth*(height/width))))
((imgheight-(imgwidth*(height/width)))/2) + (imgwidth*(height/width))))
elif imgwidth / imgheight > width / height:
img = img.crop(((imgwidth-(imgheight*(width/height)))/2,\
0,\
@ -182,3 +183,8 @@ def break_text(txt, font, max_width):
yield txttmp
txt = txt[subset+1:]
subset = 1
def random_word(length):
import random, string
letters = string.ascii_letters + string.digits + "-."
return ''.join(random.choice(letters) for i in range(length))

20
templates/fileupload.html Normal file
View file

@ -0,0 +1,20 @@
<script>
function copyText(link2copy) {
url = new URL(link2copy, document.baseURI).href;
navigator.clipboard.writeText(url).then(function() {
console.log('Async: Copying to clipboard was successful!');
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
return false;
}
</script>
{% for filename in filelinks %}
<a href="/fileuploads/{{filename}}" onclick="return copyText('/fileuploads/{{filename}}')"><img src="/fileuploads/{{filelinks[filename]['thumbnail']}}" alt="{{filelinks[filename]['filename']}}"></a><br>
{% endfor %}
<form method="POST" enctype="multipart/form-data">
<input type="hidden" value="{{linksjson}}" name="filelinks">
<input type="file" name="file">
<input type="submit">
</form>