added message ids, quoting, quotelink scrolling/previews
This commit is contained in:
parent
7f94b5d045
commit
f7627d5090
|
@ -90,16 +90,12 @@ def verify_username(username):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def log_chat_message(data):
|
def log_chat_message(message, date, room_id, user_id):
|
||||||
"""
|
"""
|
||||||
Logs chat messages into the database.
|
Logs chat messages into the database.
|
||||||
'data' should be a dict containing: message, date, room_id, name, and
|
'data' should be a dict containing: message, date, room_id, name, and
|
||||||
user_id (optional).
|
user_id (optional).
|
||||||
"""
|
"""
|
||||||
message = data["message"]
|
|
||||||
date = data["date"]
|
|
||||||
room_id = data["room"]
|
|
||||||
user_id = data.get("user_id")
|
|
||||||
_DB.execute(
|
_DB.execute(
|
||||||
"INSERT INTO `chat_messages` (" \
|
"INSERT INTO `chat_messages` (" \
|
||||||
+ "`message`, `room_id`, `date`, `name_id`) VALUES (" \
|
+ "`message`, `room_id`, `date`, `name_id`) VALUES (" \
|
||||||
|
|
37
events.py
37
events.py
|
@ -53,39 +53,52 @@ def message(data):
|
||||||
"""
|
"""
|
||||||
Sent by a client when the user entered a new message.
|
Sent by a client when the user entered a new message.
|
||||||
"""
|
"""
|
||||||
room = int(data["room"])
|
room = data["room"]
|
||||||
message = data["message"]
|
message = data["message"]
|
||||||
name = data["name"]
|
name = data["name"]
|
||||||
user_id = data.get("user_id")
|
user_id = data.get("user_id")
|
||||||
|
|
||||||
data = {}
|
|
||||||
date = int(time.time())
|
|
||||||
data["date"] = date
|
|
||||||
data["name"] = name
|
|
||||||
data["user_id"] = user_id
|
|
||||||
data["room"] = room
|
|
||||||
|
|
||||||
message = message.strip()
|
message = message.strip()
|
||||||
if not message:
|
if not message:
|
||||||
return
|
return
|
||||||
tags = ["b", "code", "i", "s"]
|
tags = ["b", "code", "i", "s"]
|
||||||
message = bleach.clean(message, tags=tags)
|
message = bleach.clean(message, tags=tags)
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
for line in message.splitlines():
|
for line in message.splitlines():
|
||||||
if line.startswith(">"):
|
if line.startswith(">") and not line.startswith(">>"):
|
||||||
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)
|
||||||
|
|
||||||
|
quotes = re.findall(r">>\d+", message)
|
||||||
|
for quote in quotes:
|
||||||
|
msg_id = quote.replace(">>", "")
|
||||||
|
msg = '<a class="quotelink" '
|
||||||
|
msg += 'href="javascript:scrollToMsg(\'' + msg_id + '\')" '
|
||||||
|
msg += 'onmousemove="showPreview(event, \'' + msg_id + '\')" '
|
||||||
|
msg += 'onmouseout="clearPreview()">' + quote + '</a>'
|
||||||
|
message = message.replace(quote, msg)
|
||||||
|
|
||||||
message = tools.handle_img(message)
|
message = tools.handle_img(message)
|
||||||
data["message"] = message
|
|
||||||
|
|
||||||
roll_msg = ""
|
roll_msg = ""
|
||||||
if message.startswith("/dice") or message.startswith("/roll"):
|
if message.startswith("/dice") or message.startswith("/roll"):
|
||||||
roll_msg = handle_dice(data)
|
roll_msg = handle_dice(data)
|
||||||
if roll_msg:
|
if roll_msg:
|
||||||
data["message"] += '<hr class="msgSrvHr" /><b>' + roll_msg + "</b>"
|
roll_msg += '<hr class="msgSrvHr" /><b>' + roll_msg + "</b>"
|
||||||
|
|
||||||
message_id = db.log_chat_message(data)
|
date = int(time.time())
|
||||||
|
message_id = db.log_chat_message(message, date, room, user_id)
|
||||||
|
if roll_msg:
|
||||||
|
message += roll_msg
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
data["date"] = date
|
||||||
|
data["name"] = name
|
||||||
|
data["user_id"] = user_id
|
||||||
|
data["message"] = message
|
||||||
|
data["message_id"] = message_id
|
||||||
emit("message", data, room=room)
|
emit("message", data, room=room)
|
||||||
|
|
||||||
if roll_msg:
|
if roll_msg:
|
||||||
|
|
|
@ -183,7 +183,7 @@ h3 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.messageContent {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,19 @@ h3 {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#preview {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
background: white;
|
||||||
|
word-wrap: break-word;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
.greenText {
|
.greenText {
|
||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quotelink {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,11 @@ var tid = setInterval( function () {
|
||||||
socket.emit('joined', {room: room_id});
|
socket.emit('joined', {room: room_id});
|
||||||
});
|
});
|
||||||
socket.on('message', function(data) {
|
socket.on('message', function(data) {
|
||||||
let msg_str = '<div class="messageHeader"><span class="messageName">' + data.name + '</span> ';
|
let msg_str = '<div id="msg-' + data.message_id + '" class="message">';
|
||||||
msg_str += '<span class="messageDate">' + strftime(data.date) + '</span></div>';
|
msg_str = '<div class="messageHeader"><span class="messageName">' + data.name + '</span> ';
|
||||||
msg_str += '<div class="message">' + data.message + '</div><hr>';
|
msg_str += '<span class="messageDate">' + strftime(data.date) + '</span> ';
|
||||||
|
msg_str += '<span class="messageID">No.<a href="javascript:quote(' + data.message_id + ')">' + data.message_id + '</a></span></div>';
|
||||||
|
msg_str += '<div class="messageContent">' + data.message + '</div></div><hr>';
|
||||||
|
|
||||||
let mbox = document.getElementById('chatWindow');
|
let mbox = document.getElementById('chatWindow');
|
||||||
mbox.innerHTML = mbox.innerHTML + msg_str;
|
mbox.innerHTML = mbox.innerHTML + msg_str;
|
||||||
|
@ -170,6 +172,33 @@ function submitWritein(post_id) {
|
||||||
if (!option_text) { return; }
|
if (!option_text) { return; }
|
||||||
socket.emit('write_in', {option_text: option_text, post_id: post_id, room: room_id});
|
socket.emit('write_in', {option_text: option_text, post_id: post_id, room: room_id});
|
||||||
}
|
}
|
||||||
|
function quote(message_id) {
|
||||||
|
let textbox = document.getElementById('messageTextArea');
|
||||||
|
textbox.value += '>>' + message_id + '\n';
|
||||||
|
textbox.focus();
|
||||||
|
}
|
||||||
|
function scrollToMsg(message_id) {
|
||||||
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
|
if (!elem) { return; }
|
||||||
|
elem.scrollIntoView();
|
||||||
|
}
|
||||||
|
function showPreview(event, message_id) {
|
||||||
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
|
if (!elem) { return; }
|
||||||
|
let preview = document.getElementById('preview');
|
||||||
|
preview.innerHTML = elem.innerHTML;
|
||||||
|
preview.style.display = '';
|
||||||
|
let x = event.clientX + 20 + 'px';
|
||||||
|
let y = event.clientY + 20 + 'px';
|
||||||
|
let maxWidth = window.innerWidth - event.clientX - 80 + 'px';
|
||||||
|
preview.style.top = y;
|
||||||
|
preview.style.left = x;
|
||||||
|
preview.style.maxWidth = maxWidth;
|
||||||
|
}
|
||||||
|
function clearPreview() {
|
||||||
|
document.getElementById('preview').innerHTML = '';
|
||||||
|
document.getElementById('preview').style.display = 'none';
|
||||||
|
}
|
||||||
function deactivate_post() {
|
function deactivate_post() {
|
||||||
let post = document.getElementsByClassName('active_post');
|
let post = document.getElementsByClassName('active_post');
|
||||||
if (post.length == 0) { return; }
|
if (post.length == 0) { return; }
|
||||||
|
|
|
@ -10,9 +10,11 @@ var tid = setInterval( function () {
|
||||||
socket.emit('joined', {room: room_id});
|
socket.emit('joined', {room: room_id});
|
||||||
});
|
});
|
||||||
socket.on('message', function(data) {
|
socket.on('message', function(data) {
|
||||||
let msg_str = '<div class="messageHeader"><span class="messageName">' + data.name + '</span> ';
|
let msg_str = '<div id="msg-' + data.message_id + '" class="message">';
|
||||||
msg_str += '<span class="messageDate">' + strftime(data.date) + '</span></div>';
|
msg_str = '<div class="messageHeader"><span class="messageName">' + data.name + '</span> ';
|
||||||
msg_str += '<div class="message">' + data.message + '</div><hr>';
|
msg_str += '<span class="messageDate">' + strftime(data.date) + '</span> ';
|
||||||
|
msg_str += '<span class="messageID">No.<a href="javascript:quote(' + data.message_id + ')">' + data.message_id + '</a></span></div>';
|
||||||
|
msg_str += '<div class="messageContent">' + data.message + '</div></div><hr>';
|
||||||
|
|
||||||
let mbox = document.getElementById('chatWindow');
|
let mbox = document.getElementById('chatWindow');
|
||||||
mbox.innerHTML = mbox.innerHTML + msg_str;
|
mbox.innerHTML = mbox.innerHTML + msg_str;
|
||||||
|
@ -156,6 +158,33 @@ function submitWritein(post_id) {
|
||||||
if (!option_text) { return; }
|
if (!option_text) { return; }
|
||||||
socket.emit('write_in', {option_text: option_text, post_id: post_id, room: room_id});
|
socket.emit('write_in', {option_text: option_text, post_id: post_id, room: room_id});
|
||||||
}
|
}
|
||||||
|
function quote(message_id) {
|
||||||
|
let textbox = document.getElementById('messageTextArea');
|
||||||
|
textbox.value += '>>' + message_id + '\n';
|
||||||
|
textbox.focus();
|
||||||
|
}
|
||||||
|
function scrollToMsg(message_id) {
|
||||||
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
|
if (!elem) { return; }
|
||||||
|
elem.scrollIntoView();
|
||||||
|
}
|
||||||
|
function showPreview(event, message_id) {
|
||||||
|
let elem = document.getElementById('msg-' + message_id);
|
||||||
|
if (!elem) { return; }
|
||||||
|
let preview = document.getElementById('preview');
|
||||||
|
preview.innerHTML = elem.innerHTML;
|
||||||
|
preview.style.display = '';
|
||||||
|
let x = event.clientX + 20 + 'px';
|
||||||
|
let y = event.clientY + 20 + 'px';
|
||||||
|
let maxWidth = window.innerWidth - event.clientX - 80 + 'px';
|
||||||
|
preview.style.top = y;
|
||||||
|
preview.style.left = x;
|
||||||
|
preview.style.maxWidth = maxWidth;
|
||||||
|
}
|
||||||
|
function clearPreview() {
|
||||||
|
document.getElementById('preview').innerHTML = '';
|
||||||
|
document.getElementById('preview').style.display = 'none';
|
||||||
|
}
|
||||||
function deactivate_post() {
|
function deactivate_post() {
|
||||||
let post = document.getElementsByClassName('active_post');
|
let post = document.getElementsByClassName('active_post');
|
||||||
if (post.length == 0) { return; }
|
if (post.length == 0) { return; }
|
||||||
|
|
|
@ -139,11 +139,13 @@
|
||||||
<div id="chatWindow">
|
<div id="chatWindow">
|
||||||
{% autoescape false %}
|
{% autoescape false %}
|
||||||
{% for message in messages %}
|
{% for message in messages %}
|
||||||
<div class="message">
|
<div id="msg-{{ message[0] }}" class="message">
|
||||||
<div class="messageHeader">
|
<div class="messageHeader">
|
||||||
<span class="messageName">Anonymous</span> <span class="messageDate">{{ message[3] | strftime }}</span>
|
<span class="messageName">Anonymous</span>
|
||||||
|
<span class="messageDate">{{ message[3] | strftime }}</span>
|
||||||
|
<span class="messageID">No.<a href="javascript:quote('{{ message[0] }}')">{{ message[0] }}</a></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="messageMessage">{{ message[4] }}</div>
|
<div class="messageContent">{{ message[4] }}</div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -152,4 +154,5 @@
|
||||||
<div id="messageTextDiv"><textarea id="messageTextArea"></textarea></div>
|
<div id="messageTextDiv"><textarea id="messageTextArea"></textarea></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="preview"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
29
todo
Normal file
29
todo
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
New Features:
|
||||||
|
Pages/appendixes
|
||||||
|
Live indicator/countdown
|
||||||
|
Notifications
|
||||||
|
Anonymous names
|
||||||
|
Banner images
|
||||||
|
Search page
|
||||||
|
Front page to show new quests
|
||||||
|
Webm posting
|
||||||
|
(you) counter
|
||||||
|
Enable namefagging
|
||||||
|
Account managament/logout
|
||||||
|
Display profile link in header bar
|
||||||
|
Tagging system
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
Revamp post editing
|
||||||
|
More options for text posts (lists and so on)
|
||||||
|
More rigorous input checking in events.py
|
||||||
|
New post displays chat message
|
||||||
|
New chat message doesn't take chat window to the bottom if it was scrolled up
|
||||||
|
Record email on signup
|
||||||
|
Change urls
|
||||||
|
Poll vote highlights entire option
|
||||||
|
Poll vote doesn't disappear checkbox
|
||||||
|
Total voters per poll
|
||||||
|
Chat archives
|
||||||
|
Only last 100 (50?) chat messages are loaded on page load
|
||||||
|
Adjust quote preview postioning
|
Loading…
Reference in New Issue
Block a user