feat: logs

This commit is contained in:
2025-08-29 21:11:36 +02:00
parent 544571829b
commit b0141bf391
12 changed files with 101 additions and 43 deletions

View File

@@ -4,6 +4,8 @@ import requests
from google import genai
from google.genai import types
from bot.log import logger
API_KEY = os.getenv("GOOGLE_API_KEY")
GENERIC_INSTRUCTION = "You are a Discord chatbot named 'AlterWare' who helps users with all kinds of topics across various subjects. You should limit your answers to fewer than 2000 characters."
@@ -19,7 +21,7 @@ class DiscourseSummarizer:
self.discourse_data = None
if not API_KEY:
print("Google API key is not set. Please contact the administrator.")
logger.error("Google API key is not set. Please contact the administrator.")
return
self.client = genai.Client(api_key=API_KEY)
@@ -50,7 +52,7 @@ class DiscourseSummarizer:
ttl=self.ttl,
),
)
print(f"Cached content created: {self.cache.name}")
logger.info("Cached content created: %s", self.cache.name)
def update_cache(self):
"""
@@ -64,7 +66,7 @@ class DiscourseSummarizer:
self.client.caches.update(
name=self.cache.name, config=types.UpdateCachedContentConfig(ttl="21600s")
)
print("Cache updated.")
logger.info("Cache updated.")
def ask(self, prompt):
"""

View File

@@ -5,6 +5,7 @@ import discord
from discord import app_commands
from bot.config import message_patterns, update_patterns
from bot.log import logger
from bot.utils import compile_stats, fetch_game_stats, perform_search
from database import add_pattern, add_user_to_blacklist, is_user_blacklisted
@@ -128,4 +129,4 @@ async def setup(bot):
await bot.tree.sync(guild=discord.Object(id=GUILD_ID)) # Force sync
print("Commands extension loaded!")
logger.info("Commands extension loaded!")

View File

