2021-10-15 14:08:27 +00:00
import time
import mistletoe
import gevent
import requests
from files . helpers . wrappers import *
from files . helpers . sanitize import *
from files . helpers . filters import *
from files . helpers . markdown import *
2021-12-20 20:03:59 +00:00
from files . helpers . alerts import *
2021-12-31 14:09:44 +00:00
from files . helpers . discord import send_discord_message
2021-10-15 14:08:27 +00:00
from files . helpers . const import *
from files . classes import *
from flask import *
from io import BytesIO
from files . __main__ import app , limiter , cache , db_session
from PIL import Image as PILimage
from . front import frontlist , changeloglist
2022-01-07 19:13:01 +00:00
from urllib . parse import ParseResult , urlunparse , urlparse , quote , unquote
2021-11-29 23:35:43 +00:00
from os import path
2021-12-18 02:59:40 +00:00
import requests
2021-12-23 15:00:07 +00:00
from shutil import copyfile
2022-01-10 23:34:56 +00:00
from psutil import cpu_percent
2021-10-15 14:08:27 +00:00
site = environ . get ( " DOMAIN " ) . strip ( )
2021-11-29 23:35:43 +00:00
site_name = environ . get ( " SITE_NAME " ) . strip ( )
2021-12-28 04:47:02 +00:00
IMGUR_KEY = environ . get ( " IMGUR_KEY " ) . strip ( )
2021-10-15 14:08:27 +00:00
2022-01-11 00:05:00 +00:00
CF_KEY = environ . get ( " CF_KEY " , " " ) . strip ( )
CF_ZONE = environ . get ( " CF_ZONE " , " " ) . strip ( )
CF_HEADERS = { " Authorization " : f " Bearer { CF_KEY } " , " Content-Type " : " application/json " }
2021-11-29 23:35:43 +00:00
if path . exists ( f ' snappy_ { site_name } .txt ' ) :
with open ( f ' snappy_ { site_name } .txt ' , " r " ) as f :
2022-01-02 17:03:40 +00:00
if site == ' pcmemes.net ' : snappyquotes = f . read ( ) . split ( " { [para]} " )
else : snappyquotes = f . read ( ) . split ( " { [para]} " ) + [ f ' :# { x } : ' for x in marseys ]
2021-10-15 14:08:27 +00:00
@app.post ( " /toggle_club/<pid> " )
@auth_required
def toggle_club ( pid , v ) :
2021-12-21 15:07:28 +00:00
if v . club_allowed == False : abort ( 403 )
2021-10-15 14:08:27 +00:00
post = get_post ( pid )
2021-11-07 20:31:36 +00:00
if post . author_id != v . id and v . admin_level == 0 : abort ( 403 )
2021-10-15 14:08:27 +00:00
post . club = not post . club
g . db . add ( post )
2021-11-26 19:31:36 +00:00
g . db . commit ( )
2021-10-15 14:08:27 +00:00
if post . club : return { " message " : " Post has been marked as club-only! " }
else : return { " message " : " Post has been unmarked as club-only! " }
@app.post ( " /publish/<pid> " )
@limiter.limit ( " 1/second " )
@auth_required
def publish ( pid , v ) :
post = get_post ( pid )
if not post . author_id == v . id : abort ( 403 )
post . private = False
2021-12-13 21:27:25 +00:00
post . created_utc = int ( time . time ( ) )
2021-10-15 14:08:27 +00:00
g . db . add ( post )
2022-01-07 19:13:01 +00:00
notify_users = NOTIFY_USERS ( post . body_html , v ) | NOTIFY_USERS2 ( post . title , v )
2021-11-28 14:51:31 +00:00
2021-12-20 20:03:59 +00:00
cid = notif_comment ( f " @ { v . username } has mentioned you: [ { post . title } ]( { post . permalink } ) " )
for x in notify_users :
add_notif ( cid , x )
2021-10-15 14:08:27 +00:00
2021-12-20 20:03:59 +00:00
cid = notif_comment ( f " @ { v . username } has made a new post: [ { post . title } ]( { post . permalink } ) " , True )
2021-10-15 14:08:27 +00:00
for follow in v . followers :
user = get_account ( follow . user_id )
2021-12-20 20:03:59 +00:00
if post . club and not user . paid_dues : continue
add_notif ( cid , user . id )
2021-10-15 14:08:27 +00:00
2021-10-25 13:55:56 +00:00
cache . delete_memoized ( frontlist )
2021-12-31 14:12:26 +00:00
cache . delete_memoized ( User . userpagelisting )
2022-01-01 00:02:53 +00:00
if v . admin_level > 1 and ( " [changelog] " in post . title or " (changelog) " in post . title ) :
send_discord_message ( f " https:// { site } { post . permalink } " )
2021-12-31 14:12:26 +00:00
cache . delete_memoized ( changeloglist )
2021-10-25 13:55:56 +00:00
2021-10-15 14:08:27 +00:00
g . db . commit ( )
return { " message " : " Post published! " }
@app.get ( " /submit " )
@auth_required
def submit_get ( v ) :
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " ,
2021-10-15 14:08:27 +00:00
v = v )
@app.get ( " /post/<pid> " )
@app.get ( " /post/<pid>/<anything> " )
@app.get ( " /logged_out/post/<pid> " )
@app.get ( " /logged_out/post/<pid>/<anything> " )
@auth_desired
def post_id ( pid , anything = None , v = None ) :
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template2 = ' '
2021-12-19 13:10:54 +00:00
else : template2 = ' CHRISTMAS/ '
2021-10-15 14:08:27 +00:00
if not v and not request . path . startswith ( ' /logged_out ' ) and not request . headers . get ( " Authorization " ) : return redirect ( f " /logged_out { request . full_path } " )
if v and request . path . startswith ( ' /logged_out ' ) : v = None
2021-11-23 14:12:19 +00:00
2021-10-15 14:08:27 +00:00
try : pid = int ( pid )
except Exception as e : pass
2021-11-26 00:34:52 +00:00
2021-10-15 14:08:27 +00:00
try : pid = int ( pid )
except :
try : pid = int ( pid , 36 )
except : abort ( 404 )
post = get_post ( pid , v = v )
2021-12-31 14:01:50 +00:00
if ' megathread ' in post . title . lower ( ) : defaultsortingcomments = ' new '
elif v : defaultsortingcomments = v . defaultsortingcomments
else : defaultsortingcomments = " top "
2021-12-31 14:03:11 +00:00
sort = request . values . get ( " sort " , defaultsortingcomments )
2021-12-31 14:01:50 +00:00
2021-12-19 03:01:21 +00:00
if post . club and not ( v and ( v . paid_dues or v . id == post . author_id ) ) : abort ( 403 )
2021-10-15 14:08:27 +00:00
if v :
2021-11-06 15:52:48 +00:00
votes = g . db . query ( CommentVote ) . filter_by ( user_id = v . id ) . subquery ( )
2021-10-15 14:08:27 +00:00
blocking = v . blocking . subquery ( )
blocked = v . blocked . subquery ( )
comments = g . db . query (
Comment ,
votes . c . vote_type ,
blocking . c . id ,
blocked . c . id ,
2021-11-06 15:52:48 +00:00
)
2021-10-15 14:08:27 +00:00
2021-11-15 22:13:29 +00:00
if not ( v and v . shadowbanned ) and not ( v and v . admin_level > 1 ) :
2021-11-06 00:33:32 +00:00
comments = comments . join ( User , User . id == Comment . author_id ) . filter ( User . shadowbanned == None )
2021-10-15 14:08:27 +00:00
2021-12-11 02:27:46 +00:00
comments = comments . filter ( Comment . parent_submission == post . id , Comment . author_id . notin_ ( ( AUTOPOLLER_ID , AUTOBETTER_ID ) ) ) . join (
2021-10-15 14:08:27 +00:00
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
)
2021-12-05 02:51:14 +00:00
output = [ ]
for c in comments . all ( ) :
comment = c [ 0 ]
comment . voted = c [ 1 ] or 0
comment . is_blocking = c [ 2 ] or 0
comment . is_blocked = c [ 3 ] or 0
output . append ( comment )
2021-12-05 16:44:09 +00:00
pinned = [ c [ 0 ] for c in comments . filter ( Comment . is_pinned != None ) . all ( ) ]
comments = comments . filter ( Comment . level == 1 , Comment . is_pinned == None )
2021-12-05 02:51:14 +00:00
2021-10-15 14:08:27 +00:00
if sort == " new " :
comments = comments . order_by ( Comment . created_utc . desc ( ) )
elif sort == " old " :
comments = comments . order_by ( Comment . created_utc . asc ( ) )
elif sort == " controversial " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( - 1 * Comment . upvotes * Comment . downvotes * Comment . downvotes )
2021-10-15 14:08:27 +00:00
elif sort == " top " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( - Comment . upvotes - Comment . downvotes )
2021-10-15 14:08:27 +00:00
elif sort == " bottom " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( Comment . upvotes - Comment . downvotes )
2021-10-15 14:08:27 +00:00
2021-12-05 02:58:30 +00:00
comments = [ c [ 0 ] for c in comments . all ( ) ]
2021-10-15 14:08:27 +00:00
else :
2021-12-05 16:44:09 +00:00
pinned = g . db . query ( Comment ) . filter ( Comment . parent_submission == post . id , Comment . is_pinned != None ) . all ( )
2021-12-11 02:27:46 +00:00
comments = g . db . query ( Comment ) . join ( User , User . id == Comment . author_id ) . filter ( User . shadowbanned == None , Comment . parent_submission == post . id , Comment . author_id . notin_ ( ( AUTOPOLLER_ID , AUTOBETTER_ID ) ) , Comment . level == 1 , Comment . is_pinned == None )
2021-10-15 14:08:27 +00:00
if sort == " new " :
comments = comments . order_by ( Comment . created_utc . desc ( ) )
elif sort == " old " :
comments = comments . order_by ( Comment . created_utc . asc ( ) )
elif sort == " controversial " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( - 1 * Comment . upvotes * Comment . downvotes * Comment . downvotes )
2021-10-15 14:08:27 +00:00
elif sort == " top " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( - Comment . upvotes - Comment . downvotes )
2021-10-15 14:08:27 +00:00
elif sort == " bottom " :
2021-11-30 23:21:29 +00:00
comments = comments . order_by ( Comment . upvotes - Comment . downvotes )
2021-10-15 14:08:27 +00:00
2021-12-05 02:58:30 +00:00
comments = comments . all ( )
2021-10-15 14:08:27 +00:00
2021-12-05 18:33:16 +00:00
offset = 0
2022-01-11 03:28:35 +00:00
if not request . headers . get ( " Authorization " ) and post . comment_count > 60 :
2021-12-05 18:33:16 +00:00
comments2 = [ ]
count = 0
if post . created_utc > 1638672040 :
for comment in comments :
comments2 . append ( comment )
count + = g . db . query ( Comment . id ) . filter_by ( parent_submission = post . id , top_comment_id = comment . id ) . count ( ) + 1
offset + = 1
if count > 50 : break
else :
for comment in comments :
comments2 . append ( comment )
count + = g . db . query ( Comment . id ) . filter_by ( parent_submission = post . id , parent_comment_id = comment . id ) . count ( ) + 1
offset + = 1
if count > 10 : break
if len ( comments ) == len ( comments2 ) : offset = None
comments = comments2
2021-12-05 02:23:39 +00:00
2021-12-24 03:59:07 +00:00
for pin in pinned :
2021-12-26 01:03:21 +00:00
if pin . is_pinned_utc and int ( time . time ( ) ) > pin . is_pinned_utc :
2021-12-24 03:59:07 +00:00
pin . is_pinned = None
2021-12-26 01:03:21 +00:00
pin . is_pinned_utc = None
2021-12-24 03:59:07 +00:00
g . db . add ( pin )
pinned . remove ( pin )
2021-12-05 02:58:30 +00:00
post . replies = pinned + comments
2021-12-05 02:21:35 +00:00
2021-10-15 14:08:27 +00:00
post . views + = 1
g . db . add ( post )
2021-12-17 04:56:15 +00:00
if request . host != ' old.rdrama.net ' and post . over_18 and not ( v and v . over_18 ) and session . get ( ' over_18 ' , 0 ) < int ( time . time ( ) ) :
2021-10-15 14:08:27 +00:00
if request . headers . get ( " Authorization " ) : return { " error " : " Must be 18+ to view " } , 451
2021-12-19 13:10:54 +00:00
return render_template ( f " { template2 } errors/nsfw.html " , v = v )
2021-10-15 14:08:27 +00:00
g . db . commit ( )
if request . headers . get ( " Authorization " ) : return post . json
2021-10-22 00:19:23 +00:00
else :
2021-12-19 13:11:05 +00:00
if post . is_banned and not ( v and ( v . admin_level > 1 or post . author_id == v . id ) ) : template = f " { template2 } submission_banned.html "
else : template = f " { template2 } submission.html "
2021-12-05 02:21:35 +00:00
return render_template ( template , v = v , p = post , sort = sort , render_replies = True , offset = offset )
2021-10-15 14:08:27 +00:00
2021-12-05 17:30:32 +00:00
@app.post ( " /viewmore/<pid>/<sort>/<offset> " )
@limiter.limit ( " 1/second " )
@auth_desired
def viewmore ( v , pid , sort , offset ) :
2021-12-05 22:52:39 +00:00
offset = int ( offset )
2021-12-05 17:30:32 +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 not ( v and v . shadowbanned ) and not ( v and v . admin_level > 1 ) :
comments = comments . join ( User , User . id == Comment . author_id ) . filter ( User . shadowbanned == None )
2021-12-11 02:27:46 +00:00
comments = comments . filter ( Comment . parent_submission == pid , Comment . author_id . notin_ ( ( AUTOPOLLER_ID , AUTOBETTER_ID ) ) , Comment . is_pinned == None ) . join (
2021-12-05 17:30:32 +00:00
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
)
output = [ ]
for c in comments . all ( ) :
comment = c [ 0 ]
comment . voted = c [ 1 ] or 0
comment . is_blocking = c [ 2 ] or 0
comment . is_blocked = c [ 3 ] or 0
output . append ( comment )
2021-12-06 17:12:34 +00:00
comments = comments . filter ( Comment . level == 1 )
2021-12-05 17:30:32 +00:00
if sort == " new " :
comments = comments . order_by ( Comment . created_utc . desc ( ) )
elif sort == " old " :
comments = comments . order_by ( Comment . created_utc . asc ( ) )
elif sort == " controversial " :
comments = comments . order_by ( - 1 * Comment . upvotes * Comment . downvotes * Comment . downvotes )
elif sort == " top " :
comments = comments . order_by ( - Comment . upvotes - Comment . downvotes )
elif sort == " bottom " :
comments = comments . order_by ( Comment . upvotes - Comment . downvotes )
2021-12-05 22:52:39 +00:00
comments = comments . offset ( offset )
2021-12-05 17:30:32 +00:00
comments = [ c [ 0 ] for c in comments . all ( ) ]
else :
2021-12-11 02:27:46 +00:00
comments = g . db . query ( Comment ) . join ( User , User . id == Comment . author_id ) . filter ( User . shadowbanned == None , Comment . parent_submission == pid , Comment . author_id . notin_ ( ( AUTOPOLLER_ID , AUTOBETTER_ID ) ) , Comment . level == 1 , Comment . is_pinned == None )
2021-12-05 17:30:32 +00:00
if sort == " new " :
comments = comments . order_by ( Comment . created_utc . desc ( ) )
elif sort == " old " :
comments = comments . order_by ( Comment . created_utc . asc ( ) )
elif sort == " controversial " :
comments = comments . order_by ( - 1 * Comment . upvotes * Comment . downvotes * Comment . downvotes )
elif sort == " top " :
comments = comments . order_by ( - Comment . upvotes - Comment . downvotes )
elif sort == " bottom " :
comments = comments . order_by ( Comment . upvotes - Comment . downvotes )
2021-12-05 22:52:39 +00:00
comments = comments . offset ( offset )
2021-12-05 17:30:32 +00:00
comments = comments . all ( )
2021-12-06 17:12:34 +00:00
comments2 = [ ]
count = 0
post = get_post ( pid , v = v )
if post . created_utc > 1638672040 :
for comment in comments :
comments2 . append ( comment )
count + = g . db . query ( Comment . id ) . filter_by ( parent_submission = post . id , top_comment_id = comment . id ) . count ( ) + 1
offset + = 1
if count > 50 : break
else :
for comment in comments :
comments2 . append ( comment )
count + = g . db . query ( Comment . id ) . filter_by ( parent_submission = post . id , parent_comment_id = comment . id ) . count ( ) + 1
offset + = 1
if count > 10 : break
if len ( comments ) == len ( comments2 ) : offset = None
comments = comments2
2021-12-05 22:52:39 +00:00
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } comments.html " , v = v , comments = comments , render_replies = True , pid = pid , sort = sort , offset = offset )
2021-12-05 17:30:32 +00:00
2021-10-15 14:08:27 +00:00
2021-12-11 00:05:01 +00:00
@app.post ( " /morecomments/<cid> " )
@limiter.limit ( " 1/second " )
@auth_desired
def morecomments ( v , cid ) :
2021-12-31 17:38:11 +00:00
tcid = g . db . query ( Comment . top_comment_id ) . filter_by ( id = cid ) . one_or_none ( ) [ 0 ]
2021-12-11 00:23:01 +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 ,
2021-12-31 17:38:11 +00:00
) . filter ( Comment . top_comment_id == tcid , Comment . level > 10 ) . join (
2021-12-11 00:23:01 +00:00
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
)
output = [ ]
2021-12-31 17:59:24 +00:00
dump = [ ]
2021-12-11 00:23:01 +00:00
for c in comments . all ( ) :
comment = c [ 0 ]
comment . voted = c [ 1 ] or 0
comment . is_blocking = c [ 2 ] or 0
comment . is_blocked = c [ 3 ] or 0
2021-12-31 17:59:24 +00:00
if c [ 0 ] . parent_comment_id == int ( cid ) : output . append ( comment )
else : dump . append ( comment )
comments = output
2021-12-11 00:23:01 +00:00
else :
2022-01-02 00:06:46 +00:00
c = g . db . query ( Comment ) . filter_by ( id = cid ) . one_or_none ( )
2021-12-11 00:23:01 +00:00
comments = c . replies
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } comments.html " , v = v , comments = comments , render_replies = True )
2021-12-11 00:05:01 +00:00
2021-10-15 14:08:27 +00:00
@app.post ( " /edit_post/<pid> " )
@limiter.limit ( " 1/second " )
@auth_required
def edit_post ( pid , v ) :
2021-11-30 18:15:33 +00:00
if v and v . patron :
2021-12-29 12:38:54 +00:00
if request . content_length > 8 * 1024 * 1024 : return { " error " : " Max file size is 8 MB. " } , 413
elif request . content_length > 4 * 1024 * 1024 : return { " error " : " Max file size is 4 MB. " } , 413
2021-10-15 14:08:27 +00:00
p = get_post ( pid )
2021-11-15 22:13:29 +00:00
if p . author_id != v . id and not ( v . admin_level > 1 and v . admin_level > 2 ) : abort ( 403 )
2021-10-15 14:08:27 +00:00
2022-01-10 22:43:00 +00:00
title = request . values . get ( " title " , " " ) . strip ( ) . replace ( ' ‎ ' , ' ' )
2021-12-10 19:53:16 +00:00
2022-01-10 22:43:00 +00:00
body = request . values . get ( " body " , " " ) . strip ( ) . replace ( ' ‎ ' , ' ' )
2021-10-15 14:08:27 +00:00
2021-10-29 16:57:50 +00:00
if len ( body ) > 10000 : return { " error " : " Character limit is 10000! " } , 403
2021-10-27 00:37:34 +00:00
if v . marseyawarded :
2021-10-27 20:12:16 +00:00
if time . time ( ) > v . marseyawarded :
v . marseyawarded = None
g . db . add ( v )
else :
marregex = list ( re . finditer ( " ^(:!?m \ w+: \ s*)+$ " , title ) )
if len ( marregex ) == 0 : return { " error " : " You can only type marseys! " } , 403
if body :
marregex = list ( re . finditer ( " ^(:!?m \ w+: \ s*)+$ " , body ) )
if len ( marregex ) == 0 : return { " error " : " You can only type marseys! " } , 403
2021-10-27 00:37:34 +00:00
2021-11-18 20:50:03 +00:00
if v . longpost :
if time . time ( ) > v . longpost :
v . longpost = None
g . db . add ( v )
2021-11-21 13:49:57 +00:00
elif len ( body ) < 280 or ' []( ' in body or body . startswith ( ' []( ' ) : return { " error " : " You have to type more than 280 characters! " } , 403
2021-11-23 22:36:38 +00:00
elif v . bird :
if time . time ( ) > v . bird :
v . bird = None
g . db . add ( v )
elif len ( body ) > 140 : return { " error " : " You have to type less than 140 characters! " } , 403
2021-11-18 20:50:03 +00:00
2021-10-15 14:08:27 +00:00
if title != p . title :
2021-12-29 06:43:20 +00:00
if v . agendaposter and not v . marseyawarded : title = torture_ap ( title , v . username )
2021-11-24 17:49:17 +00:00
2021-12-07 23:18:06 +00:00
title_html = filter_emojis_only ( title )
2021-10-27 20:59:58 +00:00
if v . marseyawarded and len ( list ( re . finditer ( ' >[^< \ s+]|[^> \ s+]< ' , title_html ) ) ) > 0 : return { " error " : " You can only type marseys! " } , 403
2021-12-21 19:56:38 +00:00
p . title = title [ : 500 ]
2021-10-27 20:12:16 +00:00
p . title_html = title_html
2021-10-15 14:08:27 +00:00
2021-11-30 18:15:33 +00:00
if request . files . get ( " file " ) and request . headers . get ( " cf-ipcountry " ) != " T1 " :
file = request . files [ " file " ]
2021-12-18 02:59:40 +00:00
if file . content_type . startswith ( ' image/ ' ) :
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) [ : - 5 ] + ' .webp '
file . save ( name )
url = process_image ( name )
2021-12-18 04:48:10 +00:00
body + = f " \n \n ![]( { url } ) "
2021-12-18 02:59:40 +00:00
elif file . content_type . startswith ( ' video/ ' ) :
file . save ( " video.mp4 " )
with open ( " video.mp4 " , ' rb ' ) as f :
2022-01-06 14:20:45 +00:00
try : url = requests . request ( " POST " , " https://api.imgur.com/3/upload " , headers = { ' Authorization ' : f ' Client-ID { IMGUR_KEY } ' } , files = [ ( ' video ' , f ) ] ) . json ( ) [ ' data ' ] [ ' link ' ]
except : return { " error " : " Imgur error " } , 400
2022-01-06 17:57:59 +00:00
if url . endswith ( ' . ' ) : url + = ' mp4 '
2021-12-18 04:48:10 +00:00
body + = f " \n \n { url } "
2022-01-07 21:03:14 +00:00
else : return { " error " : " Image/Video files only " } , 400
2021-11-30 18:15:33 +00:00
2021-10-15 14:08:27 +00:00
if body != p . body :
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 ' ![]( { i . group ( 1 ) } ) ' )
2021-11-24 17:33:44 +00:00
2021-12-29 06:43:20 +00:00
if v . agendaposter and not v . marseyawarded : body = torture_ap ( body , v . username )
2021-11-24 17:33:44 +00:00
2021-12-03 23:34:03 +00:00
if not p . options . count ( ) :
for i in re . finditer ( ' \ s* \ $ \ $([^ \ $ \n ]+) \ $ \ $ \ s* ' , body ) :
body = body . replace ( i . group ( 0 ) , " " )
c = Comment ( author_id = AUTOPOLLER_ID ,
parent_submission = p . id ,
level = 1 ,
2021-12-07 23:18:06 +00:00
body_html = filter_emojis_only ( i . group ( 1 ) ) ,
2021-12-03 23:34:03 +00:00
upvotes = 0
)
g . db . add ( c )
2021-11-24 17:33:44 +00:00
body_html = sanitize ( CustomRenderer ( ) . render ( mistletoe . Document ( body ) ) )
2021-10-15 14:08:27 +00:00
bans = filter_comment_html ( body_html )
if bans :
ban = bans [ 0 ]
reason = f " Remove the { ban . domain } link from your post and try again. "
if ban . reason :
reason + = f " { ban . reason } "
return { " error " : reason } , 403
p . body = body
2021-10-27 20:59:58 +00:00
if v . marseyawarded and len ( list ( re . finditer ( ' >[^< \ s+]|[^> \ s+]< ' , body_html ) ) ) > 0 : return { " error " : " You can only type marseys! " } , 40
2021-11-18 20:50:03 +00:00
2021-11-23 22:36:38 +00:00
if v . longpost :
if len ( body ) < 280 or ' []( ' in body or body . startswith ( ' []( ' ) : return { " error " : " You have to type more than 280 characters! " } , 403
elif v . bird :
if len ( body ) > 140 : return { " error " : " You have to type less than 140 characters! " } , 403
2021-11-18 20:50:03 +00:00
2022-01-04 21:11:29 +00:00
if len ( body_html ) > 20000 : return { " error " : " Submission body too long! " } , 400
2021-10-15 14:08:27 +00:00
p . body_html = body_html
2022-01-10 23:34:56 +00:00
if v . agendaposter and not v . marseyawarded and " trans lives matter " not in f ' { p . body } { p . title } ' . lower ( ) :
2021-10-15 14:08:27 +00:00
p . is_banned = True
2021-11-03 16:15:06 +00:00
p . ban_reason = " AutoJanny "
2021-10-15 14:08:27 +00:00
g . db . add ( p )
2022-01-10 23:34:56 +00:00
body = AGENDAPOSTER_MSG . format ( username = v . username , type = ' post ' )
2021-10-15 14:08:27 +00:00
body_md = CustomRenderer ( ) . render ( mistletoe . Document ( body ) )
body_jannied_html = sanitize ( body_md )
2021-12-28 06:28:18 +00:00
c_jannied = Comment ( author_id = NOTIFICATIONS_ID ,
2021-10-15 14:08:27 +00:00
parent_submission = p . id ,
level = 1 ,
over_18 = False ,
is_bot = True ,
app_id = None ,
2021-12-28 05:06:24 +00:00
is_pinned = ' AutoJanny ' ,
2021-10-15 14:08:27 +00:00
distinguish_level = 6 ,
body_html = body_jannied_html ,
)
g . db . add ( c_jannied )
g . db . flush ( )
n = Notification ( comment_id = c_jannied . id , user_id = v . id )
g . db . add ( n )
2022-01-07 19:13:01 +00:00
notify_users = NOTIFY_USERS ( body_html , v ) | NOTIFY_USERS2 ( title , v )
2021-10-15 14:08:27 +00:00
soup = BeautifulSoup ( body_html , features = " html.parser " )
2021-12-20 20:03:59 +00:00
cid = notif_comment ( f " @ { v . username } has mentioned you: [ { p . title } ]( { p . permalink } ) " )
for x in notify_users :
add_notif ( cid , x )
2021-10-26 21:31:39 +00:00
2021-10-15 14:08:27 +00:00
2021-11-01 18:25:10 +00:00
if ( title != p . title or body != p . body ) and v . id == p . author_id :
2021-10-15 14:08:27 +00:00
if int ( time . time ( ) ) - p . created_utc > 60 * 3 : p . edited_utc = int ( time . time ( ) )
g . db . add ( p )
g . db . commit ( )
return redirect ( p . permalink )
def archiveorg ( url ) :
try : requests . get ( f ' https://web.archive.org/save/ { url } ' , headers = { ' User-Agent ' : ' Mozilla/4.0 (compatible; MSIE 5.5; Windows NT) ' } , timeout = 100 )
except Exception as e : print ( e )
def thumbnail_thread ( pid ) :
2022-01-11 03:02:59 +00:00
db = db_session ( )
2022-01-10 23:34:56 +00:00
print ( cpu_percent ( ) , flush = True )
time . sleep ( 0.1 )
cpu = cpu_percent ( )
2022-01-11 03:29:02 +00:00
if cpu > 5 :
2022-01-10 23:53:45 +00:00
print ( ' wtf ' , flush = True )
2022-01-10 23:55:19 +00:00
with open ( ' under_attack ' , ' r ' ) as f : content = f . read ( )
with open ( ' under_attack ' , ' w ' ) as f :
if content != " yes " :
f . write ( " yes " )
ma = ModAction (
kind = " enable_under_attack " ,
user_id = AUTOJANNY_ID ,
)
2022-01-11 03:02:59 +00:00
db . add ( ma )
db . commit ( )
2022-01-10 23:55:19 +00:00
data = ' { " value " : " under_attack " } '
2022-01-11 00:06:03 +00:00
response = requests . patch ( f ' https://api.cloudflare.com/client/v4/zones/ { CF_ZONE } /settings/security_level ' , headers = CF_HEADERS , data = data )
print ( response . text , flush = True )
2022-01-10 23:34:56 +00:00
2021-10-15 14:08:27 +00:00
def expand_url ( post_url , fragment_url ) :
if fragment_url . startswith ( " https:// " ) :
return fragment_url
2021-12-05 19:45:08 +00:00
elif fragment_url . startswith ( " https:// " ) :
return f " https:// { fragment_url . split ( ' https:// ' ) [ 1 ] } "
2021-10-15 14:08:27 +00:00
elif fragment_url . startswith ( ' // ' ) :
return f " https: { fragment_url } "
elif fragment_url . startswith ( ' / ' ) :
parsed_url = urlparse ( post_url )
return f " https:// { parsed_url . netloc } { fragment_url } "
else :
return f " { post_url } { ' / ' if not post_url . endswith ( ' / ' ) else ' ' } { fragment_url } "
2022-01-02 00:06:46 +00:00
post = db . query ( Submission ) . filter_by ( id = pid ) . one_or_none ( )
2021-10-15 14:08:27 +00:00
2021-12-30 05:27:22 +00:00
if not post or not post . url :
2021-10-15 14:08:27 +00:00
time . sleep ( 5 )
2022-01-02 00:06:46 +00:00
post = db . query ( Submission ) . filter_by ( id = pid ) . one_or_none ( )
2021-10-15 14:08:27 +00:00
2021-12-30 05:27:22 +00:00
if not post or not post . url : return
2021-12-16 17:59:30 +00:00
fetch_url = post . url
2021-12-16 18:13:23 +00:00
if fetch_url . startswith ( ' / ' ) : fetch_url = f " https:// { site } { fetch_url } "
2021-10-15 14:08:27 +00:00
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 :
2021-11-14 01:19:32 +00:00
x = requests . get ( fetch_url , headers = headers , timeout = 5 )
2021-10-15 14:08:27 +00:00
except :
db . close ( )
return
if x . status_code != 200 :
db . close ( )
return
if x . headers . get ( " Content-Type " , " " ) . startswith ( " text/html " ) :
soup = BeautifulSoup ( x . content , ' html.parser ' )
thumb_candidate_urls = [ ]
meta_tags = [
2021-10-27 20:12:16 +00:00
" drama:thumbnail " ,
2021-10-15 14:08:27 +00:00
" twitter:image " ,
" og:image " ,
" thumbnail "
]
for tag_name in meta_tags :
tag = soup . find (
' meta ' ,
attrs = {
" name " : tag_name ,
" content " : True
}
)
if not tag :
tag = soup . find (
' meta ' ,
attrs = {
' property ' : tag_name ,
' content ' : True
}
)
if tag :
thumb_candidate_urls . append ( expand_url ( post . url , tag [ ' content ' ] ) )
for tag in soup . find_all ( " img " , attrs = { ' src ' : True } ) :
thumb_candidate_urls . append ( expand_url ( post . url , tag [ ' src ' ] ) )
for url in thumb_candidate_urls :
try :
2021-11-14 01:19:32 +00:00
image_req = requests . get ( url , headers = headers , timeout = 5 )
2021-10-15 14:08:27 +00:00
except :
continue
if image_req . status_code > = 400 :
continue
if not image_req . headers . get ( " Content-Type " , " " ) . startswith ( " image/ " ) :
continue
if image_req . headers . get ( " Content-Type " , " " ) . startswith ( " image/svg " ) :
continue
image = PILimage . open ( BytesIO ( image_req . content ) )
if image . width < 30 or image . height < 30 :
continue
break
else :
db . close ( )
return
elif x . headers . get ( " Content-Type " , " " ) . startswith ( " image/ " ) :
image_req = x
image = PILimage . open ( BytesIO ( x . content ) )
else :
db . close ( )
return
2021-12-13 01:00:08 +00:00
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) [ : - 5 ] + ' .webp '
2021-10-15 14:08:27 +00:00
with open ( name , " wb " ) as file :
for chunk in image_req . iter_content ( 1024 ) :
file . write ( chunk )
2021-12-14 20:25:57 +00:00
post . thumburl = process_image ( name , True )
2021-10-15 14:08:27 +00:00
db . add ( post )
db . commit ( )
db . close ( )
return
@app.post ( " /submit " )
@limiter.limit ( " 1/second " )
@limiter.limit ( " 6/minute " )
2022-01-06 16:46:09 +00:00
@auth_required
2021-10-15 14:08:27 +00:00
def submit_post ( v ) :
2022-01-06 16:46:09 +00:00
if v . is_suspended : return { " error " : " You can ' t perform this action while banned. " } , 403
2021-11-11 19:14:11 +00:00
if v and v . patron :
2021-12-29 12:38:54 +00:00
if request . content_length > 8 * 1024 * 1024 : return { " error " : " Max file size is 8 MB. " } , 413
elif request . content_length > 4 * 1024 * 1024 : return { " error " : " Max file size is 4 MB. " } , 413
if not v or v . oldsite : template = ' '
else : template = ' CHRISTMAS/ '
2021-10-15 14:08:27 +00:00
2022-01-10 22:43:00 +00:00
title = request . values . get ( " title " , " " ) . strip ( ) [ : 500 ] . replace ( ' ‎ ' , ' ' )
2021-12-10 19:53:16 +00:00
2021-10-15 14:08:27 +00:00
url = request . values . get ( " url " , " " ) . strip ( )
2021-11-24 17:49:17 +00:00
2021-12-29 06:43:20 +00:00
if v . agendaposter and not v . marseyawarded : title = torture_ap ( title , v . username )
2021-11-24 17:49:17 +00:00
2021-12-07 23:18:06 +00:00
title_html = filter_emojis_only ( title )
2022-01-10 22:43:00 +00:00
body = request . values . get ( " body " , " " ) . strip ( ) . replace ( ' ‎ ' , ' ' )
2021-11-18 20:50:03 +00:00
2021-10-27 20:59:58 +00:00
if v . marseyawarded and len ( list ( re . finditer ( ' >[^< \ s+]|[^> \ s+]< ' , title_html ) ) ) > 0 : return { " error " : " You can only type marseys! " } , 40
2021-10-15 14:08:27 +00:00
2021-11-23 22:36:38 +00:00
if v . longpost :
if len ( body ) < 280 or ' []( ' in body or body . startswith ( ' []( ' ) : return { " error " : " You have to type more than 280 characters! " } , 403
elif v . bird :
if len ( body ) > 140 : return { " error " : " You have to type less than 140 characters! " } , 403
2021-11-18 20:50:03 +00:00
2021-10-15 14:08:27 +00:00
if url :
if " /i.imgur.com/ " in url : url = url . replace ( " .png " , " .webp " ) . replace ( " .jpg " , " .webp " ) . replace ( " .jpeg " , " .webp " )
elif " /media.giphy.com/ " in url or " /c.tenor.com/ " in url : url = url . replace ( " .gif " , " .webp " )
elif " /i.ibb.com/ " in url : url = url . replace ( " .png " , " .webp " ) . replace ( " .jpg " , " .webp " ) . replace ( " .jpeg " , " .webp " ) . replace ( " .gif " , " .webp " )
for rd in [ " https://reddit.com/ " , " https://new.reddit.com/ " , " https://www.reddit.com/ " , " https://redd.it/ " ] :
url = url . replace ( rd , " https://old.reddit.com/ " )
2021-10-21 13:02:47 +00:00
2021-12-25 20:46:49 +00:00
url = url . replace ( " old.reddit.com/gallery " , " new.reddit.com/gallery " ) . replace ( " https://youtu.be/ " , " https://youtube.com/watch?v= " ) . replace ( " https://music.youtube.com/watch?v= " , " https://youtube.com/watch?v= " ) . replace ( " https://open.spotify.com/ " , " https://open.spotify.com/embed/ " ) . replace ( " https://streamable.com/ " , " https://streamable.com/e/ " ) . replace ( " https://youtube.com/shorts/ " , " https://youtube.com/watch?v= " ) . replace ( " https://mobile.twitter " , " https://twitter " ) . replace ( " https://m.facebook " , " https://facebook " ) . replace ( " m.wikipedia.org " , " wikipedia.org " ) . replace ( " https://m.youtube " , " https://youtube " ) . replace ( " https://www.youtube " , " https://youtube " )
2021-11-22 14:16:58 +00:00
2021-10-15 14:08:27 +00:00
if url . startswith ( " https://streamable.com/ " ) and not url . startswith ( " https://streamable.com/e/ " ) : url = url . replace ( " https://streamable.com/ " , " https://streamable.com/e/ " )
parsed_url = urlparse ( url )
domain = parsed_url . netloc
2021-12-28 07:33:55 +00:00
if domain == ' old.reddit.com ' :
new_url = ParseResult ( scheme = " https " ,
netloc = parsed_url . netloc ,
path = parsed_url . path ,
params = parsed_url . params ,
query = None ,
fragment = parsed_url . fragment )
else :
qd = parse_qs ( parsed_url . query )
2022-01-07 21:03:14 +00:00
filtered = { k : val for k , val in qd . items ( ) if not k . startswith ( ' utm_ ' ) and not k . startswith ( ' ref_ ' ) }
2021-12-28 07:33:55 +00:00
new_url = ParseResult ( scheme = " https " ,
netloc = parsed_url . netloc ,
path = parsed_url . path ,
params = parsed_url . params ,
query = urlencode ( filtered , doseq = True ) ,
fragment = parsed_url . fragment )
2021-10-27 20:12:16 +00:00
url = urlunparse ( new_url )
2021-10-15 14:08:27 +00:00
2022-01-07 19:13:01 +00:00
if SITE != ' localhost ' :
repost = g . db . query ( Submission ) . filter (
Submission . url . ilike ( url ) ,
Submission . deleted_utc == 0 ,
Submission . is_banned == False
) . one_or_none ( )
2021-10-15 14:08:27 +00:00
2022-01-07 19:13:01 +00:00
if repost : return redirect ( repost . permalink )
2021-10-15 14:08:27 +00:00
domain_obj = get_domain ( domain )
if domain_obj :
if request . headers . get ( " Authorization " ) : return { " error " : domain_obj . reason } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = domain_obj . reason , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-12-01 17:25:28 +00:00
elif " twitter.com " == domain :
2021-11-14 01:19:32 +00:00
try : embed = requests . get ( " https://publish.twitter.com/oembed " , timeout = 5 , params = { " url " : url , " omit_script " : " t " } ) . json ( ) [ " html " ]
2021-10-15 14:08:27 +00:00
except : embed = None
2021-12-25 20:46:49 +00:00
elif url . startswith ( ' https://youtube.com/watch?v= ' ) :
2022-01-07 19:13:01 +00:00
url = unquote ( url ) . replace ( ' ?t ' , ' &t ' )
2021-12-25 20:46:49 +00:00
yt_id = url . split ( ' https://youtube.com/watch?v= ' ) [ 1 ] . split ( ' & ' ) [ 0 ] . split ( ' % ' ) [ 0 ]
2021-11-18 21:27:15 +00:00
params = parse_qs ( urlparse ( url ) . query )
2021-11-18 21:29:42 +00:00
t = params . get ( ' t ' , params . get ( ' start ' , [ 0 ] ) ) [ 0 ]
if isinstance ( t , str ) : t = t . replace ( ' s ' , ' ' )
2021-12-31 12:37:42 +00:00
embed = f ' <lite-youtube videoid= " { yt_id } " params= " autoplay=1&modestbranding=1 '
2021-12-05 16:44:09 +00:00
if t : embed + = f ' &start= { t } '
embed + = ' " ></lite-youtube> '
2021-10-15 14:08:27 +00:00
elif app . config [ ' SERVER_NAME ' ] in domain and " /post/ " in url and " context " not in url :
id = url . split ( " /post/ " ) [ 1 ]
if " / " in id : id = id . split ( " / " ) [ 0 ]
embed = id
else : embed = None
else : embed = None
if not url and not request . values . get ( " body " ) and not request . files . get ( " file " , None ) :
if request . headers . get ( " Authorization " ) : return { " error " : " `url` or `body` parameter required. " } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = " Please enter a url or some text. " , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-10-15 14:08:27 +00:00
if not title :
if request . headers . get ( " Authorization " ) : return { " error " : " Please enter a better title " } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = " Please enter a better title. " , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-10-15 14:08:27 +00:00
elif len ( title ) > 500 :
if request . headers . get ( " Authorization " ) : return { " error " : " 500 character limit for titles " } , 400
else : render_template ( " submit.html " , v = v , error = " 500 character limit for titles. " , title = title [ : 500 ] , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-10-27 00:37:34 +00:00
if v . marseyawarded :
2021-10-27 20:12:16 +00:00
if time . time ( ) > v . marseyawarded :
v . marseyawarded = None
g . db . add ( v )
else :
marregex = list ( re . finditer ( " ^(:!?m \ w+: \ s*)+$ " , title ) )
if len ( marregex ) == 0 : return { " error " : " You can only type marseys! " } , 403
if body :
marregex = list ( re . finditer ( " ^(:!?m \ w+: \ s*)+$ " , body ) )
if len ( marregex ) == 0 : return { " error " : " You can only type marseys! " } , 403
2021-10-27 00:37:34 +00:00
2021-11-18 20:50:03 +00:00
if v . longpost :
if time . time ( ) > v . longpost :
v . longpost = None
g . db . add ( v )
2021-11-21 13:49:57 +00:00
elif len ( body ) < 280 or ' []( ' in body or body . startswith ( ' []( ' ) : return { " error " : " You have to type more than 280 characters! " } , 403
2021-11-23 22:36:38 +00:00
elif v . bird :
if time . time ( ) > v . bird :
v . bird = None
g . db . add ( v )
elif len ( body ) > 140 : return { " error " : " You have to type less than 140 characters! " } , 403
2021-11-18 20:50:03 +00:00
2021-11-06 15:52:48 +00:00
dup = g . db . query ( Submission ) . filter (
2021-10-15 14:08:27 +00:00
Submission . author_id == v . id ,
Submission . deleted_utc == 0 ,
Submission . title == title ,
Submission . url == url ,
Submission . body == body
2022-01-02 00:06:46 +00:00
) . one_or_none ( )
2021-10-15 14:08:27 +00:00
if dup : return redirect ( dup . permalink )
now = int ( time . time ( ) )
cutoff = now - 60 * 60 * 24
2021-11-07 13:37:26 +00:00
similar_posts = g . db . query ( Submission ) . filter (
2021-10-15 14:08:27 +00:00
Submission . author_id == v . id ,
Submission . title . op ( ' <-> ' ) ( title ) < app . config [ " SPAM_SIMILARITY_THRESHOLD " ] ,
Submission . created_utc > cutoff
) . all ( )
if url :
2021-11-07 13:37:26 +00:00
similar_urls = g . db . query ( Submission ) . filter (
2021-10-15 14:08:27 +00:00
Submission . author_id == v . id ,
Submission . url . op ( ' <-> ' ) ( url ) < app . config [ " SPAM_URL_SIMILARITY_THRESHOLD " ] ,
Submission . created_utc > cutoff
) . all ( )
2021-10-27 20:12:16 +00:00
else : similar_urls = [ ]
2021-10-15 14:08:27 +00:00
threshold = app . config [ " SPAM_SIMILAR_COUNT_THRESHOLD " ]
2021-10-27 20:12:16 +00:00
if v . age > = ( 60 * 60 * 24 * 7 ) : threshold * = 3
elif v . age > = ( 60 * 60 * 24 ) : threshold * = 2
2021-10-15 14:08:27 +00:00
if max ( len ( similar_urls ) , len ( similar_posts ) ) > = threshold :
text = " Your account has been suspended for 1 day for the following reason: \n \n > Too much spam! "
2021-12-20 20:03:59 +00:00
send_repeatable_notification ( v . id , text )
2021-10-15 14:08:27 +00:00
v . ban ( reason = " Spamming. " ,
days = 1 )
for post in similar_posts + similar_urls :
post . is_banned = True
post . is_pinned = False
2021-11-05 14:40:14 +00:00
post . ban_reason = " AutoJanny "
2021-10-15 14:08:27 +00:00
g . db . add ( post )
ma = ModAction (
2021-11-18 14:21:19 +00:00
user_id = AUTOJANNY_ID ,
2021-10-15 14:08:27 +00:00
target_submission_id = post . id ,
kind = " ban_post " ,
2021-10-25 18:08:03 +00:00
_note = " spam "
2021-10-15 14:08:27 +00:00
)
g . db . add ( ma )
return redirect ( " /notifications " )
if len ( str ( body ) ) > 10000 :
if request . headers . get ( " Authorization " ) : return { " error " : " 10000 character limit for text body. " } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = " 10000 character limit for text body. " , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-10-15 14:08:27 +00:00
if len ( url ) > 2048 :
if request . headers . get ( " Authorization " ) : return { " error " : " 2048 character limit for URLs. " } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = " 2048 character limit for URLs. " , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 400
2021-10-15 14:08:27 +00:00
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 ' ![]( { i . group ( 1 ) } ) ' )
2021-12-11 03:36:05 +00:00
if v and v . admin_level > 2 :
2021-12-11 02:35:21 +00:00
bet_options = [ ]
for i in re . finditer ( ' \ s* \ $ \ $ \ $([^ \ $ \n ]+) \ $ \ $ \ $ \ s* ' , body ) :
bet_options . append ( i . group ( 1 ) )
body = body . replace ( i . group ( 0 ) , " " )
2021-12-11 02:27:46 +00:00
2021-10-15 14:08:27 +00:00
options = [ ]
for i in re . finditer ( ' \ s* \ $ \ $([^ \ $ \n ]+) \ $ \ $ \ s* ' , body ) :
options . append ( i . group ( 1 ) )
body = body . replace ( i . group ( 0 ) , " " )
2021-12-29 06:43:20 +00:00
if v . agendaposter and not v . marseyawarded : body = torture_ap ( body , v . username )
2021-11-24 17:33:44 +00:00
2021-11-30 18:25:41 +00:00
if request . files . get ( " file2 " ) and request . headers . get ( " cf-ipcountry " ) != " T1 " :
file = request . files [ " file2 " ]
2021-12-18 02:59:40 +00:00
if file . content_type . startswith ( ' image/ ' ) :
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) [ : - 5 ] + ' .webp '
file . save ( name )
2021-12-29 12:38:54 +00:00
body + = f " \n \n ![]( { process_image ( name ) } ) "
2021-12-18 02:59:40 +00:00
elif file . content_type . startswith ( ' video/ ' ) :
file . save ( " video.mp4 " )
with open ( " video.mp4 " , ' rb ' ) as f :
2022-01-06 14:20:45 +00:00
try : url = requests . request ( " POST " , " https://api.imgur.com/3/upload " , headers = { ' Authorization ' : f ' Client-ID { IMGUR_KEY } ' } , files = [ ( ' video ' , f ) ] ) . json ( ) [ ' data ' ] [ ' link ' ]
except : return { " error " : " Imgur error " } , 400
2022-01-06 17:57:59 +00:00
if url . endswith ( ' . ' ) : url + = ' mp4 '
2021-12-18 04:48:10 +00:00
body + = f " \n \n { url } "
2021-12-18 02:59:40 +00:00
else :
2022-01-07 21:03:14 +00:00
if request . headers . get ( " Authorization " ) : return { " error " : " Image/Video files only " } , 400
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = f " Image/Video files only. " ) , 400
2021-11-30 18:25:41 +00:00
2021-11-24 17:33:44 +00:00
body_html = sanitize ( CustomRenderer ( ) . render ( mistletoe . Document ( body ) ) )
2021-10-15 14:08:27 +00:00
2021-11-12 14:06:22 +00:00
if v . marseyawarded and len ( list ( re . finditer ( ' >[^< \ s+]|[^> \ s+]< ' , body_html ) ) ) > 0 : return { " error " : " You can only type marseys! " } , 400
2021-10-15 14:08:27 +00:00
2021-11-23 22:36:38 +00:00
if v . longpost :
if len ( body ) < 280 or ' []( ' in body or body . startswith ( ' []( ' ) : return { " error " : " You have to type more than 280 characters! " } , 403
elif v . bird :
if len ( body ) > 140 : return { " error " : " You have to type less than 140 characters! " } , 403
2021-11-18 20:50:03 +00:00
2021-11-12 14:06:22 +00:00
if len ( body_html ) > 20000 : return { " error " : " Submission body too long! " } , 400
2021-10-15 14:08:27 +00:00
bans = filter_comment_html ( body_html )
if bans :
ban = bans [ 0 ]
reason = f " Remove the { ban . domain } link from your post and try again. "
if ban . reason : reason + = f " { ban . reason } "
if request . headers . get ( " Authorization " ) : return { " error " : reason } , 403
2021-12-20 00:27:25 +00:00
if not v or v . oldsite : template = ' '
2021-12-19 13:01:28 +00:00
else : template = ' CHRISTMAS/ '
return render_template ( f " { template } submit.html " , v = v , error = reason , title = title , url = url , body = request . values . get ( " body " , " " ) ) , 403
2021-10-15 14:08:27 +00:00
2021-12-21 15:07:28 +00:00
if v . club_allowed == False : club = False
else : club = bool ( request . values . get ( " club " , " " ) )
2021-11-27 18:23:27 +00:00
if embed and len ( embed ) > 1500 : embed = None
2021-10-15 14:08:27 +00:00
new_post = Submission (
private = bool ( request . values . get ( " private " , " " ) ) ,
club = club ,
author_id = v . id ,
2022-01-07 21:44:38 +00:00
over_18 = bool ( request . values . get ( " over_18 " , " " ) ) ,
2021-10-15 14:08:27 +00:00
app_id = v . client . application . id if v . client else None ,
2021-10-26 21:10:31 +00:00
is_bot = request . headers . get ( " Authorization " ) ,
2021-10-15 14:08:27 +00:00
url = url ,
2021-11-01 18:25:10 +00:00
body = body [ : 10000 ] ,
2021-10-15 14:08:27 +00:00
body_html = body_html ,
embed_url = embed ,
2021-12-01 17:44:24 +00:00
title = title [ : 500 ] ,
2021-12-13 21:27:25 +00:00
title_html = title_html ,
2021-12-26 05:30:19 +00:00
created_utc = int ( time . time ( ) )
2021-10-15 14:08:27 +00:00
)
g . db . add ( new_post )
g . db . flush ( )
2021-12-11 02:27:46 +00:00
2021-12-11 03:36:05 +00:00
if v and v . admin_level > 2 :
2021-12-11 02:35:21 +00:00
for option in bet_options :
bet_option = Comment ( author_id = AUTOBETTER_ID ,
parent_submission = new_post . id ,
level = 1 ,
body_html = filter_emojis_only ( option ) ,
upvotes = 0
)
2021-12-11 02:27:46 +00:00
2021-12-11 02:35:21 +00:00
g . db . add ( bet_option )
2021-12-11 02:27:46 +00:00
2021-10-15 14:08:27 +00:00
for option in options :
2021-11-18 14:21:19 +00:00
c = Comment ( author_id = AUTOPOLLER_ID ,
2021-10-15 14:08:27 +00:00
parent_submission = new_post . id ,
level = 1 ,
2021-12-07 23:18:06 +00:00
body_html = filter_emojis_only ( option ) ,
2021-10-29 16:22:51 +00:00
upvotes = 0
2021-10-15 14:08:27 +00:00
)
g . db . add ( c )
vote = Vote ( user_id = v . id ,
vote_type = 1 ,
submission_id = new_post . id
)
g . db . add ( vote )
2021-12-26 05:30:19 +00:00
2021-12-26 05:44:09 +00:00
if request . files . get ( ' file ' ) and request . headers . get ( " cf-ipcountry " ) != " T1 " :
file = request . files [ ' file ' ]
if file . content_type . startswith ( ' image/ ' ) :
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) [ : - 5 ] + ' .webp '
file . save ( name )
new_post . url = process_image ( name )
name2 = name . replace ( ' .webp ' , ' r.webp ' )
copyfile ( name , name2 )
2021-12-29 12:38:54 +00:00
new_post . thumburl = process_image ( name2 , True )
2021-12-26 05:44:09 +00:00
elif file . content_type . startswith ( ' video/ ' ) :
file . save ( " video.mp4 " )
with open ( " video.mp4 " , ' rb ' ) as f :
2022-01-06 14:20:45 +00:00
try : url = requests . request ( " POST " , " https://api.imgur.com/3/upload " , headers = { ' Authorization ' : f ' Client-ID { IMGUR_KEY } ' } , files = [ ( ' video ' , f ) ] ) . json ( ) [ ' data ' ] [ ' link ' ]
except : return { " error " : " Imgur error " } , 400
2022-01-06 17:57:59 +00:00
if url . endswith ( ' . ' ) : url + = ' mp4 '
2021-12-26 05:44:09 +00:00
new_post . url = url
2021-12-29 12:38:54 +00:00
else :
2022-01-07 21:03:14 +00:00
if request . headers . get ( " Authorization " ) : return { " error " : " File type not allowed " } , 400
return render_template ( f " { template } submit.html " , v = v , error = " File type not allowed. " , title = title , body = request . values . get ( " body " , " " ) ) , 400
2021-12-26 05:44:09 +00:00
2021-12-23 14:19:18 +00:00
if not new_post . thumburl and new_post . url and request . headers . get ( ' cf-ipcountry ' ) != " T1 " : gevent . spawn ( thumbnail_thread , new_post . id )
2021-10-15 14:08:27 +00:00
if not new_post . private :
2021-10-25 13:55:56 +00:00
2022-01-07 19:13:01 +00:00
notify_users = NOTIFY_USERS ( body_html , v ) | NOTIFY_USERS2 ( title , v )
2021-11-25 22:38:37 +00:00
2021-12-20 20:03:59 +00:00
cid = notif_comment ( f " @ { v . username } has mentioned you: [ { title } ]( { new_post . permalink } ) " )
for x in notify_users :
add_notif ( cid , x )
cid = notif_comment ( f " @ { v . username } has made a new post: [ { title } ]( { new_post . permalink } ) " , True )
2021-10-15 14:08:27 +00:00
for follow in v . followers :
user = get_account ( follow . user_id )
2021-12-20 20:03:59 +00:00
if new_post . club and not user . paid_dues : continue
add_notif ( cid , user . id )
2021-10-15 14:08:27 +00:00
2022-01-10 23:34:56 +00:00
if v . agendaposter and not v . marseyawarded and " trans lives matter " not in f ' { new_post . body } { new_post . title } ' . lower ( ) :
2021-10-15 14:08:27 +00:00
new_post . is_banned = True
2021-11-03 16:15:06 +00:00
new_post . ban_reason = " AutoJanny "
2021-10-15 14:08:27 +00:00
2022-01-10 23:34:56 +00:00
body = AGENDAPOSTER_MSG . format ( username = v . username , type = ' post ' )
2021-10-15 14:08:27 +00:00
body_md = CustomRenderer ( ) . render ( mistletoe . Document ( body ) )
body_jannied_html = sanitize ( body_md )
2021-12-28 06:28:18 +00:00
c_jannied = Comment ( author_id = NOTIFICATIONS_ID ,
2021-10-15 14:08:27 +00:00
parent_submission = new_post . id ,
level = 1 ,
over_18 = False ,
is_bot = True ,
app_id = None ,
2021-12-28 05:06:24 +00:00
is_pinned = ' AutoJanny ' ,
2021-10-15 14:08:27 +00:00
distinguish_level = 6 ,
body_html = body_jannied_html ,
)
g . db . add ( c_jannied )
g . db . flush ( )
n = Notification ( comment_id = c_jannied . id , user_id = v . id )
g . db . add ( n )
2021-12-26 02:29:01 +00:00
new_post . comment_count = 1
2021-10-15 14:08:27 +00:00
2021-12-26 02:29:01 +00:00
if v . id == CARP_ID :
if random . random ( ) < 0.02 : body = " i love you carp "
else : body = " :#marseyfuckoffcarp: "
elif v . id == LAWLZ_ID :
if random . random ( ) < 0.5 : body = " wow, this lawlzpost sucks! "
else : body = " wow, a good lawlzpost for once! "
else : body = random . choice ( snappyquotes )
body + = " \n \n "
if new_post . url :
if new_post . url . startswith ( ' https://old.reddit.com/r/ ' ) :
rev = new_post . url . replace ( ' https://old.reddit.com/ ' , ' ' )
rev = f " * [unddit.com](https://unddit.com/ { rev } ) \n "
else : rev = ' '
newposturl = new_post . url
if newposturl . startswith ( ' / ' ) : newposturl = f " https:// { site } { newposturl } "
body + = f " Snapshots: \n \n { rev } * [archive.org](https://web.archive.org/ { newposturl } ) \n * [archive.ph](https://archive.ph/?url= { quote ( newposturl ) } &run=1) (click to archive) \n \n "
gevent . spawn ( archiveorg , newposturl )
url_regex = ' <a (target= \" _blank \" )?(rel= \" nofollow noopener noreferrer \" )?href= \" (https?://[a-z] { 1,20} \ .[^ \" ]+) \" ( rel= \" nofollow noopener noreferrer \" target= \" _blank \" )?>([^ \" ]+)</a> '
for url_match in re . finditer ( url_regex , new_post . body_html , flags = re . M | re . I ) :
href = url_match . group ( 3 )
if not href : continue
title = url_match . group ( 5 )
if " Snapshots: \n \n " not in body : body + = " Snapshots: \n \n "
body + = f ' **[ { title } ]( { href } )**: \n \n '
if href . startswith ( ' https://old.reddit.com/ ' ) :
body + = f ' * [unddit.com](https://unddit.com/ { href . replace ( " https://old.reddit.com/ " , " " ) } ) \n '
body + = f ' * [archive.org](https://web.archive.org/ { href } ) \n '
body + = f ' * [archive.ph](https://archive.ph/?url= { quote ( href ) } &run=1) (click to archive) \n \n '
gevent . spawn ( archiveorg , href )
body_md = CustomRenderer ( ) . render ( mistletoe . Document ( body ) )
body_html = sanitize ( body_md )
if len ( body_html ) < 20000 :
c = Comment ( author_id = SNAPPY_ID ,
distinguish_level = 6 ,
parent_submission = new_post . id ,
level = 1 ,
over_18 = False ,
is_bot = True ,
app_id = None ,
2021-12-31 17:38:11 +00:00
body_html = body_html
2021-12-26 02:29:01 +00:00
)
2021-10-15 14:08:27 +00:00
2021-12-26 02:29:01 +00:00
g . db . add ( c )
2021-10-27 20:38:10 +00:00
2022-01-02 00:06:46 +00:00
snappy = g . db . query ( User ) . filter_by ( id = SNAPPY_ID ) . one_or_none ( )
2021-12-26 02:29:01 +00:00
snappy . comment_count + = 1
2021-12-27 01:08:06 +00:00
snappy . coins + = 1
2021-12-26 02:29:01 +00:00
g . db . add ( snappy )
2021-10-27 20:38:10 +00:00
2021-12-26 02:29:01 +00:00
if not v . is_blocking ( snappy ) :
2021-11-13 22:40:38 +00:00
g . db . flush ( )
2021-12-26 02:29:01 +00:00
n = Notification ( comment_id = c . id , user_id = v . id )
g . db . add ( n )
2021-10-15 14:08:27 +00:00
2021-11-06 15:52:48 +00:00
v . post_count = g . db . query ( Submission . id ) . filter_by ( author_id = v . id , is_banned = False , deleted_utc = 0 ) . count ( )
2021-10-15 14:08:27 +00:00
g . db . add ( v )
cache . delete_memoized ( frontlist )
cache . delete_memoized ( User . userpagelisting )
2021-12-30 15:57:06 +00:00
if v . admin_level > 1 and ( " [changelog] " in new_post . title or " (changelog) " in new_post . title ) and not new_post . private :
2021-12-31 14:09:44 +00:00
send_discord_message ( f " https:// { site } { new_post . permalink } " )
2021-10-15 14:08:27 +00:00
cache . delete_memoized ( changeloglist )
g . db . commit ( )
2021-11-23 19:54:40 +00:00
2021-10-15 14:08:27 +00:00
if request . headers . get ( " Authorization " ) : return new_post . json
else : return redirect ( new_post . permalink )
@app.post ( " /delete_post/<pid> " )
2021-12-29 15:20:47 +00:00
@limiter.limit ( " 2/second " )
2021-10-15 14:08:27 +00:00
@auth_required
def delete_post_pid ( pid , v ) :
post = get_post ( pid )
if not post . author_id == v . id :
abort ( 403 )
post . deleted_utc = int ( time . time ( ) )
post . is_pinned = False
post . stickied = None
g . db . add ( post )
cache . delete_memoized ( frontlist )
g . db . commit ( )
return { " message " : " Post deleted! " }
@app.post ( " /undelete_post/<pid> " )
@limiter.limit ( " 1/second " )
@auth_required
def undelete_post_pid ( pid , v ) :
post = get_post ( pid )
if not post . author_id == v . id : abort ( 403 )
post . deleted_utc = 0
g . db . add ( post )
cache . delete_memoized ( frontlist )
g . db . commit ( )
return { " message " : " Post undeleted! " }
@app.post ( " /toggle_comment_nsfw/<cid> " )
@auth_required
def toggle_comment_nsfw ( cid , v ) :
2022-01-02 00:06:46 +00:00
comment = g . db . query ( Comment ) . filter_by ( id = cid ) . one_or_none ( )
2021-11-15 22:19:59 +00:00
if not comment . author_id == v . id and not v . admin_level > 1 : abort ( 403 )
2021-10-15 14:08:27 +00:00
comment . over_18 = not comment . over_18
g . db . add ( comment )
g . db . commit ( )
if comment . over_18 : return { " message " : " Comment has been marked as +18! " }
else : return { " message " : " Comment has been unmarked as +18! " }
@app.post ( " /toggle_post_nsfw/<pid> " )
@auth_required
def toggle_post_nsfw ( pid , v ) :
post = get_post ( pid )
2021-11-15 22:19:59 +00:00
if not post . author_id == v . id and not v . admin_level > 1 :
2021-10-15 14:08:27 +00:00
abort ( 403 )
post . over_18 = not post . over_18
g . db . add ( post )
if post . author_id != v . id :
ma = ModAction (
kind = " set_nsfw " if post . over_18 else " unset_nsfw " ,
user_id = v . id ,
target_submission_id = post . id ,
)
g . db . add ( ma )
g . db . commit ( )
if post . over_18 : return { " message " : " Post has been marked as +18! " }
else : return { " message " : " Post has been unmarked as +18! " }
@app.post ( " /save_post/<pid> " )
@limiter.limit ( " 1/second " )
@auth_required
def save_post ( pid , v ) :
post = get_post ( pid )
2022-01-02 00:06:46 +00:00
save = g . db . query ( SaveRelationship ) . filter_by ( user_id = v . id , submission_id = post . id , type = 1 ) . one_or_none ( )
2021-10-15 14:08:27 +00:00
if not save :
new_save = SaveRelationship ( user_id = v . id , submission_id = post . id , type = 1 )
g . db . add ( new_save )
g . db . commit ( )
return { " message " : " Post saved! " }
@app.post ( " /unsave_post/<pid> " )
@limiter.limit ( " 1/second " )
@auth_required
def unsave_post ( pid , v ) :
post = get_post ( pid )
2022-01-02 00:06:46 +00:00
save = g . db . query ( SaveRelationship ) . filter_by ( user_id = v . id , submission_id = post . id , type = 1 ) . one_or_none ( )
2021-10-15 14:08:27 +00:00
if save :
g . db . delete ( save )
g . db . commit ( )
return { " message " : " Post unsaved! " }
2021-10-21 14:47:27 +00:00
@app.post ( " /pin/<post_id> " )
@auth_required
def api_pin_post ( post_id , v ) :
2022-01-02 00:06:46 +00:00
post = g . db . query ( Submission ) . filter_by ( id = post_id ) . one_or_none ( )
2021-10-21 14:47:27 +00:00
if post :
2021-12-27 05:09:22 +00:00
if v . id != post . author_id : return { " error " : " Only the post author ' s can do that! " }
2021-10-21 14:47:27 +00:00
post . is_pinned = not post . is_pinned
g . db . add ( post )
2021-12-29 06:43:20 +00:00
cache . delete_memoized ( User . userpagelisting )
g . db . commit ( )
2021-10-21 14:47:27 +00:00
if post . is_pinned : return { " message " : " Post pinned! " }
2021-12-29 06:43:20 +00:00
else : return { " message " : " Post unpinned! " }