master
Aevann1 2022-02-16 06:33:13 +02:00
parent b46978d537
commit fb9c0a23dc
23 changed files with 250 additions and 63 deletions

View File

@ -228,7 +228,7 @@ class Comment(Base):
@property
@lazy
def shortlink_context(self):
def sl(self):
return f"/comment/{self.id}?context=8#context"
@property

View File

@ -0,0 +1,12 @@
from sqlalchemy import *
from sqlalchemy.orm import relationship
from files.__main__ import Base
class Exile(Base):
__tablename__ = "exiles"
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
sub = Column(String, ForeignKey("subs.name"), primary_key=True)
def __repr__(self):
return f"<Exile(user_id={self.user_id}, sub={self.sub})>"

View File

@ -204,6 +204,13 @@ class Submission(Base):
def fullname(self):
return f"t2_{self.id}"
@property
@lazy
def sl(self):
return f'/post/{self.id}'
@property
@lazy
def shortlink(self):

View File

@ -14,6 +14,7 @@ from .badges import *
from .clients import *
from .mod_logs import *
from .mod import *
from .exiles import *
from .sub_block import *
from files.__main__ import Base, cache
from files.helpers.security import *
@ -153,7 +154,11 @@ class User(Base):
@lazy
def mods(self, sub):
return self.id == AEVANN_ID or g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none()
return self.id == AEVANN_ID or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
@lazy
def exiled_from(self, sub):
return self.admin_level < 2 and bool(g.db.query(Exile.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
@property
@lazy

View File

@ -117,9 +117,9 @@ def sanitize(sanitized, noimages=False, alert=False, comment=False, edit=False):
if u:
sanitized = sanitized.replace(i.group(0), f'''<p><a href="/id/{u.id}"><img alt="@{u.username}'s profile picture" loading="lazy" src="/uid/{u.id}/pic" class="pp20">@{u.username}</a>''', 1)
else:
sanitized = re.sub('(^|\s|\n|<p>)\/?((r|u)\/(\w|-){3,25})', r'\1<a href="https://old.reddit.com/\2" rel="nofollow noopener noreferrer">\2</a>', sanitized, re.A)
sanitized = re.sub('(^|\s|\n|<p>)\/?((r|u)\/(\w|-){3,25})', r'\1<a href="https://old.reddit.com/\2" rel="nofollow noopener noreferrer">/\2</a>', sanitized, re.A)
sanitized = re.sub('(^|\s|\n|<p>)\/?(s\/(\w|-){3,25})', r'\1<a href="/\2" rel="nofollow noopener noreferrer">\2</a>', sanitized, re.A)
sanitized = re.sub('(^|\s|\n|<p>)\/?(s\/(\w|-){3,25})', r'\1<a href="/\2" rel="nofollow noopener noreferrer">/\2</a>', sanitized, re.A)
for i in re.finditer('(^|\s|\n|<p>)@((\w|-){1,25})', sanitized, re.A):
u = get_user(i.group(2), graceful=True)

View File

@ -85,13 +85,13 @@ def distribute(v, comment):
votes = g.db.query(CommentVote).filter_by(comment_id=comment)
coinsperperson = int(pool / votes.count())
cid = notif_comment(f"You won {coinsperperson} coins betting on [{post.permalink}]({post.permalink}) :marseyparty:")
cid = notif_comment(f"You won {coinsperperson} coins betting on [{post.title}]({post.sl}) :marseyparty:")
for vote in votes:
u = vote.user
u.coins += coinsperperson
add_notif(cid, u.id)
cid = notif_comment(f"You lost the 200 coins you bet on [{post.permalink}]({post.permalink}) :marseylaugh:")
cid = notif_comment(f"You lost the 200 coins you bet on [{post.title}]({post.sl}) :marseylaugh:")
cids = [x.id for x in post.bet_options]
cids.remove(comment)
votes = g.db.query(CommentVote).filter(CommentVote.comment_id.in_(cids)).all()
@ -1240,7 +1240,7 @@ def sticky_comment(cid, v):
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} has pinned your [comment]({comment.permalink})!"
message = f"@{v.username} has pinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
@ -1267,7 +1267,7 @@ def unsticky_comment(cid, v):
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} has unpinned your [comment]({comment.permalink})!"
message = f"@{v.username} has unpinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()

