From 4e71c3334434e436dc118d92f1dc5efde7f18634 Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sat, 20 Sep 2025 11:02:05 -0500 Subject: [PATCH] Reapply bug fixes to branch --- cogs/transactions.py | 203 +++++++++++++++++++++++++------------------ helpers.py | 33 +++++-- 2 files changed, 148 insertions(+), 88 deletions(-) diff --git a/cogs/transactions.py b/cogs/transactions.py index 06f996b..a76c1f0 100644 --- a/cogs/transactions.py +++ b/cogs/transactions.py @@ -294,13 +294,39 @@ class SBaTransaction: return True return False - def get_gms(self, bot, team=None): + async def get_gms(self, bot, team=None): if team is None: - return [bot.get_user(x) for x in self.gms] + gms = [] + for gm_id in self.gms: + try: + user = await bot.fetch_user(gm_id) + if user: + gms.append(user) + except discord.NotFound: + logger.warning(f'User {gm_id} not found') + except Exception as e: + logger.error(f'Error fetching user {gm_id}: {e}') + return gms else: - these_gms = [bot.get_user(self.teams[team]['team']['gmid'])] + these_gms = [] + try: + user = await bot.fetch_user(self.teams[team]['team']['gmid']) + if user: + these_gms.append(user) + except discord.NotFound: + logger.warning(f'User {self.teams[team]["team"]["gmid"]} not found') + except Exception as e: + logger.error(f'Error fetching user {self.teams[team]["team"]["gmid"]}: {e}') + if self.teams[team]['team']['gmid2']: - these_gms.append(bot.get_user(self.teams[team]['team']['gmid2'])) + try: + user = await bot.fetch_user(self.teams[team]['team']['gmid2']) + if user: + these_gms.append(user) + except discord.NotFound: + logger.warning(f'User {self.teams[team]["team"]["gmid2"]} not found') + except Exception as e: + logger.error(f'Error fetching user {self.teams[team]["team"]["gmid2"]}: {e}') return these_gms async def send(self, content=None, embed=None): @@ -414,11 +440,11 @@ class SBaTransaction: # If player is leaving this team, remove from roster and subtract WARa if x['oldteam'] == this_team: - team_roster.remove(x['player']) + team_roster = [p for p in team_roster if p['id'] != x['player']['id']] wara -= x['player']['wara'] # If player is leaving MiL team, remove from roster and subtract WARa elif x['oldteam']['abbrev'] == f'{this_team["abbrev"]}MiL': - mil_roster.remove(x['player']) + mil_roster = [p for p in mil_roster if p['id'] != x['player']['id']] mil_wara -= x['player']['wara'] logger.info(f'updating rosters') @@ -440,7 +466,7 @@ class SBaTransaction: if self.players[x]['player']['team'] == this_team: logger.info(f'major league player') # logger.info(f'team roster: {team_roster}') - team_roster.remove(self.players[x]['player']) + team_roster = [p for p in team_roster if p['id'] != self.players[x]['player']['id']] # 06-13: COMMENTED OUT TO RESOLVE MID-WEEK IL REPLACEMENT BEING SENT BACK DOWN # if self.effective_week != self.current.week: wara -= self.players[x]['player']['wara'] @@ -448,7 +474,7 @@ class SBaTransaction: # If player is leaving MiL team next week, remove from roster and subtract WARa if self.players[x]['player']['team']['abbrev'] == f'{this_team["abbrev"]}MiL': logger.info(f'minor league player') - mil_roster.remove(self.players[x]['player']) + mil_roster = [p for p in mil_roster if p['id'] != self.players[x]['player']['id']] # logger.info(f'mil roster: {mil_roster}') if self.effective_week != self.current.week: mil_wara -= self.players[x]['player']['wara'] @@ -547,6 +573,7 @@ class Transactions(commands.Cog): def __init__(self, bot): self.bot = bot self.trade_season = False + self.weekly_warning_sent = False self.weekly_loop.start() @@ -560,54 +587,64 @@ class Transactions(commands.Cog): @tasks.loop(minutes=1) async def weekly_loop(self): - logger.info(f'Inside weekly_loop') - if OFFSEASON_FLAG: - logger.info(f'Exiting weekly_loop; OFFSEASON_FLAG: {OFFSEASON_FLAG}') - return + try: + logger.info(f'Inside weekly_loop') + if OFFSEASON_FLAG: + logger.info(f'Exiting weekly_loop; OFFSEASON_FLAG: {OFFSEASON_FLAG}') + return - current = await get_current() - now = datetime.datetime.now() - logger.info(f'Datetime: {now} / weekday: {now.weekday()} / current: {current}') + current = await get_current() + now = datetime.datetime.now() + logger.info(f'Datetime: {now} / weekday: {now.weekday()} / current: {current}') - # Begin Freeze - # if now.weekday() == 0 and now.hour == 5 and not current.freeze: # Spring/Summer - if now.weekday() == 0 and now.hour == 0 and not current.freeze: # Fall/Winter - logger.info(f'weekly_loop - setting the freeze') - current.week += 1 - await db_patch('current', object_id=current.id, params=[('week', current.week), ('freeze', True)]) - await self.run_transactions(current) + # Begin Freeze + # if now.weekday() == 0 and now.hour == 5 and not current.freeze: # Spring/Summer + if now.weekday() == 0 and now.hour == 0 and not current.freeze: # Fall/Winter + logger.info(f'weekly_loop - setting the freeze') + current.week += 1 + await db_patch('current', object_id=current.id, params=[('week', current.week), ('freeze', True)]) + await self.run_transactions(current) - logger.debug(f'Building freeze string') - week_num = f'Week {current.week}' - stars = f'{"":*<32}' - freeze_message = f'```\n' \ - f'{stars}\n'\ - f'{week_num: >9} Freeze Period Begins\n' \ - f'{stars}\n```' - logger.debug(f'Freeze string:\n\n{freeze_message}') - await send_to_channel(self.bot, 'transaction-log', freeze_message) + logger.debug(f'Building freeze string') + week_num = f'Week {current.week}' + stars = f'{"":*<32}' + freeze_message = f'```\n' \ + f'{stars}\n'\ + f'{week_num: >9} Freeze Period Begins\n' \ + f'{stars}\n```' + logger.debug(f'Freeze string:\n\n{freeze_message}') + await send_to_channel(self.bot, 'transaction-log', freeze_message) - if current.week > 0 and current.week <= 18: - await self.post_weekly_info(current) + if current.week > 0 and current.week <= 18: + await self.post_weekly_info(current) - # End Freeze - # elif now.weekday() == 5 and now.hour == 5 and current.freeze: # Spring/Summer - elif now.weekday() == 5 and now.hour == 0 and current.freeze: # Fall/Winter - logger.info(f'weekly_loop - running the un-freeze') - await db_patch('current', object_id=current.id, params=[('freeze', False)]) + # End Freeze + # elif now.weekday() == 5 and now.hour == 5 and current.freeze: # Spring/Summer + elif now.weekday() == 5 and now.hour == 0 and current.freeze: # Fall/Winter + logger.info(f'weekly_loop - running the un-freeze') + await db_patch('current', object_id=current.id, params=[('freeze', False)]) - week_num = f'Week {current.week}' - stars = f'{"":*<30}' - freeze_message = f'```\n' \ - f'{stars}\n'\ - f'{week_num: >9} Freeze Period Ends\n' \ - f'{stars}\n```' - await self.process_freeze_moves(current) - await send_to_channel(self.bot, 'transaction-log', freeze_message) - self.trade_season = False - - else: - logger.info(f'weekly_loop - No freeze actions being taken') + week_num = f'Week {current.week}' + stars = f'{"":*<30}' + freeze_message = f'```\n' \ + f'{stars}\n'\ + f'{week_num: >9} Freeze Period Ends\n' \ + f'{stars}\n```' + await self.process_freeze_moves(current) + await send_to_channel(self.bot, 'transaction-log', freeze_message) + self.trade_season = False + + else: + logger.info(f'weekly_loop - No freeze actions being taken') + except Exception as e: + logger.error(f'Unhandled exception in weekly_loop: {e}') + error_message = f"⚠️ **Weekly Freeze Task Failed**\n```\nError: {str(e)}\nTime: {datetime.datetime.now()}\nTask: weekly_loop in transactions.py\n```" + try: + if not self.weekly_warning_sent: + await send_owner_notification(error_message) + self.weekly_warning_sent = True + except Exception as e: + logger.error(f'Failed to send error message :( {e}') @weekly_loop.before_loop async def before_notif_check(self): @@ -1008,7 +1045,7 @@ class Transactions(commands.Cog): while True: prompt = 'Are you adding a team to this deal? (Yes/No)' this_q = Question(self.bot, trade.channel, prompt, 'yesno', 30) - resp = await this_q.ask(trade.get_gms(self.bot)) + resp = await this_q.ask(await trade.get_gms(self.bot)) if resp is None: await trade.send('RIP this move. Maybe next time.') @@ -1019,7 +1056,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Please enter the team\'s abbreviation.' this_q.qtype = 'text' - resp = await this_q.ask(trade.get_gms(self.bot)) + resp = await this_q.ask(await trade.get_gms(self.bot)) if not resp: await trade.send('RIP this move. Maybe next time.') @@ -1040,7 +1077,7 @@ class Transactions(commands.Cog): while True: prompt = f'Are you trading a player between teams?' this_q = Question(self.bot, trade.channel, prompt, 'yesno', 300) - resp = await this_q.ask(trade.get_gms(self.bot)) + resp = await this_q.ask(await trade.get_gms(self.bot)) if resp is None: await trade.send('RIP this move. Maybe next time.') @@ -1051,7 +1088,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Which player is being traded?' this_q.qtype = 'text' - resp = await this_q.ask(trade.get_gms(self.bot)) + resp = await this_q.ask(await trade.get_gms(self.bot)) if not resp: pass @@ -1077,7 +1114,7 @@ class Transactions(commands.Cog): await trade.send(f'Ope. {player["name"]} is already one the move next week.') else: this_q.prompt = 'Where are they going? Please enter the destination team\'s abbreviation.' - resp = await this_q.ask(trade.get_gms(self.bot)) + resp = await this_q.ask(await trade.get_gms(self.bot)) if resp is None: await trade.send('RIP this move. Maybe next time.') @@ -1103,7 +1140,7 @@ class Transactions(commands.Cog): # while True and current.pick_trade_end >= current.week >= current.pick_trade_start: # prompt = f'Are you trading any draft picks?' # this_q = Question(self.bot, trade.channel, prompt, 'yesno', 300) - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # effective_season = current.season if OFFSEASON_FLAG else current.season + 1 # team_season = current.season # @@ -1117,7 +1154,7 @@ class Transactions(commands.Cog): # # Get first pick # this_q.prompt = 'Enter the pick\'s original owner and round number like this: TIT 17' # this_q.qtype = 'text' - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1138,7 +1175,7 @@ class Transactions(commands.Cog): # f'round number, please.') # else: # this_q.prompt = 'Now enter the return pick\'s original owner and round number like this: TIT 17' - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1188,7 +1225,7 @@ class Transactions(commands.Cog): while True: this_q.prompt = f'{trade.teams[team]["role"].mention}\nAre you making an FA drop?' this_q.qtype = 'yesno' - resp = await this_q.ask(trade.get_gms(self.bot, team)) + resp = await this_q.ask(await trade.get_gms(self.bot, team)) if resp is None: await trade.send('RIP this move. Maybe next time.') @@ -1199,7 +1236,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you dropping?' this_q.qtype = 'text' - resp = await this_q.ask(trade.get_gms(self.bot, team)) + resp = await this_q.ask(await trade.get_gms(self.bot, team)) if resp is None: await trade.send('RIP this move. Maybe next time.') @@ -1271,7 +1308,7 @@ class Transactions(commands.Cog): for team in trade.teams: this_q.prompt = f'{trade.teams[team]["role"].mention}\nDo you accept this trade?' this_q.qtype = 'yesno' - resp = await this_q.ask(trade.get_gms(self.bot, team)) + resp = await this_q.ask(await trade.get_gms(self.bot, team)) if not resp: await trade.send('RIP this move. Maybe next time.') @@ -1348,7 +1385,7 @@ class Transactions(commands.Cog): # while True: # prompt = 'Are you adding a team to this deal? (Yes/No)' # this_q = Question(self.bot, trade.channel, prompt, 'yesno', 30) - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if resp is None: # await trade.send('RIP this move. Maybe next time.') @@ -1359,7 +1396,7 @@ class Transactions(commands.Cog): # else: # this_q.prompt = 'Please enter the team\'s abbreviation.' # this_q.qtype = 'text' - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1381,7 +1418,7 @@ class Transactions(commands.Cog): # while True: # prompt = f'Are you trading any draft picks?' # this_q = Question(self.bot, trade.channel, prompt, 'yesno', 300) - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # effective_season = current.season if OFFSEASON_FLAG else current.season + 1 # team_season = current.season # @@ -1395,7 +1432,7 @@ class Transactions(commands.Cog): # # Get first pick # this_q.prompt = 'Enter the overall pick number being traded.' # this_q.qtype = 'int' - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1411,7 +1448,7 @@ class Transactions(commands.Cog): # await trade.send(f'Frick, I couldn\'t find pick #{resp}.') # else: # this_q.prompt = 'Now enter the return pick\'s overall pick number.' - # resp = await this_q.ask(trade.get_gms(self.bot)) + # resp = await this_q.ask(await trade.get_gms(self.bot)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1485,7 +1522,7 @@ class Transactions(commands.Cog): # for team in trade.teams: # this_q.prompt = f'{trade.teams[team]["role"].mention}\nDo you accept this trade?' # this_q.qtype = 'yesno' - # resp = await this_q.ask(trade.get_gms(self.bot, team)) + # resp = await this_q.ask(await trade.get_gms(self.bot, team)) # # if not resp: # await trade.send('RIP this move. Maybe next time.') @@ -1558,7 +1595,7 @@ class Transactions(commands.Cog): while True and not OFFSEASON_FLAG: prompt = f'Are you adding someone to the Minor League roster?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1569,7 +1606,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you sending to the MiL?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1611,7 +1648,7 @@ class Transactions(commands.Cog): while True and not OFFSEASON_FLAG: prompt = f'Are you adding any players to the Major League roster?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1622,7 +1659,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you adding?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1671,7 +1708,7 @@ class Transactions(commands.Cog): while True: prompt = f'Are you dropping anyone to FA?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1682,7 +1719,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you dropping to FA?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1762,7 +1799,7 @@ class Transactions(commands.Cog): for team in dropadd.teams: this_q.prompt = f'{dropadd.teams[team]["role"].mention}\nWould you like me to run this move?' this_q.qtype = 'yesno' - resp = await this_q.ask(dropadd.get_gms(self.bot, team)) + resp = await this_q.ask(await dropadd.get_gms(self.bot, team)) if not resp: await dropadd.send('RIP this move. Maybe next time.') @@ -1844,7 +1881,7 @@ class Transactions(commands.Cog): while True: prompt = f'Are you sending someone to the IL?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1855,7 +1892,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you sending to the IL?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1887,7 +1924,7 @@ class Transactions(commands.Cog): while True and not OFFSEASON_FLAG: prompt = f'Are you adding someone to the Major League team?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1898,7 +1935,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you adding?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1929,7 +1966,7 @@ class Transactions(commands.Cog): while True and not OFFSEASON_FLAG: prompt = f'Are you adding someone to the Minor League team?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1940,7 +1977,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you sending to the MiL?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1975,7 +2012,7 @@ class Transactions(commands.Cog): while True: prompt = f'Are you dropping anyone to FA?' this_q = Question(self.bot, dropadd.channel, prompt, 'yesno', 300) - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -1986,7 +2023,7 @@ class Transactions(commands.Cog): else: this_q.prompt = 'Who are you dropping to FA?' this_q.qtype = 'text' - resp = await this_q.ask(dropadd.get_gms(self.bot)) + resp = await this_q.ask(await dropadd.get_gms(self.bot)) if resp is None: await dropadd.send('RIP this move. Maybe next time.') @@ -2055,7 +2092,7 @@ class Transactions(commands.Cog): for team in dropadd.teams: this_q.prompt = f'{dropadd.teams[team]["role"].mention}\nWould you like me to run this move?' this_q.qtype = 'yesno' - resp = await this_q.ask(dropadd.get_gms(self.bot, team)) + resp = await this_q.ask(await dropadd.get_gms(self.bot, team)) if not resp: await dropadd.send('RIP this move. Maybe next time.') diff --git a/helpers.py b/helpers.py index 20849f4..3f64bf2 100644 --- a/helpers.py +++ b/helpers.py @@ -14,6 +14,7 @@ import json import discord import requests +import aiohttp from discord.ext import commands from difflib import get_close_matches @@ -214,9 +215,12 @@ class Question: def text(mes): return mes.channel == self.channel and mes.author in responders + logger.info(f'Sending watched message') await self.channel.send(content=self.prompt, embed=self.embed) + logger.info(f'message is sent') try: + logger.info(f'waiting for a response') resp = await self.bot.wait_for( 'message', timeout=self.timeout, @@ -865,7 +869,7 @@ async def get_player_embed(player, current, ctx=None, season=None): embed.add_field(name='P Injury', value=f'{player["pitcher_injury"]} (6-{13 - player["pitcher_injury"]})') else: embed.add_field(name='P Injury', value=f'{player["pitcher_injury"]} (---)') - if d_query['count'] > 0: + if d_query and d_query.get('count') > 0: pick = d_query['picks'][0] num = pick["overall"] % 16 if num == 0: @@ -896,7 +900,7 @@ async def get_player_embed(player, current, ctx=None, season=None): b_query = await db_get('battingstats/totals', params=[ ('season', player['season']), ('player_id', player['id']), ('s_type', 'regular')]) - if b_query['count'] > 0: + if b_query and b_query.get('count') > 0: b = b_query['stats'][0] if b['ab'] > 0: @@ -927,7 +931,7 @@ async def get_player_embed(player, current, ctx=None, season=None): p_query = await db_get('pitchingstats/totals', params=[ ('season', player['season']), ('player_id', player['id']), ('s_type', 'regular')]) - if p_query['count'] > 0: + if p_query and p_query.get('count') > 0: p = p_query['stats'][0] if p['ip'] > 0: @@ -967,7 +971,7 @@ async def get_player_embed(player, current, ctx=None, season=None): batter_priority = True b, p, batting_string, pitching_string = None, None, None, None - if b_query['count'] > 0: + if b_query and b_query.get('count') > 0: b = b_query['stats'][0] batting_string = f'```\n' \ f' AVG OBP SLG\n' \ @@ -977,7 +981,7 @@ async def get_player_embed(player, current, ctx=None, season=None): f' PA H RBI 2B 3B HR SB\n' \ f'{b["pa"]: >3} {b["hit"]: ^3} {b["rbi"]: ^3} {b["double"]: >2} {b["triple"]: >2} ' \ f'{b["hr"]: >2} {b["sb"]: >2}```\n' - if p_query['count'] > 0: + if p_query and p_query.get('count') > 0: p = p_query['stats'][0] if b is None or p["tbf"] > b["pa"]: batter_priority = False @@ -1183,3 +1187,22 @@ def random_from_list(data_list: list): def get_team_url(this_team): return f'https://sba.manticorum.com/teams/{this_team["season"]}/{this_team["abbrev"]}' + + +async def send_owner_notification(message: str): + """ + Send a notification message to the bot owner via Discord webhook. + + Args: + message (str): The message content to send + """ + logger = logging.getLogger('discord_app') + try: + async with aiohttp.ClientSession() as session: + webhook_url = "https://discord.com/api/webhooks/1408811717424840876/7RXG_D5IqovA3Jwa9YOobUjVcVMuLc6cQyezABcWuXaHo5Fvz1en10M7J43o3OJ3bzGW" + payload = { + "content": message + } + await session.post(webhook_url, json=payload) + except Exception as webhook_error: + logger.error(f'Failed to send owner notification: {webhook_error}')