Add Discord webhook notifications for bot restarts

Sends instant notifications to Discord when the bot restarts, helping
track stability issues and auto-recovery events.

Changes:
- Add notify_restart.py script to send webhook notifications
- Integrate notification into bot startup (on_ready event)

The notification includes:
- Timestamp of restart (CST)
- Reason (healthcheck failure detection)
- Reference to diagnostics logs

Configuration:
Set RESTART_WEBHOOK_URL environment variable in docker-compose.yml
to enable notifications.

This provides immediate visibility when Docker auto-restarts the bot
due to crashes or healthcheck failures.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-02-03 23:19:24 -06:00
parent 90d7345850
commit 4c39e9c0ce
2 changed files with 59 additions and 0 deletions

55
notify_restart.py Normal file
View File

@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""
Notify admin channel when bot restarts due to healthcheck failure.
Uses Discord webhook for instant notification.
"""
import os
import urllib.request
import json
from datetime import datetime
def send_restart_notification():
"""Send notification to Discord via webhook."""
webhook_url = os.getenv("RESTART_WEBHOOK_URL")
if not webhook_url:
print("No RESTART_WEBHOOK_URL configured, skipping notification")
return False
try:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S CST")
data = {
"content": (
f"**Paper Dynasty Bot Auto-Restarted** at {timestamp}\n\n"
"Healthcheck detected bot was offline/frozen. "
"Bot has been automatically restarted.\n\n"
"Check `/logs/restart_diagnostics.log` for details."
),
"username": "Paper Dynasty Monitor",
}
req = urllib.request.Request(
webhook_url,
data=json.dumps(data).encode("utf-8"),
headers={"Content-Type": "application/json"},
)
response = urllib.request.urlopen(req, timeout=5)
if response.status == 204:
print(f"Restart notification sent successfully at {timestamp}")
return True
else:
print(f"Webhook returned status {response.status}")
return False
except Exception as e:
print(f"Failed to send restart notification: {e}")
return False
if __name__ == "__main__":
send_restart_notification()

View File

@ -9,6 +9,7 @@ from discord.ext import commands
from in_game.gameplay_models import create_db_and_tables from in_game.gameplay_models import create_db_and_tables
from health_server import run_health_server from health_server import run_health_server
from notify_restart import send_restart_notification
raw_log_level = os.getenv('LOG_LEVEL') raw_log_level = os.getenv('LOG_LEVEL')
if raw_log_level == 'DEBUG': if raw_log_level == 'DEBUG':
@ -70,6 +71,9 @@ async def on_ready():
logger.info(bot.user.name) logger.info(bot.user.name)
logger.info(bot.user.id) logger.info(bot.user.id)
# Send restart notification if configured
send_restart_notification()
@bot.tree.error @bot.tree.error
async def on_app_command_error(interaction: discord.Interaction, error: discord.app_commands.AppCommandError): async def on_app_command_error(interaction: discord.Interaction, error: discord.app_commands.AppCommandError):