2021-08-04 15:35:10 +00:00
from files . mail import *
from files . __main__ import app , limiter
from files . helpers . alerts import *
2021-08-28 12:46:34 +00:00
from files . classes . award import AWARDS
from sqlalchemy import func
2021-09-09 11:02:06 +00:00
from os import path
2021-07-21 01:12:26 +00:00
2021-08-05 14:41:32 +00:00
site = environ . get ( " DOMAIN " ) . strip ( )
2021-08-19 05:40:23 +00:00
site_name = environ . get ( " SITE_NAME " ) . strip ( )
2021-07-25 21:59:20 +00:00
2021-09-09 11:02:06 +00:00
@app.get ( ' /rules ' )
@auth_desired
def static_rules ( v ) :
2021-09-12 01:41:48 +00:00
if not path . exists ( f ' ./ { site_name } rules.html ' ) :
2021-09-09 11:02:06 +00:00
if v and v . admin_level == 6 :
return render_template ( ' norules.html ' , v = v )
else :
abort ( 404 )
2021-09-12 01:41:48 +00:00
with open ( f ' ./ { site_name } rules.html ' , ' r ' ) as f :
2021-09-09 11:02:06 +00:00
rules = f . read ( )
return render_template ( ' rules.html ' , rules = rules , v = v )
2021-08-07 12:20:00 +00:00
@app.get ( " /stats " )
@auth_desired
def participation_stats ( v ) :
now = int ( time . time ( ) )
day = now - 86400
data = { " valid_users " : g . db . query ( User ) . count ( ) ,
2021-09-17 08:29:05 +00:00
" private_users " : g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( is_private = True ) . count ( ) ,
" banned_users " : g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . is_banned > 0 ) . count ( ) ,
" verified_email_users " : g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( is_activated = True ) . count ( ) ,
2021-09-08 07:19:30 +00:00
" total_coins " : g . db . query ( func . sum ( User . coins ) ) . scalar ( ) ,
2021-09-17 08:29:05 +00:00
" signups_last_24h " : g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . created_utc > day ) . count ( ) ,
2021-08-07 12:20:00 +00:00
" total_posts " : g . db . query ( Submission ) . count ( ) ,
" posting_users " : g . db . query ( Submission . author_id ) . distinct ( ) . count ( ) ,
2021-09-17 08:29:05 +00:00
" listed_posts " : g . db . query ( Submission ) . options ( lazyload ( ' * ' ) ) . filter_by ( is_banned = False ) . filter ( Submission . deleted_utc == 0 ) . count ( ) ,
" removed_posts " : g . db . query ( Submission ) . options ( lazyload ( ' * ' ) ) . filter_by ( is_banned = True ) . count ( ) ,
" deleted_posts " : g . db . query ( Submission ) . options ( lazyload ( ' * ' ) ) . filter ( Submission . deleted_utc > 0 ) . count ( ) ,
" posts_last_24h " : g . db . query ( Submission ) . options ( lazyload ( ' * ' ) ) . filter ( Submission . created_utc > day ) . count ( ) ,
2021-08-07 12:20:00 +00:00
" total_comments " : g . db . query ( Comment ) . count ( ) ,
" commenting_users " : g . db . query ( Comment . author_id ) . distinct ( ) . count ( ) ,
2021-09-17 08:29:05 +00:00
" removed_comments " : g . db . query ( Comment ) . options ( lazyload ( ' * ' ) ) . filter_by ( is_banned = True ) . count ( ) ,
" deleted_comments " : g . db . query ( Comment ) . options ( lazyload ( ' * ' ) ) . filter ( Comment . deleted_utc > 0 ) . count ( ) ,
" comments_last_24h " : g . db . query ( Comment ) . options ( lazyload ( ' * ' ) ) . filter ( Comment . created_utc > day ) . count ( ) ,
2021-08-07 12:20:00 +00:00
" post_votes " : g . db . query ( Vote ) . count ( ) ,
" post_voting_users " : g . db . query ( Vote . user_id ) . distinct ( ) . count ( ) ,
" comment_votes " : g . db . query ( CommentVote ) . count ( ) ,
" comment_voting_users " : g . db . query ( CommentVote . user_id ) . distinct ( ) . count ( ) ,
" total_awards " : g . db . query ( AwardRelationship ) . count ( ) ,
2021-09-17 08:29:05 +00:00
" awards_given " : g . db . query ( AwardRelationship ) . options ( lazyload ( ' * ' ) ) . filter ( or_ ( AwardRelationship . submission_id != None , AwardRelationship . comment_id != None ) ) . count ( )
2021-08-07 12:20:00 +00:00
}
return render_template ( " admin/content_stats.html " , v = v , title = " Content Statistics " , data = data )
2021-09-11 02:50:12 +00:00
@app.get ( " /patrons " )
2021-09-16 11:08:06 +00:00
@app.get ( " /paypigs " )
2021-07-30 15:14:41 +00:00
@auth_desired
def patrons ( v ) :
2021-08-28 12:46:34 +00:00
query = g . db . query (
User . id , User . username , User . patron , User . namecolor ,
AwardRelationship . kind . label ( ' last_award_kind ' ) , func . count ( AwardRelationship . id ) . label ( ' last_award_count ' )
2021-08-28 12:58:59 +00:00
) . filter ( AwardRelationship . submission_id == None , AwardRelationship . comment_id == None , User . patron > 0 ) \
2021-08-28 12:46:34 +00:00
. group_by ( User . username , User . patron , User . id , User . namecolor , AwardRelationship . kind ) \
2021-08-28 12:58:59 +00:00
. order_by ( User . patron . desc ( ) , AwardRelationship . kind . desc ( ) ) \
2021-08-28 12:46:34 +00:00
. join ( User ) . all ( )
result = { }
for row in ( r . _asdict ( ) for r in query ) :
user_id = row [ ' id ' ]
if user_id not in result :
result [ user_id ] = row
result [ user_id ] [ ' awards ' ] = { }
2021-08-28 12:55:13 +00:00
kind = row [ ' last_award_kind ' ]
if kind in AWARDS . keys ( ) :
result [ user_id ] [ ' awards ' ] [ kind ] = ( AWARDS [ kind ] , row [ ' last_award_count ' ] )
2021-08-28 12:46:34 +00:00
2021-08-28 12:58:59 +00:00
return render_template ( " patrons.html " , v = v , result = result )
2021-07-30 15:14:41 +00:00
2021-08-18 15:32:27 +00:00
@app.get ( " /admins " )
2021-09-16 11:08:06 +00:00
@app.get ( " /badmins " )
2021-07-25 21:59:20 +00:00
@auth_desired
2021-08-18 15:32:27 +00:00
def admins ( v ) :
2021-09-17 08:29:05 +00:00
admins = g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter_by ( admin_level = 6 ) . order_by ( User . coins . desc ( ) ) . all ( )
2021-08-18 15:32:27 +00:00
return render_template ( " admins.html " , v = v , admins = admins )
2021-07-25 21:59:20 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /log " )
2021-09-16 11:08:29 +00:00
@app.get ( " /modlog " )
2021-07-25 21:59:20 +00:00
@auth_desired
def log ( v ) :
page = int ( request . args . get ( " page " , 1 ) )
if v and v . admin_level == 6 : actions = g . db . query ( ModAction ) . order_by ( ModAction . id . desc ( ) ) . offset ( 25 * ( page - 1 ) ) . limit ( 26 ) . all ( )
2021-09-17 08:29:05 +00:00
else : actions = g . db . query ( ModAction ) . options ( lazyload ( ' * ' ) ) . filter ( ModAction . kind != " shadowban " , ModAction . kind != " unshadowban " , ModAction . kind != " club " , ModAction . kind != " unclub " ) . order_by ( ModAction . id . desc ( ) ) . offset ( 25 * ( page - 1 ) ) . limit ( 26 ) . all ( )
2021-07-25 21:59:20 +00:00
next_exists = len ( actions ) == 26
2021-07-26 00:45:52 +00:00
actions = actions [ : 25 ]
2021-07-25 21:59:20 +00:00
2021-07-31 05:59:25 +00:00
return render_template ( " log.html " , v = v , actions = actions , next_exists = next_exists , page = page )
2021-07-25 21:59:20 +00:00
2021-07-30 08:28:18 +00:00
@app.get ( " /log/<id> " )
2021-07-25 21:59:20 +00:00
@auth_desired
2021-07-30 08:28:18 +00:00
def log_item ( id , v ) :
2021-07-25 21:59:20 +00:00
2021-07-30 08:28:18 +00:00
try : id = int ( id )
2021-07-31 06:59:18 +00:00
except :
try : id = int ( id , 36 )
except : abort ( 404 )
2021-07-30 08:28:18 +00:00
2021-09-17 08:29:05 +00:00
action = g . db . query ( ModAction ) . options ( lazyload ( ' * ' ) ) . filter_by ( id = id ) . first ( )
2021-07-25 21:59:20 +00:00
if not action :
abort ( 404 )
if request . path != action . permalink :
return redirect ( action . permalink )
2021-07-31 05:59:25 +00:00
return render_template ( " log.html " ,
2021-07-25 21:59:20 +00:00
v = v ,
actions = [ action ] ,
next_exists = False ,
page = 1 ,
action = action
)
2021-07-21 01:12:26 +00:00
@app.route ( " /sex " )
def index ( ) :
2021-09-08 08:53:57 +00:00
return render_template ( " index.html " , * * { " greeting " : " Hello from Flask! " } )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /assets/favicon.ico " )
2021-07-21 01:12:26 +00:00
def favicon ( ) :
2021-09-13 15:58:52 +00:00
return send_file ( f " ./assets/images/ { site_name } /icon.webp " )
2021-07-21 01:12:26 +00:00
2021-07-31 04:32:42 +00:00
@app.get ( " /api " )
2021-07-21 01:12:26 +00:00
@auth_desired
2021-07-31 04:32:42 +00:00
def api ( v ) :
return render_template ( " api.html " , v = v )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /contact " )
2021-07-21 01:12:26 +00:00
@auth_desired
def contact ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
return render_template ( " contact.html " , v = v )
2021-07-27 22:31:28 +00:00
@app.post ( " /contact " )
2021-07-21 01:12:26 +00:00
@auth_desired
def submit_contact ( v ) :
2021-08-02 15:05:46 +00:00
message = f ' This message has been sent automatically to all admins via https:// { site } /contact, user email is " { v . email } " \n \n Message: \n \n ' + request . form . get ( " message " , " " )
2021-07-21 01:12:26 +00:00
send_admin ( v . id , message )
2021-09-16 17:02:58 +00:00
g . db . commit ( )
2021-07-21 01:12:26 +00:00
return render_template ( " contact.html " , v = v , msg = " Your message has been sent. " )
@app.route ( ' /archives ' )
@limiter.exempt
def archivesindex ( ) :
return redirect ( " /archives/index.html " )
@app.route ( ' /archives/<path:path> ' )
@limiter.exempt
def archives ( path ) :
resp = make_response ( send_from_directory ( ' /archives ' , path ) )
if request . path . endswith ( ' .css ' ) : resp . headers . add ( " Content-Type " , " text/css " )
return resp
@app.route ( ' /assets/<path:path> ' )
@limiter.exempt
def static_service ( path ) :
resp = make_response ( send_from_directory ( ' ./assets ' , path ) )
2021-09-13 15:58:52 +00:00
if request . path . endswith ( ' .webp ' ) or request . path . endswith ( ' .gif ' ) or request . path . endswith ( ' .ttf ' ) or request . path . endswith ( ' .woff ' ) or request . path . endswith ( ' .woff2 ' ) :
2021-08-23 10:00:05 +00:00
resp . headers . remove ( " Cache-Control " )
2021-08-31 14:55:34 +00:00
resp . headers . add ( " Cache-Control " , " public, max-age=2628000 " )
2021-08-23 10:00:05 +00:00
2021-07-21 01:12:26 +00:00
return resp
2021-07-27 22:31:28 +00:00
@app.get ( " /robots.txt " )
2021-07-21 01:12:26 +00:00
def robots_txt ( ) :
return send_file ( " ./assets/robots.txt " )
2021-07-27 22:31:28 +00:00
@app.get ( " /settings " )
2021-07-21 01:12:26 +00:00
@auth_required
def settings ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
return redirect ( " /settings/profile " )
2021-07-27 22:31:28 +00:00
@app.get ( " /settings/profile " )
2021-07-21 01:12:26 +00:00
@auth_required
def settings_profile ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
return render_template ( " settings_profile.html " ,
v = v )
2021-07-27 22:31:28 +00:00
@app.get ( " /badges " )
2021-07-21 01:12:26 +00:00
@auth_desired
def badges ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
2021-08-20 05:55:53 +00:00
badges = g . db . query ( BadgeDef ) . all ( )
return render_template ( " badges.html " , v = v , badges = badges )
2021-07-21 01:12:26 +00:00
2021-07-27 22:31:28 +00:00
@app.get ( " /blocks " )
2021-07-21 01:12:26 +00:00
@auth_desired
def blocks ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
blocks = g . db . query ( UserBlock ) . all ( )
users = [ ]
targets = [ ]
for x in blocks :
users . append ( get_account ( x . user_id ) )
targets . append ( get_account ( x . target_id ) )
return render_template ( " blocks.html " , v = v , users = users , targets = targets )
2021-07-27 22:31:28 +00:00
@app.get ( " /banned " )
2021-07-21 01:12:26 +00:00
@auth_desired
def banned ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
2021-09-17 08:29:05 +00:00
users = [ x for x in g . db . query ( User ) . options ( lazyload ( ' * ' ) ) . filter ( User . is_banned > 0 , User . unban_utc == 0 ) . all ( ) ]
2021-07-21 01:12:26 +00:00
return render_template ( " banned.html " , v = v , users = users )
2021-07-27 22:31:28 +00:00
@app.get ( " /formatting " )
2021-07-21 01:12:26 +00:00
@auth_desired
def formatting ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
return render_template ( " formatting.html " , v = v )
2021-07-27 22:31:28 +00:00
@app.get ( " /.well-known/brave-rewards-verification.txt " )
2021-07-21 01:12:26 +00:00
def brave ( ) :
with open ( " .well-known/brave-rewards-verification.txt " , " r " ) as f : return Response ( f . read ( ) , mimetype = ' text/plain ' )
2021-07-27 22:31:28 +00:00
@app.get ( " /.well-known/assetlinks.json " )
2021-07-21 01:12:26 +00:00
def googleplayapp ( ) :
with open ( " .well-known/assetlinks.json " , " r " ) as f : return Response ( f . read ( ) , mimetype = ' application/json ' )
@app.route ( " /service-worker.js " )
def serviceworker ( ) :
with open ( " .well-known/service-worker.js " , " r " ) as f : return Response ( f . read ( ) , mimetype = ' application/javascript ' )
2021-07-27 22:31:28 +00:00
@app.get ( " /settings/security " )
2021-07-21 01:12:26 +00:00
@auth_required
def settings_security ( v ) :
2021-08-23 17:48:55 +00:00
2021-07-21 01:12:26 +00:00
return render_template ( " settings_security.html " ,
v = v ,
mfa_secret = pyotp . random_base32 ( ) if not v . mfa_secret else None ,
error = request . args . get ( " error " ) or None ,
msg = request . args . get ( " msg " ) or None
)
2021-07-27 22:31:28 +00:00
@app.post ( " /dismiss_mobile_tip " )
2021-07-21 01:12:26 +00:00
def dismiss_mobile_tip ( ) :
session [ " tooltip_last_dismissed " ] = int ( time . time ( ) )
session . modified = True
return " " , 204