[Core] Save package status and restore it on boot

Also better error handling on package loading
This commit is contained in:
Twentysix 2017-04-27 16:26:21 +02:00
parent 1d3b541e8f
commit 294adf270f
6 changed files with 85 additions and 40 deletions

View File

@ -21,9 +21,9 @@ class Audio:
await ctx.send("Join a voice channel first!") await ctx.send("Join a voice channel first!")
return return
if ctx.guild.voice_client: if ctx.voice_client:
if ctx.guild.voice_client.channel != ctx.author.voice.channel: if ctx.voice_client.channel != ctx.author.voice.channel:
await ctx.guild.voice_client.disconnect() await ctx.voice_client.disconnect()
path = os.path.join("cogs", "audio", "songs", filename + ".mp3") path = os.path.join("cogs", "audio", "songs", filename + ".mp3")
if not os.path.isfile(path): if not os.path.isfile(path):
await ctx.send("Let's play a file that exists pls") await ctx.send("Let's play a file that exists pls")
@ -44,9 +44,9 @@ class Audio:
await ctx.send("Youtube links pls") await ctx.send("Youtube links pls")
return return
if ctx.guild.voice_client: if ctx.voice_client:
if ctx.guild.voice_client.channel != ctx.author.voice.channel: if ctx.voice_client.channel != ctx.author.voice.channel:
await ctx.guild.voice_client.disconnect() await ctx.voice_client.disconnect()
yt = YoutubeSource(url) yt = YoutubeSource(url)
player = PCMVolumeTransformer(yt, volume=1) player = PCMVolumeTransformer(yt, volume=1)
voice = await ctx.author.voice.channel.connect() voice = await ctx.author.voice.channel.connect()
@ -56,9 +56,9 @@ class Audio:
@commands.command() @commands.command()
async def stop(self, ctx): async def stop(self, ctx):
"""Stops the music and disconnects""" """Stops the music and disconnects"""
if ctx.guild.voice_client: if ctx.voice_client:
ctx.guild.voice_client.source.cleanup() ctx.voice_client.source.cleanup()
await ctx.guild.voice_client.disconnect() await ctx.voice_client.disconnect()
else: else:
await ctx.send("I'm not even connected to a voice channel!", delete_after=2) await ctx.send("I'm not even connected to a voice channel!", delete_after=2)
await ctx.message.delete() await ctx.message.delete()
@ -66,8 +66,8 @@ class Audio:
@commands.command() @commands.command()
async def pause(self, ctx): async def pause(self, ctx):
"""Pauses the music""" """Pauses the music"""
if ctx.guild.voice_client: if ctx.voice_client:
ctx.guild.voice_client.pause() ctx.voice_client.pause()
await ctx.send("👌", delete_after=2) await ctx.send("👌", delete_after=2)
else: else:
await ctx.send("I'm not even connected to a voice channel!", delete_after=2) await ctx.send("I'm not even connected to a voice channel!", delete_after=2)
@ -76,8 +76,8 @@ class Audio:
@commands.command() @commands.command()
async def resume(self, ctx): async def resume(self, ctx):
"""Resumes the music""" """Resumes the music"""
if ctx.guild.voice_client: if ctx.voice_client:
ctx.guild.voice_client.resume() ctx.voice_client.resume()
await ctx.send("👌", delete_after=2) await ctx.send("👌", delete_after=2)
else: else:
await ctx.send("I'm not even connected to a voice channel!", delete_after=2) await ctx.send("I'm not even connected to a voice channel!", delete_after=2)
@ -86,8 +86,8 @@ class Audio:
@commands.command(hidden=True) @commands.command(hidden=True)
async def volume(self, ctx, n: float): async def volume(self, ctx, n: float):
"""Sets the volume""" """Sets the volume"""
if ctx.guild.voice_client: if ctx.voice_client:
ctx.guild.voice_client.source.volume = n ctx.voice_client.source.volume = n
await ctx.send("Volume set.", delete_after=2) await ctx.send("Volume set.", delete_after=2)
else: else:
await ctx.send("I'm not even connected to a voice channel!", delete_after=2) await ctx.send("I'm not even connected to a voice channel!", delete_after=2)

View File

@ -1,4 +1,5 @@
from .owner import Owner from .owner import Owner
def setup(bot): def setup(bot):
bot.add_cog(Owner(bot)) bot.add_cog(Owner())

View File

@ -65,6 +65,13 @@ class Red(commands.Bot):
"""Lists packages present in the cogs the folder""" """Lists packages present in the cogs the folder"""
return os.listdir("cogs") return os.listdir("cogs")
def save_packages_status(self):
loaded = []
for package in self.extensions:
if package.startswith("cogs."):
loaded.append(package)
self.db.set_global("packages", loaded)
class ExitCodes(Enum): class ExitCodes(Enum):
CRITICAL = 1 CRITICAL = 1

View File

