2023-02-24 06:31:06 +00:00
from files . classes import *
from files . helpers . alerts import *
from files . helpers . regex import *
from files . helpers . get import *
2024-08-12 18:07:55 +00:00
from files . helpers . actions import execute_under_siege
2023-02-24 06:31:06 +00:00
from files . routes . wrappers import *
from files . __main__ import app , limiter
@app.get ( " /ping_groups " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 06:31:06 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def ping_groups ( v ) :
2024-11-13 22:27:18 +00:00
groups = g . db . query ( Group ) . order_by ( Group . created_utc )
owner = request . values . get ( ' owner ' )
if owner :
owner_id = get_user ( owner , attributes = [ User . id ] ) . id
groups = groups . filter_by ( owner_id = owner_id )
2023-08-11 21:50:23 +00:00
return render_template ( ' groups.html ' , v = v , groups = groups , cost = GROUP_COST )
2023-02-24 06:31:06 +00:00
@app.post ( " /create_group " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-09-14 16:49:46 +00:00
@auth_required
2023-02-24 06:31:06 +00:00
def create_group ( v ) :
2024-09-03 17:25:14 +00:00
name = request . values . get ( " name " , " " ) . strip ( ) . lstrip ( " ! " ) . strip ( ) . lower ( )
2024-08-11 20:11:04 +00:00
if not name : stop ( 400 )
2023-02-24 06:31:06 +00:00
2023-04-29 21:27:45 +00:00
if name . startswith ( ' slots ' ) or name . startswith ( ' remindme ' ) :
2024-08-11 20:11:04 +00:00
stop ( 400 , " You can ' t make a group with that name! " )
2023-03-04 21:45:12 +00:00
2023-09-08 22:31:18 +00:00
if not hole_group_name_regex . fullmatch ( name ) :
2024-08-11 20:11:04 +00:00
stop ( 400 , " Name does not match the required format! " )
2023-02-24 06:31:06 +00:00
2023-11-04 21:28:44 +00:00
if name in { ' everyone ' , ' jannies ' , ' holejannies ' , ' followers ' , ' commenters ' } or g . db . get ( Group , name ) :
2024-08-11 20:11:04 +00:00
stop ( 400 , " This group already exists! " )
2023-03-02 19:21:38 +00:00
2024-03-06 02:04:25 +00:00
charge_reason = f ' Cost of creating <a href= " /! { name } " >! { name } </a> '
2024-03-09 12:19:38 +00:00
if not v . charge_account ( ' coins/marseybux ' , GROUP_COST , charge_reason ) :
2024-08-11 20:11:04 +00:00
stop ( 403 , " You don ' t have enough coins or marseybux! " )
2023-03-02 19:21:38 +00:00
2023-03-16 06:27:58 +00:00
g . db . add ( v )
2024-08-11 20:11:04 +00:00
if v . shadowbanned : stop ( 500 )
2023-03-02 19:21:38 +00:00
2024-02-11 13:39:16 +00:00
group = Group (
name = name ,
owner_id = v . id ,
)
2023-03-16 06:27:58 +00:00
g . db . add ( group )
2023-03-02 19:21:38 +00:00
group_membership = GroupMembership (
user_id = v . id ,
group_name = group . name ,
created_utc = time . time ( ) ,
2024-08-17 22:50:47 +00:00
approved_utc = time . time ( ) ,
is_mod = True ,
2023-03-02 19:21:38 +00:00
)
2023-03-16 06:27:58 +00:00
g . db . add ( group_membership )
2023-03-02 19:21:38 +00:00
2023-10-12 18:57:35 +00:00
g . db . flush ( ) #Necessary, to make linkfying the ping group in the notification work
2024-02-08 03:35:37 +00:00
text = f " :!marseyparty: ! { group } has been created by @ { v . username } :marseyparty: "
2024-02-10 15:34:45 +00:00
alert_active_users ( text , v . id , User . group_creation_notifs == True )
2023-02-24 06:31:06 +00:00
2024-03-06 00:11:35 +00:00
cache . delete ( " group_count " )
2023-08-11 21:50:23 +00:00
return { " message " : f " ! { group } created successfully! " }
2023-02-24 06:31:06 +00:00
2023-02-24 19:29:07 +00:00
@app.post ( " /!<group_name>/apply " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 06:31:06 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def join_group ( v , group_name ) :
2023-03-07 18:55:17 +00:00
group_name = group_name . strip ( ) . lower ( )
2024-03-27 14:17:24 +00:00
if group_name == ' verifiedrich ' and not v . patron :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only { patron } s can join !verifiedrich " )
2023-08-01 22:18:57 +00:00
2024-03-27 14:17:24 +00:00
if group_name in { ' verifiedrich ' , ' focusgroup ' } :
2023-08-01 22:18:57 +00:00
join = GroupMembership (
user_id = v . id ,
group_name = group_name ,
approved_utc = time . time ( )
)
g . db . add ( join )
2024-03-27 14:17:24 +00:00
return { " message " : f " You have joined ! { group_name } successfully! " }
2023-08-01 21:56:13 +00:00
2023-03-16 06:27:58 +00:00
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-08-01 22:18:57 +00:00
2024-10-16 23:00:39 +00:00
blacklist = g . db . query ( GroupBlacklist . user_id ) . filter_by ( user_id = v . id , group_name = group_name ) . one_or_none ( )
if blacklist :
stop ( 403 , f " You ' re blacklisted from ! { group_name } " )
2024-08-12 18:07:55 +00:00
execute_under_siege ( v , group , " ping group application " )
2023-03-16 06:27:58 +00:00
existing = g . db . query ( GroupMembership ) . filter_by ( user_id = v . id , group_name = group_name ) . one_or_none ( )
2023-02-24 06:31:06 +00:00
if not existing :
join = GroupMembership ( user_id = v . id , group_name = group_name )
2023-03-16 06:27:58 +00:00
g . db . add ( join )
2024-02-12 13:12:42 +00:00
notified_ids = [ group . owner_id ]
notified_ids + = [ x [ 0 ] for x in g . db . query ( GroupMembership . user_id ) . filter_by ( group_name = group_name , is_mod = True ) . all ( ) ]
notified_ids = list ( set ( notified_ids ) )
2024-03-02 08:10:59 +00:00
if 2249 in notified_ids :
notified_ids . remove ( 2249 )
2024-03-03 20:58:32 +00:00
text = f " @ { v . username } has applied to join ! { group } . You can approve or reject the application [here](/! { group } ). "
cid = notif_comment ( text )
2024-02-12 13:12:42 +00:00
for uid in notified_ids :
2024-03-05 22:42:13 +00:00
add_notif ( cid , uid , text , pushnotif_url = f ' { SITE_FULL } /! { group } ' )
2023-02-24 06:31:06 +00:00
2024-02-18 20:46:43 +00:00
return { " message " : f " Application to ! { group } submitted successfully! " }
2023-02-24 06:31:06 +00:00
2024-11-09 20:28:24 +00:00
def delete_group ( membership , group , v ) :
g . db . delete ( membership )
for blacklist in g . db . query ( GroupBlacklist ) . filter_by ( group_name = group . name ) :
g . db . delete ( blacklist )
g . db . delete ( group )
text = f ' :marseydisintegrate: ! { group } has been deleted by @ { v . username } :!marseydisintegrate: '
alert_active_users ( text , None , User . group_creation_notifs == True )
return { " message " : f " You have deleted ! { group } successfully! " }
2023-02-24 19:29:07 +00:00
@app.post ( " /!<group_name>/leave " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 06:31:06 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def leave_group ( v , group_name ) :
2023-03-07 18:55:17 +00:00
group_name = group_name . strip ( ) . lower ( )
2023-03-16 06:27:58 +00:00
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-03-16 06:27:58 +00:00
existing = g . db . query ( GroupMembership ) . filter_by ( user_id = v . id , group_name = group_name ) . one_or_none ( )
2023-02-24 19:29:07 +00:00
if existing :
if existing . approved_utc :
text = f " @ { v . username } has left ! { group } "
msg = f " You have left ! { group } successfully! "
2024-10-16 23:25:50 +00:00
func = send_repeatable_notification
2023-02-24 19:29:07 +00:00
else :
text = f " @ { v . username } has cancelled their application to ! { group } "
msg = f " You have cancelled your application to ! { group } successfully! "
2024-10-16 23:25:50 +00:00
func = send_notification
2023-02-24 19:29:07 +00:00
2024-10-16 06:22:18 +00:00
if v . id == group . owner_id :
new_owner_id = g . db . query ( GroupMembership . user_id ) . filter (
GroupMembership . user_id != group . owner_id ,
GroupMembership . group_name == group . name ,
GroupMembership . approved_utc != None ,
) . order_by ( GroupMembership . is_mod . desc ( ) , GroupMembership . approved_utc ) . first ( )
if new_owner_id :
new_owner_id = new_owner_id [ 0 ]
send_repeatable_notification ( new_owner_id , f " @ { group . owner . username } (! { group } ' s owner) has left the group, You ' re now the new owner! " )
group . owner_id = new_owner_id
g . db . add ( group )
2024-11-09 20:28:24 +00:00
else :
return delete_group ( existing , group , v )
2024-10-16 06:22:18 +00:00
else :
2024-10-16 23:25:50 +00:00
func ( group . owner_id , text )
2024-10-16 06:22:18 +00:00
2023-03-16 06:27:58 +00:00
g . db . delete ( existing )
2023-05-05 21:45:25 +00:00
2023-02-25 21:44:02 +00:00
return { " message " : msg }
2023-02-24 19:29:07 +00:00
2023-02-24 19:43:27 +00:00
return { " message " : ' ' }
2023-02-24 19:29:07 +00:00
2023-02-25 22:06:43 +00:00
@app.get ( " /!<group_name> " )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 19:29:07 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def memberships ( v , group_name ) :
2024-11-08 19:23:37 +00:00
page = get_page ( )
2023-03-07 18:55:17 +00:00
group_name = group_name . strip ( ) . lower ( )
2023-03-16 06:27:58 +00:00
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-02-24 19:53:40 +00:00
2024-11-09 10:38:40 +00:00
members = g . db . query ( GroupMembership ) . join ( GroupMembership . user ) . options (
joinedload ( GroupMembership . user ) ,
joinedload ( GroupMembership . approver ) ,
) . filter (
GroupMembership . group_name == group_name ,
GroupMembership . approved_utc != None ,
GroupMembership . user_id != group . owner_id ,
)
2024-11-08 19:23:37 +00:00
total = members . count ( )
2024-11-08 19:38:21 +00:00
if page == 1 : size = 499
else : size = 500
members = members . order_by ( GroupMembership . is_mod . desc ( ) , GroupMembership . approved_utc ) . offset ( size * ( page - 1 ) ) . limit ( size ) . all ( )
2024-11-08 19:23:37 +00:00
if page == 1 :
2024-11-09 10:38:40 +00:00
owner = [ g . db . query ( GroupMembership ) . options (
joinedload ( GroupMembership . user ) ,
joinedload ( GroupMembership . approver ) ,
) . filter (
2024-11-08 19:23:37 +00:00
GroupMembership . group_name == group_name ,
GroupMembership . approved_utc != None ,
GroupMembership . user_id == group . owner_id ,
) . one ( ) ]
members = owner + members
2023-02-24 19:53:40 +00:00
2023-03-16 06:27:58 +00:00
applications = g . db . query ( GroupMembership ) . filter (
2023-02-25 21:44:02 +00:00
GroupMembership . group_name == group_name ,
GroupMembership . approved_utc == None
) . order_by ( GroupMembership . created_utc ) . all ( )
2024-11-09 10:43:14 +00:00
return render_template ( ' group_memberships.html ' , v = v , group = group , members = members , applications = applications , page = page , total = total , size = size )
2023-02-24 06:31:06 +00:00
@app.post ( " /!<group_name>/<user_id>/approve " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 06:31:06 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def group_approve ( v , group_name , user_id ) :
2023-03-07 18:55:17 +00:00
group_name = group_name . strip ( ) . lower ( )
2023-03-16 06:27:58 +00:00
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-05-05 21:45:25 +00:00
2023-08-08 18:08:29 +00:00
if not v . mods_group ( group ) :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only the group owner and its mods can approve applications! " )
2023-05-05 21:45:25 +00:00
2023-03-16 06:27:58 +00:00
application = g . db . query ( GroupMembership ) . filter_by ( user_id = user_id , group_name = group . name ) . one_or_none ( )
2023-02-24 06:31:06 +00:00
if not application :
2024-08-11 20:11:04 +00:00
stop ( 404 , " There is no application to approve! " )
2023-02-24 06:31:06 +00:00
2023-12-07 18:45:19 +00:00
if not application . approved_utc :
2023-02-24 06:31:06 +00:00
application . approved_utc = time . time ( )
2024-10-16 05:08:17 +00:00
application . approver_id = v . id
2023-03-16 06:27:58 +00:00
g . db . add ( application )
2023-12-07 18:45:19 +00:00
if v . id != application . user_id :
2024-02-18 20:46:43 +00:00
send_repeatable_notification ( application . user_id , f " @ { v . username } has approved your application to ! { group } " )
2023-02-24 06:31:06 +00:00
2023-02-24 19:41:25 +00:00
return { " message " : f ' You have approved @ { application . user . username } successfully! ' }
2023-02-24 06:31:06 +00:00
@app.post ( " /!<group_name>/<user_id>/reject " )
2023-02-27 05:33:45 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath )
2023-04-02 06:52:26 +00:00
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
2023-07-13 13:50:46 +00:00
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
2023-02-24 06:31:06 +00:00
@auth_required
2023-07-30 00:42:06 +00:00
def group_reject ( v , group_name , user_id ) :
2023-03-07 18:55:17 +00:00
group_name = group_name . strip ( ) . lower ( )
2023-03-16 06:27:58 +00:00
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-05-05 21:45:25 +00:00
2023-08-08 18:08:29 +00:00
if not v . mods_group ( group ) :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only the group owner and its mods can reject memberships! " )
2023-02-24 19:41:25 +00:00
2023-03-16 06:27:58 +00:00
membership = g . db . query ( GroupMembership ) . filter_by ( user_id = user_id , group_name = group . name ) . one_or_none ( )
2023-02-24 19:41:25 +00:00
if not membership :
2024-08-11 20:11:04 +00:00
stop ( 404 , " There is no membership to reject! " )
2024-10-16 23:00:39 +00:00
uid = membership . user_id
2023-02-24 06:31:06 +00:00
2024-10-16 06:22:18 +00:00
if membership . user_id == group . owner_id and v . admin_level < PERMS [ " MODS_EVERY_GROUP " ] :
stop ( 403 , " You can ' t kick the group owner! " )
2023-12-06 20:54:42 +00:00
2024-10-16 06:22:18 +00:00
if v . id != group . owner_id and membership . is_mod and v . admin_level < PERMS [ " MODS_EVERY_GROUP " ] :
stop ( 403 , " Only the group owner can kick mods! " )
2023-08-10 10:17:27 +00:00
2024-10-16 06:22:18 +00:00
if membership . approved_utc :
text = f " @ { v . username } has kicked you from ! { group } "
msg = f " You have kicked @ { membership . user . username } successfully! "
2023-02-24 19:41:25 +00:00
else :
2024-10-16 06:22:18 +00:00
text = f " @ { v . username } has rejected your application to ! { group } "
msg = f " You have rejected @ { membership . user . username } successfully! "
send_repeatable_notification ( membership . user_id , text )
2023-02-24 19:41:25 +00:00
2024-09-28 10:51:05 +00:00
if membership . user_id == group . owner_id :
new_owner_id = g . db . query ( GroupMembership . user_id ) . filter (
GroupMembership . user_id != group . owner_id ,
GroupMembership . group_name == group . name ,
GroupMembership . approved_utc != None ,
2024-10-07 16:16:34 +00:00
) . order_by ( GroupMembership . is_mod . desc ( ) , GroupMembership . approved_utc ) . first ( )
2024-09-28 10:51:05 +00:00
if new_owner_id :
2024-10-07 16:16:34 +00:00
new_owner_id = new_owner_id [ 0 ]
2024-10-16 06:22:18 +00:00
send_repeatable_notification ( new_owner_id , f " @ { group . owner . username } (! { group } ' s owner) has been kicked from the group by site admins, You ' re now the new owner! " )
2024-09-28 10:51:05 +00:00
group . owner_id = new_owner_id
g . db . add ( group )
2024-11-09 20:28:24 +00:00
else :
return delete_group ( membership , group , v )
2024-09-28 10:51:05 +00:00
2023-03-16 06:27:58 +00:00
g . db . delete ( membership )
2023-02-24 19:43:27 +00:00
2024-11-09 20:28:24 +00:00
if v . id != uid :
2024-10-16 23:00:39 +00:00
group_blacklist = GroupBlacklist (
user_id = uid ,
group_name = group . name ,
blacklister_id = v . id ,
)
g . db . add ( group_blacklist )
2023-02-24 19:41:25 +00:00
return { " message " : msg }
2023-08-08 18:08:29 +00:00
@app.post ( " /!<group_name>/<user_id>/add_mod " )
@limiter.limit ( ' 1/second ' , scope = rpath )
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
@auth_required
def group_add_mod ( v , group_name , user_id ) :
group_name = group_name . strip ( ) . lower ( )
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-08-08 18:08:29 +00:00
2024-02-11 11:00:37 +00:00
if v . id != group . owner_id :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only the group owner (@ { group . owner . username } ) can add mods! " )
2023-08-08 18:08:29 +00:00
membership = g . db . query ( GroupMembership ) . filter_by ( user_id = user_id , group_name = group . name ) . one_or_none ( )
if not membership :
2024-08-11 20:11:04 +00:00
stop ( 404 , " The user is not a member of the group! " )
2023-08-08 18:08:29 +00:00
membership . is_mod = True
g . db . add ( membership )
send_repeatable_notification ( membership . user_id , f " @ { v . username } (! { group } ' s owner) has added you as a mod! " )
return { " message " : f ' You have added @ { membership . user . username } as a mod successfully! ' }
@app.post ( " /!<group_name>/<user_id>/remove_mod " )
@limiter.limit ( ' 1/second ' , scope = rpath )
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
@auth_required
def group_remove_mod ( v , group_name , user_id ) :
group_name = group_name . strip ( ) . lower ( )
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2023-08-08 18:08:29 +00:00
2024-02-11 11:00:37 +00:00
if v . id != group . owner_id :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only the group owner (@ { group . owner . username } ) can remove mods! " )
2023-08-08 18:08:29 +00:00
membership = g . db . query ( GroupMembership ) . filter_by ( user_id = user_id , group_name = group . name ) . one_or_none ( )
if not membership :
2024-08-11 20:11:04 +00:00
stop ( 404 , " The user is not a member of the group! " )
2023-08-08 18:08:29 +00:00
membership . is_mod = False
g . db . add ( membership )
send_repeatable_notification ( membership . user_id , f " @ { v . username } (! { group } ' s owner) has removed you as a mod! " )
return { " message " : f ' You have removed @ { membership . user . username } as a mod successfully! ' }
2024-02-11 11:31:46 +00:00
@app.post ( " /!<group_name>/usurp " )
@limiter.limit ( ' 1/second ' , scope = rpath )
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
@auth_required
def group_usurp ( v , group_name ) :
group_name = group_name . strip ( ) . lower ( )
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2024-02-11 11:31:46 +00:00
2024-02-15 22:17:04 +00:00
if v . mods_group ( group ) :
2024-11-09 20:12:30 +00:00
stop ( 403 , f " You ' re a mod of ! { group . name } and can ' t usurp it! " )
2024-02-15 22:17:04 +00:00
2024-02-11 11:31:46 +00:00
if not v . is_member_of_group ( group ) :
2024-08-11 20:11:04 +00:00
stop ( 403 , " Only members of groups can usurp them! " )
2024-02-11 11:31:46 +00:00
2024-02-18 21:57:20 +00:00
search_html = f ''' %</a> has % your application to <a href= " /! { group . name } " rel= " nofollow " >! { group . name } </a></p> '''
2024-07-26 19:34:54 +00:00
two_mo_ago = time . time ( ) - 86400 * 60
2024-02-18 21:57:20 +00:00
is_active = g . db . query ( Notification . created_utc ) . join ( Notification . comment ) . filter (
2024-07-26 19:34:54 +00:00
Notification . created_utc > two_mo_ago ,
2024-02-18 21:57:20 +00:00
Comment . author_id == AUTOJANNY_ID ,
Comment . parent_post == None ,
Comment . body_html . like ( search_html ) ,
2024-02-11 11:53:30 +00:00
) . first ( )
2024-02-11 11:57:17 +00:00
2024-07-26 19:34:54 +00:00
two_mo_old_applications = g . db . query ( GroupMembership . user_id ) . join ( GroupMembership . user ) . filter (
2024-02-18 23:09:09 +00:00
GroupMembership . group_name == group . name ,
GroupMembership . approved_utc == None ,
2024-07-26 19:34:54 +00:00
GroupMembership . created_utc < two_mo_ago ,
2024-07-24 01:23:35 +00:00
User . shadowbanned == None ,
2024-02-18 23:09:09 +00:00
) . first ( )
2024-07-26 19:34:54 +00:00
if is_active or not two_mo_old_applications :
send_notification ( group . owner_id , f " @ { v . username } has tried to usurp control of ! { group . name } from you and failed because you reviewed a membership application in the past 2 months! " )
2024-05-22 23:23:48 +00:00
g . db . commit ( )
2024-08-11 20:11:04 +00:00
stop ( 403 , " The current regime has reviewed a membership application in the past 2 months, so you can ' t usurp them! " )
2024-02-11 11:53:30 +00:00
2024-07-26 19:34:54 +00:00
send_repeatable_notification ( group . owner_id , f " @ { v . username } has usurped control of ! { group . name } from you. This was possible because you (and your mods) have spent more than 2 months not reviewing membership applications. Be active next time sweaty :!marseycheeky: " )
2024-02-11 11:31:46 +00:00
group . owner_id = v . id
g . db . add ( group )
return { " message " : f ' You have usurped control of ! { group . name } successfully! ' }
2024-02-13 13:00:58 +00:00
@app.post ( " /!<group_name>/description " )
@limiter.limit ( ' 1/second ' , scope = rpath )
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
@auth_required
def group_change_description ( v , group_name ) :
group_name = group_name . strip ( ) . lower ( )
group = g . db . get ( Group , group_name )
2024-08-11 20:11:04 +00:00
if not group : stop ( 404 )
2024-02-13 13:00:58 +00:00
if v . id != group . owner_id :
2024-08-11 20:11:04 +00:00
stop ( 403 , f " Only the group owner (@ { group . owner . username } ) can change the description! " )
2024-02-13 13:00:58 +00:00
description = request . values . get ( ' description ' )
if description :
description = description . strip ( )
2024-02-15 18:48:36 +00:00
if len ( description ) > 100 :
2024-08-11 20:11:04 +00:00
stop ( 400 , " New description is too long (max 100 characters) " )
2024-02-15 18:48:36 +00:00
2024-03-02 21:01:29 +00:00
description_html = filter_emojis_only ( description , link = True )
2024-02-15 19:01:40 +00:00
if len ( description_html ) > 1000 :
2024-08-11 20:11:04 +00:00
stop ( 400 , " Rendered description is too long! " )
2024-02-13 13:00:58 +00:00
else :
description = None
2024-02-15 18:48:36 +00:00
description_html = None
2024-02-13 13:00:58 +00:00
group . description = description
2024-02-15 18:48:36 +00:00
group . description_html = description_html
2024-02-13 13:00:58 +00:00
g . db . add ( group )
return { " message " : ' Description changed successfully! ' }
2024-10-16 23:00:39 +00:00
@app.post ( " /!<group_name>/<user_id>/unblacklist " )
@limiter.limit ( ' 1/second ' , scope = rpath )
@limiter.limit ( ' 1/second ' , scope = rpath , key_func = get_ID )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 )
@limiter.limit ( DEFAULT_RATELIMIT , deduct_when = lambda response : response . status_code < 400 , key_func = get_ID )
@auth_required
def group_unblacklist ( v , group_name , user_id ) :
group_name = group_name . strip ( ) . lower ( )
group = g . db . get ( Group , group_name )
if not group : stop ( 404 )
if not v . mods_group ( group ) :
stop ( 403 , " Only the group owner and its mods can unblacklist someone! " )
blacklist = g . db . query ( GroupBlacklist ) . filter_by ( user_id = user_id , group_name = group . name ) . one_or_none ( )
if not blacklist :
stop ( 404 , " This user is not blacklisted! " )
g . db . delete ( blacklist )
2024-10-16 23:25:50 +00:00
send_repeatable_notification ( user_id , f " @ { v . username } has unblacklisted you from ! { group } " )
2024-10-16 23:00:39 +00:00
u = get_account ( user_id )
return { " message " : f " @ { u . username } has been unblacklisted from ! { group } successfully! " }