diff --git a/files/helpers/actions.py b/files/helpers/actions.py index 11a4ba0c6..fc11a559d 100644 --- a/files/helpers/actions.py +++ b/files/helpers/actions.py @@ -343,55 +343,6 @@ def execute_antispam_submission_check(title, v, url): return False return True -def execute_blackjack(v, target, body, type): - if not blackjack or not body: return True - - execute = False - for x in blackjack.split(','): - if all(i in body.lower() for i in x.split()): - execute = True - shadowban = v.truescore < 100 - - if execute: - if shadowban: - v.shadowbanned = AUTOJANNY_ID - - ma = ModAction( - kind="shadowban", - user_id=AUTOJANNY_ID, - target_user_id=v.id, - _note='reason: "Blackjack"' - ) - g.db.add(ma) - - v.ban_reason = "Blackjack" - g.db.add(v) - elif type in {'submission', 'comment', 'message'}: - target.is_banned = True - - notified_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS'])] - extra_info = "unknown entity" - - if type == 'submission': - extra_info = target.permalink - elif type == 'chat': - extra_info = "chat message" - elif type == 'flag': - extra_info = f"reports on {target.permalink}" - elif type == 'modmail': - extra_info = "modmail" - elif type in {'comment', 'message'}: - for id in notified_ids: - n = Notification(comment_id=target.id, user_id=id) - g.db.add(n) - g.db.flush() - extra_info = None - - if extra_info: - for id in notified_ids: - send_repeatable_notification(id, f"Blackjack for @{v.username}: {extra_info}") - return True - def execute_antispam_duplicate_comment_check(v:User, body_html:str): ''' Sanity check for newfriends diff --git a/files/helpers/alerts.py b/files/helpers/alerts.py index 71ce057b1..26f764dbd 100644 --- a/files/helpers/alerts.py +++ b/files/helpers/alerts.py @@ -28,7 +28,7 @@ def send_repeatable_notification(uid, text): if uid in bots: return - text_html = sanitize(text) + text_html = sanitize(text, blackjack="notification") existing_comments = g.db.query(Comment.id).filter_by(author_id=AUTOJANNY_ID, parent_submission=None, body_html=text_html, is_bot=True).order_by(Comment.id).all() @@ -53,7 +53,7 @@ def send_notification(uid, text): def notif_comment(text): - text_html = sanitize(text) + text_html = sanitize(text, blackjack="notification") g.db.flush() @@ -94,7 +94,7 @@ def notif_comment2(p): else: text = f"@{p.author.username} has mentioned you: [{p.title}](/post/{p.id})" if p.sub: text += f" in /h/{p.sub}" - text_html = sanitize(text) + text_html = sanitize(text, blackjack="notification") return create_comment(text_html) diff --git a/files/helpers/offsitementions.py b/files/helpers/offsitementions.py index d5fdc260b..7cbdc6a34 100644 --- a/files/helpers/offsitementions.py +++ b/files/helpers/offsitementions.py @@ -11,7 +11,7 @@ import files.helpers.config.const as const from files.classes.badges import Badge from files.classes.comment import Comment from files.classes.user import User -from files.helpers.sanitize import sanitize +from files.helpers.sanitize import * from files.classes.notifications import Notification # Note: while https://api.pushshift.io/meta provides the key @@ -94,7 +94,7 @@ def notify_mentions(mentions, send_to=None, mention_str='site mention'): for m in mentions: author = m['author'] permalink = m['permalink'] - text = sanitize(m['text'], golden=False) + text = sanitize(m['text'], blackjack="reddit mention", golden=False) notif_text = ( f'

New {mention_str} by /u/{author}