View File

@ -227,7 +227,7 @@ def award_post(pid, v):
author = post.author
if v.id != author.id:
msg = f"@{v.username} has given your [post]({post.permalink}) the {AWARDS[kind]['title']} Award!"
msg = f"@{v.username} has given your [post]({post.sl}) the {AWARDS[kind]['title']} Award!"
if note: msg += f"\n\n> {note}"
send_repeatable_notification(author.id, msg)
@ -235,7 +235,7 @@ def award_post(pid, v):
return {"error": "You can't use this award on yourself."}, 400
if kind == "ban":
link = f"[this post]({post.permalink})"
link = f"[this post]({post.sl})"
if not author.is_suspended:
author.ban(reason=f"1-Day ban award used by @{v.username} on /post/{post.id}", days=1)
@ -258,7 +258,7 @@ def award_post(pid, v):
author.is_banned = AUTOJANNY_ID
author.ban_reason = f"grass award used by @{v.username} on /post/{post.id}"
author.unban_utc = int(time.time()) + 30 * 86400
link = f"[this post]({post.permalink})"
link = f"[this post]({post.sl})"
send_repeatable_notification(author.id, f"Your account has been suspended permanently for {link}. You must [provide the admins](/contact) a timestamped picture of you touching grass to get unbanned!")
elif kind == "pin":
if post.stickied and post.stickied_utc:
@ -461,7 +461,7 @@ def award_comment(cid, v):
author = c.author
if v.id != author.id:
msg = f"@{v.username} has given your [comment]({c.permalink}) the {AWARDS[kind]['title']} Award!"
msg = f"@{v.username} has given your [comment]({c.sl}) the {AWARDS[kind]['title']} Award!"
if note: msg += f"\n\n> {note}"
send_repeatable_notification(author.id, msg)
@ -469,7 +469,7 @@ def award_comment(cid, v):
return {"error": "You can't use this award on yourself."}, 400
if kind == "ban":
link = f"[this comment]({c.permalink})"
link = f"[this comment]({c.sl})"
if not author.is_suspended:
author.ban(reason=f"1-Day ban award used by @{v.username} on /comment/{c.id}", days=1)
@ -492,7 +492,7 @@ def award_comment(cid, v):
author.is_banned = AUTOJANNY_ID
author.ban_reason = f"grass award used by @{v.username} on /comment/{c.id}"
author.unban_utc = int(time.time()) + 30 * 86400
link = f"[this comment]({c.permalink})"
link = f"[this comment]({c.sl})"
send_repeatable_notification(author.id, f"Your account has been suspended permanently for {link}. You must [provide the admins](/contact) a timestamped picture of you touching grass to get unbanned!")
elif kind == "pin":
if c.is_pinned and c.is_pinned_utc: c.is_pinned_utc += 3600

View File

@ -148,6 +148,9 @@ def api_comment(v):
parent_fullname = request.values.get("parent_fullname").strip()
parent_post = get_post(parent_submission, v=v)
sub = parent_post.sub
if sub and v.exiled_from(sub): return {"error": f"You're exiled from /s/{sub}"}, 403
if parent_post.club and not (v and (v.paid_dues or v.id == parent_post.author_id)): abort(403)
if parent_fullname.startswith("t2_"):
@ -926,7 +929,7 @@ def pin_comment(cid, v):
g.db.add(comment)
if v.id != comment.author_id:
message = f"@{v.username} (OP) has pinned your [comment]({comment.permalink})!"
message = f"@{v.username} (OP) has pinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
@ -949,7 +952,7 @@ def unpin_comment(cid, v):
g.db.add(comment)
if v.id != comment.author_id:
message = f"@{v.username} (OP) has unpinned your [comment]({comment.permalink})!"
message = f"@{v.username} (OP) has unpinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
return {"message": "Comment unpinned!"}
@ -969,7 +972,7 @@ def mod_pin(cid, v):
g.db.add(comment)
if v.id != comment.author_id:
message = f"@{v.username} (Mod) has pinned your [comment]({comment.permalink})!"
message = f"@{v.username} (Mod) has pinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
@ -989,7 +992,7 @@ def mod_unpin(cid, v):
g.db.add(comment)
if v.id != comment.author_id:
message = f"@{v.username} (Mod) has unpinned your [comment]({comment.permalink})!"
message = f"@{v.username} (Mod) has unpinned your [comment]({comment.sl})!"
send_repeatable_notification(comment.author_id, message)
g.db.commit()
return {"message": "Comment unpinned!"}

