add functionality to disable poll formatting (#35)

Co-authored-by: justcool393 <justcool393@gmail.com>
Reviewed-on: #35
Co-authored-by: justcool393 <justcool393@noreply.fsdfsd.net>
Co-committed-by: justcool393 <justcool393@noreply.fsdfsd.net>
pull/46/head
justcool393 2022-12-04 21:46:27 +00:00 committed by Snakes
parent 892e35b1c3
commit ed0981cbdb
7 changed files with 71 additions and 145 deletions

View File

@ -1,5 +1,6 @@
import random
import time
from typing import Type
from urllib.parse import quote
import gevent
@ -8,6 +9,7 @@ from flask import g
from files.classes.flags import Flag
from files.classes.mod_logs import ModAction
from files.classes.notifications import Notification
from files.classes.polls import CommentOption, SubmissionOption
from files.helpers.alerts import send_repeatable_notification
from files.helpers.const import *
@ -492,3 +494,23 @@ def execute_lawlz_actions(v:User, p:Submission):
g.db.add(ma_1)
g.db.add(ma_2)
g.db.add(ma_3)
def process_poll_options(target:Union[Submission, Comment],
cls:Union[Type[SubmissionOption], Type[CommentOption]],
options:Iterable[str], exclusive:int, friendly_name:str,
db:scoped_session) -> None:
for option in options:
if len(option) > 500: abort(400, f"{friendly_name} option too long!")
if cls is SubmissionOption:
option = cls(
submission_id=target.id,
body_html=option,
exclusive=exclusive,
)
else:
option = cls(
comment_id=target.id,
body_html=option,
exclusive=exclusive,
)
db.add(option)

View File

@ -1444,6 +1444,8 @@ TROLLTITLES = [
"Hey jannies can you please ban @{username}",
]
DISABLE_POLL_COMMAND = "disablepoll"
NOTIFIED_USERS = {
'aevan': AEVANN_ID,
'avean': AEVANN_ID,

View File

@ -177,13 +177,19 @@ commands = {
"fortune": FORTUNE_REPLIES,
"factcheck": FACTCHECK_REPLIES,
"8ball": EIGHTBALL_REPLIES,
"roll": range(1, 9999)
"roll": range(1, 9999),
DISABLE_POLL_COMMAND: None,
}
command_regex = re.compile("(\s|\n|^)#(fortune|factcheck|8ball|roll)", flags=re.A|re.I)
command_regex = re.compile(f"(\s|\n|^)#({'|'.join(commands.keys())})", flags=re.A|re.I)
def command_regex_matcher(match, upper=False):
result = str(choice(commands[match.group(2).lower()]))
choices = commands[match.group(2).lower()]
if not choices:
return ''
elif isinstance(choices, str):
return choices
result = str(choice(choices))
if match.group(2) == 'roll':
color = tuple(choices(range(256), k=3))
result = f'<b style="color:rgb{color}">Your roll: {result}</b>'

View File

@ -4,6 +4,7 @@ import re
import signal
from functools import partial
from os import path
from typing import Any
from urllib.parse import parse_qs, urlparse
import bleach
@ -255,18 +256,14 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
sanitized = linefeeds_regex.sub(r'\1\n\n\2', sanitized)
sanitized = greentext_regex.sub(r'\1<g>\>\2</g>', sanitized)
sanitized = image_regex.sub(r'\1![](\2)\5', sanitized)
sanitized = image_check_regex.sub(r'\1', sanitized)
sanitized = link_fix_regex.sub(r'\1https://\2', sanitized)
if FEATURES['MARKUP_COMMANDS']:
sanitized = command_regex.sub(command_regex_matcher, sanitized)
sanitized = markdown(sanitized)
sanitized = strikethrough_regex.sub(r'\1<del>\2</del>', sanitized)
# replacing zero width characters, overlines, fake colons
@ -417,12 +414,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
return sanitized.strip()
def allowed_attributes_emojis(tag, name, value):
if tag == 'img':
if name == 'src' and value.startswith('/') and '\\' not in value: return True
if name == 'loading' and value == 'lazy': return True
@ -503,3 +495,21 @@ def validate_css(css):
return False, f"The domain '{domain}' is not allowed, please use one of these domains\n\n{approved_embed_hosts}."
return True, ""
def sanitize_poll_options(v:User, body:str, allow_bets:bool) -> tuple[str, List[Any], List[Any], List[Any]]:
if FEATURES['MARKUP_COMMANDS'] and body.startswith(f"#{DISABLE_POLL_COMMAND}"):
return (body, [], [], [])
def sanitize_poll_type(body:str, re:re.Pattern) -> tuple[str, List[str]]:
opts = []
for i in list(re.finditer(body))[:POLL_MAX_OPTIONS]:
opts.append(filter_emojis_only(i.group(1)))
body = body.replace(i.group(0), "")
return (body, opts)
bets = []
if allow_bets and v and v.admin_level >= PERMS['POST_BETS']:
body, bets = sanitize_poll_type(body, bet_regex)
body, options = sanitize_poll_type(body, poll_regex)
body, choices = sanitize_poll_type(body, choice_regex)
return (body, bets, options, choices)

View File

@ -129,15 +129,7 @@ def comment(v):
if v.admin_level < PERMS['POST_COMMENT_MODERATION'] and parent.author.any_block_exists(v):
abort(403, "You can't reply to users who have blocked you or users that you have blocked.")
options = []
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 list(choice_regex.finditer(body))[:POLL_MAX_OPTIONS]:
choices.append(i.group(1))
body = body.replace(i.group(0), "")
body, _, options, choices = sanitize_poll_options(v, body, False)
if request.files.get("file") and not g.is_tor:
files = request.files.getlist('file')[:4]
@ -241,25 +233,8 @@ def comment(v):
if c.level == 1: c.top_comment_id = c.id
else: c.top_comment_id = parent.top_comment_id
for option in options:
body_html = filter_emojis_only(option)
if len(body_html) > 500: abort(400, "Poll option too long!")
option = CommentOption(
comment_id=c.id,
body_html=body_html,
exclusive=0
)
g.db.add(option)
for choice in choices:
body_html = filter_emojis_only(choice)
if len(body_html) > 500: abort(400, "Poll option too long!")
choice = CommentOption(
comment_id=c.id,
body_html=body_html,
exclusive=1
)
g.db.add(choice)
process_poll_options(c, CommentOption, options, 0, "Poll", g.db)
process_poll_options(c, CommentOption, choices, 1, "Poll", g.db)
if SITE == 'pcmemes.net' and c.body.lower().startswith("based"):
execute_basedbot(c, level, body, parent_post, v)
@ -394,27 +369,9 @@ 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 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!")
option = CommentOption(
comment_id=c.id,
body_html=body_html,
exclusive = 0
)
g.db.add(option)
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!")
option = CommentOption(
comment_id=c.id,
body_html=body_html,
exclusive = 1
)
g.db.add(option)
body, _, options, choices = sanitize_poll_options(v, body, False)
process_poll_options(c, CommentOption, options, 0, "Poll", g.db)
process_poll_options(c, CommentOption, choices, 1, "Poll", g.db)
execute_antispam_comment_check(body, v)

View File

@ -299,39 +299,10 @@ def edit_post(pid, v):
body = body.strip()[:POST_BODY_LENGTH_LIMIT] # process_files() may be adding stuff to the body
if body != p.body:
if v and v.admin_level >= PERMS['POST_BETS']:
for i in bet_regex.finditer(body):
body = body.replace(i.group(0), "")
body_html = filter_emojis_only(i.group(1))
if len(body_html) > 500: abort(400, "Bet option too long!")
bet = SubmissionOption(
submission_id=p.id,
body_html=body_html,
exclusive = 2
)
g.db.add(bet)
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!")
option = SubmissionOption(
submission_id=p.id,
body_html=body_html,
exclusive = 0
)
g.db.add(option)
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!")
choice = SubmissionOption(
submission_id=p.id,
body_html=body_html,
exclusive = 1
)
g.db.add(choice)
body, bets, options, choices = sanitize_poll_options(v, body, False)
process_poll_options(p, SubmissionOption, bets, 2, "Bet", g.db)
process_poll_options(p, SubmissionOption, options, 0, "Poll", g.db)
process_poll_options(p, SubmissionOption, choices, 1, "Poll", g.db)
torture = (v.agendaposter and not v.marseyawarded and p.sub != 'chudrama' and v.id == p.author_id)
@ -700,21 +671,7 @@ def submit_post(v:User, sub=None):
if len(url) > 2048:
return error("There's a 2048 character limit for URLs.")
bets = []
if v and v.admin_level >= PERMS['POST_BETS']:
for i in bet_regex.finditer(body):
bets.append(i.group(1))
body = body.replace(i.group(0), "")
options = []
for i in list(poll_regex.finditer(body))[:10]:
options.append(i.group(1))
body = body.replace(i.group(0), "")
choices = []
for i in list(choice_regex.finditer(body))[:10]:
choices.append(i.group(1))
body = body.replace(i.group(0), "")
body, bets, options, choices = sanitize_poll_options(v, body, True)
body += process_files(request.files, v)
body = body.strip()[:POST_BODY_LENGTH_LIMIT] # process_files() adds content to the body, so we need to re-strip
@ -764,36 +721,9 @@ def submit_post(v:User, sub=None):
for text in {post.body, post.title, post.url}:
if not execute_blackjack(v, post, text, 'submission'): break
if v and v.admin_level >= PERMS['POST_BETS']:
for bet in bets:
body_html = filter_emojis_only(bet)
if len(body_html) > 500: abort(400, "Bet option too long!")
bet = SubmissionOption(
submission_id=post.id,
body_html=body_html,
exclusive=2
)
g.db.add(bet)
for option in options:
body_html = filter_emojis_only(option)
if len(body_html) > 500: abort(400, "Poll option too long!")
option = SubmissionOption(
submission_id=post.id,
body_html=body_html,
exclusive=0
)
g.db.add(option)
for choice in choices:
body_html = filter_emojis_only(choice)
if len(body_html) > 500: abort(400, "Poll option too long!")
choice = SubmissionOption(
submission_id=post.id,
body_html=body_html,
exclusive=1
)
g.db.add(choice)
process_poll_options(post, SubmissionOption, bets, 2, "Bet", g.db)
process_poll_options(post, SubmissionOption, options, 0, "Poll", g.db)
process_poll_options(post, SubmissionOption, choices, 1, "Poll", g.db)
vote = Vote(user_id=v.id,
vote_type=1,
@ -860,14 +790,9 @@ def submit_post(v:User, sub=None):
n = Notification(comment_id=c_jannied.id, user_id=v.id)
g.db.add(n)
if not post.private and not (post.sub and g.db.query(Exile.user_id).filter_by(user_id=SNAPPY_ID, sub=post.sub).one_or_none()):
execute_snappy(post, v)
v.post_count = g.db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
g.db.add(v)
@ -896,7 +821,6 @@ def submit_post(v:User, sub=None):
else: sort = v.defaultsortingcomments
return render_template('submission.html', v=v, p=post, sort=sort, render_replies=True, offset=0, success=True, sub=post.subr)
@app.post("/delete_post/<pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@auth_required

View File

@ -127,6 +127,11 @@ Text 2
<td>#roll</td>
<td>A number 1&ndash;9999.</td>
</tr>
<tr>
<td>Disable Poll Formatting</td>
<td>#disablepoll</td>
<td>Disables poll options (useful for large code blocks that have things like &amp;&amp;).</td>
</tr>
{%- endif %}
<tr>
<td>