Source code for tradeexecutor.cli.discord

"""Send images to the Discord logger."""

import logging
import os
from io import BytesIO
from typing import Optional

from discord_logging.handler import DiscordHandler
from discord_webhook import DiscordWebhook

from tradeexecutor.cli.log import setup_discord_logging, setup_logging


logger = logging.getLogger(__name__)


[docs]def get_discord_logging_handler() -> Optional[DiscordHandler]: """See" log.py https://stackoverflow.com/a/3630800/315168 """ root = logging.getLogger() for handler in root.handlers: if isinstance(handler, DiscordHandler): return handler return None
[docs]def post_logging_discord_image(image: bytes): """Post an image to Discord to the Discord logging channel. It's a bit broken abstraction here, as we do not specifically pass the Discord webhook data around. We will just grab it from the active logger and post using those credentials. If no Discord logger is active do nothing. """ assert isinstance(image, bytes), f"Expected bytes, got {type(images)}" handler = get_discord_logging_handler() if not handler: return discord = DiscordWebhook( url=handler.webhook_url, username=handler.service_name, rate_limit_retry=handler.rate_limit_retry, avatar_url=handler.avatar_url, timeout=60, ) discord.add_file(image, "strategy-state.png") try: discord.execute() except Exception: logger.error("Failed to post image to Discord", exc_info=True)
if __name__ == "__main__": # Manually test image posting setup_logging() setup_discord_logging("Imaeg log test", os.environ["DISCORD_WEBHOOK_URL"]) with open("/tmp/test-image.png", "rb") as inp: image_data = inp.read() post_logging_discord_image(image_data)