mirror of
https://github.com/infinition/Bjorn.git
synced 2025-12-13 16:14:57 +00:00
142 lines
5.8 KiB
Python
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)}
|