gdfsd
This commit is contained in:
parent
73bf0b3a30
commit
002e55476c
21 changed files with 1 additions and 129 deletions
|
@ -98,8 +98,7 @@ def before_request():
|
||||||
|
|
||||||
g.timestamp = int(time.time())
|
g.timestamp = int(time.time())
|
||||||
|
|
||||||
#do not access session for static files
|
if not request.path.startswith("/assets") and not request.path.startswith("/images") and not request.path.startswith("/hostedimages"):
|
||||||
if not request.path.startswith("/assets"):
|
|
||||||
session.permanent = True
|
session.permanent = True
|
||||||
if not session.get("session_id"): session["session_id"] = secrets.token_hex(16)
|
if not session.get("session_id"): session["session_id"] = secrets.token_hex(16)
|
||||||
|
|
||||||
|
|
|
@ -102,9 +102,7 @@ class Comment(Base):
|
||||||
now = time.gmtime()
|
now = time.gmtime()
|
||||||
ctd = time.gmtime(self.created_utc)
|
ctd = time.gmtime(self.created_utc)
|
||||||
|
|
||||||
# compute number of months
|
|
||||||
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
||||||
# remove a month count if current day of month < creation day of month
|
|
||||||
if now.tm_mday < ctd.tm_mday:
|
if now.tm_mday < ctd.tm_mday:
|
||||||
months -= 1
|
months -= 1
|
||||||
|
|
||||||
|
@ -234,7 +232,6 @@ class Comment(Base):
|
||||||
'score': self.score,
|
'score': self.score,
|
||||||
'upvotes': self.upvotes,
|
'upvotes': self.upvotes,
|
||||||
'downvotes': self.downvotes,
|
'downvotes': self.downvotes,
|
||||||
#'award_count': self.award_count,
|
|
||||||
'is_bot': self.is_bot,
|
'is_bot': self.is_bot,
|
||||||
'flags': flags,
|
'flags': flags,
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,9 +53,7 @@ class ModAction(Base):
|
||||||
now = time.gmtime()
|
now = time.gmtime()
|
||||||
ctd = time.gmtime(self.created_utc)
|
ctd = time.gmtime(self.created_utc)
|
||||||
|
|
||||||
# compute number of months
|
|
||||||
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
||||||
# remove a month count if current day of month < creation day of month
|
|
||||||
if now.tm_mday < ctd.tm_mday:
|
if now.tm_mday < ctd.tm_mday:
|
||||||
months -= 1
|
months -= 1
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,7 @@ class Submission(Base):
|
||||||
now = time.gmtime()
|
now = time.gmtime()
|
||||||
ctd = time.gmtime(self.created_utc)
|
ctd = time.gmtime(self.created_utc)
|
||||||
|
|
||||||
# compute number of months
|
|
||||||
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
||||||
# remove a month count if current day of month < creation day of month
|
|
||||||
if now.tm_mday < ctd.tm_mday:
|
if now.tm_mday < ctd.tm_mday:
|
||||||
months -= 1
|
months -= 1
|
||||||
|
|
||||||
|
@ -266,7 +264,6 @@ class Submission(Base):
|
||||||
'downvotes': self.downvotes,
|
'downvotes': self.downvotes,
|
||||||
'stickied': self.stickied,
|
'stickied': self.stickied,
|
||||||
'distinguish_level': self.distinguish_level,
|
'distinguish_level': self.distinguish_level,
|
||||||
#'award_count': self.award_count,
|
|
||||||
'voted': self.voted if hasattr(self, 'voted') else 0,
|
'voted': self.voted if hasattr(self, 'voted') else 0,
|
||||||
'flags': flags,
|
'flags': flags,
|
||||||
}
|
}
|
||||||
|
|
|
@ -613,9 +613,7 @@ class ViewerRelationship(Base):
|
||||||
now = time.gmtime()
|
now = time.gmtime()
|
||||||
ctd = time.gmtime(self.created_utc)
|
ctd = time.gmtime(self.created_utc)
|
||||||
|
|
||||||
# compute number of months
|
|
||||||
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
||||||
# remove a month count if current day of month < creation day of month
|
|
||||||
if now.tm_mday < ctd.tm_mday:
|
if now.tm_mday < ctd.tm_mday:
|
||||||
months -= 1
|
months -= 1
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ from .const import *
|
||||||
|
|
||||||
def send_notification(vid, user, text):
|
def send_notification(vid, user, text):
|
||||||
|
|
||||||
# for when working outside request context
|
|
||||||
if isinstance(user, int):
|
if isinstance(user, int):
|
||||||
uid = user
|
uid = user
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -20,7 +20,6 @@ def filter_comment_html(html_text):
|
||||||
|
|
||||||
domain = urlparse(href).netloc
|
domain = urlparse(href).netloc
|
||||||
|
|
||||||
# parse domain into all possible subdomains
|
|
||||||
parts = domain.split(".")
|
parts = domain.split(".")
|
||||||
for i in range(len(parts)):
|
for i in range(len(parts)):
|
||||||
new_domain = parts[i]
|
new_domain = parts[i]
|
||||||
|
@ -29,7 +28,6 @@ def filter_comment_html(html_text):
|
||||||
|
|
||||||
domain_list.add(new_domain)
|
domain_list.add(new_domain)
|
||||||
|
|
||||||
# search db for domain rules that prohibit commenting
|
|
||||||
bans = [x for x in g.db.query(BannedDomain).options(lazyload('*')).filter(BannedDomain.domain.in_(list(domain_list))).all()]
|
bans = [x for x in g.db.query(BannedDomain).options(lazyload('*')).filter(BannedDomain.domain.in_(list(domain_list))).all()]
|
||||||
|
|
||||||
if bans:
|
if bans:
|
||||||
|
|
|
@ -250,7 +250,6 @@ def get_comments(cids, v=None, load_parent=False):
|
||||||
|
|
||||||
def get_domain(s):
|
def get_domain(s):
|
||||||
|
|
||||||
# parse domain into all possible subdomains
|
|
||||||
parts = s.split(".")
|
parts = s.split(".")
|
||||||
domain_list = set([])
|
domain_list = set([])
|
||||||
for i in range(len(parts)):
|
for i in range(len(parts)):
|
||||||
|
@ -267,8 +266,6 @@ def get_domain(s):
|
||||||
if not doms:
|
if not doms:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# return the most specific domain - the one with the longest domain
|
|
||||||
# property
|
|
||||||
doms = sorted(doms, key=lambda x: len(x.domain), reverse=True)
|
doms = sorted(doms, key=lambda x: len(x.domain), reverse=True)
|
||||||
|
|
||||||
return doms[0]
|
return doms[0]
|
|
@ -148,7 +148,6 @@ def sanitize(sanitized, noimages=False):
|
||||||
|
|
||||||
tag.wrap(link)
|
tag.wrap(link)
|
||||||
|
|
||||||
#disguised link preventer
|
|
||||||
for tag in soup.find_all("a"):
|
for tag in soup.find_all("a"):
|
||||||
|
|
||||||
tag["target"] = "_blank"
|
tag["target"] = "_blank"
|
||||||
|
@ -160,16 +159,13 @@ def sanitize(sanitized, noimages=False):
|
||||||
except:
|
except:
|
||||||
tag.string = ""
|
tag.string = ""
|
||||||
|
|
||||||
#clean up tags in code
|
|
||||||
for tag in soup.find_all("code"):
|
for tag in soup.find_all("code"):
|
||||||
tag.contents=[x.string for x in tag.contents if x.string]
|
tag.contents=[x.string for x in tag.contents if x.string]
|
||||||
|
|
||||||
#whatever else happens with images, there are only two sets of classes allowed
|
|
||||||
for tag in soup.find_all("img"):
|
for tag in soup.find_all("img"):
|
||||||
if 'profile-pic-20' not in tag.attrs.get("class",""):
|
if 'profile-pic-20' not in tag.attrs.get("class",""):
|
||||||
tag.attrs['class']="in-comment-image rounded-sm my-2"
|
tag.attrs['class']="in-comment-image rounded-sm my-2"
|
||||||
|
|
||||||
#table format
|
|
||||||
for tag in soup.find_all("table"):
|
for tag in soup.find_all("table"):
|
||||||
tag.attrs['class']="table table-striped"
|
tag.attrs['class']="table table-striped"
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,6 @@ def auth_desired(f):
|
||||||
|
|
||||||
|
|
||||||
def auth_required(f):
|
def auth_required(f):
|
||||||
# decorator for any view that requires login (ex. settings)
|
|
||||||
|
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
|
||||||
|
@ -120,7 +119,6 @@ def auth_required(f):
|
||||||
|
|
||||||
g.v = v
|
g.v = v
|
||||||
|
|
||||||
# an ugly hack to make api work
|
|
||||||
resp = make_response(f(*args, v=v, **kwargs))
|
resp = make_response(f(*args, v=v, **kwargs))
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@ -129,7 +127,6 @@ def auth_required(f):
|
||||||
|
|
||||||
|
|
||||||
def is_not_banned(f):
|
def is_not_banned(f):
|
||||||
# decorator that enforces lack of ban
|
|
||||||
|
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
|
||||||
|
|
|
@ -658,7 +658,6 @@ def admin_image_ban(v):
|
||||||
i=request.files['file']
|
i=request.files['file']
|
||||||
|
|
||||||
|
|
||||||
#make phash
|
|
||||||
tempname = f"admin_image_ban_{v.username}_{int(time.time())}"
|
tempname = f"admin_image_ban_{v.username}_{int(time.time())}"
|
||||||
|
|
||||||
i.save(tempname)
|
i.save(tempname)
|
||||||
|
@ -668,20 +667,17 @@ def admin_image_ban(v):
|
||||||
value = int(str(h), 16)
|
value = int(str(h), 16)
|
||||||
bindigits = []
|
bindigits = []
|
||||||
|
|
||||||
# Seed digit: 2**0
|
|
||||||
digit = (value % 2)
|
digit = (value % 2)
|
||||||
value //= 2
|
value //= 2
|
||||||
bindigits.append(digit)
|
bindigits.append(digit)
|
||||||
|
|
||||||
while value > 0:
|
while value > 0:
|
||||||
# Next power of 2**n
|
|
||||||
digit = (value % 2)
|
digit = (value % 2)
|
||||||
value //= 2
|
value //= 2
|
||||||
bindigits.append(digit)
|
bindigits.append(digit)
|
||||||
|
|
||||||
h = ''.join([str(d) for d in bindigits])
|
h = ''.join([str(d) for d in bindigits])
|
||||||
|
|
||||||
#check db for existing
|
|
||||||
badpic = g.db.query(BadPic).options(lazyload('*')).filter_by(
|
badpic = g.db.query(BadPic).options(lazyload('*')).filter_by(
|
||||||
phash=h
|
phash=h
|
||||||
).first()
|
).first()
|
||||||
|
@ -874,7 +870,6 @@ def ban_user(user_id, v):
|
||||||
|
|
||||||
if user.admin_level >= v.admin_level: abort(403)
|
if user.admin_level >= v.admin_level: abort(403)
|
||||||
|
|
||||||
# check for number of days for suspension
|
|
||||||
if 'form' in request.values:
|
if 'form' in request.values:
|
||||||
days = float(request.values.get("days")) if request.values.get('days') else 0
|
days = float(request.values.get("days")) if request.values.get('days') else 0
|
||||||
reason = sanitize(request.values.get("reason", ""))
|
reason = sanitize(request.values.get("reason", ""))
|
||||||
|
|
|
@ -143,7 +143,6 @@ def api_comment(v):
|
||||||
level = parent.level + 1
|
level = parent.level + 1
|
||||||
else: abort(400)
|
else: abort(400)
|
||||||
|
|
||||||
#process and sanitize
|
|
||||||
body = request.values.get("body", "")[:10000]
|
body = request.values.get("body", "")[:10000]
|
||||||
body = body.strip()
|
body = body.strip()
|
||||||
|
|
||||||
|
@ -162,7 +161,6 @@ def api_comment(v):
|
||||||
body_md = CustomRenderer().render(mistletoe.Document(body_md))
|
body_md = CustomRenderer().render(mistletoe.Document(body_md))
|
||||||
body_html = sanitize(body_md)
|
body_html = sanitize(body_md)
|
||||||
|
|
||||||
# Run safety filter
|
|
||||||
bans = filter_comment_html(body_html)
|
bans = filter_comment_html(body_html)
|
||||||
|
|
||||||
if bans:
|
if bans:
|
||||||
|
@ -171,14 +169,12 @@ def api_comment(v):
|
||||||
if ban.reason:
|
if ban.reason:
|
||||||
reason += f" {ban.reason}"
|
reason += f" {ban.reason}"
|
||||||
|
|
||||||
#auto ban for digitally malicious content
|
|
||||||
if any([x.reason==4 for x in bans]):
|
if any([x.reason==4 for x in bans]):
|
||||||
v.ban(days=30, reason="Digitally malicious content")
|
v.ban(days=30, reason="Digitally malicious content")
|
||||||
if any([x.reason==7 for x in bans]):
|
if any([x.reason==7 for x in bans]):
|
||||||
v.ban( reason="Sexualizing minors")
|
v.ban( reason="Sexualizing minors")
|
||||||
return {"error": reason}, 401
|
return {"error": reason}, 401
|
||||||
|
|
||||||
# check existing
|
|
||||||
existing = g.db.query(Comment).options(lazyload('*')).filter(Comment.author_id == v.id,
|
existing = g.db.query(Comment).options(lazyload('*')).filter(Comment.author_id == v.id,
|
||||||
Comment.deleted_utc == 0,
|
Comment.deleted_utc == 0,
|
||||||
Comment.parent_comment_id == parent_comment_id,
|
Comment.parent_comment_id == parent_comment_id,
|
||||||
|
@ -191,10 +187,8 @@ def api_comment(v):
|
||||||
if parent.author.any_block_exists(v) and not v.admin_level>=3:
|
if parent.author.any_block_exists(v) and not v.admin_level>=3:
|
||||||
return {"error": "You can't reply to users who have blocked you, or users you have blocked."}, 403
|
return {"error": "You can't reply to users who have blocked you, or users you have blocked."}, 403
|
||||||
|
|
||||||
# get bot status
|
|
||||||
is_bot = request.headers.get("X-User-Type","")=="Bot"
|
is_bot = request.headers.get("X-User-Type","")=="Bot"
|
||||||
|
|
||||||
# check spam - this should hopefully be faster
|
|
||||||
if not is_bot:
|
if not is_bot:
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
cutoff = now - 60 * 60 * 24
|
cutoff = now - 60 * 60 * 24
|
||||||
|
@ -503,7 +497,6 @@ def api_comment(v):
|
||||||
|
|
||||||
|
|
||||||
if not v.shadowbanned:
|
if not v.shadowbanned:
|
||||||
# queue up notification for parent author
|
|
||||||
notify_users = set()
|
notify_users = set()
|
||||||
|
|
||||||
for x in g.db.query(Subscription.user_id).options(lazyload('*')).filter_by(submission_id=c.parent_submission).all():
|
for x in g.db.query(Subscription.user_id).options(lazyload('*')).filter_by(submission_id=c.parent_submission).all():
|
||||||
|
@ -547,7 +540,6 @@ def api_comment(v):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# create auto upvote
|
|
||||||
vote = CommentVote(user_id=v.id,
|
vote = CommentVote(user_id=v.id,
|
||||||
comment_id=c.id,
|
comment_id=c.id,
|
||||||
vote_type=1
|
vote_type=1
|
||||||
|
@ -599,7 +591,6 @@ def edit_comment(cid, v):
|
||||||
ban = bans[0]
|
ban = bans[0]
|
||||||
reason = f"Remove the {ban.domain} link from your comment and try again."
|
reason = f"Remove the {ban.domain} link from your comment and try again."
|
||||||
|
|
||||||
#auto ban for digitally malicious content
|
|
||||||
if any([x.reason==4 for x in bans]):
|
if any([x.reason==4 for x in bans]):
|
||||||
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
||||||
return {"error":"Digitally malicious content is not allowed."}
|
return {"error":"Digitally malicious content is not allowed."}
|
||||||
|
@ -614,7 +605,6 @@ def edit_comment(cid, v):
|
||||||
body=body,
|
body=body,
|
||||||
v=v
|
v=v
|
||||||
)
|
)
|
||||||
# check spam - this should hopefully be faster
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
cutoff = now - 60 * 60 * 24
|
cutoff = now - 60 * 60 * 24
|
||||||
|
|
||||||
|
@ -741,7 +731,6 @@ def edit_comment(cid, v):
|
||||||
|
|
||||||
g.db.flush()
|
g.db.flush()
|
||||||
|
|
||||||
# queue up notifications for username mentions
|
|
||||||
notify_users = set()
|
notify_users = set()
|
||||||
soup = BeautifulSoup(body_html, features="html.parser")
|
soup = BeautifulSoup(body_html, features="html.parser")
|
||||||
mentions = soup.find_all("a", href=re.compile("^/@(\w+)"))
|
mentions = soup.find_all("a", href=re.compile("^/@(\w+)"))
|
||||||
|
|
|
@ -36,7 +36,6 @@ def join_discord(v):
|
||||||
def discord_redirect(v):
|
def discord_redirect(v):
|
||||||
|
|
||||||
|
|
||||||
#validate state
|
|
||||||
now=int(time.time())
|
now=int(time.time())
|
||||||
state=request.values.get('state','').split('.')
|
state=request.values.get('state','').split('.')
|
||||||
|
|
||||||
|
@ -50,7 +49,6 @@ def discord_redirect(v):
|
||||||
if not validate_hash(f"{timestamp}+{v.id}+discord", state):
|
if not validate_hash(f"{timestamp}+{v.id}+discord", state):
|
||||||
abort(400)
|
abort(400)
|
||||||
|
|
||||||
#get discord token
|
|
||||||
code = request.values.get("code","")
|
code = request.values.get("code","")
|
||||||
if not code:
|
if not code:
|
||||||
abort(400)
|
abort(400)
|
||||||
|
@ -79,7 +77,6 @@ def discord_redirect(v):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
|
|
||||||
#get user ID
|
|
||||||
url="https://discord.com/api/users/@me"
|
url="https://discord.com/api/users/@me"
|
||||||
headers={
|
headers={
|
||||||
'Authorization': f"Bearer {token}"
|
'Authorization': f"Bearer {token}"
|
||||||
|
@ -90,13 +87,11 @@ def discord_redirect(v):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#add user to discord
|
|
||||||
headers={
|
headers={
|
||||||
'Authorization': f"Bot {BOT_TOKEN}",
|
'Authorization': f"Bot {BOT_TOKEN}",
|
||||||
'Content-Type': "application/json"
|
'Content-Type': "application/json"
|
||||||
}
|
}
|
||||||
|
|
||||||
#remove existing user if applicable
|
|
||||||
if v.discord_id and v.discord_id != x['id']:
|
if v.discord_id and v.discord_id != x['id']:
|
||||||
url=f"https://discord.com/api/guilds/{SERVER_ID}/members/{v.discord_id}"
|
url=f"https://discord.com/api/guilds/{SERVER_ID}/members/{v.discord_id}"
|
||||||
requests.delete(url, headers=headers)
|
requests.delete(url, headers=headers)
|
||||||
|
|
|
@ -121,7 +121,6 @@ def front_all(v):
|
||||||
try: page = int(request.values.get("page") or 1)
|
try: page = int(request.values.get("page") or 1)
|
||||||
except: abort(400)
|
except: abort(400)
|
||||||
|
|
||||||
# prevent invalid paging
|
|
||||||
page = max(page, 1)
|
page = max(page, 1)
|
||||||
|
|
||||||
if v:
|
if v:
|
||||||
|
@ -243,11 +242,9 @@ def changelog(v):
|
||||||
v=v,
|
v=v,
|
||||||
)
|
)
|
||||||
|
|
||||||
# check existence of next page
|
|
||||||
next_exists = (len(ids) > 25)
|
next_exists = (len(ids) > 25)
|
||||||
ids = ids[:25]
|
ids = ids[:25]
|
||||||
|
|
||||||
# check if ids exist
|
|
||||||
posts = get_posts(ids, v=v)
|
posts = get_posts(ids, v=v)
|
||||||
|
|
||||||
if request.headers.get("Authorization"): return {"data": [x.json for x in posts], "next_exists": next_exists}
|
if request.headers.get("Authorization"): return {"data": [x.json for x in posts], "next_exists": next_exists}
|
||||||
|
|
|
@ -22,12 +22,10 @@ def login_get(v):
|
||||||
|
|
||||||
|
|
||||||
def check_for_alts(current_id):
|
def check_for_alts(current_id):
|
||||||
# account history
|
|
||||||
past_accs = set(session.get("history", []))
|
past_accs = set(session.get("history", []))
|
||||||
past_accs.add(current_id)
|
past_accs.add(current_id)
|
||||||
session["history"] = list(past_accs)
|
session["history"] = list(past_accs)
|
||||||
|
|
||||||
# record alts
|
|
||||||
for past_id in session["history"]:
|
for past_id in session["history"]:
|
||||||
|
|
||||||
if past_id == current_id:
|
if past_id == current_id:
|
||||||
|
@ -95,7 +93,6 @@ def login_post():
|
||||||
time.sleep(random.uniform(0, 2))
|
time.sleep(random.uniform(0, 2))
|
||||||
return render_template("login.html", failed=True)
|
return render_template("login.html", failed=True)
|
||||||
|
|
||||||
# test password
|
|
||||||
|
|
||||||
if request.values.get("password"):
|
if request.values.get("password"):
|
||||||
|
|
||||||
|
@ -141,7 +138,6 @@ def login_post():
|
||||||
account.unban_utc = 0
|
account.unban_utc = 0
|
||||||
g.db.add(account)
|
g.db.add(account)
|
||||||
|
|
||||||
# set session and user id
|
|
||||||
session["user_id"] = account.id
|
session["user_id"] = account.id
|
||||||
session["session_id"] = token_hex(16)
|
session["session_id"] = token_hex(16)
|
||||||
session["login_nonce"] = account.login_nonce
|
session["login_nonce"] = account.login_nonce
|
||||||
|
@ -149,7 +145,6 @@ def login_post():
|
||||||
|
|
||||||
check_for_alts(account.id)
|
check_for_alts(account.id)
|
||||||
|
|
||||||
# check for previous page
|
|
||||||
|
|
||||||
redir = request.values.get("redirect", "/").replace("/logged_out", "")
|
redir = request.values.get("redirect", "/").replace("/logged_out", "")
|
||||||
|
|
||||||
|
@ -189,7 +184,6 @@ def sign_up_get(v):
|
||||||
agent = request.headers.get("User-Agent", None)
|
agent = request.headers.get("User-Agent", None)
|
||||||
if not agent: abort(403)
|
if not agent: abort(403)
|
||||||
|
|
||||||
# check for referral in link
|
|
||||||
ref = request.values.get("ref", None)
|
ref = request.values.get("ref", None)
|
||||||
if ref:
|
if ref:
|
||||||
ref_user = g.db.query(User).options(lazyload('*')).filter(User.username.ilike(ref)).first()
|
ref_user = g.db.query(User).options(lazyload('*')).filter(User.username.ilike(ref)).first()
|
||||||
|
@ -200,14 +194,12 @@ def sign_up_get(v):
|
||||||
if ref_user and (ref_user.id in session.get("history", [])):
|
if ref_user and (ref_user.id in session.get("history", [])):
|
||||||
return render_template("sign_up_failed_ref.html")
|
return render_template("sign_up_failed_ref.html")
|
||||||
|
|
||||||
# Make a unique form key valid for one account creation
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
token = token_hex(16)
|
token = token_hex(16)
|
||||||
session["signup_token"] = token
|
session["signup_token"] = token
|
||||||
|
|
||||||
formkey_hashstr = str(now) + token + agent
|
formkey_hashstr = str(now) + token + agent
|
||||||
|
|
||||||
# formkey is a hash of session token, timestamp, and IP address
|
|
||||||
formkey = hmac.new(key=bytes(environ.get("MASTER_KEY"), "utf-16"),
|
formkey = hmac.new(key=bytes(environ.get("MASTER_KEY"), "utf-16"),
|
||||||
msg=bytes(formkey_hashstr, "utf-16"),
|
msg=bytes(formkey_hashstr, "utf-16"),
|
||||||
digestmod='md5'
|
digestmod='md5'
|
||||||
|
@ -258,8 +250,6 @@ def sign_up_post(v):
|
||||||
|
|
||||||
username = request.values.get("username").strip()
|
username = request.values.get("username").strip()
|
||||||
|
|
||||||
# define function that takes an error message and generates a new signup
|
|
||||||
# form
|
|
||||||
def new_signup(error):
|
def new_signup(error):
|
||||||
|
|
||||||
args = {"error": error}
|
args = {"error": error}
|
||||||
|
@ -337,7 +327,6 @@ def sign_up_post(v):
|
||||||
if id_1 == 0 and users_count < 6: admin_level=6
|
if id_1 == 0 and users_count < 6: admin_level=6
|
||||||
else: admin_level=0
|
else: admin_level=0
|
||||||
|
|
||||||
# make new user
|
|
||||||
new_user = User(
|
new_user = User(
|
||||||
username=username,
|
username=username,
|
||||||
original_username = username,
|
original_username = username,
|
||||||
|
@ -354,14 +343,11 @@ def sign_up_post(v):
|
||||||
g.db.add(new_user)
|
g.db.add(new_user)
|
||||||
g.db.flush()
|
g.db.flush()
|
||||||
|
|
||||||
# check alts
|
|
||||||
|
|
||||||
check_for_alts(new_user.id)
|
check_for_alts(new_user.id)
|
||||||
|
|
||||||
# send welcome/verify email
|
|
||||||
if email: send_verification_email(new_user)
|
if email: send_verification_email(new_user)
|
||||||
|
|
||||||
# send welcome message
|
|
||||||
if "rdrama" in request.host: send_notification(NOTIFICATIONS_ACCOUNT, new_user, "Dude bussy lmao")
|
if "rdrama" in request.host: send_notification(NOTIFICATIONS_ACCOUNT, new_user, "Dude bussy lmao")
|
||||||
|
|
||||||
session["user_id"] = new_user.id
|
session["user_id"] = new_user.id
|
||||||
|
@ -402,7 +388,6 @@ def post_forgot():
|
||||||
User.email.ilike(email)).first()
|
User.email.ilike(email)).first()
|
||||||
|
|
||||||
if user:
|
if user:
|
||||||
# generate url
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
token = generate_hash(f"{user.id}+{now}+forgot+{user.login_nonce}")
|
token = generate_hash(f"{user.id}+{now}+forgot+{user.login_nonce}")
|
||||||
url = f"https://{app.config['SERVER_NAME']}/reset?id={user.id}&time={now}&token={token}"
|
url = f"https://{app.config['SERVER_NAME']}/reset?id={user.id}&time={now}&token={token}"
|
||||||
|
@ -533,7 +518,6 @@ def request_2fa_disable():
|
||||||
title="Removal request received",
|
title="Removal request received",
|
||||||
message="If username, password, and email match, we will send you an email.")
|
message="If username, password, and email match, we will send you an email.")
|
||||||
|
|
||||||
#compute token
|
|
||||||
valid=int(time.time())
|
valid=int(time.time())
|
||||||
token=generate_hash(f"{user.id}+{user.username}+disable2fa+{valid}+{user.mfa_secret}+{user.login_nonce}")
|
token=generate_hash(f"{user.id}+{user.username}+disable2fa+{valid}+{user.mfa_secret}+{user.login_nonce}")
|
||||||
|
|
||||||
|
@ -569,7 +553,6 @@ def reset_2fa():
|
||||||
if not validate_hash(f"{user.id}+{user.username}+disable2fa+{t}+{user.mfa_secret}+{user.login_nonce}", token):
|
if not validate_hash(f"{user.id}+{user.username}+disable2fa+{t}+{user.mfa_secret}+{user.login_nonce}", token):
|
||||||
abort(403)
|
abort(403)
|
||||||
|
|
||||||
#validation successful, remove 2fa
|
|
||||||
user.mfa_secret=None
|
user.mfa_secret=None
|
||||||
|
|
||||||
g.db.add(user)
|
g.db.add(user)
|
||||||
|
|
|
@ -211,7 +211,6 @@ def edit_post(pid, v):
|
||||||
body_md = CustomRenderer().render(mistletoe.Document(body))
|
body_md = CustomRenderer().render(mistletoe.Document(body))
|
||||||
body_html = sanitize(body_md)
|
body_html = sanitize(body_md)
|
||||||
|
|
||||||
# Run safety filter
|
|
||||||
bans = filter_comment_html(body_html)
|
bans = filter_comment_html(body_html)
|
||||||
if bans:
|
if bans:
|
||||||
ban = bans[0]
|
ban = bans[0]
|
||||||
|
@ -219,7 +218,6 @@ def edit_post(pid, v):
|
||||||
if ban.reason:
|
if ban.reason:
|
||||||
reason += f" {ban.reason}"
|
reason += f" {ban.reason}"
|
||||||
|
|
||||||
#auto ban for digitally malicious content
|
|
||||||
if any([x.reason==4 for x in bans]):
|
if any([x.reason==4 for x in bans]):
|
||||||
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -347,7 +345,6 @@ def filter_title(title):
|
||||||
title = title.replace("\r", "")
|
title = title.replace("\r", "")
|
||||||
title = title.replace("\t", "")
|
title = title.replace("\t", "")
|
||||||
|
|
||||||
# sanitize title
|
|
||||||
title = bleach.clean(title, tags=[])
|
title = bleach.clean(title, tags=[])
|
||||||
|
|
||||||
for i in re.finditer('(?<!"):([^ ]{1,30}?):', title):
|
for i in re.finditer('(?<!"):([^ ]{1,30}?):', title):
|
||||||
|
@ -370,7 +367,6 @@ def thumbnail_thread(pid):
|
||||||
|
|
||||||
def expand_url(post_url, fragment_url):
|
def expand_url(post_url, fragment_url):
|
||||||
|
|
||||||
# convert src into full url
|
|
||||||
if fragment_url.startswith("https://"):
|
if fragment_url.startswith("https://"):
|
||||||
return fragment_url
|
return fragment_url
|
||||||
elif fragment_url.startswith("http://"):
|
elif fragment_url.startswith("http://"):
|
||||||
|
@ -393,7 +389,6 @@ def thumbnail_thread(pid):
|
||||||
|
|
||||||
fetch_url=post.url
|
fetch_url=post.url
|
||||||
|
|
||||||
#mimic chrome browser agent
|
|
||||||
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
|
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -407,17 +402,12 @@ def thumbnail_thread(pid):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
#if content is image, stick with that. Otherwise, parse html.
|
|
||||||
|
|
||||||
if x.headers.get("Content-Type","").startswith("text/html"):
|
if x.headers.get("Content-Type","").startswith("text/html"):
|
||||||
#parse html, find image, load image
|
|
||||||
soup=BeautifulSoup(x.content, 'html.parser')
|
soup=BeautifulSoup(x.content, 'html.parser')
|
||||||
#parse html
|
|
||||||
|
|
||||||
#create list of urls to check
|
|
||||||
thumb_candidate_urls=[]
|
thumb_candidate_urls=[]
|
||||||
|
|
||||||
#iterate through desired meta tags
|
|
||||||
meta_tags = [
|
meta_tags = [
|
||||||
"ruqqus:thumbnail",
|
"ruqqus:thumbnail",
|
||||||
"twitter:image",
|
"twitter:image",
|
||||||
|
@ -446,12 +436,10 @@ def thumbnail_thread(pid):
|
||||||
if tag:
|
if tag:
|
||||||
thumb_candidate_urls.append(expand_url(post.url, tag['content']))
|
thumb_candidate_urls.append(expand_url(post.url, tag['content']))
|
||||||
|
|
||||||
#parse html doc for <img> elements
|
|
||||||
for tag in soup.find_all("img", attrs={'src':True}):
|
for tag in soup.find_all("img", attrs={'src':True}):
|
||||||
thumb_candidate_urls.append(expand_url(post.url, tag['src']))
|
thumb_candidate_urls.append(expand_url(post.url, tag['src']))
|
||||||
|
|
||||||
|
|
||||||
#now we have a list of candidate urls to try
|
|
||||||
for url in thumb_candidate_urls:
|
for url in thumb_candidate_urls:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -475,14 +463,12 @@ def thumbnail_thread(pid):
|
||||||
break
|
break
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#getting here means we are out of candidate urls (or there never were any)
|
|
||||||
db.close()
|
db.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
elif x.headers.get("Content-Type","").startswith("image/"):
|
elif x.headers.get("Content-Type","").startswith("image/"):
|
||||||
#image is originally loaded fetch_url
|
|
||||||
image_req=x
|
image_req=x
|
||||||
image = PILimage.open(BytesIO(x.content))
|
image = PILimage.open(BytesIO(x.content))
|
||||||
|
|
||||||
|
@ -569,7 +555,6 @@ def submit_post(v):
|
||||||
url = ""
|
url = ""
|
||||||
|
|
||||||
body = request.values.get("body", "")
|
body = request.values.get("body", "")
|
||||||
# check for duplicate
|
|
||||||
dup = g.db.query(Submission).options(lazyload('*')).filter(
|
dup = g.db.query(Submission).options(lazyload('*')).filter(
|
||||||
|
|
||||||
Submission.author_id == v.id,
|
Submission.author_id == v.id,
|
||||||
|
@ -583,13 +568,11 @@ def submit_post(v):
|
||||||
return redirect(dup.permalink)
|
return redirect(dup.permalink)
|
||||||
|
|
||||||
|
|
||||||
# check for domain specific rules
|
|
||||||
|
|
||||||
parsed_url = urlparse(url)
|
parsed_url = urlparse(url)
|
||||||
|
|
||||||
domain = parsed_url.netloc
|
domain = parsed_url.netloc
|
||||||
|
|
||||||
# check ban status
|
|
||||||
domain_obj = get_domain(domain)
|
domain_obj = get_domain(domain)
|
||||||
if domain_obj:
|
if domain_obj:
|
||||||
if domain_obj.reason==4:
|
if domain_obj.reason==4:
|
||||||
|
@ -620,7 +603,6 @@ def submit_post(v):
|
||||||
|
|
||||||
else: embed = None
|
else: embed = None
|
||||||
|
|
||||||
# similarity check
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
cutoff = now - 60 * 60 * 24
|
cutoff = now - 60 * 60 * 24
|
||||||
|
|
||||||
|
@ -628,34 +610,18 @@ def submit_post(v):
|
||||||
similar_posts = g.db.query(Submission).options(
|
similar_posts = g.db.query(Submission).options(
|
||||||
lazyload('*')
|
lazyload('*')
|
||||||
).filter(
|
).filter(
|
||||||
#or_(
|
|
||||||
# and_(
|
|
||||||
Submission.author_id == v.id,
|
Submission.author_id == v.id,
|
||||||
Submission.title.op('<->')(title) < app.config["SPAM_SIMILARITY_THRESHOLD"],
|
Submission.title.op('<->')(title) < app.config["SPAM_SIMILARITY_THRESHOLD"],
|
||||||
Submission.created_utc > cutoff
|
Submission.created_utc > cutoff
|
||||||
# ),
|
|
||||||
# and_(
|
|
||||||
# Submission.title.op('<->')(title) < app.config["SPAM_SIMILARITY_THRESHOLD"]/2,
|
|
||||||
# Submission.created_utc > cutoff
|
|
||||||
# )
|
|
||||||
#)
|
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
if url:
|
if url:
|
||||||
similar_urls = g.db.query(Submission).options(
|
similar_urls = g.db.query(Submission).options(
|
||||||
lazyload('*')
|
lazyload('*')
|
||||||
).filter(
|
).filter(
|
||||||
#or_(
|
|
||||||
# and_(
|
|
||||||
Submission.author_id == v.id,
|
Submission.author_id == v.id,
|
||||||
Submission.url.op('<->')(url) < app.config["SPAM_URL_SIMILARITY_THRESHOLD"],
|
Submission.url.op('<->')(url) < app.config["SPAM_URL_SIMILARITY_THRESHOLD"],
|
||||||
Submission.created_utc > cutoff
|
Submission.created_utc > cutoff
|
||||||
# ),
|
|
||||||
# and_(
|
|
||||||
# Submission.url.op('<->')(url) < app.config["SPAM_URL_SIMILARITY_THRESHOLD"]/2,
|
|
||||||
# Submission.created_utc > cutoff
|
|
||||||
# )
|
|
||||||
#)
|
|
||||||
).all()
|
).all()
|
||||||
else:
|
else:
|
||||||
similar_urls = []
|
similar_urls = []
|
||||||
|
@ -692,7 +658,6 @@ def submit_post(v):
|
||||||
g.db.add(ma)
|
g.db.add(ma)
|
||||||
return redirect("/notifications")
|
return redirect("/notifications")
|
||||||
|
|
||||||
# catch too-long body
|
|
||||||
if len(str(body)) > 10000:
|
if len(str(body)) > 10000:
|
||||||
|
|
||||||
if request.headers.get("Authorization"): return {"error":"10000 character limit for text body."}, 400
|
if request.headers.get("Authorization"): return {"error":"10000 character limit for text body."}, 400
|
||||||
|
@ -703,7 +668,6 @@ def submit_post(v):
|
||||||
if request.headers.get("Authorization"): return {"error":"2048 character limit for URLs."}, 400
|
if request.headers.get("Authorization"): return {"error":"2048 character limit for URLs."}, 400
|
||||||
else: return render_template("submit.html", v=v, error="2048 character limit for URLs.", title=title, url=url,body=request.values.get("body", "")), 400
|
else: return render_template("submit.html", v=v, error="2048 character limit for URLs.", title=title, url=url,body=request.values.get("body", "")), 400
|
||||||
|
|
||||||
# render text
|
|
||||||
for i in re.finditer('^(https:\/\/.*\.(png|jpg|jpeg|gif|webp|PNG|JPG|JPEG|GIF|WEBP|9999))', body, re.MULTILINE):
|
for i in re.finditer('^(https:\/\/.*\.(png|jpg|jpeg|gif|webp|PNG|JPG|JPEG|GIF|WEBP|9999))', body, re.MULTILINE):
|
||||||
if "wikipedia" not in i.group(1): body = body.replace(i.group(1), f'})')
|
if "wikipedia" not in i.group(1): body = body.replace(i.group(1), f'})')
|
||||||
body = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', body)
|
body = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', body)
|
||||||
|
@ -720,7 +684,6 @@ def submit_post(v):
|
||||||
|
|
||||||
if len(body_html) > 20000: abort(400)
|
if len(body_html) > 20000: abort(400)
|
||||||
|
|
||||||
# Run safety filter
|
|
||||||
bans = filter_comment_html(body_html)
|
bans = filter_comment_html(body_html)
|
||||||
if bans:
|
if bans:
|
||||||
ban = bans[0]
|
ban = bans[0]
|
||||||
|
@ -728,7 +691,6 @@ def submit_post(v):
|
||||||
if ban.reason:
|
if ban.reason:
|
||||||
reason += f" {ban.reason}"
|
reason += f" {ban.reason}"
|
||||||
|
|
||||||
#auto ban for digitally malicious content
|
|
||||||
if any([x.reason==4 for x in bans]):
|
if any([x.reason==4 for x in bans]):
|
||||||
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
||||||
abort(403)
|
abort(403)
|
||||||
|
@ -736,7 +698,6 @@ def submit_post(v):
|
||||||
if request.headers.get("Authorization"): return {"error": reason}, 403
|
if request.headers.get("Authorization"): return {"error": reason}, 403
|
||||||
else: return render_template("submit.html", v=v, error=reason, title=title, url=url, body=request.values.get("body", "")), 403
|
else: return render_template("submit.html", v=v, error=reason, title=title, url=url, body=request.values.get("body", "")), 403
|
||||||
|
|
||||||
# check for embeddable video
|
|
||||||
domain = parsed_url.netloc
|
domain = parsed_url.netloc
|
||||||
|
|
||||||
if v.paid_dues: club = bool(request.values.get("club",""))
|
if v.paid_dues: club = bool(request.values.get("club",""))
|
||||||
|
|
|
@ -14,7 +14,6 @@ valid_params=[
|
||||||
|
|
||||||
def searchparse(text):
|
def searchparse(text):
|
||||||
|
|
||||||
#takes test in filter:term format and returns data
|
|
||||||
|
|
||||||
criteria = {x[0]:x[1] for x in query_regex.findall(text)}
|
criteria = {x[0]:x[1] for x in query_regex.findall(text)}
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,6 @@ def settings_profile_post(v):
|
||||||
if "wikipedia" not in i.group(1): bio = bio.replace(i.group(1), f'})')
|
if "wikipedia" not in i.group(1): bio = bio.replace(i.group(1), f'})')
|
||||||
bio = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', bio)
|
bio = re.sub('([^\n])\n([^\n])', r'\1\n\n\2', bio)
|
||||||
|
|
||||||
# check for uploaded image
|
|
||||||
if request.files.get('file') and request.headers.get("cf-ipcountry") != "T1":
|
if request.files.get('file') and request.headers.get("cf-ipcountry") != "T1":
|
||||||
|
|
||||||
file = request.files['file']
|
file = request.files['file']
|
||||||
|
@ -123,7 +122,6 @@ def settings_profile_post(v):
|
||||||
|
|
||||||
bio_html = CustomRenderer().render(mistletoe.Document(bio))
|
bio_html = CustomRenderer().render(mistletoe.Document(bio))
|
||||||
bio_html = sanitize(bio_html)
|
bio_html = sanitize(bio_html)
|
||||||
# Run safety filter
|
|
||||||
bans = filter_comment_html(bio_html)
|
bans = filter_comment_html(bio_html)
|
||||||
|
|
||||||
if len(bio_html) > 10000:
|
if len(bio_html) > 10000:
|
||||||
|
@ -137,7 +135,6 @@ def settings_profile_post(v):
|
||||||
if ban.reason:
|
if ban.reason:
|
||||||
reason += f" {ban.reason}"
|
reason += f" {ban.reason}"
|
||||||
|
|
||||||
#auto ban for digitally malicious content
|
|
||||||
if any([x.reason==4 for x in bans]):
|
if any([x.reason==4 for x in bans]):
|
||||||
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
v.ban(days=30, reason="Digitally malicious content is not allowed.")
|
||||||
return {"error": reason}, 401
|
return {"error": reason}, 401
|
||||||
|
@ -416,7 +413,6 @@ def settings_security_post(v):
|
||||||
if new_email == v.email:
|
if new_email == v.email:
|
||||||
return redirect("/settings/security?error=That email is already yours!")
|
return redirect("/settings/security?error=That email is already yours!")
|
||||||
|
|
||||||
# check to see if email is in use
|
|
||||||
existing = g.db.query(User).options(lazyload('*')).filter(User.id != v.id,
|
existing = g.db.query(User).options(lazyload('*')).filter(User.id != v.id,
|
||||||
func.lower(User.email) == new_email.lower()).first()
|
func.lower(User.email) == new_email.lower()).first()
|
||||||
if existing:
|
if existing:
|
||||||
|
@ -492,10 +488,8 @@ def settings_log_out_others(v):
|
||||||
|
|
||||||
if not v.verifyPass(submitted_password): return render_template("settings_security.html", v=v, error="Incorrect Password"), 401
|
if not v.verifyPass(submitted_password): return render_template("settings_security.html", v=v, error="Incorrect Password"), 401
|
||||||
|
|
||||||
# increment account's nonce
|
|
||||||
v.login_nonce += 1
|
v.login_nonce += 1
|
||||||
|
|
||||||
# update cookie accordingly
|
|
||||||
session["login_nonce"] = v.login_nonce
|
session["login_nonce"] = v.login_nonce
|
||||||
|
|
||||||
g.db.add(v)
|
g.db.add(v)
|
||||||
|
@ -865,7 +859,6 @@ def settings_title_change(v):
|
||||||
|
|
||||||
new_name=request.values.get("title").strip()[:100].replace("𒐪","")
|
new_name=request.values.get("title").strip()[:100].replace("𒐪","")
|
||||||
|
|
||||||
#make sure name is different
|
|
||||||
if new_name==v.customtitle:
|
if new_name==v.customtitle:
|
||||||
return render_template("settings_profile.html",
|
return render_template("settings_profile.html",
|
||||||
v=v,
|
v=v,
|
||||||
|
|
|
@ -100,7 +100,6 @@ def cached_chart():
|
||||||
|
|
||||||
comment_stats = [g.db.query(Comment.id).options(lazyload('*')).filter(Comment.created_utc < day_cutoffs[i], Comment.created_utc > day_cutoffs[i + 1],Comment.is_banned == False, Comment.author_id != 1).count() for i in range(len(day_cutoffs) - 1)][2:][::-1]
|
comment_stats = [g.db.query(Comment.id).options(lazyload('*')).filter(Comment.created_utc < day_cutoffs[i], Comment.created_utc > day_cutoffs[i + 1],Comment.is_banned == False, Comment.author_id != 1).count() for i in range(len(day_cutoffs) - 1)][2:][::-1]
|
||||||
|
|
||||||
# create multiple charts
|
|
||||||
signup_chart = plt.subplot2grid((20, 4), (0, 0), rowspan=5, colspan=4)
|
signup_chart = plt.subplot2grid((20, 4), (0, 0), rowspan=5, colspan=4)
|
||||||
posts_chart = plt.subplot2grid((20, 4), (7, 0), rowspan=5, colspan=4)
|
posts_chart = plt.subplot2grid((20, 4), (7, 0), rowspan=5, colspan=4)
|
||||||
comments_chart = plt.subplot2grid((20, 4), (14, 0), rowspan=5, colspan=4)
|
comments_chart = plt.subplot2grid((20, 4), (14, 0), rowspan=5, colspan=4)
|
||||||
|
|
|
@ -395,13 +395,10 @@ def u_username(username, v=None):
|
||||||
|
|
||||||
if v and request.path.startswith('/logged_out'): v = None
|
if v and request.path.startswith('/logged_out'): v = None
|
||||||
|
|
||||||
# username is unique so at most this returns one result. Otherwise 404
|
|
||||||
|
|
||||||
# case insensitive search
|
|
||||||
|
|
||||||
u = get_user(username, v=v)
|
u = get_user(username, v=v)
|
||||||
|
|
||||||
# check for wrong cases
|
|
||||||
|
|
||||||
if username != u.username:
|
if username != u.username:
|
||||||
return redirect(request.path.replace(username, u.username))
|
return redirect(request.path.replace(username, u.username))
|
||||||
|
@ -410,7 +407,6 @@ def u_username(username, v=None):
|
||||||
if request.headers.get("Authorization"): return {"error": f"That username is reserved for: {u.reserved}"}
|
if request.headers.get("Authorization"): return {"error": f"That username is reserved for: {u.reserved}"}
|
||||||
else: return render_template("userpage_reserved.html", u=u, v=v)
|
else: return render_template("userpage_reserved.html", u=u, v=v)
|
||||||
|
|
||||||
# viewers
|
|
||||||
if v and u.id != v.id:
|
if v and u.id != v.id:
|
||||||
view = g.db.query(ViewerRelationship).options(lazyload('*')).filter(
|
view = g.db.query(ViewerRelationship).options(lazyload('*')).filter(
|
||||||
and_(
|
and_(
|
||||||
|
@ -457,7 +453,6 @@ def u_username(username, v=None):
|
||||||
|
|
||||||
ids = u.userpagelisting(v=v, page=page, sort=sort, t=t)
|
ids = u.userpagelisting(v=v, page=page, sort=sort, t=t)
|
||||||
|
|
||||||
# we got 26 items just to see if a next page exists
|
|
||||||
next_exists = (len(ids) > 25)
|
next_exists = (len(ids) > 25)
|
||||||
ids = ids[:25]
|
ids = ids[:25]
|
||||||
|
|
||||||
|
@ -508,13 +503,10 @@ def u_username_comments(username, v=None):
|
||||||
|
|
||||||
if v and request.path.startswith('/logged_out'): v = None
|
if v and request.path.startswith('/logged_out'): v = None
|
||||||
|
|
||||||
# username is unique so at most this returns one result. Otherwise 404
|
|
||||||
|
|
||||||
# case insensitive search
|
|
||||||
|
|
||||||
user = get_user(username, v=v)
|
user = get_user(username, v=v)
|
||||||
|
|
||||||
# check for wrong cases
|
|
||||||
|
|
||||||
if username != user.username: return redirect(f'{user.url}/comments')
|
if username != user.username: return redirect(f'{user.url}/comments')
|
||||||
|
|
||||||
|
@ -589,7 +581,6 @@ def u_username_comments(username, v=None):
|
||||||
comments = comments.offset(25 * (page - 1)).limit(26).all()
|
comments = comments.offset(25 * (page - 1)).limit(26).all()
|
||||||
ids = [x.id for x in comments]
|
ids = [x.id for x in comments]
|
||||||
|
|
||||||
# we got 26 items just to see if a next page exists
|
|
||||||
next_exists = (len(ids) > 25)
|
next_exists = (len(ids) > 25)
|
||||||
ids = ids[:25]
|
ids = ids[:25]
|
||||||
|
|
||||||
|
@ -624,7 +615,6 @@ def follow_user(username, v):
|
||||||
|
|
||||||
if target.id==v.id: return {"error": "You can't follow yourself!"}, 400
|
if target.id==v.id: return {"error": "You can't follow yourself!"}, 400
|
||||||
|
|
||||||
# check for existing follow
|
|
||||||
if g.db.query(Follow).options(lazyload('*')).filter_by(user_id=v.id, target_id=target.id).first(): return {"message": "User followed!"}
|
if g.db.query(Follow).options(lazyload('*')).filter_by(user_id=v.id, target_id=target.id).first(): return {"message": "User followed!"}
|
||||||
|
|
||||||
new_follow = Follow(user_id=v.id, target_id=target.id)
|
new_follow = Follow(user_id=v.id, target_id=target.id)
|
||||||
|
@ -650,7 +640,6 @@ def unfollow_user(username, v):
|
||||||
|
|
||||||
if target.id == 995: abort(403)
|
if target.id == 995: abort(403)
|
||||||
|
|
||||||
# check for existing follow
|
|
||||||
follow = g.db.query(Follow).options(lazyload('*')).filter_by(user_id=v.id, target_id=target.id).first()
|
follow = g.db.query(Follow).options(lazyload('*')).filter_by(user_id=v.id, target_id=target.id).first()
|
||||||
|
|
||||||
if not follow: return {"message": "User unfollowed!"}
|
if not follow: return {"message": "User unfollowed!"}
|
||||||
|
@ -674,7 +663,6 @@ def unfollow_user(username, v):
|
||||||
def remove_follow(username, v):
|
def remove_follow(username, v):
|
||||||
target = get_user(username)
|
target = get_user(username)
|
||||||
|
|
||||||
# check for existing follow
|
|
||||||
follow = g.db.query(Follow).options(lazyload('*')).filter_by(user_id=target.id, target_id=v.id).first()
|
follow = g.db.query(Follow).options(lazyload('*')).filter_by(user_id=target.id, target_id=v.id).first()
|
||||||
|
|
||||||
if not follow: return {"message": "Follower removed!"}
|
if not follow: return {"message": "Follower removed!"}
|
||||||
|
|
|
@ -62,14 +62,12 @@ def api_vote_post(post_id, new, v):
|
||||||
|
|
||||||
if new not in ["-1", "0", "1"]: abort(400)
|
if new not in ["-1", "0", "1"]: abort(400)
|
||||||
|
|
||||||
# disallow bots
|
|
||||||
if request.headers.get("X-User-Type","") == "Bot": abort(403)
|
if request.headers.get("X-User-Type","") == "Bot": abort(403)
|
||||||
|
|
||||||
new = int(new)
|
new = int(new)
|
||||||
|
|
||||||
post = get_post(post_id)
|
post = get_post(post_id)
|
||||||
|
|
||||||
# check for existing vote
|
|
||||||
existing = g.db.query(Vote).options(lazyload('*')).filter_by(user_id=v.id, submission_id=post.id).first()
|
existing = g.db.query(Vote).options(lazyload('*')).filter_by(user_id=v.id, submission_id=post.id).first()
|
||||||
|
|
||||||
if existing and existing.vote_type == new: return "", 204
|
if existing and existing.vote_type == new: return "", 204
|
||||||
|
@ -127,7 +125,6 @@ def api_vote_comment(comment_id, new, v):
|
||||||
|
|
||||||
comment = get_comment(comment_id)
|
comment = get_comment(comment_id)
|
||||||
|
|
||||||
# check for existing vote
|
|
||||||
existing = g.db.query(CommentVote).options(lazyload('*')).filter_by(user_id=v.id, comment_id=comment.id).first()
|
existing = g.db.query(CommentVote).options(lazyload('*')).filter_by(user_id=v.id, comment_id=comment.id).first()
|
||||||
|
|
||||||
if existing and existing.vote_type == new: return "", 204
|
if existing and existing.vote_type == new: return "", 204
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue