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
parent
892e35b1c3
commit
ed0981cbdb
|
@ -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)
|
||||
|
|
|
@ -1444,6 +1444,8 @@ TROLLTITLES = [
|
|||
"Hey jannies can you please ban @{username}",
|
||||
]
|
||||
|
||||
DISABLE_POLL_COMMAND = "disablepoll"
|
||||
|
||||
NOTIFIED_USERS = {
|
||||
'aevan': AEVANN_ID,
|
||||
'avean': AEVANN_ID,
|
||||
|
|
|
@ -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>'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -127,6 +127,11 @@ Text 2
|
|||
<td>#roll</td>
|
||||
<td>A number 1–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 &&).</td>
|
||||
</tr>
|
||||
{%- endif %}
|
||||
<tr>
|
||||
<td>
|
||||
|
|
Loading…
Reference in New Issue