Add comprehensive application redesign draft and full API documentation

- Application redesign with clean architecture, v3.0 roadmap
- Complete API documentation with examples
- Plugin system redesign
- Security architecture
- Implementation roadmap
This commit is contained in:
Aether 2026-02-23 17:23:05 +00:00
parent bf1214b3ca
commit 71803350ea
No known key found for this signature in database
GPG Key ID: 95AFEE837E39AFD2
2 changed files with 1607 additions and 0 deletions

View File

@ -0,0 +1,894 @@
# EU-Utility Complete API Documentation
## Version 2.1.0
---
## 📖 Table of Contents
1. [Overview](#overview)
2. [Core APIs](#core-apis)
3. [Plugin API](#plugin-api)
4. [Widget API](#widget-api)
5. [External API](#external-api)
6. [Nexus API Integration](#nexus-api-integration)
7. [Event System](#event-system)
8. [Data Storage](#data-storage)
9. [Security](#security)
10. [Examples](#examples)
---
## Overview
EU-Utility provides a three-tier API architecture:
| API | Purpose | Audience |
|-----|---------|----------|
| **PluginAPI** | Access core services | Plugin developers |
| **WidgetAPI** | Create overlay widgets | Widget developers |
| **ExternalAPI** | Third-party integrations | External apps |
---
## Core APIs
### Service Locator
```python
from core.api import get_api, get_widget_api, get_external_api
# Get APIs
plugin_api = get_api()
widget_api = get_widget_api()
external_api = get_external_api()
```
### Available Services
| Service | Method | Description |
|---------|--------|-------------|
| Log Reader | `get_log_reader()` | Read game chat logs |
| Window Manager | `get_window_manager()` | Control EU window |
| OCR | `get_ocr_service()` | Text recognition |
| Screenshot | `get_screenshot_service()` | Screen capture |
| Nexus API | `get_nexus_api()` | Item database |
| HTTP Client | `get_http_client()` | Web requests |
| Audio | `get_audio_manager()` | Sound playback |
| Notifications | `get_notification_manager()` | Toast notifications |
| Clipboard | `get_clipboard_manager()` | Copy/paste |
| Event Bus | `get_event_bus()` | Pub/sub events |
| Data Store | `get_data_store()` | Key-value storage |
| Task Manager | `get_task_manager()` | Background tasks |
---
## Plugin API
### Initialization
```python
from plugins.base_plugin import BasePlugin
from core.api import get_api
class MyPlugin(BasePlugin):
def initialize(self):
"""Called when plugin loads."""
self.api = get_api()
self.log_info(f"{self.name} initialized")
```
### Log Reader
```python
# Read last N log lines
lines = api.read_log_lines(100)
# Read since timestamp
from datetime import datetime, timedelta
recent = api.read_log_since(datetime.now() - timedelta(minutes=5))
# Read filtered by pattern
loot_lines = api.read_log_filtered(pattern="Loot:.*(Uber|Jackpot)")
```
**Returns:** `List[str]` - Log lines
### Window Manager
```python
# Get EU window info
window = api.get_eu_window()
if window:
print(f"Position: ({window['x']}, {window['y']})")
print(f"Size: {window['width']}x{window['height']}")
print(f"Focused: {window['is_focused']}")
# Check if EU is focused
if api.is_eu_focused():
api.play_sound("alert.wav")
# Bring EU to front
api.bring_eu_to_front()
# Get window screenshot
screenshot = api.capture_eu_window()
```
**Window Info Schema:**
```json
{
"x": 100,
"y": 100,
"width": 1920,
"height": 1080,
"is_focused": true,
"title": "Entropia Universe"
}
```
### OCR Service
```python
# Check if OCR is available
if api.ocr_available():
# Read text from screen region
text = api.recognize_text((100, 100, 200, 50))
print(f"Found: {text}")
# Read from EU window specifically
eu_text = api.recognize_eu_region("chat")
# Read with specific engine
text = api.recognize_text(
region=(100, 100, 200, 50),
engine="easyocr" # or "tesseract", "paddleocr"
)
```
**Parameters:**
- `region`: Tuple `(x, y, width, height)`
- `engine`: Optional OCR engine name
**Returns:** `str` - Recognized text
### Screenshot
```python
# Capture full screen
img = api.capture_screen()
# Capture region
img = api.capture_screen((0, 0, 1920, 1080))
# Save to file
img = api.capture_screen(save_path="screenshot.png")
# Capture EU window
img = api.capture_eu_window()
# Check availability
if api.screenshot_available():
img = api.capture_screen()
```
**Returns:** `PIL.Image` - Screenshot image
### Nexus API (Item Database)
```python
# Search items
items = api.search_items(
query="omegaton",
entity_type="weapons", # or "items", "mobs", "all"
limit=5
)
for item in items:
print(f"{item['name']}: {item['value']} PED")
# Get item details
details = api.get_item_details(item_id=12345)
# Get market data
market = api.get_market_data(item_id=12345)
print(f"Current: {market['current_price']} PED")
print(f"Markup: {market['markup']}%")
# Get blueprint info
bp = api.get_blueprint_details(bp_id=67890)
```
**Search Response Schema:**
```json
[
{
"id": "12345",
"name": "Omegaton M83 Predator",
"type": "weapon",
"category": "Rifle",
"value": 123.45,
"markup": 125.5,
"icon_url": "https://..."
}
]
```
### HTTP Client
```python
# GET request
result = api.http_get(
url="https://api.example.com/data",
params={"key": "value"},
cache=True, # Cache response
ttl=3600 # Cache for 1 hour
)
if result['success']:
data = result['data']
print(f"Status: {result['status_code']}")
# POST request
result = api.http_post(
url="https://api.example.com/save",
data={"key": "value"},
headers={"Authorization": "Bearer token"}
)
# With retry
result = api.http_get(
url="https://api.example.com/data",
retry=3,
backoff=True
)
```
**Response Schema:**
```json
{
"success": true,
"data": {...},
"status_code": 200,
"cached": false,
"error": null
}
```
### Audio
```python
# Play sound file
api.play_sound(
path="assets/sounds/alert.wav",
volume=0.7 # 0.0 to 1.0
)
# Play built-in sound
api.play_sound("success")
api.play_sound("error")
api.play_sound("notification")
# Simple beep
api.beep()
# Check availability
if api.audio_available():
api.play_sound("alert.wav")
```
### Notifications
```python
# Show toast notification
api.show_notification(
title="Loot Alert",
message="Found something valuable!",
duration=3000, # milliseconds
sound=True,
icon="loot" # or path to icon
)
# Show with actions
api.show_notification(
title="Mission Complete",
message="You finished the mission!",
actions=[
{"label": "View", "callback": on_view},
{"label": "Dismiss", "callback": on_dismiss}
]
)
# Update existing notification
notification_id = api.show_notification(...)
api.update_notification(
notification_id,
message="Updated message"
)
```
### Clipboard
```python
# Copy to clipboard
api.copy_to_clipboard("TT: 100 PED")
# Copy formatted
api.copy_to_clipboard(
text="Item: Omegaton",
rich_text="<b>Item:</b> Omegaton"
)
# Paste from clipboard
text = api.paste_from_clipboard()
# Check if has content
if api.clipboard_has_content():
text = api.paste_from_clipboard()
```
### Event Bus
```python
# Subscribe to events
def on_loot(event):
print(f"Loot: {event.data}")
sub_id = api.subscribe(
event_type="loot.received",
handler=on_loot
)
# Subscribe with filter
def on_valuable_loot(event):
if event.data['value'] > 100:
print(f"Uber loot: {event.data}")
api.subscribe(
event_type="loot.received",
handler=on_valuable_loot,
filter=lambda e: e.data.get('value', 0) > 100
)
# Subscribe once
api.subscribe_once(
event_type="skill.gain",
handler=on_skill_gain
)
# Unsubscribe
api.unsubscribe(sub_id)
# Publish event
api.publish(
event_type="my_plugin.event",
data={"key": "value"}
)
# Typed events
from core.event_bus import LootEvent
def on_loot_typed(event: LootEvent):
print(f"From {event.mob_name}: {event.total_tt}")
api.subscribe_typed(LootEvent, on_loot_typed)
```
**Event Types:**
- `loot.received` - Loot event
- `skill.gain` - Skill increase
- `global.recorded` - Global/HOF
- `mission.complete` - Mission finished
- `chat.message` - Chat message
- `window.focus` - Window focus change
### Data Store
```python
# Save data
api.save_data(
key="my_plugin.settings",
data={"theme": "dark", "volume": 0.8}
)
# Load data
settings = api.load_data(
key="my_plugin.settings",
default={"theme": "light", "volume": 1.0}
)
# Delete data
api.delete_data("my_plugin.settings")
# List keys
keys = api.list_data_keys(pattern="my_plugin.*")
# Check exists
if api.has_data("my_plugin.settings"):
settings = api.load_data("my_plugin.settings")
```
### Tasks
```python
# Run async task
task_id = api.run_task(
func=fetch_market_data,
args=(item_id,),
callback=on_data_received,
error_callback=on_error
)
# Cancel task
api.cancel_task(task_id)
# Schedule task
api.schedule_task(
func=check_prices,
interval=60, # seconds
repeat=True
)
# Run in background
api.run_in_background(
func=heavy_computation,
priority="low" # "high", "normal", "low"
)
```
---
## Widget API
### Creating Widgets
```python
from core.api import get_widget_api
widget_api = get_widget_api()
# Create overlay widget
widget = widget_api.create_widget(
name="Loot Widget",
size=(300, 200),
position=(100, 100),
draggable=True,
resizable=True,
always_on_top=True
)
# Set content
widget.set_content(my_qwidget)
# Show/hide
widget.show()
widget.hide()
# Update position
widget.move(200, 200)
widget.resize(400, 300)
# Close
widget.close()
```
### Widget Properties
```python
# Transparency
widget.set_opacity(0.8) # 0.0 to 1.0
# Click-through
widget.set_click_through(True)
# Snap to edges
widget.set_snap_to_edges(True, margin=10)
# Auto-hide
widget.set_auto_hide(
enabled=True,
hide_delay=3000,
show_on_hover=True
)
```
---
## External API
### REST Endpoints
```python
from core.api import get_external_api
api = get_external_api()
# Start HTTP server
api.start_server(port=8080)
# Register endpoint
@api.endpoint("/loot/recent", methods=["GET"])
def get_recent_loot():
return {"loot": [...]}
# With authentication
@api.endpoint("/settings", methods=["GET", "POST"], auth_required=True)
def settings():
if request.method == "POST":
api.save_settings(request.json)
return api.load_settings()
```
### WebSocket
```python
# WebSocket endpoint
@api.websocket("/events")
async def events(websocket):
async for message in websocket:
await websocket.send({"echo": message})
```
---
## Nexus API Integration
### Entity Types
```python
from core.nexus_api import EntityType
# Available types
EntityType.ITEM # Items
EntityType.WEAPON # Weapons
EntityType.ARMOR # Armor
EntityType.MOB # Creatures
EntityType.BLUEPRINT # Blueprints
EntityType.MATERIAL # Materials
EntityType.LOCATION # Locations
EntityType.TELEPORTER # Teleporters
EntityType.SKILL # Skills
```
### Search
```python
nexus = get_nexus_api()
# Basic search
results = nexus.search(
query="omegaton",
entity_type=EntityType.WEAPON,
limit=10
)
# Advanced search
results = nexus.search(
query="rifle",
entity_type=EntityType.WEAPON,
filters={
"min_damage": 50,
"max_damage": 100,
"ammo_type": "blp"
},
sort_by="markup",
sort_order="desc",
limit=20
)
```
### Item Details
```python
# Get full item info
item = nexus.get_item(item_id=12345)
# Get market data
market = nexus.get_market_history(
item_id=12345,
days=30
)
# Get price alerts
alerts = nexus.get_price_alerts(item_id=12345)
```
### Blueprints
```python
# Get blueprint details
bp = nexus.get_blueprint(bp_id=67890)
# Get required materials
materials = nexus.get_bp_materials(bp_id=67890)
# Calculate crafting cost
cost = nexus.calculate_craft_cost(
bp_id=67890,
quantity=100,
include_markup=True
)
```
---
## Event System
### Event Structure
```python
from dataclasses import dataclass
from datetime import datetime
@dataclass
class Event:
type: str
data: dict
timestamp: datetime
source: str
```
### Event Types Reference
| Event Type | Data Schema | Description |
|------------|-------------|-------------|
| `loot.received` | `{items: [], mob_name: str, total_tt: float}` | Loot received |
| `skill.gain` | `{skill: str, old_value: float, new_value: float}` | Skill increase |
| `global.recorded` | `{type: str, value: float, mob: str}` | Global/HOF |
| `mission.complete` | `{mission_id: str, name: str, rewards: []}` | Mission done |
| `chat.message` | `{channel: str, sender: str, message: str}` | Chat message |
| `window.focus` | `{window: str, is_focused: bool}` | Focus change |
---
## Security
### Permission Model
```python
# Request permissions in plugin manifest
permissions = [
"log_reader:read",
"overlay:create",
"data_store:write",
"network:external",
"ocr:read",
"clipboard:read",
"clipboard:write"
]
```
### Secure Data
```python
# Encrypt sensitive data
api.save_secure_data(
key="api_keys.nexus",
data="secret_key",
password=user_password
)
# Decrypt
data = api.load_secure_data(
key="api_keys.nexus",
password=user_password
)
```
---
## Examples
### Complete Plugin Example
```python
"""
Loot Tracker Plugin
Tracks hunting loot with analytics.
"""
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from plugins.base_plugin import BasePlugin
from core.api import get_api
from core.event_bus import LootEvent
class LootTrackerPlugin(BasePlugin):
name = "Loot Tracker"
version = "2.0.0"
author = "ImpulsiveFPS"
description = "Track hunting loot with ROI analysis"
hotkey = "ctrl+shift+l"
def initialize(self):
self.api = get_api()
self.total_loot = 0.0
self.session_start = QDateTime.currentDateTime()
# Subscribe to loot events
self.loot_sub = self.api.subscribe_typed(
LootEvent,
self.on_loot
)
# Load history
self.history = self.api.load_data(
"loot_tracker.history",
default=[]
)
self.log_info("Loot Tracker initialized")
def on_loot(self, event: LootEvent):
"""Handle loot event."""
self.total_loot += event.total_tt
# Add to history
self.history.append({
"timestamp": event.timestamp.isoformat(),
"mob": event.mob_name,
"tt": event.total_tt,
"items": len(event.items)
})
# Save (keep last 1000)
self.api.save_data(
"loot_tracker.history",
self.history[-1000:]
)
# Update UI
self.update_display()
# Notify on big loot
if event.total_tt > 50:
self.api.show_notification(
"Big Loot!",
f"{event.mob_name}: {event.total_tt:.2f} PED",
sound=True
)
def get_ui(self):
"""Create plugin UI."""
widget = QWidget()
layout = QVBoxLayout(widget)
# Header
header = QLabel("Session Loot Tracker")
header.setStyleSheet("font-size: 18px; font-weight: bold;")
layout.addWidget(header)
# Stats
self.total_label = QLabel(f"Total: {self.total_loot:.2f} PED")
self.total_label.setStyleSheet("font-size: 24px; color: #10b981;")
layout.addWidget(self.total_label)
# Session time
self.time_label = QLabel("Session: 00:00:00")
layout.addWidget(self.time_label)
# History list
self.history_list = QListWidget()
layout.addWidget(self.history_list)
# Buttons
btn_layout = QHBoxLayout()
export_btn = QPushButton("Export")
export_btn.clicked.connect(self.export_data)
btn_layout.addWidget(export_btn)
clear_btn = QPushButton("Clear")
clear_btn.clicked.connect(self.clear_history)
btn_layout.addWidget(clear_btn)
layout.addLayout(btn_layout)
# Start update timer
self.timer = QTimer()
self.timer.timeout.connect(self.update_time)
self.timer.start(1000)
self.update_display()
return widget
def update_display(self):
"""Update UI with current stats."""
self.total_label.setText(
f"Total: {self.total_loot:.2f} PED"
)
# Update history list
self.history_list.clear()
for entry in reversed(self.history[-50:]):
text = f"{entry['mob']}: {entry['tt']:.2f} PED"
self.history_list.addItem(text)
def update_time(self):
"""Update session timer."""
elapsed = self.session_start.secsTo(
QDateTime.currentDateTime()
)
hours = elapsed // 3600
minutes = (elapsed % 3600) // 60
seconds = elapsed % 60
self.time_label.setText(
f"Session: {hours:02d}:{minutes:02d}:{seconds:02d}"
)
def export_data(self):
"""Export loot history to CSV."""
import csv
from pathlib import Path
path = Path.home() / "loot_history.csv"
with open(path, 'w', newline='') as f:
writer = csv.DictWriter(f,
fieldnames=['timestamp', 'mob', 'tt', 'items'])
writer.writeheader()
writer.writerows(self.history)
self.api.show_notification(
"Export Complete",
f"Saved to {path}"
)
def clear_history(self):
"""Clear loot history."""
self.history = []
self.total_loot = 0.0
self.api.delete_data("loot_tracker.history")
self.update_display()
def shutdown(self):
"""Cleanup on shutdown."""
self.api.unsubscribe(self.loot_sub)
self.api.save_data(
"loot_tracker.history",
self.history[-1000:]
)
self.log_info("Loot Tracker shutdown")
```
---
## Error Handling
### Common Errors
```python
try:
result = api.http_get("https://api.example.com")
except APIError as e:
print(f"API Error: {e.code} - {e.message}")
except RateLimitError:
print("Rate limited, retrying...")
except ServiceNotAvailableError:
print("Service not available")
```
### Error Codes
| Code | Description |
|------|-------------|
| 1001 | Service not available |
| 1002 | Rate limit exceeded |
| 1003 | Permission denied |
| 1004 | Invalid parameters |
| 1005 | Network error |
| 1006 | Timeout |
---
## Version History
| Version | Changes |
|---------|---------|
| 2.1.0 | Added WidgetAPI, improved EventBus |
| 2.0.0 | Complete API redesign |
| 1.5.0 | Added Nexus API integration |
| 1.0.0 | Initial release |
---
*Complete API Documentation - EU-Utility v2.1.0*
*Generated: 2026-02-23*

View File

@ -0,0 +1,713 @@
# EU-Utility Application Redesign Draft
## Version 3.0 - Professional Architecture
---
## 🎯 Executive Summary
Current EU-Utility is feature-rich but architecture is fragmented. This redesign creates a unified, scalable, maintainable application.
**Key Improvements:**
- Clean Architecture (Domain-Driven Design)
- Unified API Gateway
- Reactive Event System
- Plugin Sandbox Security
- Cloud Sync Capabilities
---
## 🏗️ New Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Main UI │ │ Overlay │ │ System Tray │ │
│ │ (PyQt6) │ │ Manager │ │ Icon │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
└─────────┼────────────────┼────────────────────┼─────────────┘
│ │ │
└────────────────┴────────────────────┘
┌────────▼────────┐
│ API GATEWAY │
│ (FastAPI/REST) │
└────────┬────────┘
┌────────────────────┼────────────────────┐
│ │ │
┌───────▼──────┐ ┌─────────▼─────────┐ ┌──────▼──────┐
│ CORE │ │ PLUGIN ENGINE │ │ SERVICES │
│ SERVICES │ │ │ │ │
│ │ │ ┌─────────────┐ │ │ • Nexus │
│ • Settings │ │ │ Plugin │ │ │ • OCR │
│ • DataStore │ │ │ Manager │ │ │ • Overlay │
│ • EventBus │ │ └──────┬──────┘ │ │ • Capture │
│ • Auth │ │ │ │ └─────────────┘
└──────────────┘ │ ┌──────▼──────┐ │
│ │ Sandboxed │ │
│ │ Plugins │ │
│ └─────────────┘ │
└───────────────────┘
```
---
## 📦 Domain Modules
### 1. Domain: Core
```python
# domain/core/entities.py
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, Dict, Any
from enum import Enum
class PluginState(Enum):
INSTALLED = "installed"
ACTIVE = "active"
ERROR = "error"
DISABLED = "disabled"
@dataclass
class Plugin:
"""Core plugin entity."""
id: str
name: str
version: str
author: str
description: str
state: PluginState
hotkey: Optional[str] = None
config: Dict[str, Any] = None
created_at: datetime = None
updated_at: datetime = None
@dataclass
class UserSettings:
"""User configuration entity."""
user_id: str
hotkeys: Dict[str, str]
theme: str
plugins_enabled: list
overlay_position: tuple
ocr_engine: str
api_keys: Dict[str, str]
```
### 2. Domain: Game
```python
# domain/game/entities.py
from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional
from decimal import Decimal
@dataclass
class LootItem:
"""Represents a looted item."""
name: str
quantity: int
tt_value: Decimal
market_value: Optional[Decimal] = None
@dataclass
class LootEvent:
"""Game loot event."""
id: str
timestamp: datetime
mob_name: str
items: List[LootItem]
total_tt: Decimal
location: Optional[tuple] = None
@dataclass
class SkillGain:
"""Skill increase event."""
skill_name: str
value_before: float
value_after: float
timestamp: datetime
```
### 3. Domain: Market
```python
# domain/market/entities.py
from dataclasses import dataclass
from decimal import Decimal
from datetime import datetime
from typing import Optional
@dataclass
class MarketItem:
"""Market data for an item."""
item_id: str
name: str
category: str
current_price: Decimal
markup_percent: Decimal
volume_24h: int
last_update: datetime
@dataclass
class PriceAlert:
"""User price alert."""
item_id: str
user_id: str
target_price: Decimal
condition: str # 'above' or 'below'
is_active: bool
```
---
## 🔌 Plugin System Redesign
### Plugin Manifest (v3.0)
```json
{
"manifest_version": "3.0",
"plugin": {
"id": "com.example.loot_tracker",
"name": "Advanced Loot Tracker",
"version": "2.1.0",
"author": "ImpulsiveFPS",
"description": "Professional loot tracking with analytics",
"category": "tracking",
"min_api_version": "3.0"
},
"permissions": [
"log_reader:read",
"overlay:create",
"data_store:write",
"notification:send",
"ocr:read"
],
"resources": {
"memory_limit": "128MB",
"cpu_limit": "10%",
"storage_limit": "50MB"
},
"ui": {
"has_overlay": true,
"has_settings": true,
"hotkey": "ctrl+shift+l",
"icon": "treasure-chest"
},
"dependencies": {
"core": ">=3.0",
"plugins": []
}
}
```
### Plugin Base Class
```python
# application/plugin_base.py
from abc import ABC, abstractmethod
from typing import Dict, Any, Optional
from dataclasses import dataclass
import asyncio
@dataclass
class PluginContext:
"""Context provided to plugins."""
api: 'PluginAPI'
settings: Dict[str, Any]
storage: 'PluginStorage'
logger: 'PluginLogger'
event_bus: 'EventBus'
class BasePlugin(ABC):
"""Base class for all EU-Utility plugins."""
# Required - defined in manifest
id: str
name: str
version: str
# Optional - defined in manifest
description: str = ""
author: str = ""
category: str = "utility"
def __init__(self, context: PluginContext):
self.ctx = context
self._state = PluginState.INSTALLED
self._config: Dict[str, Any] = {}
@abstractmethod
async def initialize(self) -> bool:
"""Initialize the plugin. Return True on success."""
pass
@abstractmethod
async def activate(self) -> bool:
"""Called when plugin is activated."""
pass
@abstractmethod
async def deactivate(self) -> None:
"""Called when plugin is deactivated."""
pass
@abstractmethod
def get_ui(self) -> Optional['QWidget']:
"""Return the plugin's UI component."""
pass
async def on_event(self, event: 'Event') -> None:
"""Handle events from the event bus."""
pass
def get_config_schema(self) -> Dict[str, Any]:
"""Return JSON schema for plugin configuration."""
return {}
```
---
## 🔐 Security Architecture
### Permission System
```python
# security/permissions.py
from enum import Enum, auto
class PermissionScope(Enum):
"""Permission scopes for plugins."""
LOG_READER = auto()
OVERLAY = auto()
DATA_STORE = auto()
NETWORK = auto()
OCR = auto()
CLIPBOARD = auto()
FILE_SYSTEM = auto()
PROCESS = auto()
class PermissionLevel(Enum):
"""Permission levels."""
NONE = 0
READ = 1
WRITE = 2
ADMIN = 3
@dataclass
class Permission:
scope: PermissionScope
level: PermissionLevel
constraints: Dict[str, Any] = None
```
### Plugin Sandbox
```python
# security/sandbox.py
import subprocess
import tempfile
from pathlib import Path
class PluginSandbox:
"""Isolated execution environment for plugins."""
def __init__(self, plugin_id: str, permissions: List[Permission]):
self.plugin_id = plugin_id
self.permissions = permissions
self._temp_dir = tempfile.mkdtemp(prefix=f"eu_plugin_{plugin_id}_")
def execute(self, code: str) -> Any:
"""Execute plugin code in restricted environment."""
# Implementation uses restricted Python interpreter
# with limited builtins and custom __import__
pass
def cleanup(self) -> None:
"""Clean up sandbox resources."""
shutil.rmtree(self._temp_dir, ignore_errors=True)
```
---
## 🔄 Event System
### Reactive Event Bus
```python
# infrastructure/event_bus.py
from typing import Callable, TypeVar, Generic
import asyncio
from dataclasses import dataclass
from datetime import datetime
T = TypeVar('T')
@dataclass
class Event(Generic[T]):
"""Generic event container."""
type: str
payload: T
timestamp: datetime
source: str
class ReactiveEventBus:
"""Reactive event system with filtering and transformation."""
def __init__(self):
self._subscribers: Dict[str, List[Callable]] = {}
self._streams: Dict[str, 'EventStream'] = {}
def subscribe(self,
event_type: str,
handler: Callable[[Event], None],
filter_fn: Optional[Callable[[Event], bool]] = None) -> str:
"""Subscribe to events with optional filtering."""
subscription_id = str(uuid.uuid4())
# Implementation
return subscription_id
def publish(self, event: Event) -> None:
"""Publish event to all subscribers."""
# Async dispatch
asyncio.create_task(self._dispatch(event))
def stream(self, event_type: str) -> 'EventStream':
"""Get reactive stream for event type."""
if event_type not in self._streams:
self._streams[event_type] = EventStream(event_type)
return self._streams[event_type]
class EventStream:
"""Reactive stream for events."""
def __init__(self, event_type: str):
self.event_type = event_type
self._handlers = []
def filter(self, predicate: Callable[[Event], bool]) -> 'EventStream':
"""Filter events."""
return self
def map(self, transform: Callable[[Event], T]) -> 'EventStream':
"""Transform events."""
return self
def debounce(self, seconds: float) -> 'EventStream':
"""Debounce events."""
return self
def subscribe(self, handler: Callable[[T], None]) -> None:
"""Subscribe to stream."""
pass
```
---
## 📊 Data Layer
### Repository Pattern
```python
# infrastructure/repositories.py
from abc import ABC, abstractmethod
from typing import List, Optional, Generic, TypeVar
T = TypeVar('T')
ID = TypeVar('ID')
class Repository(ABC, Generic[T, ID]):
"""Base repository interface."""
@abstractmethod
def get(self, id: ID) -> Optional[T]:
pass
@abstractmethod
def get_all(self) -> List[T]:
pass
@abstractmethod
def create(self, entity: T) -> T:
pass
@abstractmethod
def update(self, entity: T) -> T:
pass
@abstractmethod
def delete(self, id: ID) -> bool:
pass
class SQLiteRepository(Repository[T, ID]):
"""SQLite implementation."""
def __init__(self, db_path: str, entity_class: type):
self.db_path = db_path
self.entity_class = entity_class
self._init_db()
```
### Data Sync
```python
# infrastructure/sync.py
from typing import Dict, Any
import aiohttp
class CloudSync:
"""Sync data with cloud backend."""
def __init__(self, api_base: str, api_key: str):
self.api_base = api_base
self.api_key = api_key
self._local_queue = []
async def sync_settings(self, settings: Dict[str, Any]) -> bool:
"""Sync user settings to cloud."""
async with aiohttp.ClientSession() as session:
async with session.post(
f"{self.api_base}/settings",
json=settings,
headers={"Authorization": f"Bearer {self.api_key}"}
) as resp:
return resp.status == 200
async def get_remote_settings(self) -> Dict[str, Any]:
"""Get settings from cloud."""
pass
```
---
## 🚀 API Gateway
### RESTful API
```python
# api/gateway.py
from fastapi import FastAPI, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from typing import List, Optional
app = FastAPI(
title="EU-Utility API",
version="3.0.0",
description="Unified API for EU-Utility"
)
# Authentication dependency
async def verify_token(token: str = Header(...)):
"""Verify API token."""
# Implementation
pass
@app.get("/plugins", response_model=List[PluginSchema])
async def list_plugins(
category: Optional[str] = None,
active_only: bool = True,
auth = Depends(verify_token)
):
"""List all plugins."""
pass
@app.post("/plugins/{plugin_id}/activate")
async def activate_plugin(
plugin_id: str,
auth = Depends(verify_token)
):
"""Activate a plugin."""
pass
@app.get("/market/search")
async def search_market(
query: str,
category: Optional[str] = None,
limit: int = 20
):
"""Search market items."""
pass
@app.get("/game/loot/recent")
async def get_recent_loot(
hours: int = 24,
auth = Depends(verify_token)
):
"""Get recent loot events."""
pass
@app.post("/ocr/recognize")
async def ocr_recognize(
region: tuple, # (x, y, width, height)
auth = Depends(verify_token)
):
"""Recognize text from screen region."""
pass
```
---
## 📱 UI/UX Design
### Component Library
```python
# ui/components.py
from PyQt6.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
class EUCard(QFrame):
"""Card component for EU-Utility."""
def __init__(self, title: str, parent=None):
super().__init__(parent)
self.setObjectName("EUCard")
self.setup_ui(title)
def setup_ui(self, title: str):
layout = QVBoxLayout(self)
layout.setContentsMargins(16, 16, 16, 16)
# Header
header = QLabel(title)
header.setObjectName("card-title")
layout.addWidget(header)
# Content area
self.content = QFrame()
self.content_layout = QVBoxLayout(self.content)
layout.addWidget(self.content)
# Styling
self.setStyleSheet("""
#EUCard {
background-color: #2d2d2d;
border-radius: 12px;
border: 1px solid #3d3d3d;
}
#card-title {
color: #ffffff;
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
}
""")
class EUButton(QPushButton):
"""Primary button component."""
def __init__(self, text: str, variant: str = "primary"):
super().__init__(text)
self.variant = variant
self.setup_style()
def setup_style(self):
colors = {
"primary": ("#6366f1", "#4f46e5"),
"secondary": ("#3d3d3d", "#4d4d4d"),
"danger": ("#ef4444", "#dc2626"),
"success": ("#10b981", "#059669")
}
bg, hover = colors.get(self.variant, colors["primary"])
self.setStyleSheet(f"""
EUButton {{
background-color: {bg};
color: white;
border: none;
border-radius: 8px;
padding: 10px 20px;
font-weight: 600;
}}
EUButton:hover {{
background-color: {hover};
}}
""")
```
---
## 📋 Implementation Roadmap
### Phase 1: Foundation (Week 1-2)
- [ ] Set up new project structure
- [ ] Implement domain entities
- [ ] Create repository layer
- [ ] Set up dependency injection
### Phase 2: Core Services (Week 3-4)
- [ ] Event bus implementation
- [ ] Plugin system v3.0
- [ ] Security sandbox
- [ ] Settings management
### Phase 3: API & UI (Week 5-6)
- [ ] API Gateway
- [ ] Component library
- [ ] Main UI refactoring
- [ ] Overlay system
### Phase 4: Integration (Week 7-8)
- [ ] Plugin migration tool
- [ ] Data migration
- [ ] Testing suite
- [ ] Documentation
### Phase 5: Release (Week 9)
- [ ] Beta testing
- [ ] Performance optimization
- [ ] Security audit
- [ ] Public release
---
## 📊 Migration Strategy
### From v2.x to v3.0
```python
# migration/v2_to_v3.py
class MigrationTool:
"""Migrate plugins and data from v2 to v3."""
def migrate_plugin(self, v2_plugin_path: str) -> str:
"""Convert v2 plugin to v3 format."""
# Read v2 plugin
# Generate v3 manifest
# Update imports
# Return new plugin path
pass
def migrate_settings(self, v2_settings: dict) -> dict:
"""Migrate user settings."""
mapping = {
"hotkeys.global_toggle": "hotkeys.overlay_toggle",
"plugins.enabled": "plugins.active",
# ...
}
# Apply mapping
return migrated_settings
```
---
## 🎯 Success Metrics
| Metric | Target |
|--------|--------|
| Startup Time | < 2 seconds |
| Memory Usage | < 200MB |
| Plugin Load | < 100ms each |
| API Response | < 50ms |
| Code Coverage | > 80% |
| Plugin Compatibility | 100% v2 plugins work |
---
*Draft Application Design - EU-Utility v3.0*
*Created: 2026-02-23*