View File

@ -96,11 +96,11 @@ def publish(pid, v):
if not post.ghost:
notify_users = NOTIFY_USERS(post.body_html, v) | NOTIFY_USERS2(post.title, v)
cid = notif_comment(f"@{v.username} has mentioned you: [{post.title}]({post.permalink})")
cid = notif_comment(f"@{v.username} has mentioned you: [{post.title}]({post.sl})")
for x in notify_users:
add_notif(cid, x)
cid = notif_comment(f"@{v.username} has made a new post: [{post.title}]({post.permalink})", autojanny=True)
cid = notif_comment(f"@{v.username} has made a new post: [{post.title}]({post.sl})", autojanny=True)
for follow in v.followers:
user = get_account(follow.user_id)
if post.club and not user.paid_dues: continue
@ -126,7 +126,7 @@ def submit_get(v, sub=None):
if request.path.startswith('/s/') and not sub: abort(404)
return render_template("submit.html", SUBS=() if SITE_NAME == 'Drama' else tuple(x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()), v=v, sub=sub, ghost=submit_ghost(v,g.db))
return render_template("submit.html", SUBS=tuple(x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()), v=v, sub=sub, ghost=submit_ghost(v,g.db))
@app.get("/post/<pid>")
@app.get("/post/<pid>/<anything>")
@ -603,7 +603,7 @@ def edit_post(pid, v):
if not p.private and not p.ghost:
notify_users = NOTIFY_USERS(body_html, v) | NOTIFY_USERS2(title, v)
cid = notif_comment(f"@{v.username} has mentioned you: [{p.title}]({p.permalink})")
cid = notif_comment(f"@{v.username} has mentioned you: [{p.title}]({p.sl})")
for x in notify_users:
add_notif(cid, x)
@ -844,13 +844,6 @@ def thumbnail_thread(pid):
@limiter.limit("1/second;6/minute;200/hour;1000/day")
@auth_required
def submit_post(v, sub=None):
if not sub: sub = request.values.get("sub")
if sub:
sub = g.db.query(Sub.name).filter_by(name=sub.strip().lower()).one_or_none()
if not sub: abort(404)
sub = sub[0]
else: sub = None
title = request.values.get("title", "").strip()[:500].replace('','')
@ -859,15 +852,24 @@ def submit_post(v, sub=None):
body = request.values.get("body", "").strip().replace('','')
def error(error):
print(sub, flush=True)
if request.headers.get("Authorization") or request.headers.get("xhr"): error(error)
return render_template("submit.html", SUBS=() if SITE_NAME == 'Drama' else tuple(x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()), v=v, error=error, title=title, url=url, body=body, price=submit_ghost(v,g.db)), 400
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": error}, 403
return render_template("submit.html", SUBS=tuple(x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()), v=v, error=error, title=title, url=url, body=body, ghost=submit_ghost(v,g.db)), 400
if v.is_suspended: error( "You can't perform this action while banned.")
if not sub: sub = request.values.get("sub")
if sub:
sub = g.db.query(Sub.name).filter_by(name=sub.strip().lower()).one_or_none()
if not sub: abort(404)
sub = sub[0]
if v.exiled_from(sub): return error(f"You're exiled from /s/{sub}")
else: sub = None
if v.is_suspended: return error("You can't perform this action while banned.")
if v and v.patron:
if request.content_length > 8 * 1024 * 1024: error( "Max file size is 8 MB.")
elif request.content_length > 4 * 1024 * 1024: error( "Max file size is 4 MB.")
if request.content_length > 8 * 1024 * 1024: return error( "Max file size is 8 MB.")
elif request.content_length > 4 * 1024 * 1024: return error( "Max file size is 4 MB.")
if v.agendaposter and not v.marseyawarded: title = torture_ap(title, v.username)
@ -1060,7 +1062,7 @@ def submit_post(v, sub=None):
file.save("video.mp4")
with open("video.mp4", 'rb') as f:
try: url = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)]).json()['data']['link']
except: error( "Imgur error")
except: return error( "Imgur error")
if url.endswith('.'): url += 'mp4'
body += f"\n\n{url}"
else:
@ -1188,7 +1190,7 @@ def submit_post(v, sub=None):
file.save("video.mp4")
with open("video.mp4", 'rb') as f:
try: url = requests.request("POST", "https://api.imgur.com/3/upload", headers={'Authorization': f'Client-ID {IMGUR_KEY}'}, files=[('video', f)]).json()['data']['link']
except: error( "Imgur error")
except: return error( "Imgur error")
if url.endswith('.'): url += 'mp4'
new_post.url = url
else:
@ -1207,11 +1209,11 @@ def submit_post(v, sub=None):
notify_users = NOTIFY_USERS(body_html, v) | NOTIFY_USERS2(title, v)
cid = notif_comment(f"@{v.username} has mentioned you: [{title}]({new_post.permalink})")
cid = notif_comment(f"@{v.username} has mentioned you: [{title}]({new_post.sl})")
for x in notify_users:
add_notif(cid, x)
cid = notif_comment(f"@{v.username} has made a new post: [{title}]({new_post.permalink})", autojanny=True)
cid = notif_comment(f"@{v.username} has made a new post: [{title}]({new_post.sl})", autojanny=True)
for follow in v.followers:
user = get_account(follow.user_id)
if new_post.club and not user.paid_dues: continue

