forked from MarseyWorld/MarseyWorld
Bring back orgies (watchparties), now controllable by admins, and generally better in all ways (#165)
This PR adds orgies back into rdrama. Long ago, snakes made the original orgy code, and it was super fun. But he had to rush it out, and ended up making it a bit unsustainable, and had a couple questionable coding decisions, which meant that it had to be removed. Hey, the man literally did it in a few hours before the DB trial continued, lmao. Anyways, I took my own approach to it. I do not use iframes, i just just repurpose code from /chat window. Because I had that freedom, I also moved things around to make the user experience a bit better. I also added a title to give users some context about what's happening. Check it out ![image](/attachments/6719146c-4922-4d75-967d-8d424a09b198) Most importantly, this is all configurable from the site. Admins with the permission "ORGIES" will see this in their control panel ![image](/attachments/423d6046-a11d-4e84-bd2c-a2a641afd552) Nigga, idk where to put it, so I made my own category. If there is no orgy in progress, admins will see this: ![image](/attachments/7c64b9fa-cdf4-4986-a0c4-f2324878062e) Click the button, and, viola, the orgy begins. If there is an orgy in progress, the page will look like this: ![image](/attachments/b65be4b3-5db1-43cb-8857-7d3a8ea24ca7) Click the button, and the orgy stops. If an orgy is in progress, navigating to /chat will take the user to the orgy seemlessly. But what if they don't want to participate, liek some kind of spoilsport? Just navigate to /old_chat. That's just about it, it's really that simple. I have lots of ideas for the future, but I'll let that wait til later :). A few notes about implementation: - I moved some functionality out of /templates/chat.html and into /templates/util/macros.html. This is just so I could reference the code directly from my new template, /templates/orgy.html. - The orgy is stored as a single row in the new table "orgies". Okay, I know this is a little silly, but you know what they say: "if it's stupid and it works, it's not stupid". (tbf the oceangate ceo also said that) Co-authored-by: Chuck Sneed <sneed@formerlychucks.net> Reviewed-on: rDrama/rDrama#165 Co-authored-by: HeyMoon <heymoon@noreply.fsdfsd.net> Co-committed-by: HeyMoon <heymoon@noreply.fsdfsd.net>master
parent
499781329f
commit
7c040367fa
|
@ -0,0 +1,14 @@
|
|||
.orgy-top-container {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.orgy-chat-window-item {
|
||||
flex-grow: 2;
|
||||
width: fit-content;
|
||||
}
|
||||
.orgy-info-window-item {
|
||||
max-width: 550px;
|
||||
width: 550px;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import time
|
||||
from math import floor
|
||||
from random import randint
|
||||
from urllib.parse import parse_qs, urlencode, urlparse
|
||||
from flask import g
|
||||
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from sqlalchemy.dialects.postgresql import TSVECTOR
|
||||
from sqlalchemy.orm import relationship, scoped_session
|
||||
from sqlalchemy.schema import FetchedValue
|
||||
from sqlalchemy.sql.sqltypes import *
|
||||
|
||||
from files.classes import Base
|
||||
from files.helpers.config.const import *
|
||||
from files.helpers.lazy import lazy
|
||||
from files.helpers.regex import *
|
||||
from files.helpers.sorting_and_time import *
|
||||
|
||||
class Orgy(Base):
|
||||
__tablename__ = "orgies"
|
||||
|
||||
youtube_id = Column(String, primary_key=True)
|
||||
title = Column(String)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__}(id={self.youtube_id}, title={self.title})>"
|
||||
|
||||
|
||||
def get_orgy():
|
||||
orgy = g.db.query(Orgy).one_or_none()
|
||||
return orgy
|
||||
|
||||
def create_orgy(youtube_id, title):
|
||||
assert not get_orgy()
|
||||
assert re.match(yt_id_regex, youtube_id)
|
||||
orgy = Orgy(title=title, youtube_id=youtube_id)
|
||||
g.db.add(orgy)
|
||||
g.db.flush()
|
||||
g.db.commit()
|
||||
|
||||
def end_orgy():
|
||||
assert get_orgy()
|
||||
g.db.query(Orgy).delete()
|
||||
g.db.flush()
|
||||
g.db.commit()
|
|
@ -518,6 +518,7 @@ PERMS = { # Minimum admin_level to perform action.
|
|||
'LOTTERY_VIEW_PARTICIPANTS': 2,
|
||||
'POST_COMMENT_INFINITE_PINGS': 2,
|
||||
'IGNORE_1WEEk_EDITING_LIMIT': 2,
|
||||
'ORGIES': 2,
|
||||
|
||||
'ADMIN_REMOVE': 3,
|
||||
'ADMIN_ACTIONS_REVERT': 3,
|
||||
|
|
|
@ -9,6 +9,7 @@ from psycopg2.errors import UniqueViolation
|
|||
|
||||
from files.__main__ import app, cache, limiter
|
||||
from files.classes import *
|
||||
from files.classes.orgy import *
|
||||
from files.helpers.actions import *
|
||||
from files.helpers.alerts import *
|
||||
from files.helpers.cloudflare import *
|
||||
|
@ -1906,3 +1907,27 @@ def admin_reset_password(user_id, v):
|
|||
send_repeatable_notification(user.id, text)
|
||||
|
||||
return {"message": f"@{user.username}'s password has been reset! The new password has been messaged to them!"}
|
||||
|
||||
@app.get("/admin/orgy")
|
||||
@admin_level_required(PERMS['ORGIES'])
|
||||
def orgy_control(v):
|
||||
return render_template("admin/orgy_control.html", v=v, orgy=get_orgy())
|
||||
|
||||
@app.post("/admin/start_orgy")
|
||||
@admin_level_required(PERMS['ORGIES'])
|
||||
def start_orgy(v):
|
||||
youtube_id = request.values.get("youtube_id")
|
||||
title = request.values.get("title")
|
||||
|
||||
assert youtube_id
|
||||
assert title
|
||||
|
||||
create_orgy(youtube_id, title)
|
||||
|
||||
return redirect("/chat")
|
||||
|
||||
@app.post("/admin/stop_orgy")
|
||||
@admin_level_required(PERMS['ORGIES'])
|
||||
def stop_orgy(v):
|
||||
end_orgy()
|
||||
return redirect("/chat")
|
|
@ -13,6 +13,7 @@ from files.helpers.media import *
|
|||
from files.helpers.sanitize import *
|
||||
from files.helpers.alerts import push_notif
|
||||
from files.routes.wrappers import *
|
||||
from files.classes.orgy import *
|
||||
|
||||
from files.__main__ import app, cache, limiter
|
||||
|
||||
|
@ -33,6 +34,19 @@ messages = cache.get(f'messages') or {}
|
|||
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
|
||||
@is_not_permabanned
|
||||
def chat(v):
|
||||
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!")
|
||||
orgy = get_orgy()
|
||||
if orgy:
|
||||
return render_template("orgy.html", v=v, messages=messages, orgy = orgy)
|
||||
else:
|
||||
return render_template("chat.html", v=v, messages=messages)
|
||||
|
||||
@app.get("/old_chat")
|
||||
@limiter.limit(DEFAULT_RATELIMIT)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
|
||||
@is_not_permabanned
|
||||
def old_chat(v):
|
||||
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!")
|
||||
return render_template("chat.html", v=v, messages=messages)
|
||||
|
|
|
@ -98,6 +98,12 @@
|
|||
</ul>
|
||||
{%- endif %}
|
||||
|
||||
{% if v.admin_level >= PERMS['ORGIES'] %}
|
||||
<h4>Misc</h4>
|
||||
<ul>
|
||||
<li><a href="/admin/orgy">Start/Stop Orgy</a></li>
|
||||
</ul>
|
||||
{%- endif %}
|
||||
<h4>Statistics</h4>
|
||||
<ul>
|
||||
<li><a href="/stats">Content Stats</a></li>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block pagetitle %}Orgy Control Panel{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if msg %}{{macros.alert(msg, false)}}{% endif %}
|
||||
<div class="row my-5">
|
||||
<div class="col">
|
||||
<div class="settings mx-3">
|
||||
<div id="description">
|
||||
<h2>Orgy Control Panel</h2>
|
||||
<br>
|
||||
</div>
|
||||
<div class="body d-lg-flex">
|
||||
<div class="w-lg-100">
|
||||
{%if not orgy%}
|
||||
<form id="orgy" action="/admin/start_orgy" method="post">
|
||||
<div class="d-lg-flex border-bottom">
|
||||
<div class="title w-lg-25">
|
||||
<label for="title">Title</label>
|
||||
</div>
|
||||
<div class="body w-lg-100">
|
||||
<input id="title" autocomplete="off" type="text" name="title" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-lg-flex border-bottom">
|
||||
<div class="title w-lg-25">
|
||||
<label for="youtube_id">Youtube ID</label>
|
||||
</div>
|
||||
<div class="body w-lg-100">
|
||||
<input id="youtube_id" autocomplete="off" type="text" name="youtube_id" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<input hidden name="formkey" value="{{v|formkey}}">
|
||||
<div class="d-flex mt-2">
|
||||
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Start Orgy">
|
||||
</div>
|
||||
</form>
|
||||
{%else%}
|
||||
<form id="orgy" action="/admin/stop_orgy" method="post">
|
||||
<input hidden name="formkey" value="{{v|formkey}}">
|
||||
<div class="d-flex mt-2">
|
||||
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Stop Orgy">
|
||||
</div>
|
||||
</form>
|
||||
{%endif%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -6,132 +6,27 @@
|
|||
{% include "header.html" %}
|
||||
{% include "modals/expanded_image.html" %}
|
||||
{% include "modals/emoji.html" %}
|
||||
{% include "util/macros.html" %}
|
||||
{% set vlink = '<a href="/id/' ~ v.id ~ '">' %}
|
||||
<div class="container pb-4">
|
||||
<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="border-right pb-1 px-3">
|
||||
<span id="online2" data-bs-html="true" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Users Online" class="text-muted">
|
||||
<i class="far fa-user fa-sm mr-1"></i>
|
||||
<span class="board-chat-count">0</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{% macro chat_group_template(id, m) %}
|
||||
<div class="chat-group">
|
||||
<a class="font-weight-bold userlink" target="_blank" {% if m %}style="color:#{{m['namecolor']}}" href="/@{{m['username']}}" {% endif %}><div class="avatar profile-pic-20-wrapper mr-1"><img loading="lazy" class="avatar-pic pp20 mr-1" {% if m %}src="/pp/{{m['user_id']}}"{% endif %}><img class="avatar-hat profile-pic-20-hat hat" loading="lazy" {% if m %}src="{{m['hat']}}"{% endif %}></div>{% if m %}{{m['username']}}{% else %}NULL{% endif %}</a>
|
||||
<span class="text-black time ml-1 mb-3 text-center">{% if m %}{{m['time'] | timestamp}}{% else %}just now{% endif %}</span>
|
||||
<input hidden class="user_id" {% if m %}value="{{m['user_id']}}"{% endif %}>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_line_template(id, m) %}
|
||||
{% set quote_exists = m and m['quotes'] and messages.get(m['quotes']) %}
|
||||
{% set mentioned = m and vlink in m['text_html'] or (quote_exists and messages[m['quotes']]['user_id'] == v.id) %}
|
||||
<div class="chat-line {% if mentioned %}chat-mention{% endif %}" {% if m %}id="{{id}}"{% endif %}>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="text-muted chat-line-content">
|
||||
<div class="{% if not (m and m['quotes']) %}d-none{% endif %} quotes" style="font-size:12px">
|
||||
<a class="QuotedMessageLink" {% if m and m['quotes'] %}href="#{{m['quotes']}}"{% endif %}>
|
||||
<i class="fas fa-reply"></i>
|
||||
<span class="text-primary">@<span class="QuotedUser">
|
||||
{%- if quote_exists -%}
|
||||
{{messages[m['quotes']]['username']}}
|
||||
{%- endif -%}
|
||||
</span></span>:
|
||||
<em class="QuotedMessage text-break">
|
||||
{%- if quote_exists -%}
|
||||
{{messages[m['quotes']]['text']}}
|
||||
{%- endif -%}
|
||||
</em>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex">
|
||||
<span class="chat-message text-black text-break">
|
||||
{% if m %}
|
||||
{% if v.slurreplacer %}
|
||||
{{m['text_censored'] | safe}}
|
||||
{% else %}
|
||||
{{m['text_html'] | safe}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="text d-none">{% if m %}{{m['text']}}{% endif %}</span>
|
||||
<i class="quote btn fas fa-reply ml-auto" data-nonce="{{g.nonce}}" data-onclick="quote(this)"></i>
|
||||
{% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
|
||||
<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>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{{ macros.chat_users_online() }}
|
||||
|
||||
<div id="chat-group-template" class="d-none">
|
||||
{{chat_group_template()}}
|
||||
{{macros.chat_group_template()}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="chat-line-template" class="d-none">
|
||||
{{chat_line_template()}}
|
||||
{{macros.chat_line_template()}}
|
||||
</div>
|
||||
|
||||
<div id="shrink">
|
||||
<div id="chat-window" class="container p-0">
|
||||
{% set messages_list = messages.items()|list %}
|
||||
{% for id, m in messages_list %}
|
||||
{% set same = loop.index > 1 and m['user_id'] == messages_list[loop.index-2][1]['user_id'] %}
|
||||
{% if not same %}
|
||||
{% if loop.index > 1 %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{{chat_group_template(id, m)}}
|
||||
{% endif %}
|
||||
{{chat_line_template(id, m)}}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{{macros.chat_window(vlink)}}
|
||||
</div>
|
||||
|
||||
<div class="mt-3"></div>
|
||||
<div id="quotes" class="mt-3 ml-3 mb-2 d-none" style="font-size:12px">
|
||||
<a id="QuotedMessageLink">
|
||||
<i class="fas fa-reply"></i> <span class="text-primary">@<span id="QuotedUser"></span></span>: <em id="QuotedMessage"></em>
|
||||
<button type="button" id="cancel" class="btn btn-secondary">Cancel</button>
|
||||
<input hidden id="quotes_id">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id='message' class="d-none position-relative form-group d-flex">
|
||||
<div class="position-absolute text-muted text-small ml-1" style="bottom: -1.5rem; line-height: 1;">
|
||||
<span id="typing-indicator"></span>
|
||||
<span id="loading-indicator" class="d-none"></span>
|
||||
</div>
|
||||
<span class="my-auto">
|
||||
<i class="btn btn-secondary fas fa-smile-beam" style="font-size:1.3rem!important" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('input-text')" data-bs-toggle="modal" data-bs-target="#emojiModal"></i>
|
||||
</span>
|
||||
|
||||
<span class="my-auto ml-1">
|
||||
<label class="btn btn-secondary format mb-0">
|
||||
<div class="mr-3" style="font-size:12px"><i class="fas fa-image" style="font-size:1.3rem!important"></i></div>
|
||||
<input autocomplete="off" id="file" accept="image/*" type="file" name="file" {% if g.is_tor %}disabled{% endif %} hidden>
|
||||
</label>
|
||||
<button type="button" class="text-danger text-lg font-weight-bold ml-2 remove-files d-none" data-bs-toggle="tooltip" title="Remove Files">X</button>
|
||||
</span>
|
||||
|
||||
<textarea id="input-text" minlength="1" maxlength="{% if SITE == 'rdrama.net' %}200{% else %}1000{% endif %}" {% if g.browser in ("iphone","mac") %}style="font-size:16px!important"{% endif %} class="file-ta form-control" placeholder="Message" autocomplete="off" autofocus rows="1"></textarea>
|
||||
|
||||
<i id="chatsend" data-nonce="{{g.nonce}}" data-onclick="send()" class="btn btn-secondary fas fa-reply ml-3 my-auto" style="transform:rotateY(180deg);font-size:1.3rem!important"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col text-left d-none d-lg-block pt-3" style="max-width:300px">
|
||||
<h5>Users Online</h5>
|
||||
<div id="online" class="mt-3"></div>
|
||||
</div>
|
||||
{{macros.chat_users_list()}}
|
||||
</div>
|
||||
|
||||
<input id="vid" hidden value="{{v.id}}">
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
{%- extends 'root.html' -%}
|
||||
{% block pagetitle -%}Chat{%- endblock %}
|
||||
{% block pagetype %}chat{% endblock %}
|
||||
{% block body_attributes %}class="has_header"{% endblock %}
|
||||
{% block body %}
|
||||
{% include "header.html" %}
|
||||
{% include "modals/expanded_image.html" %}
|
||||
{% include "modals/emoji.html" %}
|
||||
{% include "util/macros.html" %}
|
||||
{% set vlink = '<a href="/id/' ~ v.id ~ '">' %}
|
||||
<div class="container pb-4">
|
||||
|
||||
<div class="orgy-top-container">
|
||||
<div class="col text-left d-none d-lg-block pt-3 orgy-info-window-item">
|
||||
<h2>{{orgy.title}}</h1>
|
||||
<div>
|
||||
<lite-youtube videoid="{{orgy.youtube_id}}" params="autoplay=1&modestbranding=1"/>
|
||||
</div>
|
||||
{{macros.chat_users_list()}}
|
||||
</div>
|
||||
|
||||
<div class="orgy-chat-window-item">
|
||||
<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_users_online()}}
|
||||
{{macros.chat_window(vlink)}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="vid" hidden value="{{v.id}}">
|
||||
<input id="site_name" hidden value="{{SITE_NAME}}">
|
||||
<input id="slurreplacer" hidden value="{{v.slurreplacer}}">
|
||||
<input id="admin_level" hidden value="{{v.admin_level}}">
|
||||
<script defer src="{{'js/vendor/socketio.js' | asset}}"></script>
|
||||
<script defer src="{{'js/chat.js' | asset}}"></script>
|
||||
<script defer src="{{'js/vendor/lozad.js' | asset}}"></script>
|
||||
<script defer src="{{'js/vendor/lite-youtube.js' | asset}}"></script>
|
||||
{% endblock %}
|
|
@ -1,6 +1,6 @@
|
|||
<h3 style="filter: sepia(100%) saturate(500%) hue-rotate(60deg) drop-shadow(-4px 4px 10px lime);">CURRENT EVENTS:</h3>
|
||||
<h4 style="filter: sepia(50%) saturate(500%) hue-rotate(10deg) drop-shadow(-1px 1px 5px pink);"><a href="https://rdrama.net/h/vidya/post/182848/contest-photoshop-your-pet-as-a" rel="nofollow">Bing Bing Wahoo Pet Contest</a></h4><sup>Dramacoin prizes!</sup><br>
|
||||
<h4 style="filter: sepia(50%) saturate(500%) hue-rotate(10deg) drop-shadow(-1px 1px 5px pink);"><a href="https://rdrama.net/post/184174" rel="nofollow">Independence Gay Grill-Off</a></h4><sup>BADGE</sup><br>
|
||||
<h4 style="filter: sepia(50%) saturate(500%) hue-rotate(10deg) drop-shadow(-1px 1px 5px pink);"><a href="https://rdrama.net/h/vidya/post/182848/contest-photoshop-your-pet-as-a" rel="nofollow noopener" target="_blank">Bing Bing Wahoo Pet Contest</a></h4><sup>Dramacoin prizes!</sup><br>
|
||||
<h4 style="filter: sepia(50%) saturate(500%) hue-rotate(10deg) drop-shadow(-1px 1px 5px pink);"><a href="https://rdrama.net/post/184174" rel="nofollow noopener" target="_blank">Independence Gay Grill-Off</a></h4><sup>BADGE</sup><br>
|
||||
<hr>
|
||||
<hr>
|
||||
<hr>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<ul>
|
||||
<li><p>Asking to see who saved comments/posts=1 day ban</p></li>
|
||||
<li><p>You must be over 18 to view this site.</p></li>
|
||||
<li><p><strong><a href="https://rdrama.net//post/19711/a-short-guide-on-how-to" rel="nofollow">NO RIGHTWING AGENDAPOSTING.</a></strong></p></li>
|
||||
<li><p><strong><a href="https://rdrama.net//post/19711/a-short-guide-on-how-to" rel="nofollow noopener" target="_blank">NO RIGHTWING AGENDAPOSTING.</a></strong></p></li>
|
||||
<li><p>Discord users will be banned on sight.</p></li>
|
||||
<li><p>Don't post anything illegal.</p></li>
|
||||
<li><p>No sexualizing minors, even as a joke. This includes cartoons.</p></li>
|
||||
|
@ -46,3 +46,4 @@
|
|||
</ul>
|
||||
<br>
|
||||
<p style="color: hotpink;">𝐜𝐚𝐫𝐩 𝐰𝐨𝐳 𝐞𝐫𝐞</p>
|
||||
<p>gaming!</p>
|
|
@ -139,6 +139,7 @@
|
|||
|
||||
{% if request.path.endswith('/chat') %}
|
||||
<link rel="stylesheet" href="{{'css/chat.css' | asset}}">
|
||||
<link rel="stylesheet" href="{{'css/orgy.css' | asset}}">
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
|
|
|
@ -222,3 +222,120 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_users_online() %}
|
||||
<div class="border-right pb-1 px-3">
|
||||
<span id="online2" data-bs-html="true" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Users Online" class="text-muted">
|
||||
<i class="far fa-user fa-sm mr-1"></i>
|
||||
<span class="board-chat-count">0</span>
|
||||
</span>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_group_template(id, m) %}
|
||||
<div class="chat-group">
|
||||
<a class="font-weight-bold userlink" target="_blank" {% if m %}style="color:#{{m['namecolor']}}" href="/@{{m['username']}}" {% endif %}><div class="avatar profile-pic-20-wrapper mr-1"><img loading="lazy" class="avatar-pic pp20 mr-1" {% if m %}src="/pp/{{m['user_id']}}"{% endif %}><img class="avatar-hat profile-pic-20-hat hat" loading="lazy" {% if m %}src="{{m['hat']}}"{% endif %}></div>{% if m %}{{m['username']}}{% else %}NULL{% endif %}</a>
|
||||
<span class="text-black time ml-1 mb-3 text-center">{% if m %}{{m['time'] | timestamp}}{% else %}just now{% endif %}</span>
|
||||
<input hidden class="user_id" {% if m %}value="{{m['user_id']}}"{% endif %}>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_line_template(id, m, vlink) %}
|
||||
{% set quote_exists = m and m['quotes'] and messages.get(m['quotes']) %}
|
||||
{% set mentioned = m and vlink in m['text_html'] or (quote_exists and messages[m['quotes']]['user_id'] == v.id) %}
|
||||
<div class="chat-line {% if mentioned %}chat-mention{% endif %}" {% if m %}id="{{id}}"{% endif %}>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="text-muted chat-line-content">
|
||||
<div class="{% if not (m and m['quotes']) %}d-none{% endif %} quotes" style="font-size:12px">
|
||||
<a class="QuotedMessageLink" {% if m and m['quotes'] %}href="#{{m['quotes']}}"{% endif %}>
|
||||
<i class="fas fa-reply"></i>
|
||||
<span class="text-primary">@<span class="QuotedUser">
|
||||
{%- if quote_exists -%}
|
||||
{{messages[m['quotes']]['username']}}
|
||||
{%- endif -%}
|
||||
</span></span>:
|
||||
<em class="QuotedMessage text-break">
|
||||
{%- if quote_exists -%}
|
||||
{{messages[m['quotes']]['text']}}
|
||||
{%- endif -%}
|
||||
</em>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex">
|
||||
<span class="chat-message text-black text-break">
|
||||
{% if m %}
|
||||
{% if v.slurreplacer %}
|
||||
{{m['text_censored'] | safe}}
|
||||
{% else %}
|
||||
{{m['text_html'] | safe}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="text d-none">{% if m %}{{m['text']}}{% endif %}</span>
|
||||
<i class="quote btn fas fa-reply ml-auto" data-nonce="{{g.nonce}}" data-onclick="quote(this)"></i>
|
||||
{% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
|
||||
<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>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_window(vlink)%}
|
||||
<div id="shrink">
|
||||
<div id="chat-window" class="container p-0">
|
||||
{% set messages_list = messages.items()|list %}
|
||||
{% for id, m in messages_list %}
|
||||
{% set same = loop.index > 1 and m['user_id'] == messages_list[loop.index-2][1]['user_id'] %}
|
||||
{% if not same %}
|
||||
{% if loop.index > 1 %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{{chat_group_template(id, m)}}
|
||||
{% endif %}
|
||||
{{chat_line_template(id, m, vlink)}}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3"></div>
|
||||
<div id="quotes" class="mt-3 ml-3 mb-2 d-none" style="font-size:12px">
|
||||
<a id="QuotedMessageLink">
|
||||
<i class="fas fa-reply"></i> <span class="text-primary">@<span id="QuotedUser"></span></span>: <em id="QuotedMessage"></em>
|
||||
<button type="button" id="cancel" class="btn btn-secondary">Cancel</button>
|
||||
<input hidden id="quotes_id">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div id='message' class="d-none position-relative form-group d-flex">
|
||||
<div class="position-absolute text-muted text-small ml-1" style="bottom: -1.5rem; line-height: 1;">
|
||||
<span id="typing-indicator"></span>
|
||||
<span id="loading-indicator" class="d-none"></span>
|
||||
</div>
|
||||
<span class="my-auto">
|
||||
<i class="btn btn-secondary fas fa-smile-beam" style="font-size:1.3rem!important" data-nonce="{{g.nonce}}" data-onclick="loadEmojis('input-text')" data-bs-toggle="modal" data-bs-target="#emojiModal"></i>
|
||||
</span>
|
||||
|
||||
<span class="my-auto ml-1">
|
||||
<label class="btn btn-secondary format mb-0">
|
||||
<div class="mr-3" style="font-size:12px"><i class="fas fa-image" style="font-size:1.3rem!important"></i></div>
|
||||
<input autocomplete="off" id="file" accept="image/*" type="file" name="file" {% if g.is_tor %}disabled{% endif %} hidden>
|
||||
</label>
|
||||
<button type="button" class="text-danger text-lg font-weight-bold ml-2 remove-files d-none" data-bs-toggle="tooltip" title="Remove Files">X</button>
|
||||
</span>
|
||||
|
||||
<textarea id="input-text" minlength="1" maxlength="{% if SITE == 'rdrama.net' %}200{% else %}1000{% endif %}" {% if g.browser in ("iphone","mac") %}style="font-size:16px!important"{% endif %} class="file-ta form-control" placeholder="Message" autocomplete="off" autofocus rows="1"></textarea>
|
||||
|
||||
<i id="chatsend" data-nonce="{{g.nonce}}" data-onclick="send()" class="btn btn-secondary fas fa-reply ml-3 my-auto" style="transform:rotateY(180deg);font-size:1.3rem!important"></i>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro chat_users_list() %}
|
||||
<div class="col text-left d-none d-lg-block pt-3" style="max-width:300px">
|
||||
<h5>Users Online</h5>
|
||||
<div id="online" class="mt-3"></div>
|
||||
</div>
|
||||
{% endmacro %}
|
|
@ -0,0 +1,4 @@
|
|||
CREATE TABLE public.orgies (
|
||||
youtube_id character varying(12) NOT NULL,
|
||||
title character varying(1000) NOT NULL
|
||||
);
|
|
@ -24,6 +24,10 @@ server {
|
|||
proxy_pass http://localhost:5001/chat;
|
||||
include includes/headers;
|
||||
}
|
||||
location /old_chat {
|
||||
proxy_pass http://localhost:5001/old_chat;
|
||||
include includes/headers;
|
||||
}
|
||||
location =/offline.html {
|
||||
alias /rDrama/files/assets/offline.html;
|
||||
include includes/headers;
|
||||
|
|
|
@ -1126,6 +1126,13 @@ CREATE TABLE public.votes (
|
|||
coins smallint DEFAULT 1 NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- Name: orgies, Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
CREATE TABLE public.orgies (
|
||||
youtube_id character varying(12) NOT NULL,
|
||||
title character varying(1000) NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- Name: award_relationships id; Type: DEFAULT; Schema: public; Owner: -
|
||||
|
|
Loading…
Reference in New Issue