Merge branch 'master' into docs

pull/11/head^2
Nekobit 2022-11-25 22:27:15 +00:00
commit 2e1d2cb774
16 changed files with 67 additions and 2099 deletions

View File

@ -3528,6 +3528,11 @@ small, .small {
.post-meta::-webkit-scrollbar {
display: none;
}
.ghost-post .post-meta {
height: 30px;
}
.sub-flair {
padding: 3px 5px 2px 5px;
border-radius: 5px;

File diff suppressed because it is too large Load Diff

View File

@ -873,6 +873,24 @@ class User(Base):
def userblocks(self):
return [x[0] for x in g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all()]
def get_relationship_count(self, relationship_cls):
# TODO: deduplicate (see routes/users.py)
if relationship_cls in [SaveRelationship, Subscription]:
query = relationship_cls.submission_id
join = relationship_cls.post
cls = Submission
elif relationship_cls is CommentSaveRelationship:
query = relationship_cls.comment_id
join = relationship_cls.comment
cls = Comment
else:
raise TypeError("Relationships supported is SaveRelationship, Subscription, CommentSaveRelationship")
query = g.db.query(query).join(join).filter(relationship_cls.user_id == self.id)
if not self.admin_level >= PERMS['POST_COMMENT_MODERATION']:
query = query.filter(cls.is_banned == False, cls.deleted_utc == 0)
return query.count()
@property
@lazy
def saved_idlist(self):
@ -895,17 +913,17 @@ class User(Base):
@property
@lazy
def saved_count(self):
return g.db.query(SaveRelationship).filter_by(user_id=self.id).count()
return self.get_relationship_count(SaveRelationship)
@property
@lazy
def saved_comment_count(self):
return g.db.query(CommentSaveRelationship).filter_by(user_id=self.id).count()
return self.get_relationship_count(CommentSaveRelationship)
@property
@lazy
def subscribed_count(self):
return g.db.query(Subscription).filter_by(user_id=self.id).count()
return self.get_relationship_count(Subscription)
@property
@lazy

View File

@ -145,6 +145,7 @@ if SITE_NAME == 'rDrama':
"kys ": "keep yourself safe ",
"republican": 'republiKKKan',
"america": 'ameriKKKa',
"it's almost as if": "I'm a retard but",
}
SLURS.update(RDRAMA_SLURS)
@ -153,7 +154,6 @@ PROFANITIES = {
'fuck': 'frick',
' ass ': ' butt ',
'shitting': 'pooping',
'lmao': 'lmbo',
'damn': 'darn',
'bastard': 'fatherless child',
'bitch': 'b-word',
@ -436,6 +436,7 @@ MODMAIL_ID = 2
POLL_THREAD = 0
POLL_BET_COINS = 200
POLL_MAX_OPTIONS = 10
WELCOME_MSG = f"Welcome to {SITE_NAME}!"
LOTTERY_TICKET_COST = 12
@ -1398,6 +1399,7 @@ NOTIFIED_USERS = {
'snakes': SNAKES_ID,
'sneks': SNAKES_ID,
'snekky': SNAKES_ID,
'snekchad': SNAKES_ID,
'jc': JUSTCOOL_ID,
'justcool': JUSTCOOL_ID,
'geese': GEESE_ID,

View File

@ -2,7 +2,7 @@ from typing import Callable, Iterable, List, Optional, Union
from flask import *
from sqlalchemy import and_, any_, or_
from sqlalchemy.orm import joinedload, selectinload
from sqlalchemy.orm import joinedload, selectinload, Query
from files.classes import Comment, CommentVote, Hat, Sub, Submission, User, UserBlock, Vote
from files.helpers.const import AUTOJANNY_ID
@ -145,7 +145,7 @@ def get_post(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Option
return x
def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False) -> List[Submission]:
def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra:Optional[Callable[[Query], Query]]=None) -> List[Submission]:
if not pids: return []
if v:
@ -178,6 +178,8 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False) -> Li
else:
query = g.db.query(Submission).filter(Submission.id.in_(pids))
if extra: query = extra(query)
if eager:
query = query.options(
selectinload(Submission.author).options(
@ -276,12 +278,14 @@ def add_vote_and_block_props(target:Union[Submission, Comment], v:Optional[User]
target = add_block_props(target, v)
return add_vote_props(target, v, vote_cls)
def get_comments(cids:Iterable[int], v:Optional[User]=None) -> List[Comment]:
def get_comments(cids:Iterable[int], v:Optional[User]=None, extra:Optional[Callable[[Query], Query]]=None) -> List[Comment]:
if not cids: return []
if v:
output = get_comments_v_properties(v, True, None, Comment.id.in_(cids))[1]
output = get_comments_v_properties(v, True, None, Comment.id.in_(cids))[1] # TODO: support 'extra' for get_comments_v_properties
else:
output = g.db.query(Comment).join(Comment.author).filter(User.shadowbanned == None, Comment.id.in_(cids)).all()
output = g.db.query(Comment).join(Comment.author)
if extra: output = extra(output)
output = output.filter(User.shadowbanned == None, Comment.id.in_(cids)).all()
return sorted(output, key=lambda x: cids.index(x.id))
def get_comments_v_properties(v:User, include_shadowbanned=True, should_keep_func:Optional[Callable[[Comment], bool]]=None, *criterion):

View File

@ -133,12 +133,12 @@ def comment(v):
abort(403, "You can't reply to users who have blocked you or users that you have blocked.")
options = []
for i in poll_regex.finditer(body):
for i in list(poll_regex.finditer(body))[:POLL_MAX_OPTIONS]:
options.append(i.group(1))
body = body.replace(i.group(0), "")
choices = []
for i in choice_regex.finditer(body):
for i in list(choice_regex.finditer(body))[:POLL_MAX_OPTIONS]:
choices.append(i.group(1))
body = body.replace(i.group(0), "")
@ -391,7 +391,7 @@ def edit_comment(cid, v):
elif v.bird and len(body) > 140:
abort(403, "You have to type less than 140 characters!")
for i in poll_regex.finditer(body):
for i in list(poll_regex.finditer(body))[:POLL_MAX_OPTIONS]:
body = body.replace(i.group(0), "")
body_html = filter_emojis_only(i.group(1))
if len(body_html) > 500: abort(400, "Poll option too long!")
@ -402,7 +402,7 @@ def edit_comment(cid, v):
)
g.db.add(option)
for i in choice_regex.finditer(body):
for i in list(choice_regex.finditer(body))[:POLL_MAX_OPTIONS]:
body = body.replace(i.group(0), "")
body_html = filter_emojis_only(i.group(1))
if len(body_html) > 500: abort(400, "Poll option too long!")

View File

@ -151,7 +151,7 @@ def logout(v):
@auth_desired
def sign_up_get(v):
if not get_setting('Signups'):
return {"error": "New account registration is currently closed. Please come back later."}, 403
abort(403, "New account registration is currently closed. Please come back later.")
if v: return redirect(SITE_FULL)
@ -201,7 +201,7 @@ def sign_up_get(v):
@auth_desired
def sign_up_post(v):
if not get_setting('Signups'):
return {"error": "New account registration is currently closed. Please come back later."}, 403
abort(403, "New account registration is currently closed. Please come back later.")
if v: abort(403)

View File

@ -360,7 +360,7 @@ def edit_post(pid, v):
)
g.db.add(bet)
for i in poll_regex.finditer(body):
for i in list(poll_regex.finditer(body))[:10]:
body = body.replace(i.group(0), "")
body_html = filter_emojis_only(i.group(1))
if len(body_html) > 500: abort(400, "Poll option too long!")
@ -371,7 +371,7 @@ def edit_post(pid, v):
)
g.db.add(option)
for i in choice_regex.finditer(body):
for i in list(choice_regex.finditer(body))[:10]:
body = body.replace(i.group(0), "")
body_html = filter_emojis_only(i.group(1))
if len(body_html) > 500: abort(400, "Poll option too long!")
@ -754,12 +754,12 @@ def submit_post(v, sub=None):
body = body.replace(i.group(0), "")
options = []
for i in poll_regex.finditer(body):
for i in list(poll_regex.finditer(body))[:10]:
options.append(i.group(1))
body = body.replace(i.group(0), "")
choices = []
for i in choice_regex.finditer(body):
for i in list(choice_regex.finditer(body))[:10]:
choices.append(i.group(1))
body = body.replace(i.group(0), "")
@ -1075,6 +1075,7 @@ extensions = IMAGE_FORMATS + VIDEO_FORMATS + AUDIO_FORMATS
@ratelimit_user("3/minute")
@auth_required
def get_post_title(v):
POST_TITLE_TIMEOUT = 5
url = request.values.get("url")
if not url or '\\' in url: abort(400)
url = url.strip()
@ -1084,7 +1085,8 @@ def get_post_title(v):
if any((checking_url.endswith(f'.{x}') for x in extensions)):
abort(400)
try: x = requests.get(url, headers=titleheaders, timeout=5, proxies=proxies)
try:
x = gevent.with_timeout(POST_TITLE_TIMEOUT, requests.get, url, headers=titleheaders, timeout=POST_TITLE_TIMEOUT, proxies=proxies)
except: abort(400)
content_type = x.headers.get("Content-Type")

View File

@ -235,9 +235,7 @@ def submit_contact(v):
execute_blackjack(v, new_comment, new_comment.body_html, 'modmail')
new_comment.top_comment_id = new_comment.id
admins = g.db.query(User).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'])
if SITE == 'watchpeopledie.tv':
admins = admins.filter(User.id != AEVANN_ID)
admins = g.db.query(User).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != AEVANN_ID)
for admin in admins.all():
notif = Notification(comment_id=new_comment.id, user_id=admin.id)

