1
0
Fork 0
mirror of https://github.com/myned/modufur.git synced 2024-12-24 22:27:28 +00:00

Merge branch 'dev'

This commit is contained in:
Myned 2018-01-14 02:17:45 -05:00
commit 1759b523ab
6 changed files with 111 additions and 72 deletions

1
.gitignore vendored
View file

@ -5,6 +5,7 @@
*.DS_Store *.DS_Store
*.pkl *.pkl
*.png *.png
*.bat
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

View file

@ -1195,7 +1195,7 @@ class MsG:
n += 1 n += 1
# Searches for and returns images from e621.net given tags when not blacklisted # Searches for and returns images from e621.net given tags when not blacklisted
@cmds.group(aliases=['e6', '6'], brief='e621 | NSFW', description='e621 | NSFW\nTag-based search for e621.net\n\nYou can only search 5 tags and 6 images at once for now.\ne6 [tags...] ([# of images])') @cmds.command(aliases=['e6', '6'], brief='e621 | NSFW', description='e621 | NSFW\nTag-based search for e621.net\n\nYou can only search 5 tags and 6 images at once for now.\ne6 [tags...] ([# of images])')
@checks.is_nsfw() @checks.is_nsfw()
async def e621(self, ctx, *args): async def e621(self, ctx, *args):
try: try:

View file

