improve log outputs

This commit is contained in:
rambros3d 2026-03-30 01:26:04 +05:30
parent c581911f68
commit 3f649b3062
3 changed files with 61 additions and 16 deletions

View file

@ -1,17 +1,18 @@
import sys import sys
import logging import logging
from logging.handlers import RotatingFileHandler
from src.ui.main_app import run_disco_reaper_tui from src.ui.main_app import run_disco_reaper_tui
from src.core.configuration import load_config from src.core.configuration import load_config
def setup_logging(): def setup_logging():
try: try:
config = load_config(create_if_missing=False) config = load_config(create_if_missing=False)
log_level_str = config.migration.log_level.upper() log_level_str = config.log_level.upper()
level = getattr(logging, log_level_str, logging.INFO) level = getattr(logging, log_level_str, logging.INFO)
except Exception: except Exception:
level = logging.INFO level = logging.INFO
handlers = [logging.FileHandler('.reaper.log', mode='a')] handlers = [RotatingFileHandler('.reaper.log', mode='a', maxBytes=10*1024*1024, backupCount=3)]
logging.basicConfig( logging.basicConfig(
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
datefmt='%H:%M:%S', datefmt='%H:%M:%S',
@ -92,18 +93,21 @@ def cleanup_old_update():
"""Removes the .old executable left behind by a Windows update.""" """Removes the .old executable left behind by a Windows update."""
import os import os
import sys import sys
from pathlib import Path
if sys.platform != "win32": if sys.platform != "win32":
return return
current_exe = sys.executable if getattr(sys, 'frozen', False) else sys.argv[0]
old_exe = current_exe + ".old"
if os.path.exists(old_exe): # In frozen (PyInstaller) builds, sys.executable points to the temp _MEIxxxxx dir.
# sys.argv[0] always points to the real .exe on disk, so use that and resolve() it.
current_exe = Path(sys.argv[0]).resolve()
old_exe = current_exe.with_suffix(current_exe.suffix + ".old")
if old_exe.exists():
try: try:
os.remove(old_exe) old_exe.unlink()
except Exception: except Exception as e:
pass logging.getLogger(__name__).debug(f"Could not remove old update file {old_exe}: {e}")
def main(): def main():
import os import os

View file

@ -36,6 +36,7 @@ class FluxerWriter:
guilds_list.append((label, str(g.id))) guilds_list.append((label, str(g.id)))
return guilds_list return guilds_list
except Exception as e: except Exception as e:
print(f"Failed to fetch Fluxer communities via HTTP: {e}")
logger.error(f"Failed to fetch Fluxer communities via HTTP: {e}") logger.error(f"Failed to fetch Fluxer communities via HTTP: {e}")
raise raise
@ -61,6 +62,7 @@ class FluxerWriter:
return w return w
except Exception as e: except Exception as e:
print(f"Failed to manage webhook for channel {channel_id}: {e}") print(f"Failed to manage webhook for channel {channel_id}: {e}")
logger.error(f"Failed to manage webhook for channel {channel_id}: {e}")
return None return None
async def start(self): async def start(self):
@ -322,6 +324,7 @@ class FluxerWriter:
logger.debug(f"Fluxer: Webhook send complete, msg_id={msg.id if msg else 'None'}") logger.debug(f"Fluxer: Webhook send complete, msg_id={msg.id if msg else 'None'}")
return str(msg.id) if msg else None return str(msg.id) if msg else None
except asyncio.TimeoutError: except asyncio.TimeoutError:
print(f"Fluxer: Webhook send timed out after 45s for channel {channel_id}")
logger.error(f"Fluxer: Webhook send timed out after 45s for channel {channel_id}") logger.error(f"Fluxer: Webhook send timed out after 45s for channel {channel_id}")
return None return None
else: else:
@ -353,6 +356,7 @@ class FluxerWriter:
logger.debug(f"Fluxer: Bot send complete, msg_id={msg_data.get('id') if msg_data else 'None'}") logger.debug(f"Fluxer: Bot send complete, msg_id={msg_data.get('id') if msg_data else 'None'}")
return str(msg_data["id"]) if msg_data else None return str(msg_data["id"]) if msg_data else None
except asyncio.TimeoutError: except asyncio.TimeoutError:
print(f"Fluxer: Bot send timed out after 45s for channel {channel_id}")
logger.error(f"Fluxer: Bot send timed out after 45s for channel {channel_id}") logger.error(f"Fluxer: Bot send timed out after 45s for channel {channel_id}")
return None return None
except Exception as e: except Exception as e:
@ -386,6 +390,7 @@ class FluxerWriter:
return str(msg_data["id"]) if msg_data else None return str(msg_data["id"]) if msg_data else None
except Exception as e: except Exception as e:
print(f"Failed to send marker: {e}") print(f"Failed to send marker: {e}")
logger.error(f"Failed to send marker: {e}")
return None return None
async def create_role(self, name: str, color: int, hoist: bool, mentionable: bool, permissions: int, position: Optional[int] = None) -> str: async def create_role(self, name: str, color: int, hoist: bool, mentionable: bool, permissions: int, position: Optional[int] = None) -> str:
@ -408,6 +413,7 @@ class FluxerWriter:
return str(role["id"]) return str(role["id"])
except Exception as e: except Exception as e:
print(f"Failed to copy role {name}: {e}") print(f"Failed to copy role {name}: {e}")
logger.error(f"Failed to copy role {name}: {e}")
return "" return ""
async def create_emoji(self, name: str, image_bytes: bytes) -> str: async def create_emoji(self, name: str, image_bytes: bytes) -> str:
@ -473,6 +479,7 @@ class FluxerWriter:
) )
except Exception as e: except Exception as e:
print(f"Failed to update community metadata: {e}") print(f"Failed to update community metadata: {e}")
logger.error(f"Failed to update community metadata: {e}")
async def remove_community_logo_and_banner(self) -> dict: async def remove_community_logo_and_banner(self) -> dict:
""" """
@ -503,6 +510,7 @@ class FluxerWriter:
) )
except Exception as e: except Exception as e:
print(f"Failed to remove community icon: {e}") print(f"Failed to remove community icon: {e}")
logger.error(f"Failed to remove community icon: {e}")
# 3. Remove banner if set # 3. Remove banner if set
if has_banner: if has_banner:
@ -513,6 +521,7 @@ class FluxerWriter:
) )
except Exception as e: except Exception as e:
print(f"Failed to remove community banner: {e}") print(f"Failed to remove community banner: {e}")
logger.error(f"Failed to remove community banner: {e}")
return { return {
"icon": "REMOVED" if has_icon else "SKIP", "icon": "REMOVED" if has_icon else "SKIP",
@ -544,6 +553,7 @@ class FluxerWriter:
await progress_callback(ch.get("name", "Unknown"), deleted, total) await progress_callback(ch.get("name", "Unknown"), deleted, total)
except Exception as e: except Exception as e:
print(f"Failed to delete channel {ch.get('name')}: {e}") print(f"Failed to delete channel {ch.get('name')}: {e}")
logger.error(f"Failed to delete channel {ch.get('name')}: {e}")
return deleted return deleted
async def reset_channel_permissions(self, progress_callback=None) -> int: async def reset_channel_permissions(self, progress_callback=None) -> int:
@ -576,12 +586,14 @@ class FluxerWriter:
) )
) )
except Exception as e: except Exception as e:
print(f"Failed to delete overwrite {ow['id']} for channel {ch['id']}: {e}")
logger.error(f"Failed to delete overwrite {ow['id']} for channel {ch['id']}: {e}") logger.error(f"Failed to delete overwrite {ow['id']} for channel {ch['id']}: {e}")
processed += 1 processed += 1
if progress_callback: if progress_callback:
await progress_callback(ch.get("name", "Unknown"), processed, total) await progress_callback(ch.get("name", "Unknown"), processed, total)
except Exception as e: except Exception as e:
print(f"Failed to reset permissions for channel {ch.get('name')}: {e}") print(f"Failed to reset permissions for channel {ch.get('name')}: {e}")
logger.error(f"Failed to reset permissions for channel {ch.get('name')}: {e}")
return processed return processed
async def set_channel_permission(self, channel_id: str, overwrite_id: str, allow: int, deny: int, is_role: bool = True): async def set_channel_permission(self, channel_id: str, overwrite_id: str, allow: int, deny: int, is_role: bool = True):
@ -603,6 +615,7 @@ class FluxerWriter:
type=0 if is_role else 1 type=0 if is_role else 1
) )
except Exception as e: except Exception as e:
print(f"Failed to set permission on channel {channel_id} for overwrite {overwrite_id}: {e}")
logger.error(f"Failed to set permission on channel {channel_id} for overwrite {overwrite_id}: {e}") logger.error(f"Failed to set permission on channel {channel_id} for overwrite {overwrite_id}: {e}")
@ -644,6 +657,7 @@ class FluxerWriter:
await progress_callback(role.get("name", "Unknown"), deleted, total) await progress_callback(role.get("name", "Unknown"), deleted, total)
except Exception as e: except Exception as e:
print(f"Failed to delete role {role.get('name')}: {e}") print(f"Failed to delete role {role.get('name')}: {e}")
logger.error(f"Failed to delete role {role.get('name')}: {e}")
return deleted return deleted
async def delete_all_emojis_and_stickers(self, progress_callback=None) -> dict: async def delete_all_emojis_and_stickers(self, progress_callback=None) -> dict:
@ -667,8 +681,10 @@ class FluxerWriter:
await progress_callback(emoji.get("name", "Unknown"), "Emoji", emoji_deleted, emoji_total) await progress_callback(emoji.get("name", "Unknown"), "Emoji", emoji_deleted, emoji_total)
except Exception as e: except Exception as e:
print(f"Failed to delete emoji {emoji.get('name')}: {e}") print(f"Failed to delete emoji {emoji.get('name')}: {e}")
logger.error(f"Failed to delete emoji {emoji.get('name')}: {e}")
except Exception as e: except Exception as e:
print(f"Failed to fetch emojis: {e}") print(f"Failed to fetch emojis: {e}")
logger.error(f"Failed to fetch emojis: {e}")
# Delete stickers # Delete stickers
try: try:
@ -682,8 +698,10 @@ class FluxerWriter:
await progress_callback(sticker.get("name", "Unknown"), "Sticker", sticker_deleted, sticker_total) await progress_callback(sticker.get("name", "Unknown"), "Sticker", sticker_deleted, sticker_total)
except Exception as e: except Exception as e:
print(f"Failed to delete sticker {sticker.get('name')}: {e}") print(f"Failed to delete sticker {sticker.get('name')}: {e}")
logger.error(f"Failed to delete sticker {sticker.get('name')}: {e}")
except Exception as e: except Exception as e:
print(f"Failed to fetch stickers: {e}") print(f"Failed to fetch stickers: {e}")
logger.error(f"Failed to fetch stickers: {e}")
return {"emojis": emoji_deleted, "stickers": sticker_deleted} return {"emojis": emoji_deleted, "stickers": sticker_deleted}