' diff --git a/files/helpers/sanitize.py b/files/helpers/sanitize.py index 8b1298194..b3396ecf9 100644 --- a/files/helpers/sanitize.py +++ b/files/helpers/sanitize.py @@ -13,6 +13,8 @@ from bleach.linkifier import LinkifyFilter from bs4 import BeautifulSoup from mistletoe import markdown from files.classes.domains import BannedDomain +from files.classes.mod_logs import ModAction +from files.classes.notifications import Notification from files.helpers.config.const import * from files.helpers.const_stateful import * @@ -148,6 +150,85 @@ def callback(attrs, new=False): return attrs +def create_comment_duplicated(text_html): + new_comment = Comment(author_id=AUTOJANNY_ID, + parent_submission=None, + body_html=text_html, + distinguish_level=6, + is_bot=True) + g.db.add(new_comment) + g.db.flush() + + new_comment.top_comment_id = new_comment.id + + return new_comment.id + +def send_repeatable_notification_duplicated(uid, text): + + if uid in bots: return + + text_html = sanitize(text) + + existing_comments = g.db.query(Comment.id).filter_by(author_id=AUTOJANNY_ID, parent_submission=None, body_html=text_html, is_bot=True).order_by(Comment.id).all() + + for c in existing_comments: + existing_notif = g.db.query(Notification.user_id).filter_by(user_id=uid, comment_id=c.id).one_or_none() + if not existing_notif: + notif = Notification(comment_id=c.id, user_id=uid) + g.db.add(notif) + return + + cid = create_comment_duplicated(text_html) + notif = Notification(comment_id=cid, user_id=uid) + g.db.add(notif) + + +def execute_blackjack(v, target, body, type): + if not blackjack or not body: return False + + execute = False + for x in blackjack.split(','): + if all(i in body.lower() for i in x.split()): + execute = True + shadowban = v.truescore < 100 or not target + + if not execute: return False + + if shadowban: + v.shadowbanned = AUTOJANNY_ID + + ma = ModAction( + kind="shadowban", + user_id=AUTOJANNY_ID, + target_user_id=v.id, + _note='reason: "Blackjack"' + ) + g.db.add(ma) + + v.ban_reason = "Blackjack" + g.db.add(v) + elif target and type in {'submission', 'comment', 'message'}: + target.is_banned = True + + notified_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS'])] + extra_info = type + + if target: + if type == 'submission': + extra_info = target.permalink + elif type == 'flag': + extra_info = f"reports on {target.permalink}" + elif type in {'comment', 'message'}: + for id in notified_ids: + n = Notification(comment_id=target.id, user_id=id) + g.db.add(n) + g.db.flush() + extra_info = None + + if extra_info: + for id in notified_ids: + send_repeatable_notification_duplicated(id, f"Blackjack for @{v.username}: {extra_info}") + return True def render_emoji(html, regexp, golden, marseys_used, b=False): emojis = list(regexp.finditer(html)) @@ -270,9 +351,12 @@ def handle_youtube_links(url): return html @with_sigalrm_timeout(10) -def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys=False, torture=False, sidebar=False, snappy=False, chat=False): +def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys=False, torture=False, snappy=False, blackjack=None): sanitized = sanitized.strip() + if blackjack and execute_blackjack(g.v, None, sanitized, blackjack): + sanitized = 'g' + sanitized = utm_regex.sub('', sanitized) sanitized = utm_regex2.sub('', sanitized) @@ -431,7 +515,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys domain_list.add(d.lower()) def error(error): - if chat: + if blackjack == "chat": return error, 403 else: abort(403, error) @@ -445,7 +529,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys if discord_username_regex.match(sanitized): return error("Stop grooming!") - if '
' not in sanitized and not sidebar:
+	if '
' not in sanitized and blackjack != "rules":
 		sanitized = sanitized.replace('\n','')
 
 	if showmore:
diff --git a/files/routes/admin.py b/files/routes/admin.py
index 6c8cd1c99..2058537af 100644
--- a/files/routes/admin.py
+++ b/files/routes/admin.py
@@ -67,7 +67,7 @@ def edit_rules_get(v):
 @admin_level_required(PERMS['EDIT_RULES'])
 def edit_rules_post(v):
 	rules = request.values.get('rules', '').strip()
-	rules = sanitize(rules, sidebar=True, showmore=False)
+	rules = sanitize(rules, blackjack="rules", showmore=False)
 
 	with open(f'files/templates/rules_{SITE_NAME}.html', 'w+', encoding="utf-8") as f:
 		f.write(rules)
diff --git a/files/routes/chat.py b/files/routes/chat.py
index d3b88d383..860b09cbe 100644
--- a/files/routes/chat.py
+++ b/files/routes/chat.py
@@ -9,7 +9,7 @@ from files.helpers.alerts import *
 from files.helpers.config.const import *
 from files.helpers.regex import *
 from files.helpers.media import process_image
-from files.helpers.sanitize import sanitize
+from files.helpers.sanitize import *
 from files.helpers.alerts import push_notif
 from files.routes.wrappers import *
 
@@ -113,7 +113,7 @@ def speak(data, v):
 			emit("online", [online, muted], broadcast=True)
 			self_only = True
 
-	if self_only or v.shadowbanned or not execute_blackjack(v, None, text, "chat"):
+	if self_only or v.shadowbanned or execute_blackjack(v, None, text, "chat"):
 		emit('speak', data)
 	else:
 		emit('speak', data, broadcast=True)
