centralize chat logic

master
Aevann 2024-04-06 06:31:51 +02:00
parent c37a0de7db
commit 1a60e5a7a2
14 changed files with 212 additions and 359 deletions

View File

@ -206,7 +206,7 @@ ta.addEventListener("keydown", function(e) {
socket.on('online', function(data) { socket.on('online', function(data) {
const online_li = data[0] const online_li = data[0]
if (location.pathname.startsWith('/chat/')) { if (location.pathname != '/chat/1') {
for (const marker of document.getElementsByClassName('online-marker')) { for (const marker of document.getElementsByClassName('online-marker')) {
marker.classList.add('d-none') marker.classList.add('d-none')
} }

View File

@ -121,7 +121,7 @@ function postToastSwitch(t, url, button1, button2, cls, extraActionsOnSuccess) {
}); });
} }
if (!location.pathname.endsWith('/submit') && location.pathname != '/chat') if (!location.pathname.endsWith('/submit') && !location.pathname.startsWith('/chat/'))
{ {
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (!((e.ctrlKey || e.metaKey) && e.key === "Enter")) return; if (!((e.ctrlKey || e.metaKey) && e.key === "Enter")) return;
@ -401,7 +401,7 @@ if (is_pwa) {
} }
const gbrowser = document.getElementById('gbrowser').value const gbrowser = document.getElementById('gbrowser').value
if (!location.pathname.startsWith('/chat') && (gbrowser == 'iphone' || gbrowser == 'mac')) { if (!location.pathname.startsWith('/chat/') && (gbrowser == 'iphone' || gbrowser == 'mac')) {
const videos = document.querySelectorAll('video') const videos = document.querySelectorAll('video')
for (const video of videos) { for (const video of videos) {

View File

@ -4,7 +4,7 @@ function update_ghost_div_textarea(text)
{ {
let ghostdiv let ghostdiv
if (location.pathname.startsWith('/chat') ) if (location.pathname.startsWith('/chat/') )
ghostdiv = document.getElementById("ghostdiv-chat"); ghostdiv = document.getElementById("ghostdiv-chat");
else else
ghostdiv = text.parentNode.getElementsByClassName("ghostdiv")[0]; ghostdiv = text.parentNode.getElementsByClassName("ghostdiv")[0];

View File

@ -1,4 +1,3 @@
import atexit
import time import time
import uuid import uuid
from hashlib import md5 from hashlib import md5
@ -31,19 +30,10 @@ socketio = SocketIO(
) )
muted = cache.get(f'muted') or {} muted = cache.get(f'muted') or {}
online = {"messages": set()}
typing = {}
messages = cache.get(f'messages') or {} cache.set('loggedin_chat', 0, timeout=86400)
online = {
"chat": {},
"messages": set()
}
typing = {
"chat": []
}
cache.set('loggedin_chat', len(online["chat"]), timeout=86400)
def auth_required_socketio(f): def auth_required_socketio(f):
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
@ -61,162 +51,34 @@ def is_not_banned_socketio(f):
wrapper.__name__ = f.__name__ wrapper.__name__ = f.__name__
return wrapper return wrapper
def commit_and_close():
try: g.db.commit()
except: g.db.rollback()
g.db.close()
stdout.flush()
CHAT_ERROR_MESSAGE = f"To prevent spam, you'll need {TRUESCORE_MINIMUM} truescore (this is {TRUESCORE_MINIMUM} votes, either up or down, on any threads or comments you've made) in order to access chat. Sorry! I love you 💖" CHAT_ERROR_MESSAGE = f"To prevent spam, you'll need {TRUESCORE_MINIMUM} truescore (this is {TRUESCORE_MINIMUM} votes, either up or down, on any threads or comments you've made) in order to access chat. Sorry! I love you 💖"
@app.post('/refresh_chat') @app.post('/refresh_chat')
def refresh_chat(): def refresh_chat():
emit('refresh_chat', namespace='/', to="chat") emit('refresh_chat', namespace='/', to=f'{SITE_FULL}/chat/1')
return '' return ''
@app.get("/chat/")
def chat_redirect():
return redirect("/chat")
@app.get("/chat")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@auth_required
def chat(v):
if not v.allowed_in_chat:
abort(403, CHAT_ERROR_MESSAGE)
displayed_messages = {k: val for k, val in messages.items() if val["user_id"] not in v.userblocks}
orgy = get_running_orgy(v)
if orgy:
x = secrets.token_urlsafe(8)
orgies = g.db.query(Orgy).order_by(Orgy.start_utc).all()
return render_template("orgy.html", v=v, messages=displayed_messages, orgy=orgy, x=x, orgies=orgies)
return render_template("chat.html", v=v, messages=displayed_messages)
@socketio.on('speak') @socketio.on('speak')
@is_not_banned_socketio @is_not_banned_socketio
def speak(data, v): def speak(data, v):
if request.referrer.startswith(f'{SITE_FULL}/chat/'): chat_id = int(data['chat_id'])
chat_id = int(data['chat_id'])
chat = g.db.get(Chat, chat_id) chat = g.db.get(Chat, chat_id)
if not chat: if not chat:
abort(404, "Chat not found!") abort(404, "Chat not found!")
if chat.id == 1:
if not v.allowed_in_chat: return ''
else:
is_member = g.db.query(ChatMembership.user_id).filter_by(user_id=v.id, chat_id=chat_id).one_or_none() is_member = g.db.query(ChatMembership.user_id).filter_by(user_id=v.id, chat_id=chat_id).one_or_none()
if not is_member: return '' if not is_member: return ''
image = None
if data['file']:
name = f'/chat_images/{time.time()}'.replace('.','') + '.webp'
with open(name, 'wb') as f:
f.write(data['file'])
image = process_image(name, v)
text = data['message'].strip()[:CHAT_LENGTH_LIMIT]
if image: text += f'\n\n{image}'
if not text: return ''
text_html = sanitize(text, count_emojis=True, chat=True)
if isinstance(text_html , tuple): return ''
if v.shadowbanned or execute_blackjack(v, None, text, "chat"):
data = {
"id": secrets.token_urlsafe(5),
"quotes": data['quotes'],
"hat": v.hat_active(None)[0],
"user_id": v.id,
"username": v.username,
"namecolor": v.name_color,
"patron": v.patron,
"pride_username": bool(v.has_badge(303)),
"text": text,
"text_censored": censor_slurs_profanities(text, 'chat', True),
"text_html": text_html,
"text_html_censored": censor_slurs_profanities(text_html, 'chat'),
"created_utc": int(time.time()),
}
emit('speak', data)
return ''
execute_under_siege(v, None, text, "private chat")
quotes = data['quotes']
if quotes: quotes = int(quotes)
else: quotes = None
chat_message = ChatMessage(
user_id=v.id,
chat_id=chat_id,
quotes=quotes,
text=text,
text_censored=censor_slurs_profanities(text, 'chat', True),
text_html=text_html,
text_html_censored=censor_slurs_profanities(text_html, 'chat'),
)
g.db.add(chat_message)
g.db.flush()
if v.id == chat.owner_id:
for i in chat_adding_regex.finditer(text):
user = get_user(i.group(1), graceful=True, attributes=[User.id])
if user and not user.has_muted(v) and not user.has_blocked(v):
existing = g.db.query(ChatMembership.user_id).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
leave = g.db.query(ChatLeave.user_id).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
if not existing and not leave:
chat_membership = ChatMembership(
user_id=user.id,
chat_id=chat_id,
)
g.db.add(chat_membership)
g.db.flush()
for i in chat_kicking_regex.finditer(text):
user = get_user(i.group(1), graceful=True, attributes=[User.id])
if user:
existing = g.db.query(ChatMembership).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
if existing:
g.db.delete(existing)
g.db.flush()
alrdy_here = list(online[request.referrer].keys())
memberships = g.db.query(ChatMembership).filter(
ChatMembership.chat_id == chat_id,
ChatMembership.user_id.notin_(alrdy_here),
ChatMembership.notification == False,
)
for membership in memberships:
membership.notification = True
g.db.add(membership)
data = {
"id": chat_message.id,
"quotes": chat_message.quotes,
"hat": chat_message.hat,
"user_id": chat_message.user_id,
"username": chat_message.username,
"namecolor": chat_message.namecolor,
"patron": chat_message.patron,
"pride_username": chat_message.pride_username,
"text": chat_message.text,
"text_censored": chat_message.text_censored,
"text_html": chat_message.text_html,
"text_html_censored": chat_message.text_html_censored,
"created_utc": chat_message.created_utc,
}
emit('speak', data, room=request.referrer, broadcast=True)
try: g.db.commit()
except: g.db.rollback()
g.db.close()
stdout.flush()
typing[request.referrer] = []
return ''
if not v.allowed_in_chat: return ''
image = None image = None
if data['file']: if data['file']:
name = f'/chat_images/{time.time()}'.replace('.','') + '.webp' name = f'/chat_images/{time.time()}'.replace('.','') + '.webp'
@ -224,86 +86,123 @@ def speak(data, v):
f.write(data['file']) f.write(data['file'])
image = process_image(name, v) image = process_image(name, v)
global messages
text = data['message'].strip()[:CHAT_LENGTH_LIMIT] text = data['message'].strip()[:CHAT_LENGTH_LIMIT]
if image: text += f'\n\n{image}' if image: text += f'\n\n{image}'
if not text: return '' if not text: return ''
if chat.id == 1:
vname = v.username.lower()
if vname in muted:
if time.time() < muted[vname]:
return ''
else:
del muted[vname]
refresh_online(f'{SITE_FULL}/chat/1')
if v.admin_level >= PERMS['USER_BAN']:
text = text.lower()
for i in mute_regex.finditer(text):
username = i.group(1).lower()
muted_until = int(int(i.group(2)) * 60 + time.time())
muted[username] = muted_until
refresh_online(f'{SITE_FULL}/chat/1')
for i in unmute_regex.finditer(text):
username = i.group(1).lower()
muted.pop(username, None)
refresh_online(f'{SITE_FULL}/chat/1')
text_html = sanitize(text, count_emojis=True, chat=True) text_html = sanitize(text, count_emojis=True, chat=True)
if isinstance(text_html , tuple): return '' if isinstance(text_html , tuple): return ''
execute_under_siege(v, None, text, "chat") if v.shadowbanned or execute_blackjack(v, None, text, "chat"):
data = {
"id": secrets.token_urlsafe(5),
"quotes": data['quotes'],
"hat": v.hat_active(None)[0],
"user_id": v.id,
"username": v.username,
"namecolor": v.name_color,
"patron": v.patron,
"pride_username": bool(v.has_badge(303)),
"text": text,
"text_censored": censor_slurs_profanities(text, 'chat', True),
"text_html": text_html,
"text_html_censored": censor_slurs_profanities(text_html, 'chat'),
"created_utc": int(time.time()),
}
emit('speak', data)
return ''
execute_under_siege(v, None, text, "private chat")
quotes = data['quotes'] quotes = data['quotes']
id = secrets.token_urlsafe(5) if quotes: quotes = int(quotes)
else: quotes = None
self_only = False chat_message = ChatMessage(
user_id=v.id,
chat_id=chat_id,
quotes=quotes,
text=text,
text_censored=censor_slurs_profanities(text, 'chat', True),
text_html=text_html,
text_html_censored=censor_slurs_profanities(text_html, 'chat'),
)
g.db.add(chat_message)
g.db.flush()
vname = v.username.lower() if v.id == chat.owner_id:
if vname in muted: for i in chat_adding_regex.finditer(text):
if time.time() < muted[vname]: user = get_user(i.group(1), graceful=True, attributes=[User.id])
self_only = True if user and not user.has_muted(v) and not user.has_blocked(v):
else: existing = g.db.query(ChatMembership.user_id).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
del muted[vname] leave = g.db.query(ChatLeave.user_id).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
refresh_online("chat") if not existing and not leave:
chat_membership = ChatMembership(
user_id=user.id,
chat_id=chat_id,
)
g.db.add(chat_membership)
g.db.flush()
if SITE == 'rdrama.net' and v.admin_level < PERMS['BYPASS_ANTISPAM_CHECKS']: for i in chat_kicking_regex.finditer(text):
def shut_up(): user = get_user(i.group(1), graceful=True, attributes=[User.id])
self_only = True if user:
muted_until = int(time.time() + 600) existing = g.db.query(ChatMembership).filter_by(user_id=user.id, chat_id=chat_id).one_or_none()
muted[vname] = muted_until if existing:
refresh_online("chat") g.db.delete(existing)
g.db.flush()
if not self_only: alrdy_here = list(online[request.referrer].keys())
identical = [x for x in list(messages.values())[-5:] if v.id == x['user_id'] and text == x['text']] memberships = g.db.query(ChatMembership).filter(
if len(identical) >= 3: shut_up() ChatMembership.chat_id == chat_id,
ChatMembership.user_id.notin_(alrdy_here),
if not self_only: ChatMembership.notification == False,
count = len([x for x in list(messages.values())[-12:] if v.id == x['user_id']]) )
if count >= 10: shut_up() for membership in memberships:
membership.notification = True
if not self_only: g.db.add(membership)
count = len([x for x in list(messages.values())[-25:] if v.id == x['user_id']])
if count >= 20: shut_up()
data = { data = {
"id": id, "id": chat_message.id,
"quotes": quotes if messages.get(quotes) else '', "quotes": chat_message.quotes,
"hat": v.hat_active(None)[0], "hat": chat_message.hat,
"user_id": v.id, "user_id": chat_message.user_id,
"username": v.username, "username": chat_message.username,
"namecolor": v.name_color, "namecolor": chat_message.namecolor,
"patron": v.patron, "patron": chat_message.patron,
"pride_username": bool(v.has_badge(303)), "pride_username": chat_message.pride_username,
"text": text, "text": chat_message.text,
"text_censored": censor_slurs_profanities(text, 'chat', True), "text_censored": chat_message.text_censored,
"text_html": text_html, "text_html": chat_message.text_html,
"text_html_censored": censor_slurs_profanities(text_html, 'chat'), "text_html_censored": chat_message.text_html_censored,
"created_utc": int(time.time()), "created_utc": chat_message.created_utc,
} }
emit('speak', data, room=request.referrer, broadcast=True)
if v.admin_level >= PERMS['USER_BAN']: typing[request.referrer] = []
text = text.lower()
for i in mute_regex.finditer(text):
username = i.group(1).lower()
muted_until = int(int(i.group(2)) * 60 + time.time())
muted[username] = muted_until
refresh_online("chat")
for i in unmute_regex.finditer(text):
username = i.group(1).lower()
muted.pop(username, None)
refresh_online("chat")
if self_only or v.shadowbanned or execute_blackjack(v, None, text, "chat"): commit_and_close()
emit('speak', data)
else:
emit('speak', data, room="chat", broadcast=True)
messages[id] = data
messages = dict(list(messages.items())[-250:])
typing["chat"] = []
return '' return ''
@ -316,22 +215,20 @@ def refresh_online(room):
data = [list(online[room].values()), muted] data = [list(online[room].values()), muted]
emit("online", data, room=room, broadcast=True) emit("online", data, room=room, broadcast=True)
if room == "chat": if room == f'{SITE_FULL}/chat/1':
cache.set('loggedin_chat', len(online[room]), timeout=86400) cache.set('loggedin_chat', len(online[room]), timeout=86400)
@socketio.on('connect') @socketio.on('connect')
@auth_required_socketio @auth_required_socketio
def connect(v): def connect(v):
if request.referrer == f'{SITE_FULL}/notifications/messages': if not request.referrer: return
room = request.referrer
if room == f'{SITE_FULL}/notifications/messages':
join_room(v.id) join_room(v.id)
online["messages"].add(v.id) online["messages"].add(v.id)
return '' return ''
if request.referrer and request.referrer.startswith(f'{SITE_FULL}/chat/'):
room = request.referrer
else:
room = "chat"
join_room(room) join_room(room)
if not typing.get(room): if not typing.get(room):
@ -341,21 +238,22 @@ def connect(v):
typing[room].remove(v.username) typing[room].remove(v.username)
emit('typing', typing[room], room=room) emit('typing', typing[room], room=room)
commit_and_close()
return '' return ''
@socketio.on('disconnect') @socketio.on('disconnect')
@auth_required_socketio @auth_required_socketio
def disconnect(v): def disconnect(v):
if not request.referrer: return
room = request.referrer
if request.referrer == f'{SITE_FULL}/notifications/messages': if request.referrer == f'{SITE_FULL}/notifications/messages':
leave_room(v.id) leave_room(v.id)
online["messages"].remove(v.id) online["messages"].remove(v.id)
return '' return ''
if request.referrer and request.referrer.startswith(f'{SITE_FULL}/chat/'):
room = request.referrer
else:
room = "chat"
online[room].pop(v.id, None) online[room].pop(v.id, None)
if v.username in typing[room]: if v.username in typing[room]:
@ -364,15 +262,15 @@ def disconnect(v):
leave_room(room) leave_room(room)
refresh_online(room) refresh_online(room)
commit_and_close()
return '' return ''
@socketio.on('heartbeat') @socketio.on('heartbeat')
@auth_required_socketio @auth_required_socketio
def heartbeat(v): def heartbeat(v):
if request.referrer and request.referrer.startswith(f'{SITE_FULL}/chat/'): if not request.referrer: return
room = request.referrer room = request.referrer
else:
room = "chat"
if not online.get(room): if not online.get(room):
online[room] = {} online[room] = {}
@ -383,15 +281,15 @@ def heartbeat(v):
if not already_there: if not already_there:
refresh_online(room) refresh_online(room)
commit_and_close()
return '' return ''
@socketio.on('typing') @socketio.on('typing')
@is_not_banned_socketio @is_not_banned_socketio
def typing_indicator(data, v): def typing_indicator(data, v):
if request.referrer and request.referrer.startswith(f'{SITE_FULL}/chat/'): if not request.referrer: return
room = request.referrer room = request.referrer
else:
room = "chat"
if not typing.get(room): if not typing.get(room):
typing[room] = [] typing[room] = []
@ -402,23 +300,24 @@ def typing_indicator(data, v):
typing[room].remove(v.username) typing[room].remove(v.username)
emit('typing', typing[room], room=room, broadcast=True) emit('typing', typing[room], room=room, broadcast=True)
commit_and_close()
return '' return ''
@socketio.on('delete') @socketio.on('delete')
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def delete(id, v): def delete(id, v):
messages.pop(id, None) message = g.db.get(ChatMessage, id)
emit('delete', id, room="chat", broadcast=True) g.db.delete(message)
emit('delete', id, room=f'{SITE_FULL}/chat/1', broadcast=True)
commit_and_close()
return '' return ''
def close_running_threads():
cache.set('messages', messages, timeout=86400)
cache.set('muted', muted, timeout=86400)
atexit.register(close_running_threads)
@app.post("/reply") @app.post("/reply")
@limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID) @limiter.limit('1/second', scope=rpath, key_func=get_ID)

View File

@ -82,8 +82,6 @@ def selected_tab(request):
return 'comments' return 'comments'
elif request.path == '/casino': elif request.path == '/casino':
return 'casino' return 'casino'
elif request.path == '/chat':
return 'chat'
elif request.path.startswith('/shop/'): elif request.path.startswith('/shop/'):
return 'shop' return 'shop'

View File

@ -6,6 +6,11 @@ from files.helpers.get import *
from files.__main__ import app, limiter from files.__main__ import app, limiter
@app.get("/chat")
@app.get("/orgy")
def chat_redirect():
return redirect("/chat/1")
@app.post("/@<username>/chat") @app.post("/@<username>/chat")
@limiter.limit('1/second', scope=rpath) @limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID) @limiter.limit('1/second', scope=rpath, key_func=get_ID)

View File

@ -439,14 +439,6 @@ def transfers(v):
def donate(v): def donate(v):
return render_template(f'donate.html', v=v) return render_template(f'donate.html', v=v)
@app.get("/orgy")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@auth_required
def orgy(v):
return redirect("/chat")
@app.get("/sidebar_images") @app.get("/sidebar_images")
@app.get("/banners") @app.get("/banners")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400) @limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)

View File

@ -1,39 +0,0 @@
{%- extends 'root.html' -%}
{% block pagetitle -%}Chat{%- endblock %}
{% block pagetype %}chat{% endblock %}
{% block body_attributes %}class="has_header"{% endblock %}
{% block body %}
<link rel="stylesheet" href="{{'css/chat.css' | asset}}">
{% include "header.html" %}
{% include "modals/expanded_image.html" %}
{% include "modals/emoji.html" %}
{% include "modals/gif.html" %}
{% set vlink = '<a href="/id/' ~ v.id ~ '"' %}
<div class="container pb-4 pb-md-2">
<div class="row justify-content-around" id="main-content-row">
<div class="col h-100 {% block customPadding %}custom-gutters{% endblock %}" id="main-content-col">
<div id="chat-group-template" class="d-none">
{{macros.chat_group_template()}}
</div>
</div>
<div id="chat-line-template" class="d-none">
{{macros.chat_line_template()}}
</div>
{{macros.chat_window(vlink)}}
</div>
{{macros.chat_users_list()}}
</div>
<input id="vid" hidden value="{{v.id}}">
<input id="slurreplacer" hidden value="{{v.slurreplacer}}">
<input id="admin_level" hidden value="{{v.admin_level}}">
<input id="blocked_user_ids" hidden value="{{(v.userblocks|string)[1:-1]}}">
<script defer src="{{'js/vendor/socketio.js' | asset}}"></script>
<script defer src="{{'js/flash.js' | asset}}"></script>
<script defer src="{{'js/vendor/lozad.js' | asset}}"></script>
<script defer src="{{'js/vendor/lite-youtube.js' | asset}}"></script>
<script defer src="{{'js/chat.js' | asset}}"></script>
{% endblock %}

View File

@ -24,7 +24,7 @@
{% set class = 'site-banner-hole' %} {% set class = 'site-banner-hole' %}
{% elif get_running_orgy(v) and os_path.exists(path ~ "/orgy_banners") %} {% elif get_running_orgy(v) and os_path.exists(path ~ "/orgy_banners") %}
{% set src = macros.random_image("assets/images/" ~ SITE_NAME ~ "/orgy_banners") %} {% set src = macros.random_image("assets/images/" ~ SITE_NAME ~ "/orgy_banners") %}
{% set href = "/chat" %} {% set href = "/chat/1" %}
{% set expand = false %} {% set expand = false %}
{% elif IS_DKD() or IS_BIRTHGAY() or IS_BIRTHDEAD() %} {% elif IS_DKD() or IS_BIRTHGAY() or IS_BIRTHDEAD() %}
{% set src = macros.random_image("assets/events/" ~ IS_EVENT() ~ "/images/banners") %} {% set src = macros.random_image("assets/events/" ~ IS_EVENT() ~ "/images/banners") %}

View File

@ -281,7 +281,7 @@
{%- if FEATURES['CHAT'] -%} {%- if FEATURES['CHAT'] -%}
<li class="nav-item d-none d-lg-flex align-items-center justify-content-center text-center mx-1" id="header--chat--item"> <li class="nav-item d-none d-lg-flex align-items-center justify-content-center text-center mx-1" id="header--chat--item">
<a class="nav-link position-relative" href="/chat" style="margin-top: {% if get_running_orgy(v) %}-4px{% else %}-1.6px{% endif %} !important"> <a class="nav-link position-relative" href="/chat/1" style="margin-top: {% if get_running_orgy(v) %}-4px{% else %}-1.6px{% endif %} !important">
{% if get_running_orgy(v) %} {% if get_running_orgy(v) %}
<img src="{{SITE_FULL_IMAGES}}/i/orgy.webp" width="30"> <img src="{{SITE_FULL_IMAGES}}/i/orgy.webp" width="30">
{% else %} {% else %}
@ -490,7 +490,7 @@
</li> </li>
{% endif %} {% endif %}
<li class="mt-3"> <li class="mt-3">
{% if request.path == '/chat' %} {% if request.path == '/chat/1' %}
{% if SITE_NAME == 'WPD' %} {% if SITE_NAME == 'WPD' %}
<h5 class="ml-3">Chat Rules</h5> <h5 class="ml-3">Chat Rules</h5>
<ul class="ml-3"> <ul class="ml-3">
@ -502,7 +502,7 @@
{% endif %} {% endif %}
<div class="mx-2"> <div class="mx-2">
<h5 class="mt-3">Users Online (<span class="chat-count"></span>)</h5> <h5 class="mt-3 mb-1">Users Online (<span class="chat-count"></span>)</h5>
<div id="online3" class="col text-left d-lg-none bg-white mb-4 pb-2" style="max-width:300px"></div> <div id="online3" class="col text-left d-lg-none bg-white mb-4 pb-2" style="max-width:300px"></div>
{% if (orgies)|length > 1 %} {% if (orgies)|length > 1 %}
<h5>Orgy Playlist</h5> <h5>Orgy Playlist</h5>
@ -532,7 +532,7 @@
<br><br><br><br><br><br><br><br> <br><br><br><br><br><br><br><br>
{% elif request.path.startswith('/chat/') %} {% elif request.path.startswith('/chat/') %}
<div class="mx-2"> <div class="mx-2">
<h5 class="mt-2 mb-3">Members ({{sorted_memberships|length}})</h5> <h5 class="mt-3 mb-1">Members ({{sorted_memberships|length}})</h5>
<ul class="col text-left d-lg-none bg-white mb-4 pb-2" style="max-width:300px;list-style-type:none"> <ul class="col text-left d-lg-none bg-white mb-4 pb-2" style="max-width:300px;list-style-type:none">
{% for membership in sorted_memberships %} {% for membership in sorted_memberships %}
{% set user = membership.user %} {% set user = membership.user %}

View File

@ -48,7 +48,7 @@
{% if v %} {% if v %}
{%- if FEATURES['CHAT'] -%} {%- if FEATURES['CHAT'] -%}
<button type="button" class="nobackground border-0 col px-0 btn btn-dead m-0 {% if not get_running_orgy(v) %}pt-0{% endif %}"> <button type="button" class="nobackground border-0 col px-0 btn btn-dead m-0 {% if not get_running_orgy(v) %}pt-0{% endif %}">
<a href="/chat" class="text-decoration-none"> <a href="/chat/1" class="text-decoration-none">
<div class="text-center {% if request|selected_tab=='chat' %}text-primary{% else %}text-muted{% endif %}"> <div class="text-center {% if request|selected_tab=='chat' %}text-primary{% else %}text-muted{% endif %}">
{%- if get_running_orgy(v) -%} {%- if get_running_orgy(v) -%}
<img src="{{SITE_FULL_IMAGES}}/i/orgy.webp" width="30"> <img src="{{SITE_FULL_IMAGES}}/i/orgy.webp" width="30">

View File

@ -12,21 +12,23 @@
<div class="container pb-4 pb-md-2"> <div class="container pb-4 pb-md-2">
<div class="row justify-content-around" id="main-content-row"> <div class="row justify-content-around" id="main-content-row">
<div class="col h-100 {% block customPadding %}custom-gutters{% endblock %}" id="main-content-col"> <div class="col h-100 {% block customPadding %}custom-gutters{% endblock %}" id="main-content-col">
<h5 class="mt-2 mb-3 ml-1 toggleable d-mob-none" style="display:inline-block">{{chat.name}}</h5> {% if chat.id != 1 %}
<b class="mt-2 mb-2 ml-1 text-small toggleable d-md-none" style="display:inline-block">{{chat.name}}</b> <h5 class="mt-2 mb-3 ml-1 toggleable d-mob-none" style="display:inline-block">{{chat.name}}</h5>
<b class="mt-2 mb-2 ml-1 text-small toggleable d-md-none" style="display:inline-block">{{chat.name}}</b>
{% if v.id == chat.owner_id %} {% if v.id == chat.owner_id %}
<button class="px-2 toggleable" type="button" data-nonce="{{g.nonce}}" data-onclick="toggleElement('chat-name-form', 'chat-name')"> <button class="px-2 toggleable" type="button" data-nonce="{{g.nonce}}" data-onclick="toggleElement('chat-name-form', 'chat-name')">
<i class="fas fa-pen text-small text-muted"></i> <i class="fas fa-pen text-small text-muted"></i>
</button> </button>
<form id="chat-name-form" class="d-none mt-2" action="/chat/{{chat.id}}/name" method="post"> <form id="chat-name-form" class="d-none mt-2" action="/chat/{{chat.id}}/name" method="post">
<input hidden name="formkey" value="{{v|formkey}}" class="notranslate" translate="no"> <input hidden name="formkey" value="{{v|formkey}}" class="notranslate" translate="no">
<input id="chat-name" autocomplete="off" class="form-control d-inline-block" name="new_name" value="{{chat.name}}" style="max-width:300px"> <input id="chat-name" autocomplete="off" class="form-control d-inline-block" name="new_name" value="{{chat.name}}" style="max-width:300px">
<button type="submit" class="btn btn-primary" style="margin-top:-5px">Save</button> <button type="submit" class="btn btn-primary" style="margin-top:-5px">Save</button>
</form> </form>
{% else %} {% else %}
<button id="leave-private-chat" type="submit" class="btn btn-danger ml-1 ml-md-3 px-2 text-small-sm" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/chat/{{chat.id}}/leave')">Leave</button> <button id="leave-private-chat" type="submit" class="btn btn-danger ml-1 ml-md-3 px-2 text-small-sm" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/chat/{{chat.id}}/leave')">Leave</button>
{% endif %}
{% endif %} {% endif %}
<div id="chat-group-template" class="d-none"> <div id="chat-group-template" class="d-none">
@ -42,31 +44,48 @@
</div> </div>
<div class="col text-left d-none d-lg-block pt-3 pb-5" style="max-width:313px"> <div class="col text-left d-none d-lg-block pt-3 pb-5" style="max-width:313px">
<h5>Members ({{sorted_memberships|length}})</h5> {% if chat.id == 1 %}
<div id="members" class="mt-2"> <div class="col text-left d-none d-lg-block pt-3 pb-5" style="max-width:300px">
{% for membership in sorted_memberships %} {% if SITE_NAME == 'WPD' %}
{% set user = membership.user %} <h5>Chat Rules</h5>
{% set patron = '' %} <ul class="mt-2 mb-4">
{% if user.patron %} <li>Follow the rules mentioned on <a href="/sidebar">the sidebar</a>.</li>
{% set patron = patron + 'class="patron chat-patron" style="background-color:#' ~ user.name_color ~ '"' %} <li>Do not try to crash the chatroom with malicious code (CSS).</li>
<li>Do not send porn in chat.</li>
<li>Do not spam.</li>
</ul>
{% endif %} {% endif %}
{% if user.pride_username(None) %}
{% set patron = patron + ' pride_username' %}
{% endif %}
<li style="margin-top: 0.35rem">
<a class="font-weight-bold" target="_blank" href="/@{{user.username}}" style="color:#{{user.name_color}}">
<img loading="lazy" class="mr-1" src="/pp/{{user.id}}">
<span {{patron | safe}}>{{user.username}}</span>
</a>
{% if user.id == chat.owner_id %} <h5>Users Online (<span class="chat-count"></span>)</h5>
<img class="mx-2 chat-owner" data-bs-toggle="tooltip" alt="Owner" title="Owner" src="{{SITE_FULL_IMAGES}}/e/marseykingretard.webp"> <div id="online" class="mt-2 {% if SITE_NAME == 'WPD' %}online-wpd{% endif %}"></div>
</div>
{% else %}
<h5>Members ({{sorted_memberships|length}})</h5>
<div id="members" class="mt-2">
{% for membership in sorted_memberships %}
{% set user = membership.user %}
{% set patron = '' %}
{% if user.patron %}
{% set patron = patron + 'class="patron chat-patron" style="background-color:#' ~ user.name_color ~ '"' %}
{% endif %} {% endif %}
{% if user.pride_username(None) %}
{% set patron = patron + ' pride_username' %}
{% endif %}
<li style="margin-top: 0.35rem">
<a class="font-weight-bold" target="_blank" href="/@{{user.username}}" style="color:#{{user.name_color}}">
<img loading="lazy" class="mr-1" src="/pp/{{user.id}}">
<span {{patron | safe}}>{{user.username}}</span>
</a>
<i class="d-none ml-1 text-smaller text-success online-marker online-marker-{{user.id}} fas fa-circle" data-bs-toggle="tooltip" data-bs-placement="top" title="Here now"></i> {% if user.id == chat.owner_id %}
</li> <img class="mx-2 chat-owner" data-bs-toggle="tooltip" alt="Owner" title="Owner" src="{{SITE_FULL_IMAGES}}/e/marseykingretard.webp">
{% endfor %} {% endif %}
</div>
<i class="d-none ml-1 text-smaller text-success online-marker online-marker-{{user.id}} fas fa-circle" data-bs-toggle="tooltip" data-bs-placement="top" title="Here now"></i>
</li>
{% endfor %}
</div>
{% endif %}
</div> </div>
</div> </div>

View File

@ -329,7 +329,7 @@
{%- endif -%} {%- endif -%}
</span> </span>
<i class="quote btn fas fa-reply ml-auto" data-nonce="{{g.nonce}}" data-onclick="quote(this)"></i> <i class="quote btn fas fa-reply ml-auto" data-nonce="{{g.nonce}}" data-onclick="quote(this)"></i>
{% if not request.path.startswith("/chat/") and v.admin_level >= PERMS.POST_COMMENT_MODERATION %} {% if chat.id == 1 and v.admin_level >= PERMS.POST_COMMENT_MODERATION %}
<i class="btn del delconfirm fas fa-trash-alt"></i> <i class="btn del delconfirm fas fa-trash-alt"></i>
<i class="btn d-none del delmsg fas fa-trash-alt text-danger" data-nonce="{{g.nonce}}" data-onclick="del(this)"></i> <i class="btn d-none del delmsg fas fa-trash-alt text-danger" data-nonce="{{g.nonce}}" data-onclick="del(this)"></i>
{% endif %} {% endif %}
@ -382,23 +382,6 @@
</div> </div>
{% endmacro %} {% endmacro %}
{% macro chat_users_list() %}
<div class="col text-left d-none d-lg-block pt-3 pb-5" style="max-width:300px">
{% if SITE_NAME == 'WPD' %}
<h5>Chat Rules</h5>
<ul class="mt-2 mb-4">
<li>Follow the rules mentioned on <a href="/sidebar">the sidebar</a>.</li>
<li>Do not try to crash the chatroom with malicious code (CSS).</li>
<li>Do not send porn in chat.</li>
<li>Do not spam.</li>
</ul>
{% endif %}
<h5>Users Online (<span class="chat-count"></span>)</h5>
<div id="online" class="mt-2 {% if SITE_NAME == 'WPD' %}online-wpd{% endif %}"></div>
</div>
{% endmacro %}
{% macro time_filter_buttons() %} {% macro time_filter_buttons() %}
<div class="dropdown dropdown-actions mr-2"> <div class="dropdown dropdown-actions mr-2">
<button type="button" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton" data-bs-toggle="dropdown"> <button type="button" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton" data-bs-toggle="dropdown">

View File

@ -20,10 +20,6 @@ server {
proxy_pass http://localhost:5001/socket.io; proxy_pass http://localhost:5001/socket.io;
include includes/headers; include includes/headers;
} }
location =/chat {
proxy_pass http://localhost:5001/chat;
include includes/headers;
}
location =/reply { location =/reply {
proxy_pass http://localhost:5001/reply; proxy_pass http://localhost:5001/reply;
include includes/headers; include includes/headers;