View File

@ -7,6 +7,119 @@ from .front import frontlist
valid_sub_regex = re.compile("^[a-zA-Z0-9_\-]{3,20}$")
@app.post("/exile/post/<pid>")
@is_not_permabanned
def exile_post(v, pid):
try: pid = int(pid)
except: abort(400)
p = get_post(pid)
sub = p.sub
if not sub: abort(400)
if not v.mods(sub): abort(403)
u = p.author
if u.admin_level < 2 and not u.exiled_from(sub):
exile = Exile(user_id=u.id, sub=sub)
g.db.add(exile)
send_notification(u.id, f"You have been exiled from /s/{sub} for [{p.title}]({p.sl})")
g.db.commit()
return {"message": "User exiled successfully!"}
@app.post("/unexile/post/<pid>")
@is_not_permabanned
def unexile_post(v, pid):
try: pid = int(pid)
except: abort(400)
p = get_post(pid)
sub = p.sub
if not sub: abort(400)
if not v.mods(sub): abort(403)
u = p.author
if u.exiled_from(sub):
exile = g.db.query(Exile).filter_by(user_id=u.id, sub=sub).one_or_none()
g.db.delete(exile)
send_notification(u.id, f"Your exile from /s/{sub} has been revoked!")
g.db.commit()
return {"message": "User unexiled successfully!"}
@app.post("/exile/comment/<cid>")
@is_not_permabanned
def exile_comment(v, cid):
try: cid = int(cid)
except: abort(400)
c = get_comment(cid)
sub = c.post.sub
if not sub: abort(400)
if not v.mods(sub): abort(403)
u = c.author
if u.admin_level < 2 and not u.exiled_from(sub):
exile = Exile(user_id=u.id, sub=sub)
g.db.add(exile)
send_notification(u.id, f"You have been exiled from /s/{sub} for [{c.permalink}]({c.sl})")
g.db.commit()
return {"message": "User exiled successfully!"}
@app.post("/unexile/comment/<cid>")
@is_not_permabanned
def unexile_comment(v, cid):
try: cid = int(cid)
except: abort(400)
c = get_comment(cid)
sub = c.post.sub
if not sub: abort(400)
if not v.mods(sub): abort(403)
u = c.author
if u.exiled_from(sub):
exile = g.db.query(Exile).filter_by(user_id=u.id, sub=sub).one_or_none()
g.db.delete(exile)
send_notification(u.id, f"Your exile from /s/{sub} has been revoked!")
g.db.commit()
return {"message": "User unexiled successfully!"}
@app.post("/s/<sub>/block")
@auth_required
def block_sub(v, sub):

