2022-02-10 20:35:16 +00:00
from files . __main__ import app , limiter , mail
from files . helpers . alerts import *
from files . helpers . wrappers import *
2022-06-24 13:19:53 +00:00
from files . helpers . get import *
2022-06-24 14:30:59 +00:00
from files . helpers . regex import *
2022-02-10 20:35:16 +00:00
from files . classes import *
from . front import frontlist
2022-05-04 03:14:14 +00:00
import tldextract
2022-02-14 01:22:26 +00:00
2022-02-16 04:33:13 +00:00
@app.post ( " /exile/post/<pid> " )
@is_not_permabanned
def exile_post ( v , pid ) :
try : pid = int ( pid )
except : abort ( 400 )
p = get_post ( pid )
sub = p . sub
if not sub : abort ( 400 )
2022-06-26 21:34:09 +00:00
if sub == ' braincels ' : abort ( 403 )
2022-02-16 04:33:13 +00:00
if not v . mods ( sub ) : abort ( 403 )
u = p . author
2022-03-05 19:46:47 +00:00
if u . mods ( sub ) : abort ( 403 )
2022-02-16 04:33:13 +00:00
if u . admin_level < 2 and not u . exiled_from ( sub ) :
2022-02-22 12:39:02 +00:00
exile = Exile ( user_id = u . id , sub = sub , exiler_id = v . id )
2022-02-16 04:33:13 +00:00
g . db . add ( exile )
2022-03-09 02:04:37 +00:00
send_notification ( u . id , f " @ { v . username } has exiled you from /h/ { sub } for [ { p . title } ]( { p . shortlink } ) " )
2022-02-16 04:33:13 +00:00
return { " message " : " User exiled successfully! " }
@app.post ( " /exile/comment/<cid> " )
@is_not_permabanned
def exile_comment ( v , cid ) :
try : cid = int ( cid )
except : abort ( 400 )
c = get_comment ( cid )
sub = c . post . sub
if not sub : abort ( 400 )
2022-06-26 21:34:09 +00:00
if sub == ' braincels ' : abort ( 403 )
2022-02-16 04:33:13 +00:00
if not v . mods ( sub ) : abort ( 403 )
u = c . author
2022-03-05 19:46:47 +00:00
if u . mods ( sub ) : abort ( 403 )
2022-02-16 04:33:13 +00:00
if u . admin_level < 2 and not u . exiled_from ( sub ) :
2022-02-22 12:39:02 +00:00
exile = Exile ( user_id = u . id , sub = sub , exiler_id = v . id )
2022-02-16 04:33:13 +00:00
g . db . add ( exile )
2022-03-09 02:04:37 +00:00
send_notification ( u . id , f " @ { v . username } has exiled you from /h/ { sub } for [ { c . permalink } ]( { c . shortlink } ) " )
2022-02-16 04:33:13 +00:00
return { " message " : " User exiled successfully! " }
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/unexile/<uid> " )
2022-02-16 04:33:13 +00:00
@is_not_permabanned
2022-03-09 01:44:53 +00:00
def unexile ( v , sub , uid ) :
u = get_account ( uid )
2022-02-16 04:33:13 +00:00
if not v . mods ( sub ) : abort ( 403 )
if u . exiled_from ( sub ) :
exile = g . db . query ( Exile ) . filter_by ( user_id = u . id , sub = sub ) . one_or_none ( )
g . db . delete ( exile )
2022-03-09 02:04:37 +00:00
send_notification ( u . id , f " @ { v . username } has revoked your exile from /h/ { sub } " )
2022-02-16 04:33:13 +00:00
2022-03-09 01:44:53 +00:00
if request . headers . get ( " Authorization " ) or request . headers . get ( " xhr " ) : return { " message " : " User unexiled successfully! " }
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub } /exilees ' )
2022-03-09 01:44:53 +00:00
2022-02-16 04:33:13 +00:00
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/block " )
2022-02-14 01:22:26 +00:00
@auth_required
def block_sub ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
sub = sub . name
2022-03-05 23:53:43 +00:00
if v . mods ( sub ) : return { " error " : " You can ' t block subs you mod! " }
2022-02-14 01:22:26 +00:00
existing = g . db . query ( SubBlock ) . filter_by ( user_id = v . id , sub = sub ) . one_or_none ( )
if not existing :
block = SubBlock ( user_id = v . id , sub = sub )
g . db . add ( block )
cache . delete_memoized ( frontlist )
return { " message " : " Sub blocked successfully! " }
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/unblock " )
2022-02-14 01:22:26 +00:00
@auth_required
def unblock_sub ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
sub = sub . name
block = g . db . query ( SubBlock ) . filter_by ( user_id = v . id , sub = sub ) . one_or_none ( )
if block :
g . db . delete ( block )
cache . delete_memoized ( frontlist )
return { " message " : " Sub unblocked successfully! " }
2022-06-09 20:24:24 +00:00
@app.post ( " /h/<sub>/follow " )
@auth_required
def follow_sub ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
existing = g . db . query ( SubSubscription ) \
. filter_by ( user_id = v . id , sub = sub . name ) . one_or_none ( )
if not existing :
subscription = SubSubscription ( user_id = v . id , sub = sub . name )
g . db . add ( subscription )
return { " message " : " Sub followed successfully! " }
@app.post ( " /h/<sub>/unfollow " )
@auth_required
def unfollow_sub ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
subscription = g . db . query ( SubSubscription ) \
. filter_by ( user_id = v . id , sub = sub . name ) . one_or_none ( )
if subscription :
g . db . delete ( subscription )
return { " message " : " Sub unfollowed successfully! " }
2022-03-09 02:04:37 +00:00
@app.get ( " /h/<sub>/mods " )
2022-02-21 06:45:01 +00:00
@auth_required
2022-02-10 20:35:16 +00:00
def mods ( v , sub ) :
2022-02-11 23:32:14 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
2022-02-10 20:35:16 +00:00
if not sub : abort ( 404 )
2022-07-03 06:12:53 +00:00
users = g . db . query ( User , Mod ) . join ( Mod ) . filter_by ( sub = sub . name ) . order_by ( Mod . created_utc ) . all ( )
2022-02-11 23:32:14 +00:00
2022-02-10 20:35:16 +00:00
return render_template ( " sub/mods.html " , v = v , sub = sub , users = users )
2022-03-09 02:04:37 +00:00
@app.get ( " /h/<sub>/exilees " )
2022-02-21 06:45:01 +00:00
@auth_required
2022-06-09 20:24:24 +00:00
def sub_exilees ( v , sub ) :
2022-02-21 06:45:01 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
2022-07-03 11:58:46 +00:00
users = g . db . query ( User , Exile ) . join ( Exile , Exile . user_id == User . id ) . filter_by ( sub = sub . name ) . all ( )
2022-02-21 06:45:01 +00:00
return render_template ( " sub/exilees.html " , v = v , sub = sub , users = users )
2022-03-09 02:04:37 +00:00
@app.get ( " /h/<sub>/blockers " )
2022-02-21 06:45:01 +00:00
@auth_required
2022-06-09 20:24:24 +00:00
def sub_blockers ( v , sub ) :
2022-02-21 06:45:01 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
2022-07-03 06:12:53 +00:00
users = g . db . query ( User ) . join ( SubBlock ) . filter_by ( sub = sub . name ) . all ( )
2022-02-21 06:45:01 +00:00
2022-06-09 20:24:24 +00:00
return render_template ( " sub/blockers.html " ,
v = v , sub = sub , users = users , verb = " blocking " )
@app.get ( " /h/<sub>/followers " )
@auth_required
def sub_followers ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
users = g . db . query ( User ) \
2022-07-03 06:12:53 +00:00
. join ( SubSubscription ) \
2022-06-09 20:24:24 +00:00
. filter_by ( sub = sub . name ) . all ( )
2022-02-21 06:45:01 +00:00
2022-06-09 20:24:24 +00:00
return render_template ( " sub/blockers.html " ,
v = v , sub = sub , users = users , verb = " following " )
2022-02-21 06:45:01 +00:00
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/add_mod " )
2022-02-12 18:21:20 +00:00
@limiter.limit ( " 1/second;5/day " )
2022-05-03 02:15:35 +00:00
@limiter.limit ( " 1/second;5/day " , key_func = lambda : f ' { request . host } - { session . get ( " lo_user " ) } ' )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def add_mod ( v , sub ) :
2022-02-11 23:32:14 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
2022-02-10 20:35:16 +00:00
if not sub : abort ( 404 )
sub = sub . name
if not v . mods ( sub ) : abort ( 403 )
user = request . values . get ( ' user ' )
if not user : abort ( 400 )
user = get_user ( user )
2022-02-11 23:32:14 +00:00
existing = g . db . query ( Mod ) . filter_by ( user_id = user . id , sub = sub ) . one_or_none ( )
if not existing :
2022-02-14 21:07:31 +00:00
mod = Mod ( user_id = user . id , sub = sub )
2022-02-11 23:32:14 +00:00
g . db . add ( mod )
2022-03-02 04:27:53 +00:00
if v . id != user . id :
2022-03-09 02:04:37 +00:00
send_repeatable_notification ( user . id , f " @ { v . username } has added you as a mod to /h/ { sub } " )
2022-02-11 23:32:14 +00:00
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub } /mods ' )
2022-02-11 23:32:14 +00:00
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/remove_mod " )
2022-02-11 23:32:14 +00:00
@is_not_permabanned
def remove_mod ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
sub = sub . name
if not v . mods ( sub ) : abort ( 403 )
uid = request . values . get ( ' uid ' )
if not uid : abort ( 400 )
try : uid = int ( uid )
except : abort ( 400 )
2022-06-24 13:19:53 +00:00
user = get_account ( uid )
2022-02-12 19:33:34 +00:00
if not user : abort ( 404 )
mod = g . db . query ( Mod ) . filter_by ( user_id = user . id , sub = sub ) . one_or_none ( )
2022-02-11 23:32:14 +00:00
if not mod : abort ( 400 )
2022-02-25 12:46:33 +00:00
if not ( v . id == user . id or v . mod_date ( sub ) and v . mod_date ( sub ) < mod . created_utc ) : abort ( 403 )
2022-02-12 19:33:34 +00:00
2022-02-11 23:32:14 +00:00
g . db . delete ( mod )
2022-02-10 20:35:16 +00:00
2022-03-02 04:27:53 +00:00
if v . id != user . id :
2022-03-09 02:04:37 +00:00
send_repeatable_notification ( user . id , f " @ { v . username } has removed you as a mod from /h/ { sub } " )
2022-02-10 20:35:16 +00:00
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub } /mods ' )
2022-02-10 20:35:16 +00:00
2022-06-09 22:29:45 +00:00
@app.get ( " /create_hole " )
2022-05-09 02:16:28 +00:00
@is_not_permabanned
def create_sub ( v ) :
2022-06-21 05:20:21 +00:00
if not v . can_create_hole :
abort ( 403 )
2022-03-01 21:19:51 +00:00
2022-06-21 05:20:21 +00:00
return render_template ( " sub/create_hole.html " , v = v , cost = HOLE_COST )
2022-03-01 21:19:51 +00:00
2022-06-09 22:29:45 +00:00
@app.post ( " /create_hole " )
2022-03-02 04:24:36 +00:00
@is_not_permabanned
def create_sub2 ( v ) :
2022-06-21 05:20:21 +00:00
if not v . can_create_hole :
abort ( 403 )
2022-03-02 04:24:36 +00:00
name = request . values . get ( ' name ' )
if not name : abort ( 400 )
name = name . strip ( ) . lower ( )
2022-03-01 21:19:51 +00:00
2022-03-02 04:24:36 +00:00
if not valid_sub_regex . fullmatch ( name ) :
2022-06-10 12:48:11 +00:00
return render_template ( " sub/create_hole.html " , v = v , cost = HOLE_COST , error = " Sub name not allowed. " ) , 400
2022-03-01 21:19:51 +00:00
2022-03-02 04:24:36 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = name ) . one_or_none ( )
if not sub :
2022-06-10 12:48:11 +00:00
if v . coins < HOLE_COST :
return render_template ( " sub/create_hole.html " , v = v , cost = HOLE_COST , error = " You don ' t have enough coins! " ) , 403
2022-03-01 21:19:51 +00:00
2022-06-10 12:48:11 +00:00
v . coins - = HOLE_COST
2022-03-01 21:19:51 +00:00
2022-03-02 04:24:36 +00:00
g . db . add ( v )
sub = Sub ( name = name )
g . db . add ( sub )
g . db . flush ( )
mod = Mod ( user_id = v . id , sub = sub . name )
g . db . add ( mod )
2022-03-01 21:19:51 +00:00
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub . name } ' )
2022-02-10 20:35:16 +00:00
@app.post ( " /kick/<pid> " )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def kick ( v , pid ) :
try : pid = int ( pid )
except : abort ( 400 )
post = get_post ( pid )
if not post . sub : abort ( 403 )
if not v . mods ( post . sub ) : abort ( 403 )
2022-03-06 19:13:11 +00:00
post . sub = None
2022-02-10 20:35:16 +00:00
g . db . add ( post )
cache . delete_memoized ( frontlist )
return { " message " : " Post kicked successfully! " }
2022-06-28 23:36:40 +00:00
@app.post ( " /rehole/<pid> " , defaults = { ' hole ' : ' ' } )
@app.post ( " /rehole/<pid>/<hole> " )
@admin_level_required ( 2 )
def rehole_post ( v , pid , hole ) :
post = get_post ( pid )
sub_from = post . sub
sub_to = hole . strip ( ) . lower ( )
sub_to = g . db . query ( Sub ) . filter_by ( name = sub_to ) . one_or_none ( )
sub_to = sub_to . name if sub_to else None
if sub_from == sub_to :
abort ( 400 )
post . sub = sub_to
g . db . add ( post )
sub_from_str = ' frontpage ' if sub_from is None else \
f ' <a href= " /h/ { sub_from } " >/h/ { sub_from } </a> '
sub_to_str = ' frontpage ' if sub_to is None else \
f ' <a href= " /h/ { sub_to } " >/h/ { sub_to } </a> '
ma = ModAction (
kind = ' move_hole ' ,
user_id = v . id ,
target_submission_id = post . id ,
_note = f ' { sub_from_str } → { sub_to_str } ' ,
)
g . db . add ( ma )
on_post_hole_entered ( post , v )
return { " message " : f " Post moved to { sub_to_str } ! " }
2022-06-30 09:36:45 +00:00
def on_post_hole_entered ( post , v = None ) :
2022-06-22 21:21:12 +00:00
if not post . sub or not post . subr :
return
hole = post . subr . name
2022-06-30 09:36:45 +00:00
author = post . author
2022-06-22 21:21:12 +00:00
# Notify hole followers
2022-06-30 09:36:45 +00:00
if not post . ghost and not post . private and not author . shadowbanned :
2022-06-22 21:21:12 +00:00
text = f " <a href= ' /h/ { hole } ' >/h/ { hole } </a> has a new " \
2022-06-30 09:36:45 +00:00
+ f " post: [ { post . title } ]( { post . shortlink } ) by @ { author . username } "
2022-06-22 21:21:12 +00:00
cid = notif_comment ( text , autojanny = True )
for follow in post . subr . followers :
2022-06-30 09:36:45 +00:00
if follow . user_id == author . id or ( v and follow . user_id == v . id ) :
continue
2022-06-22 21:21:12 +00:00
user = get_account ( follow . user_id )
if post . club and not user . paid_dues : continue
add_notif ( cid , user . id )
2022-02-10 20:35:16 +00:00
2022-03-09 02:04:37 +00:00
@app.get ( ' /h/<sub>/settings ' )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def sub_settings ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
if not v . mods ( sub . name ) : abort ( 403 )
return render_template ( ' sub/settings.html ' , v = v , sidebar = sub . sidebar , sub = sub )
2022-03-09 02:04:37 +00:00
@app.post ( ' /h/<sub>/sidebar ' )
2022-02-10 20:35:16 +00:00
@limiter.limit ( " 1/second;30/minute;200/hour;1000/day " )
2022-05-03 02:15:35 +00:00
@limiter.limit ( " 1/second;30/minute;200/hour;1000/day " , key_func = lambda : f ' { request . host } - { session . get ( " lo_user " ) } ' )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def post_sub_sidebar ( v , sub ) :
2022-02-11 23:32:14 +00:00
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
2022-02-10 20:35:16 +00:00
if not sub : abort ( 404 )
if not v . mods ( sub . name ) : abort ( 403 )
2022-02-11 23:32:14 +00:00
sub . sidebar = request . values . get ( ' sidebar ' , ' ' ) . strip ( ) [ : 500 ]
2022-02-10 20:35:16 +00:00
sub . sidebar_html = sanitize ( sub . sidebar )
2022-02-11 23:32:14 +00:00
if len ( sub . sidebar_html ) > 1000 : return " Sidebar is too big! "
2022-02-10 20:35:16 +00:00
g . db . add ( sub )
2022-02-11 23:32:14 +00:00
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub . name } /settings ' )
2022-02-11 23:32:14 +00:00
2022-03-09 02:04:37 +00:00
@app.post ( ' /h/<sub>/css ' )
2022-02-11 23:32:14 +00:00
@limiter.limit ( " 1/second;30/minute;200/hour;1000/day " )
2022-05-03 02:15:35 +00:00
@limiter.limit ( " 1/second;30/minute;200/hour;1000/day " , key_func = lambda : f ' { request . host } - { session . get ( " lo_user " ) } ' )
2022-02-11 23:32:14 +00:00
@is_not_permabanned
def post_sub_css ( v , sub ) :
sub = g . db . query ( Sub ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
if not v . mods ( sub . name ) : abort ( 403 )
2022-05-03 19:07:15 +00:00
css = request . values . get ( ' css ' , ' ' ) . strip ( )
2022-05-26 20:04:39 +00:00
for i in css_regex . finditer ( css ) :
url = i . group ( 0 )
2022-05-25 18:29:22 +00:00
if not is_safe_url ( url ) :
domain = tldextract . extract ( url ) . registered_domain
2022-05-04 03:14:14 +00:00
error = f " The domain ' { domain } ' is not allowed, please use one of these domains \n \n { approved_embed_hosts } . "
return render_template ( ' sub/settings.html ' , v = v , sidebar = sub . sidebar , sub = sub , error = error )
2022-05-03 19:07:15 +00:00
sub . css = css
2022-02-11 23:32:14 +00:00
g . db . add ( sub )
2022-02-10 20:35:16 +00:00
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub . name } /settings ' )
2022-02-10 20:35:16 +00:00
2022-06-26 05:07:28 +00:00
@app.get ( " /h/<sub>/css " )
def get_sub_css ( sub ) :
2022-06-26 05:26:45 +00:00
sub = g . db . query ( Sub . css ) . filter_by ( name = sub . strip ( ) . lower ( ) ) . one_or_none ( )
2022-06-26 05:07:28 +00:00
if not sub : abort ( 404 )
resp = make_response ( sub . css or " " )
resp . headers . add ( " Content-Type " , " text/css " )
return resp
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/banner " )
2022-02-12 18:21:40 +00:00
@limiter.limit ( " 1/second;10/day " )
2022-05-03 02:15:35 +00:00
@limiter.limit ( " 1/second;10/day " , key_func = lambda : f ' { request . host } - { session . get ( " lo_user " ) } ' )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def sub_banner ( v , sub ) :
if request . headers . get ( " cf-ipcountry " ) == " T1 " : return { " error " : " Image uploads are not allowed through TOR. " } , 403
sub = g . db . query ( Sub ) . filter_by ( name = sub . lower ( ) . strip ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
if not v . mods ( sub . name ) : abort ( 403 )
file = request . files [ " banner " ]
2022-03-25 22:30:15 +00:00
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) + ' .webp '
2022-02-10 20:35:16 +00:00
file . save ( name )
2022-06-18 20:41:00 +00:00
bannerurl = process_image ( name )
2022-02-10 20:35:16 +00:00
if bannerurl :
if sub . bannerurl and ' /images/ ' in sub . bannerurl :
fpath = ' /images/ ' + sub . bannerurl . split ( ' /images/ ' ) [ 1 ]
if path . isfile ( fpath ) : os . remove ( fpath )
sub . bannerurl = bannerurl
g . db . add ( sub )
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub . name } /settings ' )
2022-02-10 20:35:16 +00:00
2022-03-09 02:04:37 +00:00
@app.post ( " /h/<sub>/sidebar_image " )
2022-02-12 18:21:40 +00:00
@limiter.limit ( " 1/second;10/day " )
2022-05-03 02:15:35 +00:00
@limiter.limit ( " 1/second;10/day " , key_func = lambda : f ' { request . host } - { session . get ( " lo_user " ) } ' )
2022-02-11 15:02:27 +00:00
@is_not_permabanned
2022-02-10 20:35:16 +00:00
def sub_sidebar ( v , sub ) :
if request . headers . get ( " cf-ipcountry " ) == " T1 " : return { " error " : " Image uploads are not allowed through TOR. " } , 403
sub = g . db . query ( Sub ) . filter_by ( name = sub . lower ( ) . strip ( ) ) . one_or_none ( )
if not sub : abort ( 404 )
if not v . mods ( sub . name ) : abort ( 403 )
file = request . files [ " sidebar " ]
2022-03-25 22:30:15 +00:00
name = f ' /images/ { time . time ( ) } ' . replace ( ' . ' , ' ' ) + ' .webp '
2022-02-10 20:35:16 +00:00
file . save ( name )
2022-06-18 20:41:00 +00:00
sidebarurl = process_image ( name )
2022-02-10 20:35:16 +00:00
if sidebarurl :
if sub . sidebarurl and ' /images/ ' in sub . sidebarurl :
fpath = ' /images/ ' + sub . sidebarurl . split ( ' /images/ ' ) [ 1 ]
if path . isfile ( fpath ) : os . remove ( fpath )
sub . sidebarurl = sidebarurl
g . db . add ( sub )
2022-03-09 02:04:37 +00:00
return redirect ( f ' /h/ { sub . name } /settings ' )
2022-02-24 12:03:28 +00:00
2022-03-09 02:04:37 +00:00
@app.get ( " /holes " )
2022-02-24 12:03:28 +00:00
@auth_desired
def subs ( v ) :
2022-03-06 01:59:45 +00:00
subs = g . db . query ( Sub , func . count ( Submission . sub ) ) . outerjoin ( Submission , Sub . name == Submission . sub ) . group_by ( Sub . name ) . order_by ( func . count ( Submission . sub ) . desc ( ) ) . all ( )
2022-06-10 09:47:41 +00:00
return render_template ( ' sub/subs.html ' , v = v , subs = subs )
def sub_inactive_purge_task ( ) :
if not HOLE_INACTIVITY_DELETION :
return False
one_week_ago = time . time ( ) - 604800
active_holes = [ x [ 0 ] for x in g . db . query ( Submission . sub ) . distinct ( ) \
. filter ( Submission . sub != None , Submission . created_utc > one_week_ago ) . all ( ) ]
dead_holes = g . db . query ( Sub ) . filter ( Sub . name . notin_ ( active_holes ) ) . all ( )
names = [ x . name for x in dead_holes ]
2022-06-10 15:41:33 +00:00
mods = g . db . query ( Mod ) . filter ( Mod . sub . in_ ( names ) ) . all ( )
for x in mods :
send_repeatable_notification ( x . user_id , f " :marseyrave: /h/ { x . sub } has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave: " )
2022-06-17 19:28:37 +00:00
admins = [ x [ 0 ] for x in g . db . query ( User . id ) . filter ( User . admin_level > 1 ) . all ( ) ]
2022-06-17 18:30:05 +00:00
for name in names :
2022-06-17 19:28:37 +00:00
for admin in admins :
send_repeatable_notification ( admin , f " :marseyrave: /h/ { name } has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave: " )
2022-06-17 18:30:05 +00:00
2022-06-10 09:47:41 +00:00
posts = g . db . query ( Submission ) . filter ( Submission . sub . in_ ( names ) ) . all ( )
for post in posts :
post . sub = None
g . db . add ( post )
2022-06-10 15:41:33 +00:00
to_delete = mods \
2022-06-10 09:47:41 +00:00
+ g . db . query ( Exile ) . filter ( Exile . sub . in_ ( names ) ) . all ( ) \
+ g . db . query ( SubBlock ) . filter ( SubBlock . sub . in_ ( names ) ) . all ( ) \
+ g . db . query ( SubSubscription ) . filter ( SubSubscription . sub . in_ ( names ) ) . all ( )
for x in to_delete :
g . db . delete ( x )
g . db . flush ( )
for x in dead_holes :
g . db . delete ( x )
return True
2022-07-01 23:11:48 +00:00
@app.post ( " /hole_pin/<pid> " )
@auth_required
def hole_pin ( v , pid ) :
p = get_post ( pid )
if not p . sub : abort ( 403 )
if not v . mods ( p . sub ) : abort ( 403 )
p . hole_pinned = v . username
g . db . add ( p )
return { " message " : f " Post pinned to /h/ { p . sub } " }
@app.post ( " /hole_unpin/<pid> " )
@auth_required
def hole_unpin ( v , pid ) :
p = get_post ( pid )
if not p . sub : abort ( 403 )
if not v . mods ( p . sub ) : abort ( 403 )
p . hole_pinned = None
g . db . add ( p )
return { " message " : f " Post unpinned from /h/ { p . sub } " }