2017-10-04 16:29:13 -04:00
import asyncio
2017-10-12 22:26:22 -04:00
import traceback as tb
2017-10-15 12:57:31 -04:00
from contextlib import suppress
2017-10-12 22:26:22 -04:00
2017-10-11 03:05:05 -04:00
import discord as d
2017-10-14 15:28:00 -04:00
from discord import errors as err
2017-10-04 16:29:13 -04:00
from discord . ext import commands
2017-10-12 22:26:22 -04:00
2017-10-04 16:29:13 -04:00
from misc import exceptions as exc
2017-10-12 22:26:22 -04:00
from misc import checks
2017-10-11 03:05:05 -04:00
from utils import utils as u
2017-10-12 22:26:22 -04:00
2017-10-04 16:29:13 -04:00
class Administration :
def __init__ ( self , bot ) :
self . bot = bot
2017-10-13 01:23:18 -04:00
self . RATE_LIMIT = 2.1
2017-10-11 03:05:05 -04:00
self . queue = asyncio . Queue ( )
2017-10-15 02:14:34 -04:00
self . deleting = False
2017-10-11 03:05:05 -04:00
2017-10-15 02:14:34 -04:00
if u . tasks [ ' auto_del ' ] :
for channel in u . tasks [ ' auto_del ' ] :
temp = self . bot . get_channel ( channel )
2017-10-16 18:50:27 -04:00
self . bot . loop . create_task ( self . queue_for_deletion ( temp ) )
print ( ' AUTO-DELETING : # {} ' . format ( temp . name ) )
2017-10-13 01:23:18 -04:00
self . bot . loop . create_task ( self . delete ( ) )
2017-10-15 02:14:34 -04:00
self . deleting = True
2017-10-11 03:05:05 -04:00
@commands.command ( name = ' ,prunefromguild ' , aliases = [ ' ,pfg ' , ' ,prunefromserver ' , ' ,pfs ' ] , brief = ' Prune a user \' s messages from the guild ' , description = ' about flag centers on message 50 of 101 messages \n \n pfg \ { user id \ } [before|after|about] [ \ { message id \ }] \n \n Example: \n pfg \ { user id \ } before \ { message id \ } ' )
2017-10-04 16:29:13 -04:00
@commands.is_owner ( )
2017-10-11 03:05:05 -04:00
@checks.del_ctx ( )
async def prune_all_user ( self , ctx , uid , when = None , reference = None ) :
def yes ( msg ) :
2017-10-14 21:52:21 -04:00
if msg . content . lower ( ) == ' y ' and msg . channel is ctx . channel and msg . author is ctx . author :
2017-10-11 03:05:05 -04:00
return True
2017-10-14 21:52:21 -04:00
elif msg . content . lower ( ) == ' n ' and msg . channel is ctx . channel and msg . author is ctx . author :
2017-10-11 03:05:05 -04:00
raise exc . CheckFail
else :
return False
2017-10-14 21:52:21 -04:00
channels = ctx . guild . text_channels
2017-10-11 03:05:05 -04:00
if reference is not None :
for channel in channels :
try :
ref = await channel . get_message ( reference )
2017-10-14 23:40:56 -04:00
2017-10-14 15:28:00 -04:00
except err . NotFound :
2017-10-11 03:05:05 -04:00
continue
2017-10-14 23:40:56 -04:00
2017-10-11 03:05:05 -04:00
history = [ ]
try :
2017-10-16 18:50:27 -04:00
pru_sent = await ctx . send ( ' ⏳ **Pruning** <@ {} >** \' s messages will take some time.** ' . format ( uid ) )
2017-10-11 03:05:05 -04:00
ch_sent = await ctx . send ( ' 🗄 **Caching channels...** ' )
if when is None :
for channel in channels :
history . extend ( await channel . history ( limit = None ) . flatten ( ) )
await ch_sent . edit ( content = ' 🗄 **Cached** ` {} / {} ` **channels.** ' . format ( channels . index ( channel ) + 1 , len ( channels ) ) )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-12 22:26:22 -04:00
elif when == ' before ' :
2017-10-11 03:05:05 -04:00
for channel in channels :
history . extend ( await channel . history ( limit = None , before = ref . created_at ) . flatten ( ) )
await ch_sent . edit ( content = ' 🗄 **Cached** ` {} / {} ` **channels.** ' . format ( channels . index ( channel ) + 1 , len ( channels ) ) )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 03:05:05 -04:00
elif when == ' after ' :
for channel in channels :
history . extend ( await channel . history ( limit = None , after = ref . created_at ) . flatten ( ) )
await ch_sent . edit ( content = ' 🗄 **Cached** ` {} / {} ` **channels.** ' . format ( channels . index ( channel ) + 1 , len ( channels ) ) )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 03:05:05 -04:00
elif when == ' about ' :
for channel in channels :
history . extend ( await channel . history ( limit = 101 , about = ref . created_at ) . flatten ( ) )
await ch_sent . edit ( content = ' 🗄 **Cached** ` {} / {} ` **channels.** ' . format ( channels . index ( channel ) + 1 , len ( channels ) ) )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 03:05:05 -04:00
history = [ message for message in history if message . author . id == int ( uid ) ]
2017-10-13 01:23:18 -04:00
est_sent = await ctx . send ( ' ⏱ **Estimated time to delete history:** ` {} m {} s` ' . format ( int ( self . RATE_LIMIT * len ( history ) / 60 ) , int ( self . RATE_LIMIT * len ( history ) % 60 ) ) )
2017-10-11 03:05:05 -04:00
cont_sent = await ctx . send ( ' {} **Continue?** `Y` or `N` ' . format ( ctx . author . mention ) )
await self . bot . wait_for ( ' message ' , check = yes , timeout = 60 )
await cont_sent . delete ( )
del_sent = await ctx . send ( ' 🗑 **Deleting messages...** ' )
for message in history :
2017-10-15 12:57:31 -04:00
with suppress ( err . NotFound ) :
2017-10-12 22:26:22 -04:00
await message . delete ( )
2017-10-11 03:05:05 -04:00
await del_sent . edit ( content = ' 🗑 **Deleted** ` {} / {} ` **messages.** ' . format ( history . index ( message ) + 1 , len ( history ) ) )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-14 21:52:21 -04:00
await del_sent . edit ( content = ' 🗑 ` {} ` **of** <@ {} >** \' s messages deleted from** {} **.** ' . format ( len ( history ) , uid , ctx . guild . name ) )
2017-10-14 23:40:56 -04:00
2017-10-16 18:50:27 -04:00
await ctx . message . add_reaction ( ' ✅ ' )
2017-10-11 03:05:05 -04:00
except exc . CheckFail :
2017-10-16 18:50:27 -04:00
await ctx . send ( ' **Deletion aborted.** ' , delete_after = 10 )
await ctx . message . add_reaction ( ' ❌ ' )
2017-10-14 23:40:56 -04:00
2017-10-11 03:05:05 -04:00
except TimeoutError :
2017-10-16 18:50:27 -04:00
await ctx . send ( ' **Deletion timed out.** ' , delete_after = 10 )
await ctx . message . add_reaction ( ' ❌ ' )
2017-10-11 03:05:05 -04:00
async def delete ( self ) :
2017-10-15 02:14:34 -04:00
while self . deleting :
2017-10-11 03:05:05 -04:00
message = await self . queue . get ( )
2017-10-13 01:23:18 -04:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-15 12:57:31 -04:00
with suppress ( err . NotFound ) :
2017-10-13 01:23:18 -04:00
if not message . pinned :
await message . delete ( )
2017-10-11 03:05:05 -04:00
2017-10-16 03:27:00 -04:00
print ( ' STOPPED : deleting ' )
2017-10-16 18:50:27 -04:00
async def queue_for_deletion ( self , channel ) :
2017-10-11 03:05:05 -04:00
def check ( msg ) :
2017-10-12 22:26:22 -04:00
if msg . content . lower ( ) == ' stop ' and msg . channel is channel and msg . author . guild_permissions . administrator :
2017-10-11 03:05:05 -04:00
raise exc . Abort
elif msg . channel is channel and not msg . pinned :
return True
2017-10-16 03:27:00 -04:00
return False
2017-10-11 03:05:05 -04:00
try :
2017-10-16 03:27:00 -04:00
async for message in channel . history ( limit = None ) :
2017-10-15 12:57:31 -04:00
if message . content . lower ( ) == ' stop ' and message . author . guild_permissions . administrator :
raise exc . Abort
2017-10-15 01:50:37 -04:00
if not message . pinned :
2017-10-15 01:49:10 -04:00
await self . queue . put ( message )
2017-10-13 01:23:18 -04:00
while not self . bot . is_closed ( ) :
2017-10-11 03:05:05 -04:00
message = await self . bot . wait_for ( ' message ' , check = check )
await self . queue . put ( message )
2017-10-14 23:40:56 -04:00
2017-10-11 03:05:05 -04:00
except exc . Abort :
2017-10-15 02:14:34 -04:00
u . tasks [ ' auto_del ' ] . remove ( channel . id )
2017-10-14 15:28:00 -04:00
u . dump ( u . tasks , ' cogs/tasks.pkl ' )
2017-10-15 02:14:34 -04:00
if not u . tasks [ ' auto_del ' ] :
self . deleting = False
2017-10-16 03:27:00 -04:00
print ( ' STOPPED : looping # {} ' . format ( channel . name ) )
2017-10-16 18:50:27 -04:00
await channel . send ( ' **Stopped queueing messages for deletion in** {} **.** ' . format ( channel . mention ) , delete_after = 5 )
2017-10-14 23:40:56 -04:00
2017-10-11 03:05:05 -04:00
@commands.command ( name = ' autodelete ' , aliases = [ ' autodel ' , ' ad ' ] )
@commands.has_permissions ( administrator = True )
@checks.del_ctx ( )
async def auto_delete ( self , ctx ) :
2017-10-11 11:08:18 -04:00
try :
2017-10-15 12:57:31 -04:00
if ctx . channel . id not in u . tasks [ ' auto_del ' ] :
u . tasks [ ' auto_del ' ] . append ( ctx . channel . id )
2017-10-14 15:28:00 -04:00
u . dump ( u . tasks , ' cogs/tasks.pkl ' )
2017-10-16 18:50:27 -04:00
self . bot . loop . create_task ( self . queue_for_deletion ( ctx . channel ) )
2017-10-15 02:14:34 -04:00
if not self . deleting :
self . bot . loop . create_task ( self . delete ( ) )
self . deleting = True
2017-10-16 18:50:27 -04:00
print ( ' AUTO-DELETING : # {} ' . format ( ctx . channel . name ) )
await ctx . send ( ' **Auto-deleting all messages in {} .** ' . format ( ctx . channel . mention ) , delete_after = 5 )
await ctx . message . add_reaction ( ' ✅ ' )
2017-10-12 22:26:22 -04:00
else :
raise exc . Exists
2017-10-14 23:40:56 -04:00
2017-10-12 22:26:22 -04:00
except exc . Exists :
2017-10-16 18:50:27 -04:00
await ctx . send ( ' **Already auto-deleting in {} .** Type `stop` to stop. ' . format ( ctx . channel . mention ) , delete_after = 10 )
await ctx . message . add_reaction ( ' ❌ ' )
2017-10-14 23:40:56 -04:00
@commands.command ( name = ' deletecommands ' , aliases = [ ' delcmds ' ] )
@commands.has_permissions ( administrator = True )
async def delete_commands ( self , ctx ) :
2017-10-15 12:57:31 -04:00
if ctx . guild . id not in u . settings [ ' del_ctx ' ] :
u . settings [ ' del_ctx ' ] . append ( ctx . guild . id )
2017-10-14 23:40:56 -04:00
else :
2017-10-15 12:57:31 -04:00
u . settings [ ' del_ctx ' ] . remove ( ctx . guild . id )
2017-10-14 23:40:56 -04:00
u . dump ( u . settings , ' settings.pkl ' )
2017-10-16 18:50:27 -04:00
await ctx . send ( ' **Delete command invocations:** ` {} ` ' . format ( ctx . guild . id in u . settings [ ' del_ctx ' ] ) )
await ctx . message . add_reaction ( ' ✅ ' )