View File

@ -550,9 +550,7 @@ def messagereply(v):
top_comment = c.top_comment(g.db)
if top_comment.sentto == MODMAIL_ID:
admins = g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != v.id)
if SITE == 'watchpeopledie.tv':
admins = admins.filter(User.id != AEVANN_ID)
admins = g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != v.id, User.id != AEVANN_ID)
admins = [x[0] for x in admins.all()]
@ -937,7 +935,6 @@ def user_profile_name(username):
return redirect(x.profile_url)
def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone=False):
PAGE_SIZE = 25
if relationship_cls in [SaveRelationship, Subscription]:
query = relationship_cls.submission_id
join = relationship_cls.post
@ -951,12 +948,18 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone
ids = [x[0] for x in g.db.query(query).join(join).filter(relationship_cls.user_id == v.id).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()]
next_exists = len(ids) > PAGE_SIZE
ids = ids[:PAGE_SIZE]
extra = None
if not v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
extra = lambda q:q.filter(cls.is_banned == False, cls.deleted_utc == 0)
if cls is Submission:
listing = get_posts(ids, v=v, eager=True)
listing = get_posts(ids, v=v, eager=True, extra=extra)
elif cls is Comment:
listing = get_comments(ids, v=v)
listing = get_comments(ids, v=v, extra=extra)
else:
raise TypeError("Only supports Submissions and Comments. This is probably the result of a bug with *this* function")
if v.client: return {"data": [x.json(g.db) for x in listing]}
return render_template(template, u=v, v=v, listing=listing, page=page, next_exists=next_exists, standalone=standalone)