diff --git a/files/routes/oauth.py b/files/routes/oauth.py
index 4ace0b89b..9e23caedf 100644
--- a/files/routes/oauth.py
+++ b/files/routes/oauth.py
@@ -63,7 +63,7 @@ def request_api_keys(v):
 	g.db.add(new_app)
 
 	body = f"@{v.username} has requested API keys for `{request.values.get('name')}`. You can approve or deny the request [here](/admin/apps)."
-	body_html = sanitize(body)
+	body_html = sanitize(body, blackjack="app description")
 
 	new_comment = Comment(author_id=AUTOJANNY_ID,
 						parent_submission=None,
diff --git a/files/routes/posts.py b/files/routes/posts.py
index c4147db7f..931e424cb 100644
--- a/files/routes/posts.py
+++ b/files/routes/posts.py
@@ -312,7 +312,7 @@ def edit_post(pid, v):
 		execute_under_siege(v, p, p.body, 'submission')
 
 		for text in [p.body, p.title, p.url]:
-			if not execute_blackjack(v, p, text, 'submission'): break
+			if execute_blackjack(v, p, text, 'submission'): break
 
 		if len(body_html) > POST_BODY_HTML_LENGTH_LIMIT:
 			abort(400, f"Submission body_html too long!")
@@ -708,7 +708,7 @@ def submit_post(v:User, sub=None):
 	g.db.flush()
 
 	for text in {post.body, post.title, post.url}:
-		if not execute_blackjack(v, post, text, 'submission'): break
+		if execute_blackjack(v, post, text, 'submission'): break
 
 	process_poll_options(post, SubmissionOption, bets, 2, "Bet", g.db)
 	process_poll_options(post, SubmissionOption, options, 0, "Poll", g.db)
diff --git a/files/routes/settings.py b/files/routes/settings.py
index ff76cabf5..485394500 100644
--- a/files/routes/settings.py
+++ b/files/routes/settings.py
@@ -227,7 +227,7 @@ def settings_personal_post(v):
 
 	elif not updated and v.patron and request.values.get("sig"):
 		sig = request.values.get("sig")[:200].replace('\n','').replace('\r','')
-		sig_html = sanitize(sig)
+		sig_html = sanitize(sig, blackjack="signature")
 		if len(sig_html) > 1000:
 			return render_template("settings/personal.html",
 								v=v,
@@ -243,7 +243,7 @@ def settings_personal_post(v):
 	elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and request.values.get("friends"):
 		friends = request.values.get("friends")[:1000]
 
-		friends_html = sanitize(friends)
+		friends_html = sanitize(friends, blackjack="friends")
 
 		if len(friends_html) > 5000:
 			return render_template("settings/personal.html",
@@ -268,7 +268,7 @@ def settings_personal_post(v):
 	elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and request.values.get("enemies"):
 		enemies = request.values.get("enemies")[:1000]
 
-		enemies_html = sanitize(enemies)
+		enemies_html = sanitize(enemies, blackjack="enemies")
 
 		if len(enemies_html) > 5000:
 			return render_template("settings/personal.html",
@@ -294,7 +294,7 @@ def settings_personal_post(v):
 		bio = request.values.get("bio")[:1500]
 		bio += process_files(request.files, v)
 		bio = bio.strip()
-		bio_html = sanitize(bio)
+		bio_html = sanitize(bio, blackjack="bio")
 
 		if len(bio_html) > 10000:
 			return render_template("settings/personal.html",
diff --git a/files/routes/subs.py b/files/routes/subs.py
index cb38a8c45..17fc725c2 100644
--- a/files/routes/subs.py
+++ b/files/routes/subs.py
@@ -406,7 +406,7 @@ def post_sub_sidebar(v:User, sub):
 	if v.shadowbanned: return redirect(f'/h/{sub}/settings')
 
 	sub.sidebar = request.values.get('sidebar', '').strip()[:10000]
-	sub.sidebar_html = sanitize(sub.sidebar, showmore=False)
+	sub.sidebar_html = sanitize(sub.sidebar, blackjack=f"/h/{sub} sidebar", showmore=False)
 	if len(sub.sidebar_html) > 20000: abort(400, "Sidebar is too big!")
 
 	g.db.add(sub)
diff --git a/files/routes/users.py b/files/routes/users.py
index 6410de421..03aafce8d 100644
--- a/files/routes/users.py
+++ b/files/routes/users.py
@@ -13,7 +13,7 @@ from files.classes import *
 from files.classes.leaderboard import Leaderboard
 from files.classes.transactions import *
 from files.classes.views import *
-from files.helpers.actions import execute_blackjack, execute_under_siege
+from files.helpers.actions import execute_under_siege
 from files.helpers.alerts import *
 from files.helpers.config.const import *
 from files.helpers.mail import *