2017-10-04 20:29:13 +00:00
import asyncio
2017-10-13 02:26:22 +00:00
import traceback as tb
2017-10-11 07:05:05 +00:00
import discord as d
2017-10-14 19:28:00 +00:00
from discord import errors as err
2017-10-04 20:29:13 +00:00
from discord . ext import commands
2017-10-13 02:26:22 +00:00
2017-10-04 20:29:13 +00:00
from misc import exceptions as exc
2017-10-13 02:26:22 +00:00
from misc import checks
2017-10-11 07:05:05 +00:00
from utils import utils as u
2017-10-13 02:26:22 +00:00
2017-10-04 20:29:13 +00:00
class Administration :
def __init__ ( self , bot ) :
self . bot = bot
2017-10-13 05:23:18 +00:00
self . RATE_LIMIT = 2.1
2017-10-11 07:05:05 +00:00
self . queue = asyncio . Queue ( )
2017-10-13 05:23:18 +00:00
for channel in u . tasks . get ( ' management ' , { } ) . get ( ' auto_delete ' , [ ] ) :
temp = self . bot . get_channel ( channel )
self . bot . loop . create_task ( self . on_message ( temp ) )
self . bot . loop . create_task ( self . delete ( ) )
print ( ' Looping # {} ' . format ( temp . name ) )
2017-10-11 07:05:05 +00:00
# @commands.group(aliases=['pr', 'clear', 'cl'])
# @commands.is_owner()
# @checks.del_ctx()
# async def prune(self, ctx):
# pass
#
# @prune.group(name='all', aliases=['a'])
# async def _all(self, ctx):
# pass
# @_all.group(name='user')
# async def __user(self, ctx, user: d.Member):
# channels = ctx.message.guild.text_channels
# bulk_history = {}
# bulk = {}
# history = []
# c = 0
# if ctx.invoked_subcommand is None:
# for channel in channels:
# bulk_history[channel] = await channel.history(limit=None, after=dt.datetime.utcnow() - dt.timedelta(days=14)).flatten()
# await ch_sent.edit(content='🗄 **Cached** `' + str(channels.index(channel) + 1) + '/' + str(len(channels)) + '` **channels.**')
2017-10-13 05:23:18 +00:00
# await asyncio.sleep(self.RATE_LIMIT)
2017-10-11 07:05:05 +00:00
# for channel, messages in bulk_history.items():
# bulk[channel] = [message for message in messages if message.author.id == int(uid)]
# for channel, messages in bulk_history.items():
# bulk[channel] = [bulk[channel][i:i+100] for i in range(0, len(bulk[channel]), 100)]
2017-10-13 05:23:18 +00:00
# await ctx.send('⏱ **Estimated time to delete `bulk-history`:** `' + str(int(self.RATE_LIMIT * sum([len(v) for v in bulk.values()]) / 60)) + ' mins ' + str(int(self.RATE_LIMIT * sum([len(v) for v in bulk.values()]) % 60)) + ' secs`')
2017-10-11 07:05:05 +00:00
# check = await ctx.send(ctx.author.mention + ' **Continue?** `Y` or `N`')
# await self.bot.wait_for('message', check=yes, timeout=60)
# del_sent = await ctx.send('🗑 **Deleting messages...**')
# for channel, messages in bulk.items():
# for chunk in messages:
# c += len(chunk)
# await channel.delete_messages(chunk)
# await del_sent.edit(content='🗑 **Deleted** `' + str(c) + '/' + str(sum([len(v) for v in bulk.values()])) + '` **messages.**')
# await asyncio.sleep(5)
# await ctx.send('✅ `' + str(sum([len(v) for v in bulk.values()])) + '` **of** <@' + uid + '>**\'s messages deleted from** ' + ctx.message.guild.name + '**.**')
# for channel in channels:
# history.extend(await channel.history(limit=None, before=dt.datetime.utcnow() - dt.timedelta(days=14)).flatten())
# await ch_sent.edit(content='🗄 **Cached** `' + str(channels.index(channel) + 1) + '/' + str(len(channels)) + '` **channels.**')
2017-10-13 05:23:18 +00:00
# await asyncio.sleep(self.RATE_LIMIT)
2017-10-04 20:29:13 +00:00
2017-10-11 07:05:05 +00: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 20:29:13 +00:00
@commands.is_owner ( )
2017-10-11 07:05:05 +00:00
@checks.del_ctx ( )
async def prune_all_user ( self , ctx , uid , when = None , reference = None ) :
def yes ( msg ) :
if msg . content . lower ( ) == ' y ' and msg . channel is ctx . message . channel and msg . author is ctx . message . author :
return True
elif msg . content . lower ( ) == ' n ' and msg . channel is ctx . message . channel and msg . author is ctx . message . author :
raise exc . CheckFail
else :
return False
channels = ctx . message . guild . text_channels
if reference is not None :
for channel in channels :
try :
ref = await channel . get_message ( reference )
2017-10-14 19:28:00 +00:00
except err . NotFound :
2017-10-11 07:05:05 +00:00
continue
history = [ ]
try :
pru_sent = await ctx . send ( ' ⌛️ **Pruning** <@ {} >** \' s messages will take some time.** ' . format ( uid ) )
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 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-13 02:26:22 +00:00
elif when == ' before ' :
2017-10-11 07:05:05 +00: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 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 07:05:05 +00: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 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 07:05:05 +00: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 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 07:05:05 +00:00
history = [ message for message in history if message . author . id == int ( uid ) ]
2017-10-13 05:23:18 +00: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 07:05:05 +00: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-13 02:26:22 +00:00
try :
await message . delete ( )
except d . NotFound :
pass
2017-10-11 07:05:05 +00:00
# print('Deleted {}/{} messages.'.format(history.index(message) + 1, len(history)))
await del_sent . edit ( content = ' 🗑 **Deleted** ` {} / {} ` **messages.** ' . format ( history . index ( message ) + 1 , len ( history ) ) )
2017-10-13 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-11 07:05:05 +00:00
await del_sent . edit ( content = ' 🗑 ` {} ` **of** <@ {} >** \' s messages deleted from** {} **.** ' . format ( len ( history ) , uid , ctx . message . guild . name ) )
except exc . CheckFail :
await ctx . send ( ' ❌ **Deletion aborted.** ' , delete_after = 10 )
except TimeoutError :
await ctx . send ( ' ❌ **Deletion timed out.** ' , delete_after = 10 )
async def delete ( self ) :
2017-10-13 05:23:18 +00:00
while not self . bot . is_closed ( ) :
2017-10-11 07:05:05 +00:00
message = await self . queue . get ( )
2017-10-13 05:23:18 +00:00
await asyncio . sleep ( self . RATE_LIMIT )
2017-10-13 02:26:22 +00:00
try :
2017-10-13 05:23:18 +00:00
if not message . pinned :
await message . delete ( )
2017-10-14 19:28:00 +00:00
except err . NotFound :
2017-10-13 02:26:22 +00:00
pass
2017-10-11 07:05:05 +00:00
async def on_message ( self , channel ) :
def check ( msg ) :
2017-10-13 02:26:22 +00:00
if msg . content . lower ( ) == ' stop ' and msg . channel is channel and msg . author . guild_permissions . administrator :
2017-10-11 07:05:05 +00:00
raise exc . Abort
elif msg . channel is channel and not msg . pinned :
return True
else :
return False
try :
2017-10-13 05:23:18 +00:00
while not self . bot . is_closed ( ) :
2017-10-11 07:05:05 +00:00
message = await self . bot . wait_for ( ' message ' , check = check )
await self . queue . put ( message )
except exc . Abort :
2017-10-13 05:23:18 +00:00
u . tasks [ ' management ' ] [ ' auto_delete ' ] . remove ( channel . id )
2017-10-14 19:28:00 +00:00
u . dump ( u . tasks , ' cogs/tasks.pkl ' )
2017-10-11 07:05:05 +00:00
print ( ' Stopped looping {} ' . format ( channel . id ) )
await channel . send ( ' ✅ **Stopped deleting messages in** {} **.** ' . format ( channel . mention ) , delete_after = 5 )
except AttributeError :
pass
@commands.command ( name = ' autodelete ' , aliases = [ ' autodel ' , ' ad ' ] )
@commands.has_permissions ( administrator = True )
@checks.del_ctx ( )
async def auto_delete ( self , ctx ) :
channel = ctx . message . channel
2017-10-11 15:08:18 +00:00
try :
2017-10-13 05:23:18 +00:00
if channel . id not in u . tasks . setdefault ( ' management ' , { } ) . setdefault ( ' auto_delete ' , [ ] ) :
u . tasks [ ' management ' ] [ ' auto_delete ' ] . append ( channel . id )
2017-10-14 19:28:00 +00:00
u . dump ( u . tasks , ' cogs/tasks.pkl ' )
2017-10-11 15:08:18 +00:00
self . bot . loop . create_task ( self . on_message ( channel ) )
self . bot . loop . create_task ( self . delete ( ) )
2017-10-13 05:23:18 +00:00
print ( ' Looping # {} ' . format ( channel . name ) )
2017-10-11 15:08:18 +00:00
await ctx . send ( ' ✅ **Auto-deleting all messages in this channel.** ' , delete_after = 5 )
2017-10-13 02:26:22 +00:00
else :
raise exc . Exists
except exc . Exists :
await ctx . send ( ' ❌ **Already auto-deleting in this channel.** Type `stop` to stop. ' , delete_after = 10 )