add /admin/chat and dont store profile_url in chat dict

pull/90/head
Aevann 2023-01-20 06:10:25 +02:00
parent 1919fc822a
commit acc71d4cae
6 changed files with 69 additions and 56 deletions

View File

@ -32931,7 +32931,6 @@
themeColor, themeColor,
siteName, siteName,
nameColor, nameColor,
avatar,
hat hat
}, },
setContext setContext
@ -32943,7 +32942,6 @@
themeColor: "#ff66ac", themeColor: "#ff66ac",
siteName: "", siteName: "",
nameColor: "", nameColor: "",
avatar: "",
hat: "" hat: ""
}); });
(0, import_react13.useEffect)(() => { (0, import_react13.useEffect)(() => {
@ -32956,7 +32954,6 @@
themeColor: root2.dataset.themecolor, themeColor: root2.dataset.themecolor,
siteName: root2.dataset.sitename, siteName: root2.dataset.sitename,
nameColor: root2.dataset.namecolor, nameColor: root2.dataset.namecolor,
avatar: root2.dataset.avatar,
hat: root2.dataset.hat hat: root2.dataset.hat
}); });
}, []); }, []);
@ -32968,7 +32965,6 @@
themeColor, themeColor,
siteName, siteName,
nameColor, nameColor,
avatar,
hat hat
}; };
} }
@ -33014,7 +33010,7 @@
var DIRECT_MESSAGE_ID = "DIRECT_MESSAGE"; var DIRECT_MESSAGE_ID = "DIRECT_MESSAGE";
var OPTIMISTIC_MESSAGE_ID = "OPTIMISTIC"; var OPTIMISTIC_MESSAGE_ID = "OPTIMISTIC";
function ChatProvider({ children }) { function ChatProvider({ children }) {
const { username, id, siteName, hat, avatar, nameColor } = useRootContext(); const { username, id, siteName, hat, nameColor } = useRootContext();
const socket = (0, import_react15.useRef)(null); const socket = (0, import_react15.useRef)(null);
const [online, setOnline] = (0, import_react15.useState)([]); const [online, setOnline] = (0, import_react15.useState)([]);
const [typing, setTyping] = (0, import_react15.useState)([]); const [typing, setTyping] = (0, import_react15.useState)([]);
@ -33054,7 +33050,6 @@
id: DIRECT_MESSAGE_ID, id: DIRECT_MESSAGE_ID,
username, username,
user_id: id, user_id: id,
avatar,
hat, hat,
namecolor: nameColor, namecolor: nameColor,
text: directMessage, text: directMessage,
@ -33070,7 +33065,6 @@
id: OPTIMISTIC_MESSAGE_ID, id: OPTIMISTIC_MESSAGE_ID,
username, username,
user_id: id, user_id: id,
avatar,
hat, hat,
namecolor: nameColor, namecolor: nameColor,
text: draft, text: draft,
@ -33485,14 +33479,14 @@
// src/features/chat/Username.tsx // src/features/chat/Username.tsx
var import_react20 = __toESM(require_react()); var import_react20 = __toESM(require_react());
function Username({ avatar, color, name, hat = "" }) { function Username({ id, color, name, hat = "" }) {
return /* @__PURE__ */ import_react20.default.createElement("div", { return /* @__PURE__ */ import_react20.default.createElement("div", {
className: "Username" className: "Username"
}, /* @__PURE__ */ import_react20.default.createElement("div", { }, /* @__PURE__ */ import_react20.default.createElement("div", {
className: "profile-pic-20-wrapper" className: "profile-pic-20-wrapper"
}, /* @__PURE__ */ import_react20.default.createElement("img", { }, /* @__PURE__ */ import_react20.default.createElement("img", {
alt: name, alt: name,
src: avatar, src: `/pp/${id}`,
className: "pp20" className: "pp20"
}), hat && /* @__PURE__ */ import_react20.default.createElement("img", { }), hat && /* @__PURE__ */ import_react20.default.createElement("img", {
className: "avatar-hat profile-pic-20-hat hat", className: "avatar-hat profile-pic-20-hat hat",
@ -33559,7 +33553,6 @@
const { const {
id, id,
user_id, user_id,
avatar,
namecolor, namecolor,
username, username,
hat, hat,
@ -33676,10 +33669,10 @@
}, /* @__PURE__ */ import_react22.default.createElement("i", null, "X"), " Close")), showUser && /* @__PURE__ */ import_react22.default.createElement("div", { }, /* @__PURE__ */ import_react22.default.createElement("i", null, "X"), " Close")), showUser && /* @__PURE__ */ import_react22.default.createElement("div", {
className: "ChatMessage-top" className: "ChatMessage-top"
}, /* @__PURE__ */ import_react22.default.createElement(Username, { }, /* @__PURE__ */ import_react22.default.createElement(Username, {
avatar, id: user_id,
name: username, name: username,
color: namecolor, color: namecolor,
hat hat,
}), /* @__PURE__ */ import_react22.default.createElement("div", { }), /* @__PURE__ */ import_react22.default.createElement("div", {
className: "ChatMessage-timestamp" className: "ChatMessage-timestamp"
}, timestamp)), quotes && quotedMessage && /* @__PURE__ */ import_react22.default.createElement("div", { }, timestamp)), quotes && quotedMessage && /* @__PURE__ */ import_react22.default.createElement("div", {

View File

@ -2,7 +2,7 @@ import atexit
import time import time
import uuid import uuid
from flask_socketio import SocketIO, emit from flask_socketio import SocketIO, emit, join_room, leave_room
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
@ -28,12 +28,20 @@ else:
async_mode='gevent', async_mode='gevent',
) )
typing = [] typing = {
online = [] f'{SITE_FULL}/chat': [],
f'{SITE_FULL}/admin/chat': []
}
online = []
cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0) cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0)
muted = cache.get(f'{SITE}_muted') or {} muted = cache.get(f'muted') or {
messages = cache.get(f'{SITE}_chat') or [] f'{SITE_FULL}/chat': {},
total = cache.get(f'{SITE}_total') or 0 f'{SITE_FULL}/admin/chat': {}
}
messages = cache.get(f'messages') or {
f'{SITE_FULL}/chat': [],
f'{SITE_FULL}/admin/chat': []
}
socket_ids_to_user_ids = {} socket_ids_to_user_ids = {}
user_ids_to_socket_ids = {} user_ids_to_socket_ids = {}
@ -42,8 +50,12 @@ user_ids_to_socket_ids = {}
def chat(v): def chat(v):
if not v.admin_level and TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM: if not v.admin_level and TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM:
abort(403, f"Need at least {TRUESCORE_CHAT_MINIMUM} truescore for access to chat.") abort(403, f"Need at least {TRUESCORE_CHAT_MINIMUM} truescore for access to chat.")
return render_template("chat.html", v=v, messages=messages) return render_template("chat.html", v=v)
@app.get("/admin/chat")
@admin_level_required(2)
def admin_chat(v):
return render_template("chat.html", v=v)
@socketio.on('speak') @socketio.on('speak')
@limiter.limit("3/second;10/minute") @limiter.limit("3/second;10/minute")
@ -56,11 +68,11 @@ def speak(data, v):
return '', 403 return '', 403
vname = v.username.lower() vname = v.username.lower()
if vname in muted and not v.admin_level >= PERMS['CHAT_BYPASS_MUTE']: if vname in muted[request.referrer] and not v.admin_level >= PERMS['CHAT_BYPASS_MUTE']:
if time.time() < muted[vname]: return '', 403 if time.time() < muted[request.referrer][vname]: return '', 403
else: del muted[vname] else: del muted[request.referrer][vname]
global messages, total global messages
text = sanitize_raw_body(data['message'], False)[:CHAT_LENGTH_LIMIT] text = sanitize_raw_body(data['message'], False)[:CHAT_LENGTH_LIMIT]
if not text: return '', 400 if not text: return '', 400
@ -71,7 +83,6 @@ def speak(data, v):
data = { data = {
"id": str(uuid.uuid4()), "id": str(uuid.uuid4()),
"quotes": quotes, "quotes": quotes,
"avatar": v.profile_url,
"hat": v.hat_active(v)[0], "hat": v.hat_active(v)[0],
"user_id": v.id, "user_id": v.id,
"dm": bool(recipient and recipient != ""), "dm": bool(recipient and recipient != ""),
@ -91,50 +102,50 @@ def speak(data, v):
recipient_sid = user_ids_to_socket_ids[recipient] recipient_sid = user_ids_to_socket_ids[recipient]
emit('speak', data, broadcast=False, to=recipient_sid) emit('speak', data, broadcast=False, to=recipient_sid)
else: else:
emit('speak', data, broadcast=True) emit('speak', data, room=request.referrer, broadcast=True)
messages.append(data) messages[request.referrer].append(data)
messages = messages[-500:] messages[request.referrer] = messages[request.referrer][-500:]
total += 1
if v.admin_level >= PERMS['USER_BAN']: if v.admin_level >= PERMS['USER_BAN']:
text = text.lower() text = text.lower()
for i in mute_regex.finditer(text): for i in mute_regex.finditer(text):
username = i.group(1).lower() username = i.group(1).lower()
duration = int(int(i.group(2)) * 60 + time.time()) duration = int(int(i.group(2)) * 60 + time.time())
muted[username] = duration muted[request.referrer][username] = duration
typing = [] typing = []
# if SITE == 'rdrama.net': if request.referrer == f'{SITE_FULL}/admin/chat':
# title = f'New chat message from @{v.username}' title = f'New message in admin chat from @{v.username}'
# notifbody = text notifbody = text
# url = f'{SITE_FULL}/chat' url = f'{SITE_FULL}/admin/chat'
# admin_ids = [x[0] for x in g.db.query(User.id).filter( admin_ids = [x[0] for x in g.db.query(User.id).filter(
# User.id != v.id, User.id != v.id,
# User.admin_level >= PERMS['CHAT'], User.admin_level >= PERMS['CHAT'],
# ).all()] ).all()]
# push_notif(admin_ids, title, notifbody, url) push_notif(admin_ids, title, notifbody, url)
return '', 204 return '', 204
@socketio.on('connect') @socketio.on('connect')
@admin_level_required(PERMS['CHAT']) @admin_level_required(PERMS['CHAT'])
def connect(v): def connect(v):
join_room(request.referrer)
if v.username not in online: if v.username not in online:
online.append(v.username) online.append(v.username)
emit("online", online, broadcast=True) emit("online", online, room=request.referrer, broadcast=True)
cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0) cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0)
if not socket_ids_to_user_ids.get(request.sid): if not socket_ids_to_user_ids.get(request.sid):
socket_ids_to_user_ids[request.sid] = v.id socket_ids_to_user_ids[request.sid] = v.id
user_ids_to_socket_ids[v.id] = request.sid user_ids_to_socket_ids[v.id] = request.sid
emit('online', online) emit('online', online, room=request.referrer)
emit('catchup', messages) emit('catchup', messages[request.referrer], room=request.referrer)
emit('typing', typing) emit('typing', typing[request.referrer], room=request.referrer)
return '', 204 return '', 204
@socketio.on('disconnect') @socketio.on('disconnect')
@ -142,26 +153,31 @@ def connect(v):
def disconnect(v): def disconnect(v):
if v.username in online: if v.username in online:
online.remove(v.username) online.remove(v.username)
emit("online", online, broadcast=True) emit("online", online, room=request.referrer, broadcast=True)
cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0) cache.set(CHAT_ONLINE_CACHE_KEY, len(online), timeout=0)
if v.username in typing: typing.remove(v.username) if v.username in typing[request.referrer]:
typing[request.referrer].remove(v.username)
if socket_ids_to_user_ids.get(request.sid): if socket_ids_to_user_ids.get(request.sid):
del socket_ids_to_user_ids[request.sid] del socket_ids_to_user_ids[request.sid]
del user_ids_to_socket_ids[v.id] del user_ids_to_socket_ids[v.id]
emit('typing', typing, broadcast=True) emit('typing', typing[request.referrer], room=request.referrer, broadcast=True)
leave_room(request.referrer)
return '', 204 return '', 204
@socketio.on('typing') @socketio.on('typing')
@admin_level_required(PERMS['CHAT']) @admin_level_required(PERMS['CHAT'])
def typing_indicator(data, v): def typing_indicator(data, v):
if data and v.username not in typing: typing.append(v.username) if data and v.username not in typing[request.referrer]:
elif not data and v.username in typing: typing.remove(v.username) typing[request.referrer].append(v.username)
elif not data and v.username in typing[request.referrer]:
typing[request.referrer].remove(v.username)
emit('typing', typing, broadcast=True) emit('typing', typing[request.referrer], room=request.referrer, broadcast=True)
return '', 204 return '', 204
@ -171,15 +187,14 @@ def delete(text, v):
for message in messages: for message in messages:
if message['text'] == text: if message['text'] == text:
messages.remove(message) messages[request.referrer].remove(message)
emit('delete', text, broadcast=True) emit('delete', text, room=request.referrer, broadcast=True)
return '', 204 return '', 204
def close_running_threads(): def close_running_threads():
cache.set(f'{SITE}_chat', messages) cache.set(f'messages', messages)
cache.set(f'{SITE}_total', total) cache.set(f'muted', muted)
cache.set(f'{SITE}_muted', muted)
atexit.register(close_running_threads) atexit.register(close_running_threads)

View File

@ -116,6 +116,8 @@ def admin_level_required(x):
if v.admin_level < x: abort(403) if v.admin_level < x: abort(403)
if x and SITE != 'devrama.net' and not IS_LOCALHOST and not v.mfa_secret: if x and SITE != 'devrama.net' and not IS_LOCALHOST and not v.mfa_secret:
abort(403, "You need to enable 2FA to use admin features!") abort(403, "You need to enable 2FA to use admin features!")
if request.referrer == f'{SITE_FULL}/admin/chat' and v.admin_level < PERMS['CHAT']:
abort(403)
return make_response(f(*args, v=v, **kwargs)) return make_response(f(*args, v=v, **kwargs))
wrapper.__name__ = f.__name__ wrapper.__name__ = f.__name__

View File

@ -14,7 +14,6 @@
data-sitename="{{SITE_NAME}}" data-sitename="{{SITE_NAME}}"
data-themecolor="{{v.themecolor}}" data-themecolor="{{v.themecolor}}"
data-namecolor="{{v.namecolor}}" data-namecolor="{{v.namecolor}}"
data-avatar="{{v.profile_url}}"
data-hat="{{v.hat_active(v)[0]}}"> data-hat="{{v.hat_active(v)[0]}}">
</div> </div>
<script defer src="{{'js/chat.js' | asset}}"></script> <script defer src="{{'js/chat.js' | asset}}"></script>

View File

@ -134,7 +134,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if request.path == '/chat' %} {% if request.path.endswith('/chat') %}
<link rel="stylesheet" href="{{'css/chat_done.css' | asset}}"> <link rel="stylesheet" href="{{'css/chat_done.css' | asset}}">
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}

View File

@ -23,6 +23,10 @@ server {
proxy_pass http://localhost:5001/chat; proxy_pass http://localhost:5001/chat;
include includes/headers; include includes/headers;
} }
location /admin/chat {
proxy_pass http://localhost:5001/admin/chat;
include includes/headers;
}
location =/offline.html { location =/offline.html {
alias /rDrama/files/assets/offline.html; alias /rDrama/files/assets/offline.html;
include includes/headers; include includes/headers;