From 2386d54c3d1d97aab55532854f49a9bd5edead64 Mon Sep 17 00:00:00 2001 From: iou1name Date: Mon, 25 Jun 2018 15:52:10 -0400 Subject: [PATCH] added image support --- README.md | 2 +- anonkun.py | 2 +- events.py | 4 ++++ static/anonkun.css | 10 +++++++++ templates/quest.html | 3 ++- tools.py | 52 ++++++++++++++++++++++++++++++++++++++++++++ views.py | 13 ++--------- 7 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 tools.py diff --git a/README.md b/README.md index 08591cf..4579c0f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ By popular demand, I'm building a better anonkun. It doesn't do much right now t ## Requirements Python 3.6+ MariaDB 10.2+ -Python packages: `flask flask_socketio flask-paranoid passlib argon2_cffi bleach flask-session` +Python packages: `flask flask_socketio flask-paranoid passlib argon2_cffi bleach flask-session requests python-magic` ## Install ``` diff --git a/anonkun.py b/anonkun.py index 5393bb0..43730fe 100644 --- a/anonkun.py +++ b/anonkun.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -Simple file host using Flask. +A Flask-based questing platform. """ import os import time diff --git a/events.py b/events.py index 30264dd..bdb5e09 100644 --- a/events.py +++ b/events.py @@ -9,6 +9,7 @@ from flask import session from flask_socketio import SocketIO, emit, join_room import database as db +import tools socketio = SocketIO() @@ -43,6 +44,7 @@ def message(data): line = '' + line + '' lines.append(line) message = "
".join(lines) + message = tools.handle_img(message) data["message"] = message db.log_chat_message(data) @@ -64,6 +66,7 @@ def new_post(data): post = data["post"] post = bleach.clean(post.strip()) post = post.replace("\n", "
") + message = tools.handle_img(message) data["post"] = [post] db.insert_quest_post(room, post, int(time.time())) @@ -84,6 +87,7 @@ def update_post(data): post = data["post"] post = post.strip().replace("
", "
") + message = tools.handle_img(message) data["post"] = post post_id = data["post_id"] diff --git a/static/anonkun.css b/static/anonkun.css index 19dc225..239944a 100644 --- a/static/anonkun.css +++ b/static/anonkun.css @@ -1,3 +1,8 @@ +img { + max-width:100%; + max-height:100%; +} + .header { display: initial; position: fixed; @@ -60,6 +65,11 @@ flex: 1; } +.message { + width: 100%; + word-wrap: break-word; +} + #messageTextDiv { padding-bottom: 10px; width: 100%; diff --git a/templates/quest.html b/templates/quest.html index 6cde408..772dbe0 100644 --- a/templates/quest.html +++ b/templates/quest.html @@ -8,7 +8,8 @@ var tid = setInterval( function () { if ( document.readyState !== 'complete' ) return; clearInterval( tid ); - + + document.getElementById('chatWindow').scrollTop = document.getElementById('chatWindow').scrollHeight; socket = io.connect('https://' + document.domain + ':' + location.port); socket.on('connect', function() { socket.emit('joined', {room: {{ room_id }}}); diff --git a/tools.py b/tools.py new file mode 100644 index 0000000..38d6b35 --- /dev/null +++ b/tools.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +""" +Miscellaneous tools and help functions. +""" +import os +import re +import hashlib + +import magic +import requests + +IMG_DIR = "/usr/local/www/html/img" + +def sanitize_title(canon_title): + """ + Sanitizes the given canonical title for a quest and returns a + url-friendly version. + """ + ident_title = canon_title.lower().replace(" ", "-") + ident_title = urllib.parse.quote(ident_title) + return ident_title + + +def handle_img(post): + """ + Handles [img] tags within a quest post appropriately. + """ + urls = re.findall(r"\[img\](.*?)\[/img\]", post) + for url in urls: + try: + res = requests.get(url) + res.raise_for_status() + mime = magic.from_buffer(res.content, mime=True) + assert mime in ["image/jpeg", "image/png","image/gif","video/webm"] + h = hashlib.sha256() + h.update(res.content) + fname = h.hexdigest() + fname += "." + mime.partition("/")[2] + with open(os.path.join(IMG_DIR, fname), "wb") as file: + for chunk in res.iter_content(100000): + file.write(chunk) + alt_text = os.path.basename(url) + img_tag = f'{alt_text}' + except requests.exceptions: + img_tag = "INVALID_IMG_URL" + except assertion: + img_tag = "INVALID_IMG_MIME_TYPE" + except: + img_tag = "UNKNOWN_ERROR" + + post = post.replace("[img]" + url + "[/img]", img_tag) + return post diff --git a/views.py b/views.py index 535e253..c8ce195 100644 --- a/views.py +++ b/views.py @@ -12,6 +12,7 @@ from flask import session, request, abort, redirect, url_for, render_template from flask import Blueprint import database as db +import tools views = Blueprint("views", __name__) @@ -41,16 +42,6 @@ def login_required(url=None): return actual_decorator -def sanitize_title(canon_title): - """ - Sanitizes the given canonical title for a quest and returns a - url-friendly version. - """ - ident_title = canon_title.lower().replace(" ", "-") - ident_title = urllib.parse.quote(ident_title) - return ident_title - - @views.route("/quest/") def quest(quest_title): """ @@ -99,7 +90,7 @@ def create_quest(): canon_title = request.form.get("quest_title") quest_body = request.form.get("quest_body") - ident_title = sanitize_title(canon_title) + ident_title = tools.sanitize_title(canon_title) quest_body = bleach.clean(quest_body.strip()) quest_body = quest_body.replace("\n", "
")