added image support
This commit is contained in:
parent
96363c55b2
commit
2386d54c3d
|
@ -4,7 +4,7 @@ By popular demand, I'm building a better anonkun. It doesn't do much right now t
|
||||||
## Requirements
|
## Requirements
|
||||||
Python 3.6+
|
Python 3.6+
|
||||||
MariaDB 10.2+
|
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
|
## Install
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Simple file host using Flask.
|
A Flask-based questing platform.
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
|
@ -9,6 +9,7 @@ from flask import session
|
||||||
from flask_socketio import SocketIO, emit, join_room
|
from flask_socketio import SocketIO, emit, join_room
|
||||||
|
|
||||||
import database as db
|
import database as db
|
||||||
|
import tools
|
||||||
|
|
||||||
socketio = SocketIO()
|
socketio = SocketIO()
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ def message(data):
|
||||||
line = '<span class="greenText">' + line + '</span>'
|
line = '<span class="greenText">' + line + '</span>'
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
message = "<br />".join(lines)
|
message = "<br />".join(lines)
|
||||||
|
message = tools.handle_img(message)
|
||||||
data["message"] = message
|
data["message"] = message
|
||||||
|
|
||||||
db.log_chat_message(data)
|
db.log_chat_message(data)
|
||||||
|
@ -64,6 +66,7 @@ def new_post(data):
|
||||||
post = data["post"]
|
post = data["post"]
|
||||||
post = bleach.clean(post.strip())
|
post = bleach.clean(post.strip())
|
||||||
post = post.replace("\n", "<br />")
|
post = post.replace("\n", "<br />")
|
||||||
|
message = tools.handle_img(message)
|
||||||
data["post"] = [post]
|
data["post"] = [post]
|
||||||
db.insert_quest_post(room, post, int(time.time()))
|
db.insert_quest_post(room, post, int(time.time()))
|
||||||
|
|
||||||
|
@ -84,6 +87,7 @@ def update_post(data):
|
||||||
|
|
||||||
post = data["post"]
|
post = data["post"]
|
||||||
post = post.strip().replace("<br>", "<br />")
|
post = post.strip().replace("<br>", "<br />")
|
||||||
|
message = tools.handle_img(message)
|
||||||
data["post"] = post
|
data["post"] = post
|
||||||
|
|
||||||
post_id = data["post_id"]
|
post_id = data["post_id"]
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
img {
|
||||||
|
max-width:100%;
|
||||||
|
max-height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: initial;
|
display: initial;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -60,6 +65,11 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
width: 100%;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
#messageTextDiv {
|
#messageTextDiv {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
if ( document.readyState !== 'complete' ) return;
|
if ( document.readyState !== 'complete' ) return;
|
||||||
clearInterval( tid );
|
clearInterval( tid );
|
||||||
|
|
||||||
|
document.getElementById('chatWindow').scrollTop = document.getElementById('chatWindow').scrollHeight;
|
||||||
socket = io.connect('https://' + document.domain + ':' + location.port);
|
socket = io.connect('https://' + document.domain + ':' + location.port);
|
||||||
socket.on('connect', function() {
|
socket.on('connect', function() {
|
||||||
socket.emit('joined', {room: {{ room_id }}});
|
socket.emit('joined', {room: {{ room_id }}});
|
||||||
|
|
52
tools.py
Normal file
52
tools.py
Normal file
|
@ -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'<img src="/img/{fname}" alt="{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
|
13
views.py
13
views.py
|
@ -12,6 +12,7 @@ from flask import session, request, abort, redirect, url_for, render_template
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
|
|
||||||
import database as db
|
import database as db
|
||||||
|
import tools
|
||||||
|
|
||||||
views = Blueprint("views", __name__)
|
views = Blueprint("views", __name__)
|
||||||
|
|
||||||
|
@ -41,16 +42,6 @@ def login_required(url=None):
|
||||||
return actual_decorator
|
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/<path:quest_title>")
|
@views.route("/quest/<path:quest_title>")
|
||||||
def quest(quest_title):
|
def quest(quest_title):
|
||||||
"""
|
"""
|
||||||
|
@ -99,7 +90,7 @@ def create_quest():
|
||||||
canon_title = request.form.get("quest_title")
|
canon_title = request.form.get("quest_title")
|
||||||
quest_body = request.form.get("quest_body")
|
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 = bleach.clean(quest_body.strip())
|
||||||
quest_body = quest_body.replace("\n", "<br />")
|
quest_body = quest_body.replace("\n", "<br />")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user