2021-08-03 17:55:02 +00:00
import traceback
import sys
2021-08-04 15:35:10 +00:00
from files . helpers . wrappers import *
from files . helpers . filters import *
from files . helpers . alerts import *
from files . helpers . images import *
from files . helpers . session import *
from files . classes import *
from files . routes . front import comment_idlist
2021-08-11 02:54:52 +00:00
from pusher_push_notifications import PushNotifications
2021-07-21 01:12:26 +00:00
from flask import *
2021-08-04 15:35:10 +00:00
from files . __main__ import app , limiter
2021-07-21 01:12:26 +00:00
2021-08-05 14:41:32 +00:00
site = environ . get ( " DOMAIN " ) . strip ( )
2021-08-02 14:27:20 +00:00
2021-08-14 21:23:07 +00:00
choices = [ ' Wow, you must be a JP fan. ' , ' This is one of the worst posts I have EVER seen. Delete it. ' , " No, don ' t reply like this, please do another wall of unhinged rant please. " , ' # 😴😴😴 ' , " Ma ' am we ' ve been over this before. You need to stop. " , " I ' ve known more coherent downies. " , " Your pulitzer ' s in the mail " , " That ' s great and all, but I asked for my burger without cheese. " , ' That degree finally paying off ' , " That ' s nice sweaty. Why don ' t you have a seat in the time out corner with Pizzashill until you calm down, then you can have your Capri Sun. " , " All them words won ' t bring your pa back. " , " You had a chance to not be completely worthless, but it looks like you threw it away. At least you ' re consistent. " , ' Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot. ' , " You can type 10,000 characters and you decided that these were the one ' s that you wanted. " , ' Have you owned the libs yet? ' , " I don ' t know what you said, because I ' ve seen another human naked. " , ' Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities. ' , " This is a really long way of saying you don ' t fuck. " , " Sorry ma ' am, looks like his delusions have gotten worse. We ' ll have to admit him, " , ' ![](https://i.kym-cdn.com/photos/images/newsfeed/001/038/094/0a1.jpg) ' , ' If only you could put that energy into your relationships ' , ' Posts like this is why I do Heroine. ' , ' still unemployed then? ' , ' K ' , ' look im gunna have 2 ask u 2 keep ur giant dumps in the toilet not in my replys 😷😷😷 ' , " Mommy is soooo proud of you, sweaty. Let ' s put this sperg out up on the fridge with all your other failures. " , " Good job bobby, here ' s a star " , " That was a mistake. You ' re about to find out the hard way why. " , ' You sat down and wrote all this shit. You could have done so many other things with your life. What happened to your life that made you decide writing novels of bullshit on rdrama.net was the best option? ' , " I don ' t have enough spoons to read this shit " , " All those words won ' t bring daddy back. " , ' OUT! ' , " Mommy is soooo proud of you, sweaty. Let ' s put this sperg out up on the fridge with all your other failures. " ]
2021-07-21 01:12:26 +00:00
PUSHER_KEY = environ . get ( " PUSHER_KEY " , " " ) . strip ( )
beams_client = PushNotifications (
instance_id = ' 02ddcc80-b8db-42be-9022-44c546b4dce6 ' ,
secret_key = PUSHER_KEY ,
)
2021-07-27 22:31:28 +00:00
@app.get ( " /comment/<cid> " )
@app.get ( " /post/<pid>/<anything>/<cid> " )
2021-08-13 01:38:51 +00:00
@app.get ( " /logged_out/comment/<cid> " )
2021-08-13 02:55:52 +00:00
@app.get ( " /logged_out/post/<pid>/<anything>/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_desired
def post_pid_comment_cid ( cid , pid = None , anything = None , v = None ) :
if v and v . is_banned and not v . unban_utc : return render_template ( " seized.html " )
2021-08-13 01:38:51 +00:00
if not v and " logged_out " not in request . path : return redirect ( f " /logged_out/comment/ { cid } " )
2021-08-13 18:53:11 +00:00
if v and " logged_out " in request . full_path : v = None
2021-07-30 06:17:38 +00:00
try : cid = int ( cid )
2021-07-31 06:59:18 +00:00
except :
try : cid = int ( cid , 36 )
except : abort ( 404 )
2021-07-30 06:17:38 +00:00
2021-07-21 01:12:26 +00:00
comment = get_comment ( cid , v = v )
2021-08-12 23:19:00 +00:00
if not comment . parent_submission and not ( v and ( comment . author . id == v . id or comment . sentto == v . id ) ) and not ( v and v . admin_level == 6 and comment . sentto == 0 ) : abort ( 403 )
2021-07-21 01:12:26 +00:00
if not pid :
if comment . parent_submission : pid = comment . parent_submission
else : pid = 6489
try : pid = int ( pid )
except : abort ( 404 )
post = get_post ( pid , v = v )
2021-07-26 17:47:52 +00:00
if post . over_18 and not ( v and v . over_18 ) and not session . get ( ' over_18 ' , 0 ) > = int ( time . time ( ) ) :
2021-07-31 05:28:05 +00:00
if request . headers . get ( " Authorization " ) : return { ' error ' : f ' This content is not suitable for some users and situations. ' }
else : render_template ( " errors/nsfw.html " , v = v )
2021-07-21 01:12:26 +00:00
2021-08-07 23:23:10 +00:00
post . _preloaded_comments = [ comment ]
2021-07-21 01:12:26 +00:00
# context improver
2021-07-22 14:54:19 +00:00
try : context = int ( request . args . get ( " context " , 0 ) )
except : context = 0
2021-08-07 23:14:32 +00:00
comment_info = comment
2021-08-07 23:23:10 +00:00
c = comment
while context > 0 and c . level > 1 :
2021-07-21 01:12:26 +00:00
2021-08-07 23:23:10 +00:00
parent = get_comment ( c . parent_comment_id , v = v )
2021-07-21 01:12:26 +00:00
2021-08-07 23:23:10 +00:00
post . _preloaded_comments + = [ parent ]
2021-07-21 01:12:26 +00:00
2021-08-07 23:23:10 +00:00
c = parent
2021-07-21 01:12:26 +00:00
context - = 1
2021-08-07 23:23:10 +00:00
top_comment = c
2021-07-21 01:12:26 +00:00
if v : defaultsortingcomments = v . defaultsortingcomments
else : defaultsortingcomments = " top "
sort = request . args . get ( " sort " , defaultsortingcomments )
2021-08-07 23:14:32 +00:00
post . replies = [ top_comment ]
2021-07-21 01:12:26 +00:00
2021-08-11 03:24:13 +00:00
if v :
votes = g . db . query ( CommentVote ) . filter_by ( user_id = v . id ) . subquery ( )
blocking = v . blocking . subquery ( )
blocked = v . blocked . subquery ( )
comments = g . db . query (
Comment ,
votes . c . vote_type ,
blocking . c . id ,
blocked . c . id ,
)
if v . admin_level > = 4 :
comments = comments . options ( joinedload ( Comment . oauth_app ) )
comments = comments . filter (
Comment . parent_submission == post . id
) . join (
votes ,
votes . c . comment_id == Comment . id ,
isouter = True
) . join (
blocking ,
blocking . c . target_id == Comment . author_id ,
isouter = True
) . join (
blocked ,
blocked . c . user_id == Comment . author_id ,
isouter = True
)
for c in comments :
comment = c [ 0 ]
if comment . author and comment . author . shadowbanned and not ( v and v . id == comment . author_id ) : continue
comment . voted = c [ 1 ] or 0
comment . _is_blocking = c [ 2 ] or 0
comment . _is_blocked = c [ 3 ] or 0
2021-08-07 23:14:32 +00:00
if request . headers . get ( " Authorization " ) : return top_comment . json
else : return post . rendered_page ( v = v , sort = sort , comment = top_comment , comment_info = comment_info )
2021-07-31 05:59:25 +00:00
2021-07-21 01:12:26 +00:00
2021-07-31 06:55:22 +00:00
@app.post ( " /comment " )
2021-07-21 01:12:26 +00:00
@limiter.limit ( " 6/minute " )
@is_not_banned
@validate_formkey
def api_comment ( v ) :
2021-07-30 05:31:38 +00:00
parent_submission = request . form . get ( " submission " )
2021-07-21 01:12:26 +00:00
parent_fullname = request . form . get ( " parent_fullname " )
# get parent item info
parent_id = parent_fullname . split ( " _ " ) [ 1 ]
if parent_fullname . startswith ( " t2 " ) :
parent_post = get_post ( parent_id , v = v )
parent = parent_post
parent_comment_id = None
level = 1
2021-07-30 05:31:38 +00:00
parent_submission = parent_id
2021-07-21 01:12:26 +00:00
elif parent_fullname . startswith ( " t3 " ) :
parent = get_comment ( parent_id , v = v )
parent_comment_id = parent . id
level = parent . level + 1
parent_id = parent . parent_submission
parent_submission = parent_id
2021-07-30 05:31:38 +00:00
parent_post = get_post ( parent_id )
2021-07-21 01:12:26 +00:00
else :
abort ( 400 )
#process and sanitize
2021-08-02 07:37:46 +00:00
body = request . form . get ( " body " , " " ) [ : 10000 ]
2021-07-21 01:12:26 +00:00
body = body . strip ( )
2021-08-11 17:01:19 +00:00
if not body and not request . files . get ( ' file ' ) : return { " error " : " You need to actually write something! " } , 400
2021-07-21 01:12:26 +00:00
2021-08-19 05:14:52 +00:00
for i in re . finditer ( ' ^(https: \ / \ /.* \ .(png|jpg|jpeg|gif|PNG|JPG|JPEG|GIF|?maxwidth=9999)) ' , body , re . MULTILINE ) : body = body . replace ( i . group ( 1 ) , f ' ![]( { i . group ( 1 ) } ) ' )
2021-07-31 08:47:10 +00:00
body = body . replace ( " \n " , " \n \n " ) . replace ( " \n \n \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n " , " \n \n " )
2021-07-21 01:12:26 +00:00
with CustomRenderer ( post_id = parent_id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
body_html = sanitize ( body_md , linkgen = True )
# Run safety filter
bans = filter_comment_html ( body_html )
if bans :
ban = bans [ 0 ]
reason = f " Remove the { ban . domain } link from your comment and try again. "
if ban . reason :
2021-08-03 12:20:40 +00:00
reason + = f " { ban . reason } "
2021-07-21 01:12:26 +00:00
#auto ban for digitally malicious content
if any ( [ x . reason == 4 for x in bans ] ) :
v . ban ( days = 30 , reason = " Digitally malicious content " )
if any ( [ x . reason == 7 for x in bans ] ) :
v . ban ( reason = " Sexualizing minors " )
2021-08-11 17:01:19 +00:00
return { " error " : reason } , 401
2021-07-21 01:12:26 +00:00
# check existing
existing = g . db . query ( Comment ) . join ( CommentAux ) . filter ( Comment . author_id == v . id ,
Comment . deleted_utc == 0 ,
Comment . parent_comment_id == parent_comment_id ,
Comment . parent_submission == parent_submission ,
CommentAux . body == body
) . options ( contains_eager ( Comment . comment_aux ) ) . first ( )
if existing :
2021-08-11 17:01:19 +00:00
return { " error " : f " You already made that comment: { existing . permalink } " } , 409
2021-07-21 01:12:26 +00:00
if parent . author . any_block_exists ( v ) and not v . admin_level > = 3 :
2021-08-11 17:01:19 +00:00
return { " error " : " You can ' t reply to users who have blocked you, or users you have blocked. " } , 403
2021-07-21 01:12:26 +00:00
# get bot status
is_bot = request . headers . get ( " X-User-Type " , " " ) == " Bot "
# check spam - this should hopefully be faster
if not is_bot :
now = int ( time . time ( ) )
cutoff = now - 60 * 60 * 24
similar_comments = g . db . query ( Comment
) . options (
lazyload ( ' * ' )
) . join ( Comment . comment_aux
) . filter (
Comment . author_id == v . id ,
CommentAux . body . op (
' <-> ' ) ( body ) < app . config [ " COMMENT_SPAM_SIMILAR_THRESHOLD " ] ,
Comment . created_utc > cutoff
) . options ( contains_eager ( Comment . comment_aux ) ) . all ( )
threshold = app . config [ " COMMENT_SPAM_COUNT_THRESHOLD " ]
if v . age > = ( 60 * 60 * 24 * 7 ) :
threshold * = 3
elif v . age > = ( 60 * 60 * 24 ) :
threshold * = 2
if len ( similar_comments ) > threshold :
2021-08-04 16:00:57 +00:00
text = " Your account has been suspended for 1 day for the following reason: \n \n > Too much spam! "
2021-07-21 01:12:26 +00:00
send_notification ( 1046 , v , text )
v . ban ( reason = " Spamming. " ,
days = 1 )
for alt in v . alts :
if not alt . is_suspended :
2021-07-30 08:37:55 +00:00
alt . ban ( reason = " Spamming. " , days = 1 )
2021-07-21 01:12:26 +00:00
for comment in similar_comments :
comment . is_banned = True
comment . ban_reason = " Automatic spam removal. This happened because the post ' s creator submitted too much similar content too quickly. "
g . db . add ( comment )
ma = ModAction (
user_id = 2317 ,
target_comment_id = comment . id ,
kind = " ban_comment " ,
note = " spam "
)
g . db . add ( ma )
2021-08-11 17:01:19 +00:00
return { " error " : " Too much spam! " } , 403
2021-07-21 01:12:26 +00:00
# check badlinks
soup = BeautifulSoup ( body_html , features = " html.parser " )
links = [ x [ ' href ' ] for x in soup . find_all ( ' a ' ) if x . get ( ' href ' ) ]
for link in links :
parse_link = urlparse ( link )
check_url = ParseResult ( scheme = " https " ,
netloc = parse_link . netloc ,
path = parse_link . path ,
params = parse_link . params ,
query = parse_link . query ,
fragment = ' ' )
check_url = urlunparse ( check_url )
badlink = g . db . query ( BadLink ) . filter (
literal ( check_url ) . contains (
BadLink . link ) ) . first ( )
2021-08-11 17:01:19 +00:00
if badlink : return { " error " : f " Remove the following link and try again: ` { check_url } `. Reason: { badlink . reason } " } , 403
2021-07-21 01:12:26 +00:00
# create comment
2021-07-25 23:59:02 +00:00
parent_id = parent_fullname . split ( " _ " ) [ 1 ]
2021-07-21 01:12:26 +00:00
c = Comment ( author_id = v . id ,
parent_submission = parent_submission ,
parent_comment_id = parent_comment_id ,
level = level ,
2021-07-26 03:26:57 +00:00
over_18 = parent_post . over_18 or request . form . get ( " over_18 " , " " ) == " true " ,
2021-07-21 01:12:26 +00:00
is_bot = is_bot ,
2021-08-03 17:33:13 +00:00
app_id = v . client . application . id if v . client else None ,
2021-07-26 02:45:35 +00:00
shadowbanned = v . shadowbanned
2021-07-21 01:12:26 +00:00
)
g . db . add ( c )
g . db . flush ( )
2021-07-31 09:00:56 +00:00
if request . files . get ( " file " ) and request . headers . get ( " cf-ipcountry " ) != " T1 " :
2021-07-27 21:35:50 +00:00
file = request . files [ " file " ]
2021-08-11 17:01:19 +00:00
if not file . content_type . startswith ( ' image/ ' ) : return { " error " : " That wasn ' t an image! " } , 400
2021-07-27 21:35:50 +00:00
2021-07-29 08:03:00 +00:00
url = upload_file ( file )
2021-07-27 21:35:50 +00:00
body = request . form . get ( " body " ) + f " \n ![]( { url } ) "
2021-07-31 08:47:10 +00:00
body = body . replace ( " \n " , " \n \n " ) . replace ( " \n \n \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n " , " \n \n " )
2021-07-27 21:35:50 +00:00
with CustomRenderer ( post_id = parent_id ) as renderer :
body_md = renderer . render ( mistletoe . Document ( body ) )
body_html = sanitize ( body_md , linkgen = True )
2021-07-21 01:12:26 +00:00
c_aux = CommentAux (
id = c . id ,
body_html = body_html ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
2021-07-21 21:36:46 +00:00
if v . agendaposter and " trans lives matter " not in c_aux . body_html . lower ( ) :
c . is_banned = True
c . ban_reason = " ToS Violation "
g . db . add ( c )
c_jannied = Comment ( author_id = 2317 ,
parent_submission = parent_submission ,
distinguish_level = 6 ,
parent_comment_id = c . id ,
level = level + 1 ,
is_bot = True ,
)
g . db . add ( c_jannied )
g . db . flush ( )
body = f """ Hi @ { v . username } , \n \n Your comment has been automatically removed because you forgot
to include ` trans lives matter ` . \n \nDon ' t worry, we ' re here to help ! We
won ' t let you post or comment anything that doesn ' t express your love and acceptance towards
the trans community . Feel free to resubmit your comment with ` trans lives matter `
included . \n \n * This is an automated message ; if you need help ,
you can message us [ here ] ( / contact ) . * """
2021-07-31 08:47:10 +00:00
#body = body.replace("\n", "\n\n").replace("\n\n\n\n\n\n", "\n\n").replace("\n\n\n\n", "\n\n").replace("\n\n\n", "\n\n")
2021-07-21 21:36:46 +00:00
with CustomRenderer ( post_id = parent_id ) as renderer :
body_md = renderer . render ( mistletoe . Document ( body ) )
body_jannied_html = sanitize ( body_md )
c_aux = CommentAux (
id = c_jannied . id ,
body_html = body_jannied_html ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
n = Notification ( comment_id = c_jannied . id , user_id = v . id )
g . db . add ( n )
2021-07-21 01:12:26 +00:00
if len ( body ) > = 1000 and v . username != " Snappy " and " </blockquote> " not in body_html :
c2 = Comment ( author_id = 1832 ,
parent_submission = parent_submission ,
parent_comment_id = c . id ,
level = level + 1 ,
is_bot = True ,
)
g . db . add ( c2 )
g . db . flush ( )
body = random . choice ( choices )
2021-07-31 08:47:10 +00:00
body = body . replace ( " \n " , " \n \n " ) . replace ( " \n \n \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n " , " \n \n " )
2021-07-21 01:12:26 +00:00
with CustomRenderer ( post_id = parent_id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
body_html2 = sanitize ( body_md , linkgen = True )
c_aux = CommentAux (
id = c2 . id ,
body_html = body_html2 ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
n = Notification ( comment_id = c2 . id , user_id = v . id )
g . db . add ( n )
if random . random ( ) < 0.001 and v . username != " Snappy " and v . username != " zozbot " :
c2 = Comment ( author_id = 1833 ,
parent_submission = parent_submission ,
parent_comment_id = c . id ,
level = level + 1 ,
is_bot = True ,
)
g . db . add ( c2 )
g . db . flush ( )
body = " zoz "
with CustomRenderer ( post_id = parent_id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
body_html2 = sanitize ( body_md , linkgen = True )
c_aux = CommentAux (
id = c2 . id ,
body_html = body_html2 ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
n = Notification ( comment_id = c2 . id , user_id = v . id )
g . db . add ( n )
c3 = Comment ( author_id = 1833 ,
parent_submission = parent_submission ,
parent_comment_id = c2 . id ,
level = level + 2 ,
is_bot = True ,
)
g . db . add ( c3 )
g . db . flush ( )
body = " zle "
with CustomRenderer ( post_id = parent_id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
body_html2 = sanitize ( body_md , linkgen = True )
c_aux = CommentAux (
id = c3 . id ,
body_html = body_html2 ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
c4 = Comment ( author_id = 1833 ,
parent_submission = parent_submission ,
parent_comment_id = c3 . id ,
level = level + 3 ,
is_bot = True ,
)
g . db . add ( c4 )
g . db . flush ( )
body = " zozzle "
with CustomRenderer ( post_id = parent_id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
body_html2 = sanitize ( body_md , linkgen = True )
c_aux = CommentAux (
id = c4 . id ,
body_html = body_html2 ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
2021-07-26 02:45:35 +00:00
if not v . shadowbanned :
2021-07-22 11:32:47 +00:00
# queue up notification for parent author
notify_users = set ( )
for x in g . db . query ( Subscription . user_id ) . filter_by ( submission_id = c . parent_submission ) . all ( ) :
notify_users . add ( x )
if parent . author . id != v . id : notify_users . add ( parent . author . id )
soup = BeautifulSoup ( body_html , features = " html.parser " )
mentions = soup . find_all ( " a " , href = re . compile ( " ^/@( \ w+) " ) )
for mention in mentions :
username = mention [ " href " ] . split ( " @ " ) [ 1 ]
user = g . db . query ( User ) . filter_by ( username = username ) . first ( )
if user :
if v . any_block_exists ( user ) :
continue
if user . id != v . id :
notify_users . add ( user . id )
for x in notify_users :
n = Notification ( comment_id = c . id , user_id = x )
g . db . add ( n )
try : g . db . flush ( )
except : g . db . rollback ( )
if parent . author . id != v . id :
2021-08-03 17:55:02 +00:00
try :
beams_client . publish_to_interests (
interests = [ str ( parent . author . id ) ] ,
publish_body = {
' web ' : {
' notification ' : {
' title ' : f ' New reply by @ { v . username } ' ,
' body ' : c . body ,
' deep_link ' : f ' https:// { site } { c . permalink } ?context=5#context ' ,
} ,
} ,
2021-07-22 11:32:47 +00:00
} ,
2021-08-03 17:55:02 +00:00
)
2021-08-11 02:54:52 +00:00
except Exception as e :
print ( e )
2021-07-21 01:12:26 +00:00
# create auto upvote
vote = CommentVote ( user_id = v . id ,
comment_id = c . id ,
vote_type = 1
)
g . db . add ( vote )
c = get_comment ( c . id , v = v )
cache . delete_memoized ( comment_idlist )
2021-08-11 17:06:56 +00:00
cache . delete_memoized ( User . commentlisting , v )
2021-07-21 01:12:26 +00:00
2021-07-28 03:55:47 +00:00
v . comment_count = v . comments . filter ( Comment . parent_submission != None ) . filter_by ( is_banned = False , deleted_utc = 0 ) . count ( )
g . db . add ( v )
2021-07-31 06:51:58 +00:00
2021-07-31 06:55:22 +00:00
if request . headers . get ( " Authorization " ) : return c . json
else : return jsonify ( { " html " : render_template ( " comments.html " ,
v = v ,
comments = [ c ] ,
render_replies = False ,
) } )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.post ( " /edit_comment/<cid> " )
2021-07-31 06:27:21 +00:00
@is_not_banned
@validate_formkey
2021-07-21 01:12:26 +00:00
def edit_comment ( cid , v ) :
c = get_comment ( cid , v = v )
if not c . author_id == v . id : abort ( 403 )
if c . is_banned or c . deleted_utc > 0 : abort ( 403 )
2021-08-02 07:37:46 +00:00
body = request . form . get ( " body " , " " ) [ : 10000 ]
2021-08-19 05:14:52 +00:00
for i in re . finditer ( ' ^(https: \ / \ /.* \ .(png|jpg|jpeg|gif|PNG|JPG|JPEG|GIF|?maxwidth=9999)) ' , body , re . MULTILINE ) : body = body . replace ( i . group ( 1 ) , f ' ![]( { i . group ( 1 ) } ) ' )
2021-07-31 08:47:10 +00:00
body = body . replace ( " \n " , " \n \n " ) . replace ( " \n \n \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n " , " \n \n " )
2021-07-30 05:31:38 +00:00
with CustomRenderer ( post_id = c . post . id ) as renderer : body_md = renderer . render ( mistletoe . Document ( body ) )
2021-07-21 01:12:26 +00:00
body_html = sanitize ( body_md , linkgen = True )
bans = filter_comment_html ( body_html )
if bans :
ban = bans [ 0 ]
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 ] ) :
v . ban ( days = 30 , reason = " Digitally malicious content is not allowed. " )
2021-07-31 05:28:05 +00:00
return { " error " : " Digitally malicious content is not allowed. " }
2021-07-21 01:12:26 +00:00
if ban . reason :
2021-08-03 12:20:40 +00:00
reason + = f " { ban . reason } "
2021-07-21 01:12:26 +00:00
2021-07-31 05:59:25 +00:00
if request . headers . get ( " Authorization " ) : return { ' error ' : f ' A blacklisted domain was used. ' } , 400
else : return render_template ( " comment_failed.html " ,
2021-07-30 05:31:38 +00:00
action = f " /edit_comment/ { c . id } " ,
2021-07-21 01:12:26 +00:00
badlinks = [
x . domain for x in bans ] ,
body = body ,
v = v
2021-07-31 05:59:25 +00:00
)
2021-07-21 01:12:26 +00:00
# check badlinks
soup = BeautifulSoup ( body_html , features = " html.parser " )
links = [ x [ ' href ' ] for x in soup . find_all ( ' a ' ) if x . get ( ' href ' ) ]
for link in links :
parse_link = urlparse ( link )
check_url = ParseResult ( scheme = " https " ,
netloc = parse_link . netloc ,
path = parse_link . path ,
params = parse_link . params ,
query = parse_link . query ,
fragment = ' ' )
check_url = urlunparse ( check_url )
badlink = g . db . query ( BadLink ) . filter (
literal ( check_url ) . contains (
BadLink . link ) ) . first ( )
if badlink :
2021-08-03 12:20:40 +00:00
return { " error " : f " Remove the following link and try again: ` { check_url } `. Reason: { badlink . reason } " } , 403
2021-07-21 01:12:26 +00:00
# check spam - this should hopefully be faster
now = int ( time . time ( ) )
cutoff = now - 60 * 60 * 24
similar_comments = g . db . query ( Comment
) . options (
lazyload ( ' * ' )
) . join ( Comment . comment_aux
) . filter (
Comment . author_id == v . id ,
CommentAux . body . op (
' <-> ' ) ( body ) < app . config [ " SPAM_SIMILARITY_THRESHOLD " ] ,
Comment . created_utc > cutoff
) . options ( contains_eager ( Comment . comment_aux ) ) . all ( )
threshold = app . config [ " SPAM_SIMILAR_COUNT_THRESHOLD " ]
if v . age > = ( 60 * 60 * 24 * 30 ) :
threshold * = 4
elif v . age > = ( 60 * 60 * 24 * 7 ) :
threshold * = 3
elif v . age > = ( 60 * 60 * 24 ) :
threshold * = 2
if len ( similar_comments ) > threshold :
2021-08-04 16:00:57 +00:00
text = " Your account has been suspended for 1 day for the following reason: \n \n > Too much spam! "
2021-07-21 01:12:26 +00:00
send_notification ( 1046 , v , text )
v . ban ( reason = " Spamming. " ,
days = 1 )
for comment in similar_comments :
comment . is_banned = True
comment . ban_reason = " Automatic spam removal. This happened because the post ' s creator submitted too much similar content too quickly. "
g . db . add ( comment )
2021-07-31 05:28:05 +00:00
return { " error " : " Too much spam! " } , 403
2021-07-21 01:12:26 +00:00
2021-07-31 09:00:56 +00:00
if request . files . get ( " file " ) and request . headers . get ( " cf-ipcountry " ) != " T1 " :
2021-07-27 21:35:50 +00:00
file = request . files [ " file " ]
2021-07-31 05:28:05 +00:00
if not file . content_type . startswith ( ' image/ ' ) : return { " error " : " That wasn ' t an image! " } , 400
2021-07-27 21:35:50 +00:00
2021-07-30 05:31:38 +00:00
name = f ' comment/ { c . id } / { secrets . token_urlsafe ( 8 ) } '
2021-07-29 08:03:00 +00:00
url = upload_file ( file )
2021-07-27 21:35:50 +00:00
body + = f " \n ![]( { url } ) "
2021-07-31 08:47:10 +00:00
body = body . replace ( " \n " , " \n \n " ) . replace ( " \n \n \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n \n " , " \n \n " ) . replace ( " \n \n \n " , " \n \n " )
2021-07-27 21:35:50 +00:00
with CustomRenderer ( post_id = c . parent_submission ) as renderer :
body_md = renderer . render ( mistletoe . Document ( body ) )
body_html = sanitize ( body_md , linkgen = True )
2021-07-21 01:12:26 +00:00
c . body = body
c . body_html = body_html
2021-07-21 21:36:46 +00:00
if v . agendaposter and " trans lives matter " not in c . body_html . lower ( ) :
c . is_banned = True
c . ban_reason = " ToS Violation "
g . db . add ( c )
c_jannied = Comment ( author_id = 2317 ,
parent_submission = c . parent_submission ,
distinguish_level = 6 ,
parent_comment_id = c . id ,
level = c . level + 1 ,
is_bot = True ,
)
g . db . add ( c_jannied )
g . db . flush ( )
body = f """ Hi @ { v . username } , \n \n Your comment has been automatically removed because you forgot
to include ` trans lives matter ` . \n \nDon ' t worry, we ' re here to help ! We
won ' t let you post or comment anything that doesn ' t express your love and acceptance towards
the trans community . Feel free to resubmit your comment with ` trans lives matter `
included . \n \n * This is an automated message ; if you need help ,
you can message us [ here ] ( / contact ) . * """
with CustomRenderer ( post_id = c . parent_submission ) as renderer :
body_md = renderer . render ( mistletoe . Document ( body ) )
body_jannied_html = sanitize ( body_md )
c_aux = CommentAux (
id = c_jannied . id ,
body_html = body_jannied_html ,
body = body
)
g . db . add ( c_aux )
g . db . flush ( )
n = Notification ( comment_id = c_jannied . id , user_id = v . id )
g . db . add ( n )
2021-07-21 01:12:26 +00:00
if int ( time . time ( ) ) - c . created_utc > 60 * 3 : c . edited_utc = int ( time . time ( ) )
g . db . add ( c )
2021-08-11 17:01:19 +00:00
g . db . flush ( )
2021-07-21 01:12:26 +00:00
# queue up notifications for username mentions
notify_users = set ( )
soup = BeautifulSoup ( body_html , features = " html.parser " )
mentions = soup . find_all ( " a " , href = re . compile ( " ^/@( \ w+) " ) )
if len ( mentions ) > 0 :
notifs = g . db . query ( Notification )
for mention in mentions :
username = mention [ " href " ] . split ( " @ " ) [ 1 ]
user = g . db . query ( User ) . filter_by ( username = username ) . first ( )
if user :
if v . any_block_exists ( user ) :
continue
if user . id != v . id :
notify_users . add ( user . id )
for x in notify_users :
notif = notifs . filter_by ( comment_id = c . id , user_id = x ) . first ( )
if not notif :
n = Notification ( comment_id = c . id , user_id = x )
g . db . add ( n )
2021-07-31 06:55:22 +00:00
return jsonify ( { " html " : c . body_html } )
2021-07-21 01:12:26 +00:00
2021-07-28 03:55:47 +00:00
@app.post ( " /delete/comment/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
def delete_comment ( cid , v ) :
2021-07-30 05:31:38 +00:00
c = g . db . query ( Comment ) . filter_by ( id = cid ) . first ( )
2021-07-21 01:12:26 +00:00
if not c :
abort ( 404 )
if not c . author_id == v . id :
abort ( 403 )
c . deleted_utc = int ( time . time ( ) )
g . db . add ( c )
2021-07-27 22:24:06 +00:00
2021-08-11 17:01:19 +00:00
cache . delete_memoized ( comment_idlist )
2021-08-11 17:06:56 +00:00
cache . delete_memoized ( User . commentlisting , v )
2021-07-21 01:12:26 +00:00
2021-07-31 05:28:05 +00:00
return " " , 204
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.post ( " /undelete/comment/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
def undelete_comment ( cid , v ) :
2021-07-30 05:31:38 +00:00
c = g . db . query ( Comment ) . filter_by ( id = cid ) . first ( )
2021-07-21 01:12:26 +00:00
if not c :
abort ( 404 )
if not c . author_id == v . id :
abort ( 403 )
c . deleted_utc = 0
g . db . add ( c )
2021-08-11 17:01:19 +00:00
cache . delete_memoized ( comment_idlist )
2021-08-11 17:06:56 +00:00
cache . delete_memoized ( User . commentlisting , v )
2021-07-21 01:12:26 +00:00
2021-07-31 05:28:05 +00:00
return " " , 204
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.post ( " /comment_pin/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
2021-07-25 21:59:20 +00:00
def toggle_comment_pin ( cid , v ) :
2021-07-21 01:12:26 +00:00
comment = get_comment ( cid , v = v )
2021-07-28 22:11:18 +00:00
if v . admin_level < 1 and v . id != comment . post . author_id :
2021-07-21 01:12:26 +00:00
abort ( 403 )
comment . is_pinned = not comment . is_pinned
g . db . add ( comment )
2021-08-11 17:01:19 +00:00
g . db . flush ( )
2021-07-21 01:12:26 +00:00
if v . admin_level == 6 :
ma = ModAction (
kind = " pin_comment " if comment . is_pinned else " unpin_comment " ,
user_id = v . id ,
target_comment_id = comment . id
)
g . db . add ( ma )
html = render_template (
" comments.html " ,
v = v ,
comments = [ comment ] ,
render_replies = False ,
)
2021-07-30 05:31:38 +00:00
html = str ( BeautifulSoup ( html , features = " html.parser " ) . find ( id = f " comment- { comment . id } -only " ) )
2021-07-21 01:12:26 +00:00
2021-07-31 05:28:05 +00:00
return html
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.post ( " /save_comment/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
def save_comment ( cid , v ) :
comment = get_comment ( cid )
new_save = SaveRelationship ( user_id = v . id , submission_id = comment . id , type = 2 )
g . db . add ( new_save )
try : g . db . flush ( )
2021-07-28 05:04:30 +00:00
except : g . db . rollback ( )
2021-07-21 01:12:26 +00:00
return " " , 204
2021-07-27 22:31:28 +00:00
@app.post ( " /unsave_comment/<cid> " )
2021-07-21 01:12:26 +00:00
@auth_required
@validate_formkey
def unsave_comment ( cid , v ) :
comment = get_comment ( cid )
save = g . db . query ( SaveRelationship ) . filter_by ( user_id = v . id , submission_id = comment . id , type = 2 ) . first ( )
2021-08-11 18:30:25 +00:00
if save : g . db . delete ( save )
2021-07-21 01:12:26 +00:00
2021-08-07 23:23:10 +00:00
return " " , 204