[Downloader] Better user facing feedback on cog update (#2165)

This commit is contained in:
Michael H 2018-10-05 18:24:55 -04:00 committed by Toby Harradine
parent fb839084fe
commit d79996aeea
3 changed files with 67 additions and 29 deletions

View File

@ -3,8 +3,9 @@ from redbot.core import commands
from .installable import Installable
class InstalledCog(commands.Converter):
async def convert(self, ctx: commands.Context, arg: str) -> Installable:
class InstalledCog(Installable):
@classmethod
async def convert(cls, ctx: commands.Context, arg: str) -> Installable:
downloader = ctx.bot.get_cog("Downloader")
if downloader is None:
raise commands.CommandError("Downloader not loaded.")

View File

@ -1,16 +1,20 @@
import asyncio
import contextlib
import os
import shutil
import sys
from pathlib import Path
from sys import path as syspath
from typing import Tuple, Union
from typing import Tuple, Union, Iterable
import discord
from redbot.core import checks, commands, Config
from redbot.core.bot import Red
from redbot.core.data_manager import cog_data_path
from redbot.core.i18n import Translator, cog_i18n
from redbot.core.utils.chat_formatting import box, pagify
from redbot.core.utils.chat_formatting import box, pagify, humanize_list, inline
from redbot.core.utils.menus import start_adding_reactions
from redbot.core.utils.predicates import MessagePredicate, ReactionPredicate
from . import errors
from .checks import do_install_agreement
@ -108,7 +112,7 @@ class Downloader(commands.Cog):
installed.remove(cog_json)
await self.conf.installed.set(installed)
async def _reinstall_cogs(self, cogs: Tuple[Installable]) -> Tuple[Installable]:
async def _reinstall_cogs(self, cogs: Iterable[Installable]) -> Tuple[Installable]:
"""
Installs a list of cogs, used when updating.
:param cogs:
@ -122,7 +126,7 @@ class Downloader(commands.Cog):
# noinspection PyTypeChecker
return tuple(failed)
async def _reinstall_libraries(self, cogs: Tuple[Installable]) -> Tuple[Installable]:
async def _reinstall_libraries(self, cogs: Iterable[Installable]) -> Tuple[Installable]:
"""
Reinstalls any shared libraries from the repos of cogs that
were updated.
@ -142,7 +146,7 @@ class Downloader(commands.Cog):
# noinspection PyTypeChecker
return tuple(failed)
async def _reinstall_requirements(self, cogs: Tuple[Installable]) -> bool:
async def _reinstall_requirements(self, cogs: Iterable[Installable]) -> bool:
"""
Reinstalls requirements for given cogs that have been updated.
Returns a bool that indicates if all requirement installations
@ -356,6 +360,7 @@ class Downloader(commands.Cog):
"""
installed_cogs = set(await self.installed_cogs())
async with ctx.typing():
if cog_name is None:
updated = await self._repo_manager.update_all_repos()
@ -366,18 +371,52 @@ class Downloader(commands.Cog):
# Thrown if the repo no longer exists
updated = {}
updated_cogs = set(cog for repo in updated.keys() for cog in repo.available_cogs)
updated_cogs = set(cog for repo in updated for cog in repo.available_cogs)
installed_and_updated = updated_cogs & installed_cogs
# noinspection PyTypeChecker
if installed_and_updated:
await self._reinstall_requirements(installed_and_updated)
# noinspection PyTypeChecker
await self._reinstall_cogs(installed_and_updated)
# noinspection PyTypeChecker
await self._reinstall_libraries(installed_and_updated)
await ctx.send(_("Cog update completed successfully."))
message = _("Cog update completed successfully.")
cognames = [c.name for c in installed_and_updated]
message += _("\nUpdated: ") + humanize_list(tuple(map(inline, cognames)))
else:
await ctx.send(_("All installed cogs are already up to date."))
return
await ctx.send(message)
message = _("Would you like to reload the updated cogs?")
can_react = ctx.channel.permissions_for(ctx.me).add_reactions
if not can_react:
message += " (y/n)"
query: discord.Message = await ctx.send(message)
if can_react:
# noinspection PyAsyncCall
start_adding_reactions(query, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop)
pred = ReactionPredicate.yes_or_no(query, ctx.author)
event = "reaction_add"
else:
pred = MessagePredicate.yes_or_no(ctx)
event = "message"
try:
await ctx.bot.wait_for(event, check=pred, timeout=30)
except asyncio.TimeoutError:
await query.delete()
return
if pred.result is True:
if can_react:
with contextlib.suppress(discord.Forbidden):
await query.clear_reactions()
await ctx.invoke(ctx.bot.get_cog("Core").reload, *cognames)
else:
if can_react:
await query.delete()
else:
await ctx.send(_("OK then."))
@cog.command(name="list")
async def _cog_list(self, ctx, repo_name: Repo):

View File

@ -545,12 +545,10 @@ class Core(commands.Cog, CoreLogic):
@commands.command(name="reload")
@checks.is_owner()
async def reload_(self, ctx, *, cog_name: str):
async def reload(self, ctx, *cogs: str):
"""Reloads packages"""
cog_names = [c.strip() for c in cog_name.split(" ")]
async with ctx.typing():
loaded, failed, not_found = await self._reload(cog_names)
loaded, failed, not_found = await self._reload(cogs)
if loaded:
fmt = "Package{plural} {packs} {other} reloaded."