forked from MarseyWorld/MarseyWorld
add custom css for chats
parent
dede32f545
commit
ed3a1b94d0
|
@ -2,7 +2,7 @@ import time
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
from sqlalchemy import Column, ForeignKey
|
from sqlalchemy import Column, ForeignKey
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import deferred, relationship
|
||||||
from sqlalchemy.sql.sqltypes import *
|
from sqlalchemy.sql.sqltypes import *
|
||||||
|
|
||||||
from files.classes import Base
|
from files.classes import Base
|
||||||
|
@ -14,6 +14,7 @@ class Chat(Base):
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
name = Column(String)
|
name = Column(String)
|
||||||
created_utc = Column(Integer)
|
created_utc = Column(Integer)
|
||||||
|
css = deferred(Column(String))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@lazy
|
@lazy
|
||||||
|
|
|
@ -112,9 +112,9 @@ def chat(v, chat_id):
|
||||||
orgy = get_running_orgy(v, chat_id)
|
orgy = get_running_orgy(v, chat_id)
|
||||||
if orgy:
|
if orgy:
|
||||||
orgies = g.db.query(Orgy).filter_by(chat_id=chat_id).order_by(Orgy.start_utc).all()
|
orgies = g.db.query(Orgy).filter_by(chat_id=chat_id).order_by(Orgy.start_utc).all()
|
||||||
return render_template("orgy.html", v=v, messages=displayed_messages, chat=chat, sorted_memberships=sorted_memberships, muting_chat=muting_chat, orgy=orgy, orgies=orgies, membership=membership)
|
return render_template("orgy.html", v=v, messages=displayed_messages, chat=chat, sorted_memberships=sorted_memberships, muting_chat=muting_chat, orgy=orgy, orgies=orgies, membership=membership, chat_css=chat.css)
|
||||||
|
|
||||||
return render_template("chat.html", v=v, messages=displayed_messages, chat=chat, sorted_memberships=sorted_memberships, muting_chat=muting_chat, membership=membership)
|
return render_template("chat.html", v=v, messages=displayed_messages, chat=chat, sorted_memberships=sorted_memberships, muting_chat=muting_chat, membership=membership, chat_css=chat.css)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/chat/<int:chat_id>/name")
|
@app.post("/chat/<int:chat_id>/name")
|
||||||
|
@ -188,6 +188,63 @@ def mute_chat(v, chat_id):
|
||||||
|
|
||||||
return {"message": msg}
|
return {"message": msg}
|
||||||
|
|
||||||
|
@app.get("/chat/<int:chat_id>/custom_css")
|
||||||
|
@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_custom_css_get(v, chat_id):
|
||||||
|
chat = g.db.get(Chat, chat_id)
|
||||||
|
if not chat:
|
||||||
|
abort(404, "Chat not found!")
|
||||||
|
|
||||||
|
if v.id != chat.owner_id:
|
||||||
|
abort(403, "Only the chat owner can change its custom css!")
|
||||||
|
|
||||||
|
return render_template("chat_css.html", v=v, chat=chat)
|
||||||
|
|
||||||
|
@app.post("/chat/<int:chat_id>/custom_css")
|
||||||
|
@limiter.limit('1/second', scope=rpath)
|
||||||
|
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||||
|
@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_custom_css_post(v, chat_id):
|
||||||
|
chat = g.db.get(Chat, chat_id)
|
||||||
|
if not chat:
|
||||||
|
abort(404, "Chat not found!")
|
||||||
|
|
||||||
|
if v.id != chat.owner_id:
|
||||||
|
abort(403, "Only the chat owner can change its custom css!")
|
||||||
|
|
||||||
|
if v.shadowbanned: abort(400)
|
||||||
|
|
||||||
|
css = request.values.get('css', '').strip()
|
||||||
|
|
||||||
|
if len(css) > CSS_LENGTH_LIMIT:
|
||||||
|
abort(400, f"Chat CSS is too long (max {CSS_LENGTH_LIMIT} characters)")
|
||||||
|
|
||||||
|
valid, error = validate_css(css)
|
||||||
|
if not valid:
|
||||||
|
abort(400, error)
|
||||||
|
|
||||||
|
chat.css = css
|
||||||
|
g.db.add(chat)
|
||||||
|
|
||||||
|
return {"message": "Chat Custom CSS successfully updated!"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/chat/<int:chat_id>/css")
|
||||||
|
@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_css(v, chat_id):
|
||||||
|
chat = g.db.query(Chat.css).filter_by(id=chat_id).one_or_none()
|
||||||
|
if not chat:
|
||||||
|
abort(404, "Chat not found!")
|
||||||
|
resp = make_response(chat.css or "")
|
||||||
|
resp.headers.add("Content-Type", "text/css")
|
||||||
|
return resp
|
||||||
|
|
||||||
@app.get("/chat/<int:chat_id>/orgies")
|
@app.get("/chat/<int:chat_id>/orgies")
|
||||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
@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)
|
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
<b class="mt-2 mb-2 ml-1 text-small toggleable d-md-none" style="display:inline-block">{{chat.name}}</b>
|
<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="chat-control fas fa-pen text-small text-muted 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>
|
|
||||||
</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">
|
||||||
|
@ -27,7 +26,9 @@
|
||||||
<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>
|
||||||
|
|
||||||
<a href="/chat/{{chat.id}}/orgies" class="orgy-control fas fa-tv text-muted ml-2"></a>
|
<a href="/chat/{{chat.id}}/orgies" class="chat-control fas fa-tv text-muted mx-2"></a>
|
||||||
|
|
||||||
|
<a href="/chat/{{chat.id}}/custom_css" class="chat-control fas fa-palette text-muted ml-2"></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="px-2" type="button" data-nonce="{{g.nonce}}" data-bs-toggle="tooltip" title="{% if muting_chat %}Unmute (do it){% else %}Mute (don't do it){% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this, '/chat/{{chat.id}}/toggle_mute')">
|
<button class="px-2" type="button" data-nonce="{{g.nonce}}" data-bs-toggle="tooltip" title="{% if muting_chat %}Unmute (do it){% else %}Mute (don't do it){% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this, '/chat/{{chat.id}}/toggle_mute')">
|
||||||
<i class="fas fa-bell-slash {% if muting_chat %}text-danger{% else %}text-muted{% endif %}"></i>
|
<i class="fas fa-bell-slash {% if muting_chat %}text-danger{% else %}text-muted{% endif %}"></i>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "default.html" %}
|
||||||
|
|
||||||
|
{% block pagetitle %}Chat CSS{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="settings my-5 mx-3">
|
||||||
|
<section>
|
||||||
|
<a href="/chat/{{chat.id}}">
|
||||||
|
<i class="fas fa-long-arrow-left mr-2"></i>Go back to chat
|
||||||
|
</a>
|
||||||
|
<h2 class="mt-4">Chat Custom CSS</h2>
|
||||||
|
<div class="settings-section rounded mb-0">
|
||||||
|
<p class="text-small text-muted pt-2 pl-3">Edit your chat's custom CSS</p>
|
||||||
|
<div class="body d-lg-flex border-bottom">
|
||||||
|
<div class="w-lg-100">
|
||||||
|
<form id="chat-custom-css" action="/chat/{{chat.id}}/custom_css" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHR(this)">
|
||||||
|
<input hidden name="formkey" value="{{v|formkey}}" class="notranslate" translate="no">
|
||||||
|
<textarea autocomplete="off" class="form-control rounded" id="css-textarea" placeholder="Custom CSS" rows="3" name="css" form="chat-custom-css" maxlength="{{CSS_LENGTH_LIMIT}}">{% if chat.css %}{{chat.css}}{% endif %}</textarea>
|
||||||
|
<small>Limit of {{CSS_LENGTH_LIMIT}} characters</small>
|
||||||
|
<div class="d-flex mt-2">
|
||||||
|
<input autocomplete="off" id="submit-btn" class="btn btn-primary ml-auto" type="submit" value="Save">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -15,7 +15,9 @@
|
||||||
<b class="mt-2 mb-2 ml-1 text-small d-md-none" style="display:inline-block">{{orgy.title}}</b>
|
<b class="mt-2 mb-2 ml-1 text-small d-md-none" style="display:inline-block">{{orgy.title}}</b>
|
||||||
|
|
||||||
{% if v.id == chat.owner_id %}
|
{% if v.id == chat.owner_id %}
|
||||||
<a href="/chat/{{chat.id}}/orgies" class="orgy-control fas fa-tv text-muted ml-2"></a>
|
<a href="/chat/{{chat.id}}/orgies" class="chat-control fas fa-tv text-muted mx-2"></a>
|
||||||
|
|
||||||
|
<a href="/chat/{{chat.id}}/custom_css" class="chat-control fas fa-palette text-muted ml-2"></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="px-2" type="button" data-nonce="{{g.nonce}}" data-bs-toggle="tooltip" title="{% if muting_chat %}Unmute (do it){% else %}Mute (don't do it){% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this, '/chat/{{chat.id}}/toggle_mute')">
|
<button class="px-2" type="button" data-nonce="{{g.nonce}}" data-bs-toggle="tooltip" title="{% if muting_chat %}Unmute (do it){% else %}Mute (don't do it){% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastReload(this, '/chat/{{chat.id}}/toggle_mute')">
|
||||||
<i class="fas fa-bell-slash {% if muting_chat %}text-danger{% else %}text-muted{% endif %}"></i>
|
<i class="fas fa-bell-slash {% if muting_chat %}text-danger{% else %}text-muted{% endif %}"></i>
|
||||||
|
|
|
@ -151,6 +151,10 @@
|
||||||
{% if v and (v.css or v.background) and not request.path.startswith('/settings') %}
|
{% if v and (v.css or v.background) and not request.path.startswith('/settings') %}
|
||||||
<link rel="stylesheet" href="/@{{v.username}}/css">
|
<link rel="stylesheet" href="/@{{v.username}}/css">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if chat_css %}
|
||||||
|
<link rel="stylesheet" href="/chat/{{chat.id}}/css">
|
||||||
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro seo() %}
|
{% macro seo() %}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
alter table chats add column css character varying(20000);
|
Loading…
Reference in New Issue