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.
@ -3173,4 +3173,4 @@ Normies can't understand the thrill of pinning the Weasel. Night spent chasing a
{[para]}
I am the “office manager” of AHS. Ive spent the past three years keeping spreadsheets and have inboxes full of ticket closures, and have written reports characterizing the response accuracy of Reddit AEO.
Would you like to escalate and mansplain my field of expertise to me more?
Would you like to escalate and mansplain my field of expertise to me more?