mirror of
https://github.com/myned/modufur.git
synced 2024-12-24 14:27:27 +00:00
File map update
This commit is contained in:
parent
91b86ca3ed
commit
9f487cb57c
6 changed files with 2361 additions and 2358 deletions
3
Pipfile
3
Pipfile
|
@ -4,6 +4,8 @@ url = "https://pypi.python.org/simple"
|
|||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[requires]
|
||||
python_version = "3.6"
|
||||
|
||||
[packages]
|
||||
|
||||
|
@ -25,4 +27,3 @@ pynacl = "*"
|
|||
|
||||
|
||||
[dev-packages]
|
||||
|
||||
|
|
52
Pipfile.lock
generated
52
Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "19fd84259fea739bf9a47e9ea60f364a06fd636ae4eaf50d40683569f9830f7e"
|
||||
"sha256": "c8426f63f07b00a7dcc5220e1210acfc6279bb1eccb40d9a884d34e203bf8f85"
|
||||
},
|
||||
"host-environment-markers": {
|
||||
"implementation_name": "cpython",
|
||||
|
@ -17,7 +17,9 @@
|
|||
"sys_platform": "darwin"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
"requires": {
|
||||
"python_version": "3.6"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
|
@ -29,30 +31,23 @@
|
|||
"default": {
|
||||
"aiohttp": {
|
||||
"hashes": [
|
||||
"sha256:834f687b806fbf49cb135b5a208b5c27338e19c219d6e09e9049936e01e8bea8",
|
||||
"sha256:6b8c5a00432b8a5a083792006e8fdfb558b8b10019ce254200855264d3a25895",
|
||||
"sha256:7b407c22b0ab473ffe0a7d3231f2084a8ae80fdb64a31842b88d57d6b7bdab7c",
|
||||
"sha256:14821eb8613bfab9118be3c55afc87bf4cef97689896fa0874c6877b117afbeb",
|
||||
"sha256:8f32a4e157bad9c60ebc38c3bb93fcc907a020b017ddf8f7ab1580390e21940e",
|
||||
"sha256:82a9068d9cb15eb2d99ecf39f8d56b4ed9f931a77a3622a0de747465fd2a7b96",
|
||||
"sha256:7ac6378ae364d8e5e5260c7224ea4a1965cb6f4719f15d0552349d0b0cc93953",
|
||||
"sha256:5a952d4af7de5f78dfb3206dbc352717890b37d447f0bbd4b5969b3c8bb713af",
|
||||
"sha256:b25c7720c495048ed658086a29925ab485ac7ececf1b346f2b459e5431d85016",
|
||||
"sha256:528b0b811b6260a79222b055664b82093d01f35fe5c82521d8659cb2b28b8044",
|
||||
"sha256:46ace48789865a89992419205024ae451d577876f9919fbb0f22f71189822dea",
|
||||
"sha256:5436ca0ed752bb05a399fc07dc86dc23c756db523a3b7d5da46a457eacf4c4b5",
|
||||
"sha256:f5e7d41d924a1d5274060c467539ee0c4f3bab318c1671ad65abd91f6b637baf",
|
||||
"sha256:a8c12f3184c7cad8f66cae6c945d2c97e598b0cb7afd655a5b9471475e67f30e",
|
||||
"sha256:756fc336a29c551b02252685f01bc87116bc9b04bbd02c1a6b8a96b3c6ad713b",
|
||||
"sha256:cf790e61c2af0278f39dcedad9a22532bf81fb029c2cd73b1ceba7bea062c908",
|
||||
"sha256:44c9cf24e63576244c13265ef0786b56d6751f5fb722225ecc021d6ecf91b4d2",
|
||||
"sha256:ef1a36a16e72b6689ce0a6c7fc6bd88837d8fef4590b16bd72817644ae1f414d",
|
||||
"sha256:3a4cdb9ca87c099d8ba5eb91cb8f000b60c21f8c1b50c75e04e8777e903bd278",
|
||||
"sha256:f72bb19cece43483171264584bbaaf8b97717d9c0f244d1ef4a51df1cdb34085",
|
||||
"sha256:c77e29243a79e376a1b51d71a13df4a61bc54fd4d9597ce3790b8d82ec6eb44d",
|
||||
"sha256:8adda6583ba438a4c70693374e10b60168663ffa6564c5c75d3c7a9055290964"
|
||||
"sha256:2e8be4c46083ced9d9bc9ff4d77f31bfcd3e7486613f6138c5aa302d33ea54ed",
|
||||
"sha256:4634dd3bbb68d0c7e5e4bca7571369d53c497b3300d9d678f939038e1b1231ee",
|
||||
"sha256:25825c61688fc95e09d6be19e513e925cb4f08aae4d7a7c38a1fa75e0e4c22bd",
|
||||
"sha256:9e6d6f0bca955923b515f8b5631c4c4f43aa152763852284cbefc89bd544069e",
|
||||
"sha256:6eef1d7eff9e6fa1029f7a62504f88b2b0afce89ced5c95d3a4cf1c2faef1231",
|
||||
"sha256:040eecbc37aa5bd007108388fab6c42b2a01b964c4feac26bdffc8fe8af6c110",
|
||||
"sha256:53988a8cf76c3fb74a759e77b1c2f55ab36880d57c6e7d0d59ad28743a2535fe",
|
||||
"sha256:d51673140330c660e68c182e14164ddba47810dca873bbd28662f31d7d8c0185",
|
||||
"sha256:2fe26e836a1803c7414613c376fe29fc4ae0e5145e3813e1db1854cb05c91a3c",
|
||||
"sha256:15ad4d76bddfd98bf9e48263c70f6603e96d823c5a5c0c842646e9871be72c64",
|
||||
"sha256:7910089093296b5c8f683965044f553b0c5c9c2dbf310a219db76c6e793fea55",
|
||||
"sha256:a19b96f77763ddf0249420438ebfc4d9a470daeb26f6614366d913ff520fa29b",
|
||||
"sha256:b53bc7b44b1115af50bd18d9671972603e5a4934e98dd3f4d671104c070e331d",
|
||||
"sha256:4b6fa00885ec778154244b010acecb862d277e6652b87fcd85c0f4735d26451c",
|
||||
"sha256:7aee5c0750584946fde40da70f0b28fe769f85182f1171acef18a35fd8ecd221"
|
||||
],
|
||||
"version": "==2.3.10"
|
||||
"version": "==3.0.1"
|
||||
},
|
||||
"appdirs": {
|
||||
"hashes": [
|
||||
|
@ -68,6 +63,13 @@
|
|||
],
|
||||
"version": "==2.0.0"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
|
||||
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
|
||||
],
|
||||
"version": "==17.4.0"
|
||||
},
|
||||
"beautifulsoup4": {
|
||||
"hashes": [
|
||||
"sha256:7015e76bf32f1f574636c4288399a6de66ce08fb7b2457f628a8d70c0fbabb11",
|
||||
|
|
3322
src/cogs/booru.py
3322
src/cogs/booru.py
File diff suppressed because it is too large
Load diff
|
@ -1,235 +1,235 @@
|
|||
import asyncio
|
||||
import traceback as tb
|
||||
from contextlib import suppress
|
||||
from datetime import datetime as dt
|
||||
|
||||
import discord as d
|
||||
from discord import errors as err
|
||||
from discord.ext import commands as cmds
|
||||
from discord.ext.commands import errors as errext
|
||||
|
||||
from misc import exceptions as exc
|
||||
from misc import checks
|
||||
from utils import utils as u
|
||||
|
||||
|
||||
class Administration:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.RATE_LIMIT = u.RATE_LIMIT
|
||||
self.queue = asyncio.Queue()
|
||||
self.deleting = False
|
||||
|
||||
if u.tasks['auto_del']:
|
||||
for channel in u.tasks['auto_del']:
|
||||
temp = self.bot.get_channel(channel)
|
||||
self.bot.loop.create_task(self.queue_for_deletion(temp))
|
||||
print('STARTED : auto-deleting in #{}'.format(temp.name))
|
||||
self.deleting = True
|
||||
self.bot.loop.create_task(self.delete())
|
||||
|
||||
@cmds.group(aliases=['pru', 'purge', 'pur', 'clear', 'cl'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def prune(self, ctx):
|
||||
pass
|
||||
|
||||
@prune.group(name='user', aliases=['u', 'member', 'm'])
|
||||
async def _prune_user(self, ctx):
|
||||
pass
|
||||
|
||||
@_prune_user.command(name='channel', aliases=['channels', 'chans', 'chan', 'ch', 'c'])
|
||||
async def _prune_user_channel(self, ctx, user: d.User, *channels: d.TextChannel):
|
||||
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
|
||||
|
||||
if not channels:
|
||||
channels = [ctx.channel]
|
||||
|
||||
try:
|
||||
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}?')
|
||||
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 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 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:
|
||||
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:
|
||||
await ctx.send('**Deletion timed out**', delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
@cmds.group(aliases=['task', 'tsk'])
|
||||
async def tasks(self):
|
||||
pass
|
||||
|
||||
async def delete(self):
|
||||
while self.deleting:
|
||||
message = await self.queue.get()
|
||||
await asyncio.sleep(self.RATE_LIMIT)
|
||||
with suppress(err.NotFound):
|
||||
if not message.pinned:
|
||||
await message.delete()
|
||||
|
||||
print('STOPPED : deleting')
|
||||
|
||||
async def queue_for_deletion(self, channel):
|
||||
def check(msg):
|
||||
if 'stop d' in msg.content.lower() and msg.channel is channel and msg.author.guild_permissions.administrator:
|
||||
raise exc.Abort
|
||||
elif msg.channel is channel and not msg.pinned:
|
||||
return True
|
||||
return False
|
||||
|
||||
try:
|
||||
async for message in channel.history(limit=None):
|
||||
if 'stop d' in message.content.lower() and message.author.guild_permissions.administrator:
|
||||
raise exc.Abort
|
||||
if not message.pinned:
|
||||
await self.queue.put(message)
|
||||
|
||||
while not self.bot.is_closed():
|
||||
message = await self.bot.wait_for('message', check=check)
|
||||
await self.queue.put(message)
|
||||
|
||||
except exc.Abort:
|
||||
u.tasks['auto_del'].remove(channel.id)
|
||||
u.dump(u.tasks, 'cogs/tasks.pkl')
|
||||
if not u.tasks['auto_del']:
|
||||
self.deleting = False
|
||||
print('STOPPED : deleting #{}'.format(channel.name))
|
||||
await channel.send('**Stopped queueing messages for deletion in** {}'.format(channel.mention), delete_after=5)
|
||||
|
||||
@cmds.command(name='autodelete', aliases=['autodel'])
|
||||
@cmds.has_permissions(administrator=True)
|
||||
async def auto_delete(self, ctx):
|
||||
try:
|
||||
if ctx.channel.id not in u.tasks['auto_del']:
|
||||
u.tasks['auto_del'].append(ctx.channel.id)
|
||||
u.dump(u.tasks, 'cogs/tasks.pkl')
|
||||
self.bot.loop.create_task(self.queue_for_deletion(ctx.channel))
|
||||
if not self.deleting:
|
||||
self.bot.loop.create_task(self.delete())
|
||||
self.deleting = True
|
||||
print('STARTED : auto-deleting in #{}'.format(ctx.channel.name))
|
||||
await ctx.send('**Auto-deleting all messages in {}**'.format(ctx.channel.mention), delete_after=5)
|
||||
else:
|
||||
raise exc.Exists
|
||||
|
||||
except exc.Exists:
|
||||
await ctx.send('**Already auto-deleting in {}.** Type `stop d(eleting)` to stop.'.format(ctx.channel.mention), delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
@cmds.group(aliases=['setting', 'set', 's'])
|
||||
@cmds.has_permissions(administrator=True)
|
||||
async def settings(self, ctx):
|
||||
pass
|
||||
|
||||
@settings.command(name='deletecommands', aliases=['delcmds', 'delcmd'])
|
||||
async def _settings_deletecommands(self, ctx):
|
||||
if ctx.guild.id not in u.settings['del_ctx']:
|
||||
u.settings['del_ctx'].append(ctx.guild.id)
|
||||
else:
|
||||
u.settings['del_ctx'].remove(ctx.guild.id)
|
||||
u.dump(u.settings, 'settings.pkl')
|
||||
|
||||
await ctx.send('**Delete command invocations:** `{}`'.format(ctx.guild.id in u.settings['del_ctx']))
|
||||
|
||||
@settings.command(name='prefix', aliases=['pre', 'p'])
|
||||
async def _settings_prefix(self, ctx, *prefixes):
|
||||
if prefixes:
|
||||
u.settings['prefixes'][ctx.guild.id] = prefixes
|
||||
else:
|
||||
with suppress(KeyError):
|
||||
del u.settings['prefixes'][ctx.guild.id]
|
||||
|
||||
await ctx.send(f'**Prefix set to:** `{"` or `".join(prefixes if ctx.guild.id in u.settings["prefixes"] else u.config["prefix"])}`')
|
||||
|
||||
@settings.command(name='deleteresponses', aliases=['delresps', 'delresp'])
|
||||
async def _settings_deleteresponses(self, ctx):
|
||||
if ctx.guild.id not in u.settings['del_resp']:
|
||||
u.settings['del_resp'].append(ctx.guild.id)
|
||||
else:
|
||||
u.settings['del_resp'].remove(ctx.guild.id)
|
||||
u.dump(u.settings, 'settings.pkl')
|
||||
|
||||
await ctx.send(f'**Delete command responses:** `{ctx.guild.id in u.settings["del_resp"]}`')
|
||||
import asyncio
|
||||
import traceback as tb
|
||||
from contextlib import suppress
|
||||
from datetime import datetime as dt
|
||||
|
||||
import discord as d
|
||||
from discord import errors as err
|
||||
from discord.ext import commands as cmds
|
||||
from discord.ext.commands import errors as errext
|
||||
|
||||
from misc import exceptions as exc
|
||||
from misc import checks
|
||||
from utils import utils as u
|
||||
|
||||
|
||||
class Administration:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.RATE_LIMIT = u.RATE_LIMIT
|
||||
self.queue = asyncio.Queue()
|
||||
self.deleting = False
|
||||
|
||||
if u.tasks['auto_del']:
|
||||
for channel in u.tasks['auto_del']:
|
||||
temp = self.bot.get_channel(channel)
|
||||
self.bot.loop.create_task(self.queue_for_deletion(temp))
|
||||
print('STARTED : auto-deleting in #{}'.format(temp.name))
|
||||
self.deleting = True
|
||||
self.bot.loop.create_task(self.delete())
|
||||
|
||||
@cmds.group(aliases=['pru', 'purge', 'pur', 'clear', 'cl'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def prune(self, ctx):
|
||||
pass
|
||||
|
||||
@prune.group(name='user', aliases=['u', 'member', 'm'])
|
||||
async def _prune_user(self, ctx):
|
||||
pass
|
||||
|
||||
@_prune_user.command(name='channel', aliases=['channels', 'chans', 'chan', 'ch', 'c'])
|
||||
async def _prune_user_channel(self, ctx, user: d.User, *channels: d.TextChannel):
|
||||
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
|
||||
|
||||
if not channels:
|
||||
channels = [ctx.channel]
|
||||
|
||||
try:
|
||||
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}?')
|
||||
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 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 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:
|
||||
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:
|
||||
await ctx.send('**Deletion timed out**', delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
@cmds.group(aliases=['task', 'tsk'])
|
||||
async def tasks(self):
|
||||
pass
|
||||
|
||||
async def delete(self):
|
||||
while self.deleting:
|
||||
message = await self.queue.get()
|
||||
await asyncio.sleep(self.RATE_LIMIT)
|
||||
with suppress(err.NotFound):
|
||||
if not message.pinned:
|
||||
await message.delete()
|
||||
|
||||
print('STOPPED : deleting')
|
||||
|
||||
async def queue_for_deletion(self, channel):
|
||||
def check(msg):
|
||||
if 'stop d' in msg.content.lower() and msg.channel is channel and msg.author.guild_permissions.administrator:
|
||||
raise exc.Abort
|
||||
elif msg.channel is channel and not msg.pinned:
|
||||
return True
|
||||
return False
|
||||
|
||||
try:
|
||||
async for message in channel.history(limit=None):
|
||||
if 'stop d' in message.content.lower() and message.author.guild_permissions.administrator:
|
||||
raise exc.Abort
|
||||
if not message.pinned:
|
||||
await self.queue.put(message)
|
||||
|
||||
while not self.bot.is_closed():
|
||||
message = await self.bot.wait_for('message', check=check)
|
||||
await self.queue.put(message)
|
||||
|
||||
except exc.Abort:
|
||||
u.tasks['auto_del'].remove(channel.id)
|
||||
u.dump(u.tasks, 'cogs/tasks.pkl')
|
||||
if not u.tasks['auto_del']:
|
||||
self.deleting = False
|
||||
print('STOPPED : deleting #{}'.format(channel.name))
|
||||
await channel.send('**Stopped queueing messages for deletion in** {}'.format(channel.mention), delete_after=5)
|
||||
|
||||
@cmds.command(name='autodelete', aliases=['autodel'])
|
||||
@cmds.has_permissions(administrator=True)
|
||||
async def auto_delete(self, ctx):
|
||||
try:
|
||||
if ctx.channel.id not in u.tasks['auto_del']:
|
||||
u.tasks['auto_del'].append(ctx.channel.id)
|
||||
u.dump(u.tasks, 'cogs/tasks.pkl')
|
||||
self.bot.loop.create_task(self.queue_for_deletion(ctx.channel))
|
||||
if not self.deleting:
|
||||
self.bot.loop.create_task(self.delete())
|
||||
self.deleting = True
|
||||
print('STARTED : auto-deleting in #{}'.format(ctx.channel.name))
|
||||
await ctx.send('**Auto-deleting all messages in {}**'.format(ctx.channel.mention), delete_after=5)
|
||||
else:
|
||||
raise exc.Exists
|
||||
|
||||
except exc.Exists:
|
||||
await ctx.send('**Already auto-deleting in {}.** Type `stop d(eleting)` to stop.'.format(ctx.channel.mention), delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
@cmds.group(aliases=['setting', 'set', 's'])
|
||||
@cmds.has_permissions(administrator=True)
|
||||
async def settings(self, ctx):
|
||||
pass
|
||||
|
||||
@settings.command(name='deletecommands', aliases=['delcmds', 'delcmd'])
|
||||
async def _settings_deletecommands(self, ctx):
|
||||
if ctx.guild.id not in u.settings['del_ctx']:
|
||||
u.settings['del_ctx'].append(ctx.guild.id)
|
||||
else:
|
||||
u.settings['del_ctx'].remove(ctx.guild.id)
|
||||
u.dump(u.settings, 'settings.pkl')
|
||||
|
||||
await ctx.send('**Delete command invocations:** `{}`'.format(ctx.guild.id in u.settings['del_ctx']))
|
||||
|
||||
@settings.command(name='prefix', aliases=['pre', 'p'])
|
||||
async def _settings_prefix(self, ctx, *prefixes):
|
||||
if prefixes:
|
||||
u.settings['prefixes'][ctx.guild.id] = prefixes
|
||||
else:
|
||||
with suppress(KeyError):
|
||||
del u.settings['prefixes'][ctx.guild.id]
|
||||
|
||||
await ctx.send(f'**Prefix set to:** `{"` or `".join(prefixes if ctx.guild.id in u.settings["prefixes"] else u.config["prefix"])}`')
|
||||
|
||||
@settings.command(name='deleteresponses', aliases=['delresps', 'delresp'])
|
||||
async def _settings_deleteresponses(self, ctx):
|
||||
if ctx.guild.id not in u.settings['del_resp']:
|
||||
u.settings['del_resp'].append(ctx.guild.id)
|
||||
else:
|
||||
u.settings['del_resp'].remove(ctx.guild.id)
|
||||
u.dump(u.settings, 'settings.pkl')
|
||||
|
||||
await ctx.send(f'**Delete command responses:** `{ctx.guild.id in u.settings["del_resp"]}`')
|
||||
|
|
|
@ -1,245 +1,245 @@
|
|||
import asyncio
|
||||
import code
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback as tb
|
||||
from contextlib import redirect_stdout, suppress
|
||||
|
||||
import discord as d
|
||||
import pyrasite as pyr
|
||||
from discord.ext import commands as cmds
|
||||
|
||||
from misc import exceptions as exc
|
||||
from misc import checks
|
||||
from utils import utils as u
|
||||
|
||||
|
||||
class Bot:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Close connection to Discord - immediate offline
|
||||
@cmds.command(name=',die', aliases=[',d'], brief='Kills the bot', description='BOT OWNER ONLY\nCloses the connection to Discord', hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def die(self, ctx):
|
||||
await ctx.message.add_reaction('\N{CRESCENT MOON}')
|
||||
|
||||
await self.bot.get_channel(u.config['info_channel']).send('**Shutting down** \N{CRESCENT MOON} . . .')
|
||||
|
||||
chantype = 'guild' if isinstance(ctx.channel, d.TextChannel) else 'private'
|
||||
u.temp['startup'] = (chantype, ctx.channel.id if chantype == 'guild' else ctx.author.id, ctx.message.id)
|
||||
u.dump(u.temp, 'temp/temp.pkl')
|
||||
|
||||
# loop = self.bot.loop.all_tasks()
|
||||
# for task in loop:
|
||||
# task.cancel()
|
||||
await self.bot.logout()
|
||||
u.close(self.bot.loop)
|
||||
print('\n< < < < < < < < < < < <\nD I S C O N N E C T E D\n< < < < < < < < < < < <\n')
|
||||
# u.notify('D I S C O N N E C T E D')
|
||||
|
||||
@cmds.command(name=',restart', aliases=[',res', ',r'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def restart(self, ctx):
|
||||
await ctx.message.add_reaction('\N{SLEEPING SYMBOL}')
|
||||
|
||||
print('\n^ ^ ^ ^ ^ ^ ^ ^ ^ ^\nR E S T A R T I N G\n^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n')
|
||||
await self.bot.get_channel(u.config['info_channel']).send('**Restarting** \N{SLEEPING SYMBOL} . . .')
|
||||
# u.notify('R E S T A R T I N G')
|
||||
|
||||
chantype = 'guild' if isinstance(ctx.channel, d.TextChannel) else 'private'
|
||||
u.temp['startup'] = (chantype, ctx.channel.id if chantype == 'guild' else ctx.author.id, ctx.message.id)
|
||||
u.dump(u.temp, 'temp/temp.pkl')
|
||||
|
||||
# loop = self.bot.loop.all_tasks()
|
||||
# for task in loop:
|
||||
# task.cancel()
|
||||
await self.bot.logout()
|
||||
u.close(self.bot.loop)
|
||||
os.execl(sys.executable, 'python3', 'run.py')
|
||||
|
||||
# Invite bot to bot owner's server
|
||||
@cmds.command(name=',invite', aliases=[',inv', ',link'], brief='Invite the bot', description='BOT OWNER ONLY\nInvite the bot to a server (Requires admin)', hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def invite(self, ctx):
|
||||
await ctx.message.add_reaction('\N{ENVELOPE}')
|
||||
|
||||
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.is_owner()
|
||||
async def change_status(self, ctx, *, game=None):
|
||||
if game:
|
||||
await self.bot.change_presence(game=d.Game(name=game))
|
||||
u.config['playing'] = game
|
||||
u.dump(u.config, 'config.json', json=True)
|
||||
await ctx.send(f'**Game changed to** `{game}`')
|
||||
else:
|
||||
await self.bot.change_presence(game=None)
|
||||
u.config['playing'] = ''
|
||||
u.dump(u.config, 'config.json', json=True)
|
||||
await ctx.send('**Game changed to** ` `')
|
||||
|
||||
@cmds.command(name=',username', aliases=[',user'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def change_username(self, ctx, *, username=None):
|
||||
if username:
|
||||
await self.bot.user.edit(username=username)
|
||||
await ctx.send(f'**Username changed to** `{username}`')
|
||||
else:
|
||||
await ctx.send('**Invalid string**', delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
|
||||
class Tools:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
def format(self, i='', o=''):
|
||||
if len(o) > 1:
|
||||
return '>>> {}\n{}'.format(i, o)
|
||||
else:
|
||||
return '>>> {}'.format(i)
|
||||
|
||||
async def generate(self, d, i='', o=''):
|
||||
return await d.send('```python\n{}```'.format(self.format(i, o)))
|
||||
|
||||
async def refresh(self, m, i='', o=''):
|
||||
output = m.content[9:-3]
|
||||
if len(re.findall('\n', output)) <= 20:
|
||||
await m.edit(content='```python\n{}\n{}\n>>>```'.format(output, self.format(i, o)))
|
||||
else:
|
||||
await m.edit(content='```python\n{}```'.format(self.format(i, o)))
|
||||
|
||||
async def generate_err(self, d, o=''):
|
||||
return await d.send('```\n{}```'.format(o))
|
||||
|
||||
async def refresh_err(self, m, o=''):
|
||||
await m.edit(content='```\n{}```'.format(o))
|
||||
|
||||
@cmds.command(name=',console', aliases=[',con', ',c'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def console(self, ctx):
|
||||
def execute(msg):
|
||||
if msg.content.lower().startswith('exec ') and msg.author is ctx.author and msg.channel is ctx.channel:
|
||||
msg.content = msg.content[5:]
|
||||
return True
|
||||
return False
|
||||
|
||||
def evaluate(msg):
|
||||
if msg.content.lower().startswith('eval ') and msg.author is ctx.author and msg.channel is ctx.channel:
|
||||
msg.content = msg.content[5:]
|
||||
return True
|
||||
return False
|
||||
|
||||
def exit(reaction, user):
|
||||
if reaction.emoji == '\N{OCTAGONAL SIGN}' and user is ctx.author and reaction.message.id == ctx.message.id:
|
||||
raise exc.Abort
|
||||
return False
|
||||
|
||||
try:
|
||||
console = await self.generate(ctx)
|
||||
exception = await self.generate_err(ctx)
|
||||
|
||||
await ctx.message.add_reaction('\N{OCTAGONAL SIGN}')
|
||||
|
||||
while not self.bot.is_closed():
|
||||
try:
|
||||
done, pending = await asyncio.wait([self.bot.wait_for('message', check=execute), self.bot.wait_for('message', check=evaluate), self.bot.wait_for('reaction_add', check=exit)], return_when=asyncio.FIRST_COMPLETED)
|
||||
|
||||
message = done.pop().result()
|
||||
print(message.content)
|
||||
|
||||
except exc.Execute:
|
||||
try:
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stderr = io.StringIO()
|
||||
exec(message.content)
|
||||
|
||||
except Exception:
|
||||
await self.refresh_err(exception, tb.format_exc(limit=1))
|
||||
|
||||
finally:
|
||||
await self.refresh(console, message.content, sys.stdout.getvalue() if sys.stdout.getvalue() != console.content else None)
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
with suppress(d.NotFound):
|
||||
await message.delete()
|
||||
|
||||
except exc.Evaluate:
|
||||
try:
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stderr = io.StringIO()
|
||||
eval(message.content)
|
||||
|
||||
except Exception:
|
||||
await self.refresh_err(exception, tb.format_exc(limit=1))
|
||||
|
||||
finally:
|
||||
await self.refresh(console, message.content, sys.stdout.getvalue() if sys.stdout.getvalue() != console.content else None)
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
with suppress(d.NotFound):
|
||||
await message.delete()
|
||||
|
||||
except exc.Abort:
|
||||
pass
|
||||
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
print('RESET : sys.std output/error')
|
||||
|
||||
@cmds.command(name=',execute', aliases=[',exec'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def execute(self, ctx, *, exe):
|
||||
try:
|
||||
with io.StringIO() as buff, redirect_stdout(buff):
|
||||
exec(exe)
|
||||
await self.generate(ctx, exe, f'\n{buff.getvalue()}')
|
||||
|
||||
except Exception:
|
||||
await self.generate(ctx, exe, f'\n{tb.format_exc()}')
|
||||
|
||||
@cmds.command(name=',evaluate', aliases=[',eval'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def evaluate(self, ctx, *, evl):
|
||||
try:
|
||||
with io.StringIO() as buff, redirect_stdout(buff):
|
||||
eval(evl)
|
||||
await self.generate(ctx, evl, f'\n{buff.getvalue()}')
|
||||
|
||||
except Exception:
|
||||
await self.generate(ctx, evl, f'\n{tb.format_exc()}')
|
||||
|
||||
@cmds.group(aliases=[',db'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def debug(self, ctx):
|
||||
console = await self.generate(ctx)
|
||||
|
||||
@debug.command(name='inject', aliases=['inj'])
|
||||
async def _inject(self, ctx, *, input_):
|
||||
pass
|
||||
|
||||
@debug.command(name='inspect', aliases=['ins'])
|
||||
async def _inspect(self, ctx, *, input_):
|
||||
pass
|
||||
|
||||
# @cmds.command(name='endpoint', aliases=['end'])
|
||||
# async def get_endpoint(self, ctx, *args):
|
||||
# await ctx.send(f'```\n{await u.fetch(f"https://{args[0]}/{args[1]}/{args[2]}", params={args[3]: args[4], "limit": 1}, json=True)}```')
|
||||
import asyncio
|
||||
import code
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback as tb
|
||||
from contextlib import redirect_stdout, suppress
|
||||
|
||||
import discord as d
|
||||
import pyrasite as pyr
|
||||
from discord.ext import commands as cmds
|
||||
|
||||
from misc import exceptions as exc
|
||||
from misc import checks
|
||||
from utils import utils as u
|
||||
|
||||
|
||||
class Bot:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
# Close connection to Discord - immediate offline
|
||||
@cmds.command(name=',die', aliases=[',d'], brief='Kills the bot', description='BOT OWNER ONLY\nCloses the connection to Discord', hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def die(self, ctx):
|
||||
await ctx.message.add_reaction('\N{CRESCENT MOON}')
|
||||
|
||||
await self.bot.get_channel(u.config['info_channel']).send('**Shutting down** \N{CRESCENT MOON} . . .')
|
||||
|
||||
chantype = 'guild' if isinstance(ctx.channel, d.TextChannel) else 'private'
|
||||
u.temp['startup'] = (chantype, ctx.channel.id if chantype == 'guild' else ctx.author.id, ctx.message.id)
|
||||
u.dump(u.temp, 'temp/temp.pkl')
|
||||
|
||||
# loop = self.bot.loop.all_tasks()
|
||||
# for task in loop:
|
||||
# task.cancel()
|
||||
await self.bot.logout()
|
||||
u.close(self.bot.loop)
|
||||
print('\n< < < < < < < < < < < <\nD I S C O N N E C T E D\n< < < < < < < < < < < <\n')
|
||||
# u.notify('D I S C O N N E C T E D')
|
||||
|
||||
@cmds.command(name=',restart', aliases=[',res', ',r'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def restart(self, ctx):
|
||||
await ctx.message.add_reaction('\N{SLEEPING SYMBOL}')
|
||||
|
||||
print('\n^ ^ ^ ^ ^ ^ ^ ^ ^ ^\nR E S T A R T I N G\n^ ^ ^ ^ ^ ^ ^ ^ ^ ^\n')
|
||||
await self.bot.get_channel(u.config['info_channel']).send('**Restarting** \N{SLEEPING SYMBOL} . . .')
|
||||
# u.notify('R E S T A R T I N G')
|
||||
|
||||
chantype = 'guild' if isinstance(ctx.channel, d.TextChannel) else 'private'
|
||||
u.temp['startup'] = (chantype, ctx.channel.id if chantype == 'guild' else ctx.author.id, ctx.message.id)
|
||||
u.dump(u.temp, 'temp/temp.pkl')
|
||||
|
||||
# loop = self.bot.loop.all_tasks()
|
||||
# for task in loop:
|
||||
# task.cancel()
|
||||
await self.bot.logout()
|
||||
u.close(self.bot.loop)
|
||||
os.execl(sys.executable, 'python3', 'run.py')
|
||||
|
||||
# Invite bot to bot owner's server
|
||||
@cmds.command(name=',invite', aliases=[',inv', ',link'], brief='Invite the bot', description='BOT OWNER ONLY\nInvite the bot to a server (Requires admin)', hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def invite(self, ctx):
|
||||
await ctx.message.add_reaction('\N{ENVELOPE}')
|
||||
|
||||
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.is_owner()
|
||||
async def change_status(self, ctx, *, game=None):
|
||||
if game:
|
||||
await self.bot.change_presence(game=d.Game(name=game))
|
||||
u.config['playing'] = game
|
||||
u.dump(u.config, 'config.json', json=True)
|
||||
await ctx.send(f'**Game changed to** `{game}`')
|
||||
else:
|
||||
await self.bot.change_presence(game=None)
|
||||
u.config['playing'] = ''
|
||||
u.dump(u.config, 'config.json', json=True)
|
||||
await ctx.send('**Game changed to** ` `')
|
||||
|
||||
@cmds.command(name=',username', aliases=[',user'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def change_username(self, ctx, *, username=None):
|
||||
if username:
|
||||
await self.bot.user.edit(username=username)
|
||||
await ctx.send(f'**Username changed to** `{username}`')
|
||||
else:
|
||||
await ctx.send('**Invalid string**', delete_after=7)
|
||||
await ctx.message.add_reaction('\N{CROSS MARK}')
|
||||
|
||||
|
||||
class Tools:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
def format(self, i='', o=''):
|
||||
if len(o) > 1:
|
||||
return '>>> {}\n{}'.format(i, o)
|
||||
else:
|
||||
return '>>> {}'.format(i)
|
||||
|
||||
async def generate(self, d, i='', o=''):
|
||||
return await d.send('```python\n{}```'.format(self.format(i, o)))
|
||||
|
||||
async def refresh(self, m, i='', o=''):
|
||||
output = m.content[9:-3]
|
||||
if len(re.findall('\n', output)) <= 20:
|
||||
await m.edit(content='```python\n{}\n{}\n>>>```'.format(output, self.format(i, o)))
|
||||
else:
|
||||
await m.edit(content='```python\n{}```'.format(self.format(i, o)))
|
||||
|
||||
async def generate_err(self, d, o=''):
|
||||
return await d.send('```\n{}```'.format(o))
|
||||
|
||||
async def refresh_err(self, m, o=''):
|
||||
await m.edit(content='```\n{}```'.format(o))
|
||||
|
||||
@cmds.command(name=',console', aliases=[',con', ',c'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def console(self, ctx):
|
||||
def execute(msg):
|
||||
if msg.content.lower().startswith('exec ') and msg.author is ctx.author and msg.channel is ctx.channel:
|
||||
msg.content = msg.content[5:]
|
||||
return True
|
||||
return False
|
||||
|
||||
def evaluate(msg):
|
||||
if msg.content.lower().startswith('eval ') and msg.author is ctx.author and msg.channel is ctx.channel:
|
||||
msg.content = msg.content[5:]
|
||||
return True
|
||||
return False
|
||||
|
||||
def exit(reaction, user):
|
||||
if reaction.emoji == '\N{OCTAGONAL SIGN}' and user is ctx.author and reaction.message.id == ctx.message.id:
|
||||
raise exc.Abort
|
||||
return False
|
||||
|
||||
try:
|
||||
console = await self.generate(ctx)
|
||||
exception = await self.generate_err(ctx)
|
||||
|
||||
await ctx.message.add_reaction('\N{OCTAGONAL SIGN}')
|
||||
|
||||
while not self.bot.is_closed():
|
||||
try:
|
||||
done, pending = await asyncio.wait([self.bot.wait_for('message', check=execute), self.bot.wait_for('message', check=evaluate), self.bot.wait_for('reaction_add', check=exit)], return_when=asyncio.FIRST_COMPLETED)
|
||||
|
||||
message = done.pop().result()
|
||||
print(message.content)
|
||||
|
||||
except exc.Execute:
|
||||
try:
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stderr = io.StringIO()
|
||||
exec(message.content)
|
||||
|
||||
except Exception:
|
||||
await self.refresh_err(exception, tb.format_exc(limit=1))
|
||||
|
||||
finally:
|
||||
await self.refresh(console, message.content, sys.stdout.getvalue() if sys.stdout.getvalue() != console.content else None)
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
with suppress(d.NotFound):
|
||||
await message.delete()
|
||||
|
||||
except exc.Evaluate:
|
||||
try:
|
||||
sys.stdout = io.StringIO()
|
||||
sys.stderr = io.StringIO()
|
||||
eval(message.content)
|
||||
|
||||
except Exception:
|
||||
await self.refresh_err(exception, tb.format_exc(limit=1))
|
||||
|
||||
finally:
|
||||
await self.refresh(console, message.content, sys.stdout.getvalue() if sys.stdout.getvalue() != console.content else None)
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
with suppress(d.NotFound):
|
||||
await message.delete()
|
||||
|
||||
except exc.Abort:
|
||||
pass
|
||||
|
||||
finally:
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
print('RESET : sys.std output/error')
|
||||
|
||||
@cmds.command(name=',execute', aliases=[',exec'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def execute(self, ctx, *, exe):
|
||||
try:
|
||||
with io.StringIO() as buff, redirect_stdout(buff):
|
||||
exec(exe)
|
||||
await self.generate(ctx, exe, f'\n{buff.getvalue()}')
|
||||
|
||||
except Exception:
|
||||
await self.generate(ctx, exe, f'\n{tb.format_exc()}')
|
||||
|
||||
@cmds.command(name=',evaluate', aliases=[',eval'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def evaluate(self, ctx, *, evl):
|
||||
try:
|
||||
with io.StringIO() as buff, redirect_stdout(buff):
|
||||
eval(evl)
|
||||
await self.generate(ctx, evl, f'\n{buff.getvalue()}')
|
||||
|
||||
except Exception:
|
||||
await self.generate(ctx, evl, f'\n{tb.format_exc()}')
|
||||
|
||||
@cmds.group(aliases=[',db'], hidden=True)
|
||||
@cmds.is_owner()
|
||||
async def debug(self, ctx):
|
||||
console = await self.generate(ctx)
|
||||
|
||||
@debug.command(name='inject', aliases=['inj'])
|
||||
async def _inject(self, ctx, *, input_):
|
||||
pass
|
||||
|
||||
@debug.command(name='inspect', aliases=['ins'])
|
||||
async def _inspect(self, ctx, *, input_):
|
||||
pass
|
||||
|
||||
# @cmds.command(name='endpoint', aliases=['end'])
|
||||
# async def get_endpoint(self, ctx, *args):
|
||||
# await ctx.send(f'```\n{await u.fetch(f"https://{args[0]}/{args[1]}/{args[2]}", params={args[3]: args[4], "limit": 1}, json=True)}```')
|
||||
|
|
|
@ -1,191 +1,191 @@
|
|||
import asyncio
|
||||
import json as jsn
|
||||
import os
|
||||
import pickle as pkl
|
||||
import subprocess
|
||||
from contextlib import suppress
|
||||
from fractions import gcd
|
||||
import math
|
||||
import gmusicapi as gpm
|
||||
|
||||
import aiohttp
|
||||
import discord as d
|
||||
|
||||
from misc import exceptions as exc
|
||||
|
||||
# from pync import Notifier
|
||||
|
||||
|
||||
print('\nPID : {}\n'.format(os.getpid()))
|
||||
|
||||
|
||||
# def notify(message):
|
||||
# subprocess.run(['terminal-notifier', '-message', message, '-title',
|
||||
# 'Modumind', '-activate', 'com.apple.Terminal', '-appIcon', 'icon.png', '-sound', 'Ping'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
|
||||
try:
|
||||
with open('config.json') as infile:
|
||||
config = jsn.load(infile)
|
||||
print('LOADED : config.json')
|
||||
|
||||
except FileNotFoundError:
|
||||
with open('config.json', 'w') as outfile:
|
||||
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)
|
||||
print('FILE NOT FOUND : config.json created with abstract values. Restart run.py with correct values')
|
||||
|
||||
|
||||
def setdefault(filename, default=None, json=False):
|
||||
if json:
|
||||
try:
|
||||
with open(filename, 'r') as infile:
|
||||
print(f'LOADED : {filename}')
|
||||
return jsn.load(infile)
|
||||
|
||||
except FileNotFoundError:
|
||||
with open(filename, 'w+') as iofile:
|
||||
print(f'FILE NOT FOUND : {filename} created and loaded with default values')
|
||||
jsn.dump(default, iofile)
|
||||
iofile.seek(0)
|
||||
return jsn.load(iofile)
|
||||
else:
|
||||
try:
|
||||
with open(filename, 'rb') as infile:
|
||||
print(f'LOADED : {filename}')
|
||||
return pkl.load(infile)
|
||||
|
||||
except FileNotFoundError:
|
||||
with open(filename, 'wb+') as iofile:
|
||||
print(f'FILE NOT FOUND : {filename} created and loaded with default values')
|
||||
pkl.dump(default, iofile)
|
||||
iofile.seek(0)
|
||||
return pkl.load(iofile)
|
||||
|
||||
|
||||
def load(filename, *, json=False):
|
||||
if not json:
|
||||
with open(filename, 'rb') as infile:
|
||||
return pkl.load(infile)
|
||||
else:
|
||||
with open(filename) as infile:
|
||||
return jsn.load(infile)
|
||||
|
||||
|
||||
def dump(obj, filename, *, json=False):
|
||||
if not json:
|
||||
with open(filename, 'wb') as outfile:
|
||||
pkl.dump(obj, outfile)
|
||||
else:
|
||||
with open(filename, 'w') as outfile:
|
||||
jsn.dump(obj, outfile, indent=4, sort_keys=True)
|
||||
|
||||
|
||||
settings = setdefault('misc/settings.pkl', default={'del_ctx': [], 'del_resp': [], 'prefixes': {}})
|
||||
tasks = setdefault('cogs/tasks.pkl', default={'auto_del': [], 'auto_hrt': [], 'auto_rev': [], 'periodic_gpm': []})
|
||||
temp = setdefault('temp/temp.pkl', default={'startup': ()})
|
||||
secrets = setdefault('secrets.json', default={'client_secrets': {'client_id': '', 'client_secret': ''}}, json=True)
|
||||
|
||||
RATE_LIMIT = 2.2
|
||||
color = d.Color(0x1A1A1A)
|
||||
session = aiohttp.ClientSession()
|
||||
last_commands = {}
|
||||
|
||||
|
||||
async def fetch(url, *, params={}, json=False, response=False):
|
||||
async with session.get(url, params=params, headers={'User-Agent': 'Myned/Modufur'}) as r:
|
||||
if response:
|
||||
return r
|
||||
elif json:
|
||||
return await r.json()
|
||||
return await r.read()
|
||||
|
||||
|
||||
# async def clear(obj, interval=10 * 60, replace=None):
|
||||
# if replace is None:
|
||||
# if type(obj) is list:
|
||||
# replace = []
|
||||
# elif type(obj) is dict:
|
||||
# replace = {}
|
||||
# elif type(obj) is int:
|
||||
# replace = 0
|
||||
# elif type(obj) is str:
|
||||
# replace = ''
|
||||
#
|
||||
# while True:
|
||||
# obj = replace
|
||||
# asyncio.sleep(interval)
|
||||
|
||||
|
||||
def close(loop):
|
||||
if session:
|
||||
session.close()
|
||||
|
||||
loop.stop()
|
||||
pending = asyncio.Task.all_tasks()
|
||||
for task in pending:
|
||||
task.cancel()
|
||||
# with suppress(asyncio.CancelledError):
|
||||
# loop.run_until_complete(task)
|
||||
# loop.close()
|
||||
|
||||
print('Finished cancelling tasks.')
|
||||
|
||||
|
||||
def generate_embed(ctx, *, title=d.Embed.Empty, kind='rich', description=d.Embed.Empty, url=d.Embed.Empty, timestamp=d.Embed.Empty, colour=color, footer={}, image=d.Embed.Empty, thumbnail=d.Embed.Empty, author={}, fields=[]):
|
||||
embed = d.Embed(title=title, type=kind, description=description, url=url, timestamp=timestamp, colour=colour if isinstance(ctx.channel, d.TextChannel) else color)
|
||||
|
||||
if footer:
|
||||
embed.set_footer(text=footer.get('text', d.Embed.Empty), icon_url=footer.get('icon_url', d.Embed.Empty))
|
||||
if image:
|
||||
embed.set_image(url=image)
|
||||
if thumbnail:
|
||||
embed.set_thumbnail(url=thumbnail)
|
||||
if author:
|
||||
embed.set_author(name=author.get('name', d.Embed.Empty), url=author.get('url', d.Embed.Empty), icon_url=author.get('icon_url', d.Embed.Empty))
|
||||
for field in fields:
|
||||
embed.add_field(name=field.get('name', d.Embed.Empty), value=field.get('value', d.Embed.Empty), inline=field.get('inline', True))
|
||||
|
||||
return embed
|
||||
|
||||
def get_kwargs(ctx, args, *, limit=False):
|
||||
destination = ctx
|
||||
remaining = list(args[:])
|
||||
rm = False
|
||||
lim = 1
|
||||
|
||||
for flag in ('-d', '-dm'):
|
||||
if flag in remaining:
|
||||
destination = ctx.author
|
||||
|
||||
remaining.remove(flag)
|
||||
|
||||
for flag in ('-r', '-rm', '-remove', '-re', '-repl', '-replace'):
|
||||
if flag in remaining and ctx.author.permissions_in(ctx.channel).manage_messages:
|
||||
rm = True
|
||||
|
||||
remaining.remove(flag)
|
||||
|
||||
if limit:
|
||||
for arg in remaining:
|
||||
if arg.isdigit():
|
||||
if 1 <= int(arg) <= limit:
|
||||
lim = int(arg)
|
||||
remaining.remove(arg)
|
||||
break
|
||||
else:
|
||||
raise exc.BoundsError(arg)
|
||||
|
||||
return {'destination': destination, 'remaining': remaining, 'remove': rm, 'limit': lim}
|
||||
|
||||
|
||||
def get_aspectratio(a, b):
|
||||
divisor = gcd(a, b)
|
||||
return f'{int(a / divisor)}:{int(b / divisor)}'
|
||||
|
||||
|
||||
def ci(pos, n):
|
||||
z = 1.96
|
||||
phat = float(pos) / n
|
||||
|
||||
return (phat + z*z/(2*n) - z * math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
|
||||
import asyncio
|
||||
import json as jsn
|
||||
import os
|
||||
import pickle as pkl
|
||||
import subprocess
|
||||
from contextlib import suppress
|
||||
from fractions import gcd
|
||||
import math
|
||||
import gmusicapi as gpm
|
||||
|
||||
import aiohttp
|
||||
import discord as d
|
||||
|
||||
from misc import exceptions as exc
|
||||
|
||||
# from pync import Notifier
|
||||
|
||||
|
||||
print('\nPID : {}\n'.format(os.getpid()))
|
||||
|
||||
|
||||
# def notify(message):
|
||||
# subprocess.run(['terminal-notifier', '-message', message, '-title',
|
||||
# 'Modumind', '-activate', 'com.apple.Terminal', '-appIcon', 'icon.png', '-sound', 'Ping'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
|
||||
try:
|
||||
with open('config.json') as infile:
|
||||
config = jsn.load(infile)
|
||||
print('LOADED : config.json')
|
||||
|
||||
except FileNotFoundError:
|
||||
with open('config.json', 'w') as outfile:
|
||||
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)
|
||||
print('FILE NOT FOUND : config.json created with abstract values. Restart run.py with correct values')
|
||||
|
||||
|
||||
def setdefault(filename, default=None, json=False):
|
||||
if json:
|
||||
try:
|
||||
with open(filename, 'r') as infile:
|
||||
print(f'LOADED : {filename}')
|
||||
return jsn.load(infile)
|
||||
|
||||
except FileNotFoundError:
|
||||
with open(filename, 'w+') as iofile:
|
||||
print(f'FILE NOT FOUND : {filename} created and loaded with default values')
|
||||
jsn.dump(default, iofile)
|
||||
iofile.seek(0)
|
||||
return jsn.load(iofile)
|
||||
else:
|
||||
try:
|
||||
with open(filename, 'rb') as infile:
|
||||
print(f'LOADED : {filename}')
|
||||
return pkl.load(infile)
|
||||
|
||||
except FileNotFoundError:
|
||||
with open(filename, 'wb+') as iofile:
|
||||
print(f'FILE NOT FOUND : {filename} created and loaded with default values')
|
||||
pkl.dump(default, iofile)
|
||||
iofile.seek(0)
|
||||
return pkl.load(iofile)
|
||||
|
||||
|
||||
def load(filename, *, json=False):
|
||||
if not json:
|
||||
with open(filename, 'rb') as infile:
|
||||
return pkl.load(infile)
|
||||
else:
|
||||
with open(filename) as infile:
|
||||
return jsn.load(infile)
|
||||
|
||||
|
||||
def dump(obj, filename, *, json=False):
|
||||
if not json:
|
||||
with open(filename, 'wb') as outfile:
|
||||
pkl.dump(obj, outfile)
|
||||
else:
|
||||
with open(filename, 'w') as outfile:
|
||||
jsn.dump(obj, outfile, indent=4, sort_keys=True)
|
||||
|
||||
|
||||
settings = setdefault('misc/settings.pkl', default={'del_ctx': [], 'del_resp': [], 'prefixes': {}})
|
||||
tasks = setdefault('cogs/tasks.pkl', default={'auto_del': [], 'auto_hrt': [], 'auto_rev': [], 'periodic_gpm': []})
|
||||
temp = setdefault('temp/temp.pkl', default={'startup': ()})
|
||||
secrets = setdefault('secrets.json', default={'client_secrets': {'client_id': '', 'client_secret': ''}}, json=True)
|
||||
|
||||
RATE_LIMIT = 2.2
|
||||
color = d.Color(0x1A1A1A)
|
||||
session = aiohttp.ClientSession()
|
||||
last_commands = {}
|
||||
|
||||
|
||||
async def fetch(url, *, params={}, json=False, response=False):
|
||||
async with session.get(url, params=params, headers={'User-Agent': 'Myned/Modufur'}) as r:
|
||||
if response:
|
||||
return r
|
||||
elif json:
|
||||
return await r.json()
|
||||
return await r.read()
|
||||
|
||||
|
||||
# async def clear(obj, interval=10 * 60, replace=None):
|
||||
# if replace is None:
|
||||
# if type(obj) is list:
|
||||
# replace = []
|
||||
# elif type(obj) is dict:
|
||||
# replace = {}
|
||||
# elif type(obj) is int:
|
||||
# replace = 0
|
||||
# elif type(obj) is str:
|
||||
# replace = ''
|
||||
#
|
||||
# while True:
|
||||
# obj = replace
|
||||
# asyncio.sleep(interval)
|
||||
|
||||
|
||||
def close(loop):
|
||||
if session:
|
||||
session.close()
|
||||
|
||||
loop.stop()
|
||||
pending = asyncio.Task.all_tasks()
|
||||
for task in pending:
|
||||
task.cancel()
|
||||
# with suppress(asyncio.CancelledError):
|
||||
# loop.run_until_complete(task)
|
||||
# loop.close()
|
||||
|
||||
print('Finished cancelling tasks.')
|
||||
|
||||
|
||||
def generate_embed(ctx, *, title=d.Embed.Empty, kind='rich', description=d.Embed.Empty, url=d.Embed.Empty, timestamp=d.Embed.Empty, colour=color, footer={}, image=d.Embed.Empty, thumbnail=d.Embed.Empty, author={}, fields=[]):
|
||||
embed = d.Embed(title=title, type=kind, description=description, url=url, timestamp=timestamp, colour=colour if isinstance(ctx.channel, d.TextChannel) else color)
|
||||
|
||||
if footer:
|
||||
embed.set_footer(text=footer.get('text', d.Embed.Empty), icon_url=footer.get('icon_url', d.Embed.Empty))
|
||||
if image:
|
||||
embed.set_image(url=image)
|
||||
if thumbnail:
|
||||
embed.set_thumbnail(url=thumbnail)
|
||||
if author:
|
||||
embed.set_author(name=author.get('name', d.Embed.Empty), url=author.get('url', d.Embed.Empty), icon_url=author.get('icon_url', d.Embed.Empty))
|
||||
for field in fields:
|
||||
embed.add_field(name=field.get('name', d.Embed.Empty), value=field.get('value', d.Embed.Empty), inline=field.get('inline', True))
|
||||
|
||||
return embed
|
||||
|
||||
def get_kwargs(ctx, args, *, limit=False):
|
||||
destination = ctx
|
||||
remaining = list(args[:])
|
||||
rm = False
|
||||
lim = 1
|
||||
|
||||
for flag in ('-d', '-dm'):
|
||||
if flag in remaining:
|
||||
destination = ctx.author
|
||||
|
||||
remaining.remove(flag)
|
||||
|
||||
for flag in ('-r', '-rm', '-remove', '-re', '-repl', '-replace'):
|
||||
if flag in remaining and ctx.author.permissions_in(ctx.channel).manage_messages:
|
||||
rm = True
|
||||
|
||||
remaining.remove(flag)
|
||||
|
||||
if limit:
|
||||
for arg in remaining:
|
||||
if arg.isdigit():
|
||||
if 1 <= int(arg) <= limit:
|
||||
lim = int(arg)
|
||||
remaining.remove(arg)
|
||||
break
|
||||
else:
|
||||
raise exc.BoundsError(arg)
|
||||
|
||||
return {'destination': destination, 'remaining': remaining, 'remove': rm, 'limit': lim}
|
||||
|
||||
|
||||
def get_aspectratio(a, b):
|
||||
divisor = gcd(a, b)
|
||||
return f'{int(a / divisor)}:{int(b / divisor)}'
|
||||
|
||||
|
||||
def ci(pos, n):
|
||||
z = 1.96
|
||||
phat = float(pos) / n
|
||||
|
||||
return (phat + z*z/(2*n) - z * math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
|
||||
|
|
Loading…
Reference in a new issue