View File

@ -18,6 +18,7 @@ def session_init():
session["session_id"] = secrets.token_hex(49)
def calc_users(v):
if g.is_api_or_xhr: return
loggedin = cache.get(f'{SITE}_loggedin') or {}
loggedout = cache.get(f'{SITE}_loggedout') or {}
timestamp = int(time.time())

View File

@ -78,7 +78,7 @@
<div id="post-root" class="col-12">
<div class="card border-0 mt-3 {% if p.stickied %}stickied{% endif %} {% if voted==1 %}upvoted{% elif voted==-1 %} downvoted{% endif %}">
<div id="post-{{p.id}}" class="actual-post {% if p.is_banned %}banned{% endif %} {% if p.deleted_utc %}deleted {% endif %} {% if p.award_count('tilt', v) %}p-3{% endif %} {% if p.award_count('glowie', v) %}glow{% endif %} d-flex flex-row-reverse flex-nowrap justify-content-end">
<div id="post-{{p.id}}" class="actual-post {% if p.ghost %}ghost-post{% endif %} {% if p.is_banned %}banned{% endif %} {% if p.deleted_utc %}deleted {% endif %} {% if p.award_count('tilt', v) %}p-3{% endif %} {% if p.award_count('glowie', v) %}glow{% endif %} d-flex flex-row-reverse flex-nowrap justify-content-end">
{% if not p.is_image and p.thumb_url and not p.embed_url %}
<div class="card-header bg-transparent border-0 d-none d-md-flex flex-row flex-nowrap pl-3 p-0">