View file

@ -58,6 +58,7 @@ class StoatWriter:
else: else:
raise asyncio.TimeoutError("Timed out waiting for Stoat to be ready") raise asyncio.TimeoutError("Timed out waiting for Stoat to be ready")
except Exception as e: except Exception as e:
print(f"Failed to fetch Stoat servers: {e}")
logger.error(f"Failed to fetch Stoat servers: {e}") logger.error(f"Failed to fetch Stoat servers: {e}")
raise raise
finally: finally:
@ -88,6 +89,7 @@ class StoatWriter:
try: try:
self._me = await self.client.fetch_user("@me") self._me = await self.client.fetch_user("@me")
except Exception as e: except Exception as e:
print(f"Failed to fetch bot user in StoatWriter: {e}")
logger.error(f"Failed to fetch bot user in StoatWriter: {e}") logger.error(f"Failed to fetch bot user in StoatWriter: {e}")
self.client = None # Reset if we can't even fetch @me self.client = None # Reset if we can't even fetch @me
@ -235,6 +237,7 @@ class StoatWriter:
return results return results
except Exception as e: except Exception as e:
print(f"Failed to fetch Stoat channels: {e}")
logger.error(f"Failed to fetch Stoat channels: {e}") logger.error(f"Failed to fetch Stoat channels: {e}")
return [] return []
@ -272,6 +275,7 @@ class StoatWriter:
self._server = None # Clear cache self._server = None # Clear cache
return str(ch.id) return str(ch.id)
except Exception as e: except Exception as e:
print(f"Failed to create Stoat channel {name}: {e}")
logger.error(f"Failed to create Stoat channel {name}: {e}") logger.error(f"Failed to create Stoat channel {name}: {e}")
return "" return ""
@ -297,6 +301,7 @@ class StoatWriter:
# clone_server.py now handles all parenting bulk logic # clone_server.py now handles all parenting bulk logic
return True return True
except Exception as e: except Exception as e:
print(f"Failed to modify Stoat channel {channel_id}: {e}")
logger.error(f"Failed to modify Stoat channel {channel_id}: {e}") logger.error(f"Failed to modify Stoat channel {channel_id}: {e}")
return False return False
@ -419,6 +424,7 @@ class StoatWriter:
return str(msg.id) if msg else None return str(msg.id) if msg else None
raise # Re-raise MissingPermission and other errors raise # Re-raise MissingPermission and other errors
except Exception as e: except Exception as e:
print(f"Failed to send Stoat message to {channel_id}: {e}")
logger.error(f"Failed to send Stoat message to {channel_id}: {e}") logger.error(f"Failed to send Stoat message to {channel_id}: {e}")
raise # Let caller handle (migration loop will stop for permission errors) raise # Let caller handle (migration loop will stop for permission errors)
@ -442,6 +448,7 @@ class StoatWriter:
) )
return str(msg.id) return str(msg.id)
except Exception as e: except Exception as e:
print(f"Failed to send Stoat marker to {channel_id}: {e}")
logger.error(f"Failed to send Stoat marker to {channel_id}: {e}") logger.error(f"Failed to send Stoat marker to {channel_id}: {e}")
return None return None
@ -470,6 +477,7 @@ class StoatWriter:
return str(role.id) return str(role.id)
except Exception as e: except Exception as e:
print(f"Failed to create Stoat role {name}: {e}")
logger.error(f"Failed to create Stoat role {name}: {e}") logger.error(f"Failed to create Stoat role {name}: {e}")
return "" return ""
@ -526,6 +534,7 @@ class StoatWriter:
await server.set_default_permissions(s_perms) await server.set_default_permissions(s_perms)
return True return True
except Exception as e: except Exception as e:
print(f"Failed to update Stoat default permissions: {e}")
logger.error(f"Failed to update Stoat default permissions: {e}") logger.error(f"Failed to update Stoat default permissions: {e}")
return False return False
@ -536,6 +545,7 @@ class StoatWriter:
emoji = await server.create_server_emoji(name=name, image=image_bytes) emoji = await server.create_server_emoji(name=name, image=image_bytes)
return str(emoji.id) return str(emoji.id)
except Exception as e: except Exception as e:
print(f"Failed to create Stoat emoji {name}: {e}")
logger.error(f"Failed to create Stoat emoji {name}: {e}") logger.error(f"Failed to create Stoat emoji {name}: {e}")
return "" return ""
@ -551,6 +561,7 @@ class StoatWriter:
banner=banner if banner is not None else stoat.UNDEFINED banner=banner if banner is not None else stoat.UNDEFINED
) )
except Exception as e: except Exception as e:
print(f"Failed to update Stoat guild metadata: {e}")
logger.error(f"Failed to update Stoat guild metadata: {e}") logger.error(f"Failed to update Stoat guild metadata: {e}")
async def remove_community_logo_and_banner(self) -> dict: async def remove_community_logo_and_banner(self) -> dict:
@ -562,12 +573,14 @@ class StoatWriter:
try: try:
await server.edit(icon=None) await server.edit(icon=None)
except Exception as e: except Exception as e:
print(f"Failed to remove Stoat community icon: {e}")
logger.error(f"Failed to remove Stoat community icon: {e}") logger.error(f"Failed to remove Stoat community icon: {e}")
if has_banner: if has_banner:
try: try:
await server.edit(banner=None) await server.edit(banner=None)
except Exception as e: except Exception as e:
print(f"Failed to remove Stoat community banner: {e}")
logger.error(f"Failed to remove Stoat community banner: {e}") logger.error(f"Failed to remove Stoat community banner: {e}")
return { return {
@ -594,6 +607,7 @@ class StoatWriter:
if progress_callback: if progress_callback:
await progress_callback(name, i, total) await progress_callback(name, i, total)
except Exception as e: except Exception as e:
print(f"Failed to delete Stoat channel {ch.id}: {e}")
logger.error(f"Failed to delete Stoat channel {ch.id}: {e}") logger.error(f"Failed to delete Stoat channel {ch.id}: {e}")
# To delete categories, we can wipe the categories array via server.edit to avoid 404 endpoint # To delete categories, we can wipe the categories array via server.edit to avoid 404 endpoint
@ -618,6 +632,7 @@ class StoatWriter:
await progress_callback(name, j, total) await progress_callback(name, j, total)
j += 1 j += 1
except Exception as e: except Exception as e:
print(f"Failed to wipe Stoat categories via edit: {e}")
logger.error(f"Failed to wipe Stoat categories via edit: {e}") logger.error(f"Failed to wipe Stoat categories via edit: {e}")
return count return count
@ -634,17 +649,23 @@ class StoatWriter:
logger.info(f"Danger Zone: Skipping permission reset for audit channel {name}") logger.info(f"Danger Zone: Skipping permission reset for audit channel {name}")
total -= 1 total -= 1
continue continue
# In Stoat, clearing overrides might involve setting them to default or explicitly removing the role_permissions/default_permissions
# Since we don't know an explicit "clear_overrides" method, we'll wipe them by setting empty/none if possible. # Fetch fresh channel to get current role_permissions
# Actually Stoat allows overwriting. Setting allow=0 deny=0 for role overrides isn't explicitly clear. fresh_ch = await self.client.fetch_channel(ch.id)
# For safety, we will just pass. If the user expects it, we'd iterate over roles and set empty. # Clear default permissions
# A quick way is to edit the channel permissions to empty state if possible. if hasattr(fresh_ch, "default_permissions") and fresh_ch.default_permissions is not None:
# Let's count them anyway. await fresh_ch.set_default_permissions(None)
# (Fluxer writer does a loop over existing overrides, we can just return 0 for now until we inspect Stoat `PermissionOverride` deletion)
# Clear all role overrides
if hasattr(fresh_ch, "role_permissions"):
for role_id in list(fresh_ch.role_permissions.keys()):
await fresh_ch.set_role_permissions(str(role_id), allow=stoat.Permissions.none(), deny=stoat.Permissions.none())
count += 1 count += 1
if progress_callback: if progress_callback:
await progress_callback(name, i, total) await progress_callback(name, i, total)
except Exception as e: except Exception as e:
print(f"Failed to reset Stoat channel permissions for {ch.id}: {e}")
logger.error(f"Failed to reset Stoat channel permissions for {ch.id}: {e}") logger.error(f"Failed to reset Stoat channel permissions for {ch.id}: {e}")
return count return count
@ -671,6 +692,7 @@ class StoatWriter:
if "MissingPermission" in err_msg and "ViewChannel" in err_msg: if "MissingPermission" in err_msg and "ViewChannel" in err_msg:
logger.error(f"Stoat LOCKOUT: Bot lacks 'ViewChannel' to edit {channel_id}. " logger.error(f"Stoat LOCKOUT: Bot lacks 'ViewChannel' to edit {channel_id}. "
"Ensure the bot has 'Manage Server' or a role with 'Allow View Channel' rank higher than @everyone.") "Ensure the bot has 'Manage Server' or a role with 'Allow View Channel' rank higher than @everyone.")
print(f"Failed to set Stoat channel permission for {overwrite_id} on {channel_id}: {e}")
logger.error(f"Failed to set Stoat channel permission for {overwrite_id} on {channel_id}: {e}") logger.error(f"Failed to set Stoat channel permission for {overwrite_id} on {channel_id}: {e}")
@ -712,6 +734,7 @@ class StoatWriter:
await emoji.delete() await emoji.delete()
count += 1 count += 1
except Exception as e: except Exception as e:
print(f"Failed to delete Stoat emoji {emoji.name}: {e}")
logger.error(f"Failed to delete Stoat emoji {emoji.name}: {e}") logger.error(f"Failed to delete Stoat emoji {emoji.name}: {e}")
return {"emojis": count, "stickers": 0} return {"emojis": count, "stickers": 0}