[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 from .installable import Installable
class InstalledCog(commands.Converter): class InstalledCog(Installable):
async def convert(self, ctx: commands.Context, arg: str) -> Installable: @classmethod
async def convert(cls, ctx: commands.Context, arg: str) -> Installable:
downloader = ctx.bot.get_cog("Downloader") downloader = ctx.bot.get_cog("Downloader")
if downloader is None: if downloader is None:
raise commands.CommandError("Downloader not loaded.") raise commands.CommandError("Downloader not loaded.")

View File

@ -1,16 +1,20 @@
import asyncio
import contextlib
import os import os
import shutil import shutil
import sys import sys
from pathlib import Path from pathlib import Path
from sys import path as syspath from sys import path as syspath
from typing import Tuple, Union from typing import Tuple, Union, Iterable
import discord import discord
from redbot.core import checks, commands, Config from redbot.core import checks, commands, Config
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.data_manager import cog_data_path from redbot.core.data_manager import cog_data_path
from redbot.core.i18n import Translator, cog_i18n 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 . import errors
from .checks import do_install_agreement from .checks import do_install_agreement
@ -108,7 +112,7 @@ class Downloader(commands.Cog):
installed.remove(cog_json) installed.remove(cog_json)
await self.conf.installed.set(installed) 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. Installs a list of cogs, used when updating.
:param cogs: :param cogs:
@ -122,7 +126,7 @@ class Downloader(commands.Cog):
# noinspection PyTypeChecker # noinspection PyTypeChecker
return tuple(failed) 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 Reinstalls any shared libraries from the repos of cogs that
were updated. were updated.
@ -142,7 +146,7 @@ class Downloader(commands.Cog):
# noinspection PyTypeChecker # noinspection PyTypeChecker
return tuple(failed) 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. Reinstalls requirements for given cogs that have been updated.
Returns a bool that indicates if all requirement installations Returns a bool that indicates if all requirement installations
@ -356,6 +360,7 @@ class Downloader(commands.Cog):
""" """
installed_cogs = set(await self.installed_cogs()) installed_cogs = set(await self.installed_cogs())
async with ctx.typing():
if cog_name is None: if cog_name is None:
updated = await self._repo_manager.update_all_repos() updated = await self._repo_manager.update_all_repos()
@ -366,18 +371,52 @@ class Downloader(commands.Cog):
# Thrown if the repo no longer exists # Thrown if the repo no longer exists
updated = {} 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 installed_and_updated = updated_cogs & installed_cogs
# noinspection PyTypeChecker if installed_and_updated:
await self._reinstall_requirements(installed_and_updated) await self._reinstall_requirements(installed_and_updated)
# noinspection PyTypeChecker
await self._reinstall_cogs(installed_and_updated) await self._reinstall_cogs(installed_and_updated)
# noinspection PyTypeChecker
await self._reinstall_libraries(installed_and_updated) 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") @cog.command(name="list")
async def _cog_list(self, ctx, repo_name: Repo): async def _cog_list(self, ctx, repo_name: Repo):

View File

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