View File

@ -45,7 +45,7 @@
</div>
{% endif %}
<div id="post-{{p.id}}" class="actual-post {% if p.unread %}unread{% else %}card{% endif %} {% if p.is_banned %} banned{% endif %}{% if p.deleted_utc %} deleted{% endif %}{% if p.stickied %} stickied{% endif %}{% if voted==1 %} upvoted{% elif voted==-1 %} downvoted{% endif %}{% if p.over_18 %} nsfw{% endif %}">
<div id="post-{{p.id}}" class="actual-post {% if p.ghost %}ghost-post{% endif %} {% if p.unread %}unread{% else %}card{% endif %} {% if p.is_banned %} banned{% endif %}{% if p.deleted_utc %} deleted{% endif %}{% if p.stickied %} stickied{% endif %}{% if voted==1 %} upvoted{% elif voted==-1 %} downvoted{% endif %}{% if p.over_18 %} nsfw{% endif %}">
<div class="d-flex flex-row-reverse flex-md-row flex-nowrap" style="align-items:flex-start">
<div class="voting my-2 d-none d-md-flex pr-2">

View File

@ -105,7 +105,7 @@
</div>
<div class="col text-right">
{% if error %}<span class="text-danger text-large mr-2">{{error | safe}}</span>{% endif %}
<button type="submit" class="btn btn-primary" id="create_button" type="submit" onclick="disable(this)" disabled>Post</button>
<button type="submit" class="btn btn-primary" id="create_button" type="submit" onclick="disable(this)">Post</button>
</div>
</div>
</div>

View File

@ -1,52 +0,0 @@
#!/usr/bin/python3
import subprocess
import sys
# we want to leave the container in whatever state it currently is, so check to see if it's running
docker_inspect = subprocess.run([
"docker",
"container",
"inspect",
"-f", "{{.State.Status}}",
"rDrama",
],
capture_output = True,
).stdout.decode("utf-8").strip()
was_running = docker_inspect == "running"
# update containers, just in case they're out of date
if was_running:
print("Updating containers . . .", flush=True)
else:
print("Starting containers . . .", flush=True)
subprocess.run([
"docker-compose",
"up",
"--build",
"-d",
],
check = True,
)
# run the test
print("Running test . . .", flush=True)
result = subprocess.run([
"docker",
"exec",
"rDrama",
"bash", "-c", "cd service && python3 -m pytest -s"
])
if not was_running:
# shut down, if we weren't running in the first place
print("Shutting down containers . . .", flush=True)
subprocess.run([
"docker-compose",
"stop",
],
check = True,
)
sys.exit(result.returncode)

View File

@ -2993,7 +2993,7 @@ https://media.giphy.com/media/3oz8xLd9DJq2l2VFtu/giphy.webp
{[para]}
Rape
{[para]}
Here is the Contributors listing for the github project: https://github.com/Aevann1/rDrama
Here is the Contributors listing for the github project: https://fsdfsd.net/rDrama/rDrama/activity
That list shows CarpathianFlorist as a contributor. CarpathianFlorist is a Racially Motivated Violent Extremist - a White Identity Extremist - who was involved in /r/MillionDollarExtreme and its many hundreds of spinoffs and descendants. I've collected dozens of his Reddit accts.