Files
Bjorn/web_utils/comment_utils.py

142 lines
5.8 KiB
Python

# web_utils/comment_utils.py
"""
Comment and status message management utilities.
Handles status comments/messages displayed in the UI.
"""
from __future__ import annotations
import json
import re
import traceback
from typing import Any, Dict, Optional
import logging
from logger import Logger
logger = Logger(name="comment_utils.py", level=logging.DEBUG)
class CommentUtils:
"""Utilities for managing comments and status messages."""
def __init__(self, shared_data):
self.logger = logger
self.shared_data = shared_data
def get_sections(self, handler):
"""Get list of comment sections (statuses) from DB."""
try:
rows = self.shared_data.db.query("SELECT DISTINCT status FROM comments ORDER BY status;")
sections = [r["status"] for r in rows]
handler.send_response(200)
handler.send_header('Content-Type', 'application/json')
handler.end_headers()
response = json.dumps({'status': 'success', 'sections': sections})
handler.wfile.write(response.encode('utf-8'))
except Exception as e:
self.logger.error(f"Error in get_sections: {e}")
handler.send_response(500)
handler.send_header('Content-Type', 'application/json')
handler.end_headers()
error_response = json.dumps({'status': 'error', 'message': str(e)})
handler.wfile.write(error_response.encode('utf-8'))
def get_comments(self, handler):
"""Get comments for a specific section from DB."""
try:
from urllib.parse import urlparse, parse_qs
query_components = parse_qs(urlparse(handler.path).query)
section = query_components.get('section', [None])[0]
if not section:
raise ValueError('Section parameter is required')
rows = self.shared_data.db.query(
"SELECT text FROM comments WHERE status=? ORDER BY id;",
(section,)
)
comments = [r["text"] for r in rows]
handler.send_response(200)
handler.send_header('Content-Type', 'application/json')
handler.end_headers()
response = json.dumps({'status': 'success', 'comments': comments})
handler.wfile.write(response.encode('utf-8'))
except Exception as e:
self.logger.error(f"Error in get_comments: {e}")
handler.send_response(500)
handler.send_header('Content-Type', 'application/json')
handler.end_headers()
error_response = json.dumps({'status': 'error', 'message': str(e)})
handler.wfile.write(error_response.encode('utf-8'))
def save_comments(self, data):
"""Save comment list for a section to DB (replaces existing)."""
try:
section = data.get('section')
comments = data.get('comments')
lang = data.get('lang', 'fr')
theme = data.get('theme', section or 'general')
weight = int(data.get('weight', 1))
if not section or comments is None:
return {'status': 'error', 'message': 'Section and comments are required'}
if not isinstance(comments, list):
return {'status': 'error', 'message': 'Comments must be a list of strings'}
# Replace section content
with self.shared_data.db.transaction(immediate=True):
self.shared_data.db.execute("DELETE FROM comments WHERE status=? AND lang=?", (section, lang))
rows = []
for txt in comments:
t = str(txt).strip()
if not t:
continue
rows.append((t, section, theme, lang, weight))
if rows:
self.shared_data.db.insert_comments(rows)
return {'status': 'success', 'message': 'Comments saved successfully'}
except Exception as e:
self.logger.error(f"Error in save_comments: {e}")
return {'status': 'error', 'message': str(e)}
def restore_default_comments(self, data=None):
"""Restore default comments from JSON file to DB."""
try:
inserted = self.shared_data.db.import_comments_from_json(
self.shared_data.default_comments_file,
lang=(data.get('lang') if isinstance(data, dict) else None) or 'fr',
clear_existing=True
)
return {
'status': 'success',
'message': f'Comments restored ({inserted} entries).'
}
except Exception as e:
self.logger.error(f"Error in restore_default_comments: {e}")
self.logger.error(traceback.format_exc())
return {'status': 'error', 'message': str(e)}
def delete_comment_section(self, data):
"""Delete a comment section and its associated comments from DB."""
try:
section_name = data.get('section')
lang = data.get('lang', 'fr')
if not section_name:
return {'status': 'error', 'message': "Section name is required."}
if not re.match(r'^[\w\-\s]+$', section_name):
return {'status': 'error', 'message': "Invalid section name."}
count = self.shared_data.db.execute(
"DELETE FROM comments WHERE status=? AND lang=?;",
(section_name, lang)
)
if count == 0:
return {'status': 'error', 'message': f"Section '{section_name}' not found for lang='{lang}'."}
return {'status': 'success', 'message': 'Section deleted successfully.'}
except Exception as e:
self.logger.error(f"Error in delete_comment_section: {e}")
self.logger.error(traceback.format_exc())
return {'status': 'error', 'message': str(e)}