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''
+ 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", "
")