@ -6,6 +6,7 @@ from datetime import datetime as dt
import discord as d import discord as d
from discord import errors as err from discord import errors as err
from discord.ext import commands as cmds from discord.ext import commands as cmds
from discord.ext.commands import errors as errext
from misc import exceptions as exc from misc import exceptions as exc
from misc import checks from misc import checks
@ -28,7 +29,7 @@ class Administration:
self.deleting = True self.deleting = True
self.bot.loop.create_task(self.delete()) self.bot.loop.create_task(self.delete())
@cmds.group(aliases=['pru', 'clear', 'cl'], hidden=True) @cmds.group(aliases=['pru', 'purge', 'pur', 'clear', 'cl'], hidden=True)
@cmds.is_owner() @cmds.is_owner()
async def prune(self, ctx): async def prune(self, ctx):
pass pass
@ -37,81 +38,102 @@ class Administration:
async def _prune_user(self, ctx): async def _prune_user(self, ctx):
pass pass
@_prune_user.command(name='all', aliases=['a'], brief='Prune a user\'s messages from the guild', description='about flag centers on message 50 of 101 messages\n\npfg \{user id\} [before|after|about] [\{message id\}]\n\nExample:\npfg \{user id\} before \{message id\}', hidden=True) @_prune_user.command(name='channel', aliases=['channels', 'chans', 'chan', 'ch', 'c'])
@cmds.is_owner() async def _prune_user_channel(self, ctx, user: d.User, *channels: d.TextChannel):
async def _prune_user_all(self, ctx, user, when=None, reference=None): def confirm(r, u):
def yes(msg): if u is ctx.author:
if msg.content.lower() == 'y' and msg.channel is ctx.channel and msg.author is ctx.author: if r.emoji == '\N{OCTAGONAL SIGN}':
return True raise exc.Abort
elif msg.content.lower() == 'n' and msg.channel is ctx.channel and msg.author is ctx.author: if r.emoji == '\N{THUMBS UP SIGN}':
raise exc.CheckFail return True
else: return False
return False
channels = ctx.guild.text_channels if not channels:
if reference is not None: channels = [ctx.channel]
for channel in channels:
try:
ref = await channel.get_message(reference)
except err.NotFound:
continue
history = []
try: try:
pru_sent = await ctx.send('\N{HOURGLASS} **Pruning** <@{}>**\'s messages will take some time**'.format(user)) pruning = await ctx.send(f'\N{HOURGLASS} **Pruning** {user.mention}**\'s messages from** {"**,** ".join([channel.mention for channel in channels])} **might take some time.** Proceed, {ctx.author.mention}?')
ch_sent = await ctx.send('\N{FILE CABINET} **Caching channels...**') await pruning.add_reaction('\N{THUMBS UP SIGN}')
await pruning.add_reaction('\N{OCTAGONAL SIGN}')
await asyncio.sleep(1)
if when is None: await self.bot.wait_for('reaction_add', check=confirm, timeout=10 * 60)
for channel in channels:
async for message in channel.history(limit=None): deleting = await ctx.send(f'\N{WASTEBASKET} **Deleting** {user.mention}**\'s messages...**')
if message.author.id == int(user): await asyncio.sleep(1)
history.append(message)
await ch_sent.edit(content='\N{FILE CABINET} **Cached** `{}/{}` **channels**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(self.RATE_LIMIT)
elif when == 'before':
for channel in channels:
async for message in channel.history(limit=None, before=ref.created_at):
if message.author.id == int(user):
history.append(message)
await ch_sent.edit(content='\N{FILE CABINET} **Cached** `{}/{}` **channels**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(self.RATE_LIMIT)
elif when == 'after':
for channel in channels:
async for message in channel.history(limit=None, after=ref.created_at):
if message.author.id == int(user):
history.append(message)
await ch_sent.edit(content='\N{FILE CABINET} **Cached** `{}/{}` **channels**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(self.RATE_LIMIT)
elif when == 'about':
for channel in channels:
async for message in channel.history(limit=None, about=ref.created_at):
if message.author.id == int(user):
history.append(message)
await ch_sent.edit(content='\N{FILE CABINET} **Cached** `{}/{}` **channels**'.format(channels.index(channel) + 1, len(channels)))
await asyncio.sleep(self.RATE_LIMIT)
est_sent = await ctx.send('\N{STOPWATCH} **Estimated time to delete history:** `{}m {}s`'.format(int(self.RATE_LIMIT * len(history) / 60), int(self.RATE_LIMIT * len(history) % 60)))
cont_sent = await ctx.send('{} **Continue?** `Y` or `N`'.format(ctx.author.mention))
await self.bot.wait_for('message', check=yes, timeout=10 * 60)
await cont_sent.delete()
del_sent = await ctx.send('\N{WASTEBASKET} **Deleting messages..**')
await del_sent.pin()
c = 0 c = 0
for message in history: for channel in channels:
with suppress(err.NotFound): await deleting.edit(content=f'\N{WASTEBASKET} **Deleting** {user.mention}**\'s messages from** {channel.mention}')
await message.delete()
c += 1
await del_sent.edit(content='\N{WASTEBASKET} **Deleted** `{}/{}` **messages**'.format(history.index(message) + 1, len(history)))
await asyncio.sleep(self.RATE_LIMIT)
await del_sent.unpin()
await ctx.send('\N{WASTEBASKET} `{}` **of** <@{}>**\'s messages left in** {}****'.format(len(history) - c, user, ctx.guild.name)) deleted = await channel.purge(check=lambda m: m.author.id == user.id, before=pruning, limit=None)
c += len(deleted)
except exc.CheckFail: await asyncio.sleep(1)
for channel in channels:
missed = 0
async for message in channel.history(before=pruning, limit=None):
if message.author.id == user.id:
missed += 1
if missed > 0:
await ctx.send(f'\N{DOUBLE EXCLAMATION MARK} `{missed}` **messages were not deleted in** {channel.mention}')
await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**')
except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7) await ctx.send('**Deletion aborted**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')
except TimeoutError:
await ctx.send('**Deletion timed out**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
@_prune_user.command(name='all', aliases=['a'], brief='Prune a user\'s messages from the guild', description='about flag centers on message 50 of 101 messages\n\npfg \{user id\} [before|after|about] [\{message id\}]\n\nExample:\npfg \{user id\} before \{message id\}', hidden=True)
@cmds.is_owner()
async def _prune_user_all(self, ctx, user: d.User):
def confirm(r, u):
if u is ctx.author:
if r.emoji == '\N{OCTAGONAL SIGN}':
raise exc.Abort
if r.emoji == '\N{THUMBS UP SIGN}':
return True
return False
try:
pruning = await ctx.send(f'\N{HOURGLASS} **Pruning** {user.mention}**\'s messages might take some time.** Proceed, {ctx.author.mention}?')
await pruning.add_reaction('\N{THUMBS UP SIGN}')
await pruning.add_reaction('\N{OCTAGONAL SIGN}')
await asyncio.sleep(1)
await self.bot.wait_for('reaction_add', check=confirm, timeout=10 * 60)
deleting = await ctx.send(f'\N{WASTEBASKET} **Deleting** {user.mention}**\'s messages...**')
await asyncio.sleep(1)
c = 0
for channel in ctx.guild.text_channels:
await deleting.edit(content=f'\N{WASTEBASKET} **Deleting** {user.mention}**\'s messages from** {channel.mention}')
deleted = await channel.purge(check=lambda m: m.author.id == user.id, before=pruning, limit=None)
c += len(deleted)
await asyncio.sleep(1)
for channel in ctx.guild.text_channels:
missed = 0
async for message in channel.history(before=pruning, limit=None):
if message.author.id == user.id:
missed += 1
if missed > 0:
await ctx.send(f'\N{DOUBLE EXCLAMATION MARK} `{missed}` **messages were not deleted in** {channel.mention}')
await ctx.send(f'\N{WHITE HEAVY CHECK MARK} **Finished deleting** `{c}` **of** {user.mention}**\'s messages**')
except exc.Abort:
await ctx.send('**Deletion aborted**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
except TimeoutError: except TimeoutError:
await ctx.send('**Deletion timed out**', delete_after=7) await ctx.send('**Deletion timed out**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}') await ctx.message.add_reaction('\N{CROSS MARK}')

View file

@ -69,6 +69,17 @@ class Bot:
await ctx.send('https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}'.format(u.config['client_id'], u.config['permissions']), delete_after=5) await ctx.send('https://discordapp.com/oauth2/authorize?&client_id={}&scope=bot&permissions={}'.format(u.config['client_id'], u.config['permissions']), delete_after=5)
@cmds.command(name=',guilds', aliases=[',glds', ',servers', ',servs'])
@cmds.is_owner()
async def guilds(self, ctx):
paginator = cmds.Paginator()
for guild in self.bot.guilds:
paginator.add_line(guild.name)
for page in paginator.pages:
await ctx.send(f'**Guilds:**\n{page}')
@cmds.command(name=',status', aliases=[',presence', ',game'], hidden=True) @cmds.command(name=',status', aliases=[',presence', ',game'], hidden=True)
@cmds.is_owner() @cmds.is_owner()
async def change_status(self, ctx, *, game=None): async def change_status(self, ctx, *, game=None):
@ -192,7 +203,7 @@ class Tools:
finally: finally:
sys.stdout = sys.__stdout__ sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__ sys.stderr = sys.__stderr__
print('Reset sys output.') print('RESET : sys.std output/error')
@cmds.command(name=',execute', aliases=[',exec'], hidden=True) @cmds.command(name=',execute', aliases=[',exec'], hidden=True)
@cmds.is_owner() @cmds.is_owner()

View file

@ -62,7 +62,7 @@ bot = cmds.Bot(command_prefix=get_prefix, self_bot=u.config['selfbot'], formatte
@bot.command(help='help', brief='brief', description='description', usage='usage', hidden=True) @bot.command(help='help', brief='brief', description='description', usage='usage', hidden=True)
async def test(ctx): async def test(ctx):
pass await ctx.send('test')
# Send and print ready message to #testing and console after logon # Send and print ready message to #testing and console after logon
@ -143,8 +143,14 @@ async def on_error(error, *args, **kwargs):
async def on_command_error(ctx, error): async def on_command_error(ctx, error):
if isinstance(error, err.NotFound): if isinstance(error, err.NotFound):
print('NOT FOUND') print('NOT FOUND')
elif isinstance(error, errext.MissingRequiredArgument):
await ctx.send('**Missing required argument**', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
elif isinstance(error, errext.BadArgument):
await ctx.send(f'**Invalid argument.** {error}', delete_after=7)
await ctx.message.add_reaction('\N{CROSS MARK}')
elif isinstance(error, errext.CheckFailure): elif isinstance(error, errext.CheckFailure):
await ctx.send('**Insufficient permissions**', delete_after=10) await ctx.send('**Insufficient permissions**', delete_after=7)
await ctx.message.add_reaction('\N{NO ENTRY}') await ctx.message.add_reaction('\N{NO ENTRY}')
elif isinstance(error, errext.CommandNotFound): elif isinstance(error, errext.CommandNotFound):
print('INVALID COMMAND : {}'.format(error), file=sys.stderr) print('INVALID COMMAND : {}'.format(error), file=sys.stderr)

View file

@ -33,8 +33,7 @@ except FileNotFoundError:
with open('config.json', 'w') as outfile: with open('config.json', 'w') as outfile:
jsn.dump({'client_id': 0, 'info_channel': 0, 'owner_id': 0, 'permissions': 126016, jsn.dump({'client_id': 0, 'info_channel': 0, 'owner_id': 0, 'permissions': 126016,
'playing': 'a game', 'prefix': [',', 'm,'], 'selfbot': False, 'token': 'str'}, outfile, indent=4, sort_keys=True) 'playing': 'a game', 'prefix': [',', 'm,'], 'selfbot': False, 'token': 'str'}, outfile, indent=4, sort_keys=True)
raise FileNotFoundError( print('FILE NOT FOUND : config.json created with abstract values. Restart run.py with correct values')
'FILE NOT FOUND : config.json created with abstract values. Restart run.py with correct values')
def setdefault(filename, default=None, json=False): def setdefault(filename, default=None, json=False):
@ -94,7 +93,7 @@ last_commands = {}
async def fetch(url, *, params={}, json=False, response=False): async def fetch(url, *, params={}, json=False, response=False):
async with session.get(url, params=params, headers={'User-Agent': 'Myned/Modumind'}) as r: async with session.get(url, params=params, headers={'User-Agent': 'Myned/Modufur'}) as r:
if response: if response:
return r return r
elif json: elif json: