aboutsummaryrefslogtreecommitdiffstats
path: root/bot/bot.py
diff options
context:
space:
mode:
authorGravatar kwzrd <[email protected]>2020-03-29 14:29:36 +0200
committerGravatar kwzrd <[email protected]>2020-03-29 14:43:41 +0200
commitabc62d3e09a39decfdd400ed6f2e9c631ef2eca1 (patch)
treeb3b906932568f34b3425a82aeac87c6d74a9f674 /bot/bot.py
parentDeseasonify: 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.py32
1 files changed, 30 insertions, 2 deletions
diff --git a/bot/bot.py b/bot/bot.py
index 76ce5607..0809f7a5 100644
--- a/bot/bot.py
+++ b/bot/bot.py
@@ -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."""