View File

@ -15,7 +15,7 @@
{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% if v.agendaposter %}
<style>
html {
@ -39,7 +39,7 @@
{% endif %}
{% else %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
{% endif %}
</head>

View File

@ -214,6 +214,13 @@
{% endfor %}
{% endif %}
{% if c.post %}
{% set sub = c.post.sub %}
{% if sub and c.author.exiled_from(sub) %}
<a role="button"><i class="fad fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User has been exiled from /s/{{sub}}"></i></a>
{% endif %}
{% endif %}
{% if c.bannedfor %}
<a role="button"><i class="fad fa-gavel text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User was banned for this comment{% if c.author.banned_by %} by @{{c.author.banned_by.username}}{% endif %}"></i></a>
{% endif %}
@ -490,7 +497,7 @@
<a class="btn caction nobackground px-1 text-muted" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
<button class="btn caction py-0 nobackground px-1 text-muted copy-link" role="button" role="button" data-clipboard-text="{% if SITE_NAME == 'Drama' %}https://rdrama.com{{c.shortlink_context}}{% else %}{{c.permalink}}{% endif %}"><i class="fas fa-copy"></i>Copy link</button>
<button class="btn caction py-0 nobackground px-1 text-muted copy-link" role="button" role="button" data-clipboard-text="{% if SITE_NAME == 'Drama' %}https://rdrama.com{{c.sl}}{% else %}{{c.permalink}}{% endif %}"><i class="fas fa-copy"></i>Copy link</button>
{% if v %}
<button class="btn caction py-0 nobackground px-1 text-muted" data-bs-toggle="modal" data-bs-target="#reportCommentModal" onclick="report_commentModal('{{c.id}}','{{c.author_name}}',)"><i class="fas fa-flag fa-fw"></i>Report</button>
@ -571,14 +578,22 @@
{% if v.admin_level > 1 %}
{% if "/reported/" in request.path %}
<button class="dropdown-item list-inline-item text-muted text-success" onclick="approveComment('{{c.id}}')"><i class="fas fa-check text-success fa-fw"></i>Approve</button>
<button class="dropdown-item list-inline-item text-muted text-danger" onclick="removeComment('{{c.id}}')"><i class="fas fa-ban text-danger fa-fw"></i>Remove</button>
<button class="dropdown-item list-inline-item text-success" onclick="approveComment('{{c.id}}')"><i class="fas fa-check text-success fa-fw"></i>Approve</button>
<button class="dropdown-item list-inline-item text-danger" onclick="removeComment('{{c.id}}')"><i class="fas fa-ban text-danger fa-fw"></i>Remove</button>
{% else %}
<button id="approve-{{c.id}}" class="dropdown-item list-inline-item text-success d-none {% if c.is_banned %}d-md-block{% endif %} text-success" onclick="approveComment('{{c.id}}','approve-{{c.id}}','remove-{{c.id}}')"><i class="fas fa-check text-success fa-fw"></i>Approve</button>
<button id="remove-{{c.id}}" class="dropdown-item list-inline-item text-danger d-none {% if not c.is_banned %}d-md-block{% endif %} text-danger" onclick="removeComment('{{c.id}}','approve-{{c.id}}','remove-{{c.id}}')"><i class="fas fa-ban text-danger fa-fw"></i>Remove</button>
<button id="approve-{{c.id}}" class="dropdown-item list-inline-item d-none {% if c.is_banned %}d-md-block{% endif %} text-success" onclick="approveComment('{{c.id}}','approve-{{c.id}}','remove-{{c.id}}')"><i class="fas fa-check text-success fa-fw"></i>Approve</button>
<button id="remove-{{c.id}}" class="dropdown-item list-inline-item d-none {% if not c.is_banned %}d-md-block{% endif %} text-danger" onclick="removeComment('{{c.id}}','approve-{{c.id}}','remove-{{c.id}}')"><i class="fas fa-ban text-danger fa-fw"></i>Remove</button>
{% endif %}
{% endif %}
{% if c.post %}
{% set sub = c.post.sub %}
{% if sub and v.mods(sub) %}
<button id="exile-{{c.id}}" class="d-none {% if not c.author.exiled_from(sub) %}d-md-block{% endif %} dropdown-item list-inline-item text-danger" onclick="post_toast2(this,'/exile/comment/{{c.id}}','exile-{{c.id}}','unexile-{{c.id}}')"><i class="fas fa-campfire text-danger"></i>Exile user</button>
<button id="unexile-{{c.id}}" class="d-none {% if c.author.exiled_from(sub) %}d-md-block{% endif %} dropdown-item list-inline-item text-success" onclick="post_toast2(this,'/unexile/comment/{{c.id}}','exile-{{c.id}}','unexile-{{c.id}}')"><i class="fas fa-campfire text-success"></i>Unexile user</button>
{% endif %}
{% endif %}
{% if c.parent_submission and (c.author_id==v.id or v.admin_level > 1) %}
<button id="unmark-{{c.id}}" class="dropdown-item list-inline-item d-none {% if c.over_18 %}d-md-block{% endif %} text-danger" onclick="post_toast3(this,'/toggle_comment_nsfw/{{c.id}}','mark-{{c.id}}','unmark-{{c.id}}')"><i class="fas fa-eye-evil text-danger fa-fw"></i>Unmark +18</button>
<button id="mark-{{c.id}}" class="dropdown-item list-inline-item d-none {% if not c.over_18 %}d-md-block{% endif %} text-danger" onclick="post_toast3(this,'/toggle_comment_nsfw/{{c.id}}','mark-{{c.id}}','unmark-{{c.id}}')"><i class="fas fa-eye-evil text-danger fa-fw"></i>Mark +18</button>
@ -698,7 +713,7 @@
{% if not c.ghost %}<a href="/votes?link={{c.fullname}}"><li class="list-group-item"><i class="fas fa-arrows-v"></i>Votes</li></a>{% endif %}
<a role="button" role="button" class="list-group-item copy-link" data-bs-dismiss="modal" data-clipboard-text="{% if SITE_NAME == 'Drama' %}https://rdrama.com{{c.shortlink_context}}{% else %}{{c.permalink}}{% endif %}"><i class="fas fa-copy"></i>Copy link</a>
<a role="button" role="button" class="list-group-item copy-link" data-bs-dismiss="modal" data-clipboard-text="{% if SITE_NAME == 'Drama' %}https://rdrama.com{{c.sl}}{% else %}{{c.permalink}}{% endif %}"><i class="fas fa-copy"></i>Copy link</a>
<a class="list-group-item" href="{{c.permalink}}"><i class="fas fa-book-open"></i>Context</a>
@ -747,6 +762,14 @@
<a id="unpin2-{{c.id}}" class="list-group-item {% if not c.is_pinned %}d-none{% endif %} text-info" role="button" data-bs-target="#actionsModal-{{c.id}}" onclick="post_toast2(this,'/mod_unpin/{{c.id}}','pin2-{{c.id}}','unpin2-{{c.id}}')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-info"></i>Unpin</a>
{% endif %}
{% endif %}
{% if c.post %}
{% set sub = c.post.sub %}
{% if sub and v.mods(sub) %}
<a data-bs-dismiss="modal" id="exile2-{{c.id}}" class="{% if c.author.exiled_from(sub) %}d-none{% endif %} list-group-item text-danger" onclick="post_toast2(this,'/exile/comment/{{c.id}}','exile2-{{c.id}}','unexile2-{{c.id}}')"><i class="fas fa-campfire text-danger"></i>Exile user</a>
<a data-bs-dismiss="modal" id="unexile2-{{c.id}}" class="{% if not c.author.exiled_from(sub) %}d-none{% endif %} list-group-item text-success" onclick="post_toast2(this,'/unexile/comment/{{c.id}}','exile2-{{c.id}}','unexile2-{{c.id}}')"><i class="fas fa-campfire text-success"></i>Unexile user</a>
{% endif %}
{% endif %}
{% endif %}
</ul>
</div>

View File

@ -7,7 +7,7 @@
<script src="/static/assets/js/bootstrap.js?a=240"></script>
{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128">
<link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% if v.agendaposter %}
<style>
@ -32,7 +32,7 @@
{% endif %}
{% else %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
{% endif %}
{% if sub and sub.css and not request.path.endswith('settings') %}

View File

@ -6,7 +6,7 @@
{% block content %}
{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% if v.agendaposter %}
<style>
html {
@ -30,7 +30,7 @@
{% endif %}
{% else %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
{% endif %}
<div class="row justify-content-around">

View File

@ -18,7 +18,7 @@
{% endblock %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128">
<link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
</head>

View File

@ -14,7 +14,7 @@
<title>2-Step Login - {{SITE_NAME}}</title>
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
</head>

View File

@ -34,7 +34,7 @@
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% if v.agendaposter %}
<style>
html {

View File

@ -39,10 +39,10 @@
{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% else %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
{% endif %}
</head>

View File

@ -31,7 +31,7 @@
<title>{% if ref_user %}{{ref_user.username}} invites you to {{SITE_NAME}}{% else %}Sign up - {{SITE_NAME}}{% endif %}</title>
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
</head>

View File

@ -32,7 +32,7 @@
<title>{% if ref_user %}{{ref_user.username}} invites you to {{SITE_NAME}}{% else %}{{SITE_NAME}}{% endif %}</title>
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
</head>

View File

@ -398,7 +398,10 @@
{% endif %}
{% if p.sub and v.mods(p.sub) %}
<button class="nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger text-center mr-3"></i>Kick</button>
<button data-bs-dismiss="modal" class="nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger text-center mr-3"></i>Kick</button>
<button data-bs-dismiss="modal" id="exile2" class="{% if p.author.exiled_from(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast2(this,'/exile/post/{{p.id}}','exile2','unexile2')"><i class="fas fa-campfire mr-3 text-danger"></i>Exile user</button>
<button data-bs-dismiss="modal" id="unexile2" class="{% if not p.author.exiled_from(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" onclick="post_toast2(this,'/unexile/post/{{p.id}}','exile2','unexile2')"><i class="fas fa-campfire mr-3 text-success"></i>Unexile user</button>
{% endif %}
</ul>
</div>
@ -489,6 +492,10 @@
<a href='/s/{{p.sub}}'>/s/{{p.sub}}</a>&nbsp;&nbsp;
{% endif %}
{% if p.sub and p.author.exiled_from(p.sub) %}
<a role="button"><i class="fad fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User has been exiled from /s/{{p.sub}}"></i></a>
{% endif %}
{% if p.bannedfor %}
<a role="button"><i class="fad fa-gavel text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User was banned for this post{% if p.author.banned_by %} by @{{p.author.banned_by.username}}{% endif %}"></i></a>
{% endif %}
@ -759,6 +766,10 @@
{% if p.sub and v.mods(p.sub) %}
<a class="dropdown-item list-inline-item text-danger" role="button" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger"></i>Kick</a>
<a id="exile" class="{% if p.author.exiled_from(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-danger" role="button" onclick="post_toast2(this,'/exile/post/{{p.id}}','exile','unexile')"><i class="fas fa-campfire text-danger"></i>Exile user</a>
<a id="unexile" class="{% if not p.author.exiled_from(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-success" role="button" onclick="post_toast2(this,'/unexile/post/{{p.id}}','exile','unexile')"><i class="fas fa-campfire text-success"></i>Unexile user</a>
{% endif %}

View File

@ -156,6 +156,10 @@
<a href='/s/{{p.sub}}'>/s/{{p.sub}}</a>&nbsp;&nbsp;
{% endif %}
{% if p.sub and p.author.exiled_from(p.sub) %}
<a role="button"><i class="fad fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User has been exiled from /s/{{p.sub}}"></i></a>
{% endif %}
{% if p.bannedfor %}
<a role="button"><i class="fad fa-gavel text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="User was banned for this post{% if p.author.banned_by %} by @{{p.author.banned_by.username}}{% endif %}"></i></a>
{% endif %}
@ -165,6 +169,7 @@
<i class="{{a.class_list}} px-1" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="{{a.title}} Award{% if a.kind != 'ghosts' %} given by @{{a.user.username}}{% endif %}"></i>
{% endfor %}
{% endif %}
{% if v and v.admin_level > 1 and p.author.shadowbanned %}
<i class="fas fa-user-times text-admin" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-original-title="Shadowbanned by @{{p.author.shadowbanned}}"></i>
{% endif %}
@ -297,6 +302,9 @@
{% if p.sub and v.mods(p.sub) %}
<a class="dropdown-item list-inline-item text-danger" role="button" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger"></i>Kick</a>
<a id="exile-{{p.id}}" class="{% if p.author.exiled_from(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-danger" role="button" onclick="post_toast2(this,'/exile/post/{{p.id}}','exile-{{p.id}}','unexile-{{p.id}}')"><i class="fas fa-campfire text-danger"></i>Exile user</a>
<a id="unexile-{{p.id}}" class="{% if not p.author.exiled_from(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-success" role="button" onclick="post_toast2(this,'/unexile/post/{{p.id}}','exile-{{p.id}}','unexile-{{p.id}}')"><i class="fas fa-campfire text-success"></i>Unexile user</a>
{% endif %}
@ -455,7 +463,10 @@
{% endif %}
{% if p.sub and v.mods(p.sub) %}
<button class="nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger text-center mr-3"></i>Kick</button>
<button data-bs-dismiss="modal" class="nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger text-center mr-3"></i>Kick</button>
<button data-bs-dismiss="modal" id="exile2-{{p.id}}" class="{% if p.author.exiled_from(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" onclick="post_toast2(this,'/exile/post/{{p.id}}','exile2-{{p.id}}','unexile2-{{p.id}}')"><i class="fas fa-campfire text-danger mr-3 "></i>Exile user</button>
<button data-bs-dismiss="modal" id="unexile2-{{p.id}}" class="{% if not p.author.exiled_from(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" onclick="post_toast2(this,'/unexile/post/{{p.id}}','exile2-{{p.id}}','unexile2-{{p.id}}')"><i class="fas fa-campfire text-success mr-3 "></i>Unexile user</button>
{% endif %}
</ul>
</div>

View File

@ -26,7 +26,7 @@
{% block stylesheets %}
{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128"><link rel="stylesheet" href="/static/assets/css/{{v.theme}}.css?a=21">
{% if v.agendaposter %}
<style>
html {
@ -50,7 +50,7 @@
{% endif %}
{% else %}
<style>:root{--primary:#{{config('DEFAULT_COLOR')}}</style>
<link rel="stylesheet" href="/static/assets/css/main.css?a=127">
<link rel="stylesheet" href="/static/assets/css/main.css?a=128">
<link rel="stylesheet" href="/static/assets/css/{{config('DEFAULT_THEME')}}.css?a=21">
{% endif %}
{% endblock %}
@ -79,7 +79,7 @@
<input autocomplete="off" type="hidden" name="formkey" value="{{v.formkey}}">
{% if SITE_NAME == 'Ruqqus' %}
{% if SITE_NAME == 'Ruqqus' or sub %}
<label class='mt-4' for="title">Sub</label>
<div class="input-group mb2">