@ -8,7 +8,7 @@ from core.utils.chat_formatting import inline
log = logging.getLogger("red") log = logging.getLogger("red")
def init_events(bot): def init_events(bot, cli_flags):
@bot.event @bot.event
async def on_connect(): async def on_connect():
@ -17,14 +17,33 @@ def init_events(bot):
@bot.event @bot.event
async def on_ready(): async def on_ready():
if bot.uptime is None: if bot.uptime is not None:
return
bot.uptime = datetime.datetime.utcnow() bot.uptime = datetime.datetime.utcnow()
print("Loading cogs...")
# load the packages at this point if cli_flags.no_cogs is False:
total_channels = len([c for c in bot.get_all_channels()]) print("Loading packages...")
total_users = len(set([m for m in bot.get_all_members()])) failed = []
print("Ready and operational on {} servers.\n" packages = bot.db.get_global("packages", [])
"".format(len(bot.guilds)))
for package in packages:
try:
bot.load_extension(package)
except Exception as e:
log.exception("Failed to load package {}".format(package),
exc_info=e)
failed.append(package)
if failed:
bot.save_packages_status()
if packages:
print("Loaded packages: " + ", ".join(packages))
# total_channels = len([c for c in bot.get_all_channels()])
# total_users = len(set([m for m in bot.get_all_members()]))
print("Ready and operational on {} servers.".format(len(bot.guilds)))
@bot.event @bot.event
async def on_command_error(error, ctx): async def on_command_error(error, ctx):
@ -61,7 +80,7 @@ def init_events(bot):
elif isinstance(error, commands.CommandNotFound): elif isinstance(error, commands.CommandNotFound):
pass pass
elif isinstance(error, commands.CheckFailure): elif isinstance(error, commands.CheckFailure):
await ctx.send("") await ctx.send(" You are not authorized to issue that command.")
elif isinstance(error, commands.NoPrivateMessage): elif isinstance(error, commands.NoPrivateMessage):
await ctx.send("That command is not available in DMs.") await ctx.send("That command is not available in DMs.")
elif isinstance(error, commands.CommandOnCooldown): elif isinstance(error, commands.CommandOnCooldown):

View File

@ -1,25 +1,33 @@
from discord.ext import commands from discord.ext import commands
from core import checks from core import checks
from core.utils.chat_formatting import box from core.utils.chat_formatting import box
import logging
import asyncio import asyncio
import importlib import importlib
import os import os
import discord import discord
log = logging.getLogger("red")
class Owner: class Owner:
"""All owner-only commands that relate to debug bot operations.""" """All owner-only commands that relate to debug bot operations."""
def __init__(self, bot):
self.bot = bot
@commands.command() @commands.command()
@checks.is_owner() @checks.is_owner()
async def load(self, ctx, *, cog_name: str): async def load(self, ctx, *, cog_name: str):
"""Loads a package""" """Loads a package"""
if not cog_name.startswith("cogs."): if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name cog_name = "cogs." + cog_name
self.bot.load_extension(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:
ctx.bot.save_packages_status()
await ctx.send("Done.") await ctx.send("Done.")
@commands.group() @commands.group()
@ -28,8 +36,10 @@ class Owner:
"""Unloads a package""" """Unloads a package"""
if not cog_name.startswith("cogs."): if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name cog_name = "cogs." + cog_name
if cog_name in self.bot.extensions:
self.bot.unload_extension(cog_name) if cog_name in ctx.bot.extensions:
ctx.bot.unload_extension(cog_name)
ctx.bot.save_packages_status()
await ctx.send("Done.") await ctx.send("Done.")
else: else:
await ctx.send("That extension is not loaded.") await ctx.send("That extension is not loaded.")
@ -40,9 +50,17 @@ class Owner:
"""Reloads a package""" """Reloads a package"""
if not cog_name.startswith("cogs."): if not cog_name.startswith("cogs."):
cog_name = "cogs." + cog_name cog_name = "cogs." + cog_name
try:
self.refresh_modules(cog_name) self.refresh_modules(cog_name)
self.bot.unload_extension(cog_name) ctx.bot.unload_extension(cog_name)
self.bot.load_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:
ctx.bot.save_packages_status()
await ctx.send("Done.") await ctx.send("Done.")
def refresh_modules(self, module): def refresh_modules(self, module):
@ -69,7 +87,7 @@ class Owner:
result = None result = None
global_vars = globals().copy() global_vars = globals().copy()
global_vars['bot'] = self.bot global_vars['bot'] = ctx.bot
global_vars['ctx'] = ctx global_vars['ctx'] = ctx
global_vars['message'] = ctx.message global_vars['message'] = ctx.message
global_vars['author'] = ctx.message.author global_vars['author'] = ctx.message.author
@ -109,7 +127,7 @@ class Owner:
ctx.message.author = user ctx.message.author = user
ctx.message.content = ctx.prefix + command ctx.message.content = ctx.prefix + command
await self.bot.process_commands(ctx.message) await ctx.bot.process_commands(ctx.message)
ctx.message.author = old_author ctx.message.author = old_author
ctx.message.content = old_content ctx.message.content = old_content

View File

@ -57,7 +57,7 @@ if __name__ == '__main__':
description = "Red v3 - Alpha" description = "Red v3 - Alpha"
red = Red(cli_flags, description=description, pm_help=None) red = Red(cli_flags, description=description, pm_help=None)
init_global_checks(red) init_global_checks(red)
init_events(red) init_events(red, cli_flags)
red.load_extension('core') red.load_extension('core')
if cli_flags.dev: if cli_flags.dev:
pass # load dev cog here? pass # load dev cog here?