EU-Utility/plugins/chat_logger/plugin.py

286 lines
9.0 KiB
Python

"""
EU-Utility - Chat Logger Plugin
Log and search chat messages with filters.
"""
import re
import json
from datetime import datetime, timedelta
from pathlib import Path
from collections import deque
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QPushButton, QTextEdit, QLineEdit, QComboBox,
QCheckBox, QFrame
)
from PyQt6.QtCore import Qt, QTimer
from plugins.base_plugin import BasePlugin
from core.icon_manager import get_icon_manager
class ChatLoggerPlugin(BasePlugin):
"""Log and search chat messages."""
name = "Chat Logger"
version = "1.0.0"
author = "ImpulsiveFPS"
description = "Log, search, and filter chat messages"
hotkey = "ctrl+shift+t" # T for chaT
# Chat channels
CHANNELS = {
'main': 'Main',
'society': 'Society',
'team': 'Team',
'local': 'Local',
'global': 'Global',
'trade': 'Trade',
'private': 'Private',
}
def initialize(self):
"""Setup chat logger."""
self.data_file = Path("data/chat_log.json")
self.data_file.parent.mkdir(parents=True, exist_ok=True)
# Keep last 10000 messages in memory
self.messages = deque(maxlen=10000)
self.filters = {
'show_main': True,
'show_society': True,
'show_team': True,
'show_local': True,
'show_global': True,
'show_trade': True,
'show_private': True,
'search_text': '',
'show_globals_only': False,
'show_loot': False,
}
self._load_recent()
def _load_recent(self):
"""Load recent messages."""
if self.data_file.exists():
try:
with open(self.data_file, 'r') as f:
data = json.load(f)
self.messages.extend(data.get('messages', [])[-1000:])
except:
pass
def _save_messages(self):
"""Save messages to file."""
# Keep last 24 hours
cutoff = (datetime.now() - timedelta(hours=24)).isoformat()
recent = [m for m in self.messages if m['time'] > cutoff]
with open(self.data_file, 'w') as f:
json.dump({'messages': recent}, f)
def get_ui(self):
"""Create plugin UI."""
widget = QWidget()
widget.setStyleSheet("background: transparent;")
layout = QVBoxLayout(widget)
layout.setSpacing(10)
layout.setContentsMargins(0, 0, 0, 0)
# Get icon manager
icon_mgr = get_icon_manager()
# Title with icon
title_layout = QHBoxLayout()
title_icon = QLabel()
icon_pixmap = icon_mgr.get_pixmap('message-square', size=20)
title_icon.setPixmap(icon_pixmap)
title_icon.setFixedSize(20, 20)
title_layout.addWidget(title_icon)
title = QLabel("Chat Logger")
title.setStyleSheet("color: white; font-size: 16px; font-weight: bold;")
title_layout.addWidget(title)
title_layout.addStretch()
layout.addLayout(title_layout)
# Search bar
search_layout = QHBoxLayout()
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Search messages...")
self.search_input.setStyleSheet("""
QLineEdit {
background-color: rgba(255, 255, 255, 15);
color: white;
border: 1px solid rgba(255, 255, 255, 30);
border-radius: 6px;
padding: 8px;
}
""")
self.search_input.textChanged.connect(self._update_filter)
search_layout.addWidget(self.search_input)
search_btn = QPushButton("🔍")
search_btn.setFixedSize(32, 32)
search_btn.setStyleSheet("""
QPushButton {
background-color: rgba(255, 255, 255, 15);
border: none;
border-radius: 6px;
font-size: 14px;
}
QPushButton:hover {
background-color: rgba(255, 255, 255, 30);
}
""")
search_layout.addWidget(search_btn)
layout.addLayout(search_layout)
# Filters
filters_frame = QFrame()
filters_frame.setStyleSheet("""
QFrame {
background-color: rgba(0, 0, 0, 50);
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 20);
}
""")
filters_layout = QHBoxLayout(filters_frame)
filters_layout.setContentsMargins(10, 6, 10, 6)
# Channel filters
self.filter_checks = {}
for channel_id, channel_name in self.CHANNELS.items():
cb = QCheckBox(channel_name)
cb.setChecked(True)
cb.setStyleSheet("color: rgba(255, 255, 255, 180); font-size: 10px;")
cb.stateChanged.connect(self._update_filter)
self.filter_checks[channel_id] = cb
filters_layout.addWidget(cb)
filters_layout.addStretch()
layout.addWidget(filters_frame)
# Chat display
self.chat_display = QTextEdit()
self.chat_display.setReadOnly(True)
self.chat_display.setStyleSheet("""
QTextEdit {
background-color: rgba(20, 25, 35, 150);
color: white;
border: 1px solid rgba(255, 255, 255, 20);
border-radius: 8px;
padding: 10px;
font-family: Consolas, monospace;
font-size: 11px;
}
""")
layout.addWidget(self.chat_display)
# Stats
self.stats_label = QLabel("Messages: 0")
self.stats_label.setStyleSheet("color: rgba(255, 255, 255, 100); font-size: 10px;")
layout.addWidget(self.stats_label)
# Refresh display
self._refresh_display()
return widget
def _update_filter(self):
"""Update filter settings."""
self.filters['search_text'] = self.search_input.text().lower()
for channel_id, cb in self.filter_checks.items():
self.filters[f'show_{channel_id}'] = cb.isChecked()
self._refresh_display()
def _refresh_display(self):
"""Refresh chat display."""
html = []
for msg in reversed(self.messages):
# Apply filters
channel = msg.get('channel', 'main')
if not self.filters.get(f'show_{channel}', True):
continue
text = msg.get('text', '')
if self.filters['search_text']:
if self.filters['search_text'] not in text.lower():
continue
# Format message
time_str = msg['time'][11:16] if msg['time'] else '--:--'
author = msg.get('author', 'Unknown')
# Color by channel
colors = {
'main': '#ffffff',
'society': '#9c27b0',
'team': '#4caf50',
'local': '#ffc107',
'global': '#f44336',
'trade': '#ff9800',
'private': '#00bcd4',
}
color = colors.get(channel, '#ffffff')
html.append(f'''
<div style="margin: 2px 0;">
<span style="color: #666;">[{time_str}]</span>
<span style="color: {color}; font-weight: bold;">{author}:</span>
<span style="color: #ccc;">{text}</span>
</div>
''')
self.chat_display.setHtml(''.join(html[:100])) # Show last 100
self.stats_label.setText(f"Messages: {len(self.messages)}")
def parse_chat_message(self, message, channel='main', author='Unknown'):
"""Parse and log chat message."""
entry = {
'time': datetime.now().isoformat(),
'channel': channel,
'author': author,
'text': message,
}
self.messages.append(entry)
self._refresh_display()
# Auto-save periodically
if len(self.messages) % 100 == 0:
self._save_messages()
def search(self, query):
"""Search chat history."""
results = []
query_lower = query.lower()
for msg in self.messages:
if query_lower in msg.get('text', '').lower():
results.append(msg)
return results
def get_globals(self):
"""Get global messages."""
return [m for m in self.messages if m.get('channel') == 'global']
def get_loot_messages(self):
"""Get loot-related messages."""
loot_keywords = ['received', 'loot', 'item', 'ped']
return [
m for m in self.messages
if any(kw in m.get('text', '').lower() for kw in loot_keywords)
]