@@ -1,6 +1,7 @@
import csv
import os
from bot.log import logger
from database import get_patterns
message_patterns = get_patterns()
@@ -9,7 +10,7 @@ message_patterns = get_patterns()
def update_patterns(regex: str, response: str):
"""update patterns in memory."""
message_patterns.append({"regex": regex, "response": response})
print(f"Pattern added in memory: {regex}")
logger.info(f"Pattern added in memory: {regex}")
def load_chat_messages(csv_path="chat/chat_messages.csv"):
@@ -24,7 +25,7 @@ def load_chat_messages(csv_path="chat/chat_messages.csv"):
"""
messages = []
if not os.path.exists(csv_path):
print(f"CSV file not found: {csv_path}")
logger.info(f"CSV file not found: {csv_path}")
return messages
with open(csv_path, newline="", encoding="utf-8") as csvfile:

View File

@@ -3,6 +3,8 @@ import os
import requests
from bs4 import BeautifulSoup
from bot.log import logger
DISCOURSE_BASE_URL = os.getenv("DISCOURSE_BASE_URL")
API_KEY = os.getenv("DISCOURSE_API_KEY")
API_USERNAME = os.getenv("DISCOURSE_API_USERNAME")
@@ -23,8 +25,11 @@ def get_topics_by_id(topic_id):
response = requests.get(f"{DISCOURSE_BASE_URL}/t/{topic_id}.json", headers=headers)
if response.status_code == 200:
return response.json()
elif response.status_code == 403:
logger.error(f"Access forbidden for topic {topic_id}: {response.status_code}")
return None
else:
print(
logger.error(
f"Error fetching topic {topic_id}: {response.status_code} - {response.text}"
)
return None
@@ -56,8 +61,11 @@ def get_topics_by_tag(tag_name):
for post in posts:
cooked_strings.append(post.get("cooked", ""))
return cooked_strings
elif response.status_code == 403:
logger.error(f"Access forbidden for topic {topic_id}: {response.status_code}")
return None
else:
print(
logger.error(
f"Error fetching topics with tag '{tag_name}': {response.status_code} - {response.text}"
)
return []

View File

@@ -8,6 +8,7 @@ from bot.events_handlers import (
handle_reaction_add,
handle_voice_state_update,
)
from bot.log import logger
async def setup(bot):
@@ -43,4 +44,4 @@ async def setup(bot):
async def on_voice_state_update(member, before, after):
await handle_voice_state_update(member, before, after, bot)
print("Events extension loaded!")
logger.info("Events extension loaded!")

View File

@@ -4,6 +4,7 @@ from datetime import timedelta
import discord
from bot.ai.handle_request import forward_to_google_api
from bot.log import logger
from bot.utils import aware_utcnow, timeout_member
from database import add_user_to_role
@@ -89,11 +90,15 @@ async def handle_bot_mention(message, bot, no_context=False):
image_object = fetch_image_from_message(referenced_message)
except discord.NotFound:
print("Referenced message not found.")
logger.error("Referenced message not found.")
except discord.Forbidden:
print("Bot does not have permission to fetch the referenced message.")
logger.error(
"Bot does not have permission to fetch the referenced message."
)
except discord.HTTPException as e:
print(f"An error occurred while fetching the referenced message: {e}")
logger.error(
"An error occurred while fetching the referenced message: %s", e
)
# Pass the reply content to forward_to_google_api
await forward_to_google_api(message, bot, image_object, reply_content, no_context)
@@ -162,7 +167,7 @@ async def is_message_a_duplicate(message):
time_difference = current_time - message_time
if time_difference >= timedelta(minutes=5):
print(
logger.debug(
f"Message is probably not a duplicate. Time difference: {time_difference}"
)
continue
@@ -174,9 +179,11 @@ async def is_message_a_duplicate(message):
await timeout_member(member)
return
except discord.Forbidden:
print(f"Bot does not have permission to read messages in {channel.name}.")
logger.error(
f"Bot does not have permission to read messages in {channel.name}."
)
except discord.HTTPException as e:
print(f"An error occurred: {e}")
logger.error("An error occurred: %s", e)
async def was_message_replied_by_bot(message, bot):

View File

@@ -2,6 +2,8 @@ import asyncio
import discord
from bot.log import logger
MP3_PATH = "sounds/hello.mp3"
@@ -29,4 +31,4 @@ async def handle_voice_state_update(member, before, after, bot):
await vc.disconnect()
except Exception as e:
print(f"Error: {e}")
logger.error("Error: %s", e)

23
bot/log.py Normal file
View File

@@ -0,0 +1,23 @@
import logging
import logging.handlers
import os
log_dir = "/bot-data"
os.makedirs(log_dir, exist_ok=True)
logger = logging.getLogger("discord")
logger.setLevel(logging.INFO)
logging.getLogger("discord.http").setLevel(logging.INFO)
handler = logging.handlers.RotatingFileHandler(
filename=os.path.join(log_dir, "discord.log"),
encoding="utf-8",
maxBytes=32 * 1024 * 1024, # 32 MiB
backupCount=5, # Rotate through 5 files
)
dt_fmt = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter(
"[{asctime}] [{levelname:<8}] {name}: {message}", dt_fmt, style="{"
)
handler.setFormatter(formatter)
logger.addHandler(handler)

View File

@@ -7,6 +7,7 @@ from discord.ext import commands, tasks
from bot.config import schizo_messages
from bot.discourse.handle_request import combine_posts_text, fetch_cooked_posts
from bot.log import logger
from bot.utils import aware_utcnow, fetch_api_data
from database import migrate_users_with_role
@@ -53,7 +54,9 @@ class SteamSaleChecker(commands.Cog):
channel = self.bot.get_channel(channel_id)
if channel is None:
print(f"Error: Channel ID {channel_id} for {game_name} not found.")
logger.error(
f"Error: Channel ID {channel_id} for {game_name} not found."
)
return
steam_api_url = (
@@ -65,7 +68,9 @@ class SteamSaleChecker(commands.Cog):
data = response.json().get(str(app_id), {}).get("data", {})
if not data:
print(f"Warning: No data returned for {game_name}. Skipping...")
logger.warning(
f"Warning: No data returned for {game_name}. Skipping..."
)
return
price_info = data.get("price_overview", {})
@@ -113,7 +118,7 @@ class SteamSaleChecker(commands.Cog):
await channel.send(embed=embed)
except requests.RequestException as e:
print(f"Error fetching Steam sale data for {game_name}: {e}")
logger.error("Error fetching Steam sale data for %s: %s", game_name, e)
@check_steam_sale.before_loop
async def before_check_steam_sale(self):
@@ -134,16 +139,16 @@ class DiscourseUpdater(commands.Cog):
Periodically fetches and updates Discourse data for the bot.
"""
tag_name = "docs"
print("Fetching Discourse data...")
logger.info("Fetching Discourse data...")
cooked_posts = fetch_cooked_posts(tag_name)
if cooked_posts:
combined_text = combine_posts_text(
[{"cooked": post} for post in cooked_posts]
)
self.bot.ai_helper.set_discourse_data(combined_text)
print("Discourse data updated successfully.")
logger.info("Discourse data updated successfully.")
else:
print(f"No posts found for tag '{tag_name}'.")
logger.warning(f"No posts found for tag '{tag_name}'.")
@update_discourse_data.before_loop
async def before_update_discourse_data(self):
@@ -167,7 +172,7 @@ async def setup(bot):
now = aware_utcnow()
remaining_seconds = int((TARGET_DATE - now).total_seconds())
print(f"Seconds until August 12, 2036, UTC: {remaining_seconds}")
logger.info(f"Seconds until August 12, 2036, UTC: {remaining_seconds}")
channel = bot.get_channel(OFFTOPIC_CHANNEL)
if channel:
@@ -180,9 +185,11 @@ async def setup(bot):
"The heat death of the universe has come and gone. We exist in a post-time void. Nothing remains but this message."
)
else:
print("Debug: Channel not found. Check the OFFTOPIC_CHANNEL variable.")
logger.debug(
"Debug: Channel not found. Check the OFFTOPIC_CHANNEL variable."
)
except Exception as e:
print(f"An error occurred in heat_death task: {e}")
logger.error("An error occurred in heat_death task: %s", e)
@tasks.loop(hours=5)
async def shizo_message():
@@ -191,7 +198,7 @@ async def setup(bot):
message = random.choice(schizo_messages)
await channel.send(message)
else:
print("Debug: Channel not found or schizo_messages is empty.")
logger.debug("Debug: Channel not found or schizo_messages is empty.")
@tasks.loop(hours=24)
async def share_dementia_image():
@@ -200,7 +207,9 @@ async def setup(bot):
for _ in range(3):
await channel.send(DEMENTIA_URL)
else:
print("Debug: Channel not found. Check the OFFTOPIC_CHANNEL variable.")
logger.debug(
"Debug: Channel not found. Check the OFFTOPIC_CHANNEL variable."
)
await migrate_all_users(bot)
@@ -212,4 +221,4 @@ async def setup(bot):
await bot.add_cog(SteamSaleChecker(bot))
await bot.add_cog(DiscourseUpdater(bot))
print("Tasks extension loaded!")
logger.info("Tasks extension loaded!")

