Red-DiscordBot/core/owner.py
Twentysix 9fc4e54ece [Core] Removed flusher, helpers now save on changes
After some considerations, while the flusher was an interesting experiment, it doesn't seem to be reliable enough. It's been removed in favor of the helpers autosaving on any change in a threadsafe way.
2017-04-29 19:26:34 +02:00

134 lines
4.3 KiB
Python

from discord.ext import commands
from core import checks
from core.utils.chat_formatting import box
import logging
import asyncio
import importlib
import os
import discord
log = logging.getLogger("red")
class Owner:
"""All owner-only commands that relate to debug bot operations."""
@commands.command()
@checks.is_owner()
async def load(self, ctx, *, cog_name: str):
"""Loads a package"""
if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name
try:
ctx.bot.load_extension(cog_name)
except Exception as e:
log.exception("Package loading failed", exc_info=e)
await ctx.send("Failed to load package. Check your console or "
"logs for details.")
else:
await ctx.bot.save_packages_status()
await ctx.send("Done.")
@commands.group()
@checks.is_owner()
async def unload(self, ctx, *, cog_name: str):
"""Unloads a package"""
if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name
if cog_name in ctx.bot.extensions:
ctx.bot.unload_extension(cog_name)
await ctx.bot.save_packages_status()
await ctx.send("Done.")
else:
await ctx.send("That extension is not loaded.")
@commands.command(name="reload")
@checks.is_owner()
async def _reload(self, ctx, *, cog_name: str):
"""Reloads a package"""
if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name
try:
self.refresh_modules(cog_name)
ctx.bot.unload_extension(cog_name)
ctx.bot.load_extension(cog_name)
except Exception as e:
log.exception("Package reloading failed", exc_info=e)
await ctx.send("Failed to reload package. Check your console or "
"logs for details.")
else:
await ctx.bot.save_packages_status()
await ctx.send("Done.")
def refresh_modules(self, module):
"""Interally reloads modules so that changes are detected"""
module = module.replace(".", os.sep)
for root, dirs, files in os.walk(module):
for name in files:
if name.endswith(".py"):
path = os.path.join(root, name)
path, _ = os.path.splitext(path)
path = ".".join(path.split(os.sep))
print("Reloading " + path)
m = importlib.import_module(path)
importlib.reload(m)
@commands.command(hidden=True)
@checks.is_owner()
async def debug(self, ctx, *, code):
"""Evaluates code"""
author = ctx.message.author
channel = ctx.message.channel
code = code.strip('` ')
result = None
global_vars = globals().copy()
global_vars['bot'] = ctx.bot
global_vars['ctx'] = ctx
global_vars['message'] = ctx.message
global_vars['author'] = ctx.message.author
global_vars['channel'] = ctx.message.channel
global_vars['guild'] = ctx.message.guild
try:
result = eval(code, global_vars, locals())
except Exception as e:
await ctx.send('```py\n{}: {}```'.format(type(e).__name__, str(e)),)
return
if asyncio.iscoroutine(result):
result = await result
result = str(result)
if ctx.message.guild is not None:
token = ctx.bot.http.token
r = "[EXPUNGED]"
result = result.replace(token, r)
result = result.replace(token.lower(), r)
result = result.replace(token.upper(), r)
await ctx.send(box(result, lang="py"))
@commands.command(hidden=True)
@checks.is_owner()
async def mock(self, ctx, user: discord.Member, *, command):
"""Runs a command as if it was issued by a different user
The prefix must not be entered"""
# Since we have stateful objects now this might be pretty bad
# Sorry Danny
old_author = ctx.author
old_content = ctx.message.content
ctx.message.author = user
ctx.message.content = ctx.prefix + command
await ctx.bot.process_commands(ctx.message)
ctx.message.author = old_author
ctx.message.content = old_content