diff options
author | 2020-03-29 14:29:36 +0200 | |
---|---|---|
committer | 2020-03-29 14:43:41 +0200 | |
commit | abc62d3e09a39decfdd400ed6f2e9c631ef2eca1 (patch) | |
tree | b3b906932568f34b3425a82aeac87c6d74a9f674 /bot/bot.py | |
parent | Deseasonify: add AssetType enum (diff) |
Deseasonify: implement generic media asset setter
Current `set_avatar`, `set_icon` and `set_banner` methods are almost
identical - they only differ in the type of asset they upload. This
leads to a lot of code repetition, especially w.r.t. error handling.
We instead add a generic method that is parametrized by an AssetType
param, and by the target entity (i.e. bot, or guild) that the asset
should be applied to. All error handling can then be done in one place.
Error handling methodology is adjusted - instead of suppressing errors,
we catch and log them. Since we no longer determine whether the upload
succeeded based on 'before' != 'after', this solves a bug where
re-applying the same asset resulted in a warning-level log, triggering
Sentry.
Diffstat (limited to 'bot/bot.py')
-rw-r--r-- | bot/bot.py | 32 |
1 files changed, 30 insertions, 2 deletions
@@ -2,12 +2,12 @@ import asyncio import enum import logging import socket -from typing import Optional +from typing import Optional, Union import async_timeout import discord from aiohttp import AsyncResolver, ClientSession, TCPConnector -from discord import DiscordException, Embed +from discord import DiscordException, Embed, Guild, User from discord.ext import commands from bot.constants import Channels, Client @@ -85,6 +85,34 @@ class SeasonalBot(commands.Bot): return None return guild.me + async def _apply_asset(self, target: Union[Guild, User], asset: AssetType, url: str) -> bool: + """ + Internal method for applying media assets to the guild or the bot. + + This shouldn't be called directly. The purpose of this method is mainly generic + error handling to reduce needless code repetition. + + Return True if upload was successful, False otherwise. + """ + log.info(f"Attempting to set {asset.name}: {url}") + + kwargs = {asset.value: await self._fetch_image(url)} + try: + async with async_timeout.timeout(5): + await target.edit(**kwargs) + + except asyncio.TimeoutError: + log.info("Asset upload timed out") + return False + + except discord.HTTPException as discord_error: + log.exception("Asset upload failed", exc_info=discord_error) + return False + + else: + log.info(f"Asset successfully applied") + return True + @mock_in_debug(return_value=True) async def set_avatar(self, url: str) -> bool: """Sets the bot's avatar based on a URL.""" |