View File

@@ -5,6 +5,8 @@ from datetime import datetime, timedelta, timezone
import discord
import requests
from bot.log import logger
def aware_utcnow():
return datetime.now(timezone.utc)
@@ -73,24 +75,24 @@ async def timeout_member(
reason: str = "Requested by the bot",
):
if not member:
print("Debug: Member is None. Skipping timeout.")
logger.error("Member is None. Skipping timeout.")
return
try:
# Debug: Print the member object and timeout duration
print(f"Debug: Attempting to timeout member {member} (ID: {member.id}).")
print(f"Debug: Timeout duration set to {duration}.")
print(f"Debug: Reason: {reason}")
logger.debug(f"Debug: Attempting to timeout member {member} (ID: {member.id}).")
logger.debug(f"Debug: Timeout duration set to {duration}.")
logger.debug(f"Debug: Reason: {reason}")
await member.timeout(duration, reason=reason)
print(f"Debug: Successfully timed out {member}.")
logger.info(f"Successfully timed out {member}.")
except discord.Forbidden:
print(f"Debug: Bot lacks permissions to timeout member {member}.")
logger.error(f"Bot lacks permissions to timeout member {member}.")
except discord.HTTPException as e:
print(f"Debug: HTTPException occurred: {e}")
logger.error("HTTPException occurred: %s", e)
except Exception as e:
print(f"Debug: Unexpected error occurred: {e}")
logger.error("Unexpected error occurred: %s", e)
# Check if a username is valid