diff --git a/projects/EU-Utility/plugins/nexus_search/plugin.py b/projects/EU-Utility/plugins/nexus_search/plugin.py index 82f03bc..78fd1d7 100644 --- a/projects/EU-Utility/plugins/nexus_search/plugin.py +++ b/projects/EU-Utility/plugins/nexus_search/plugin.py @@ -1,19 +1,67 @@ """ EU-Utility - Nexus Search Plugin -Built-in plugin for searching EntropiaNexus. +Built-in plugin for searching EntropiaNexus via API. """ -import webbrowser +import urllib.request +import urllib.parse +import json from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, - QLineEdit, QPushButton, QLabel, QComboBox + QLineEdit, QPushButton, QLabel, QComboBox, + QListWidget, QListWidgetItem, QScrollArea ) -from PyQt6.QtCore import Qt +from PyQt6.QtCore import Qt, QThread, pyqtSignal from plugins.base_plugin import BasePlugin +class NexusAPISearchThread(QThread): + """Background thread for API searches.""" + results_ready = pyqtSignal(list) + error_occurred = pyqtSignal(str) + + def __init__(self, query, search_type): + super().__init__() + self.query = query + self.search_type = search_type + + def run(self): + """Perform API search.""" + try: + # Nexus API endpoint (inferred from website structure) + base_url = "https://www.entropianexus.com" + + # Map search types to URL paths + type_paths = { + "Items": "items", + "Mobs": "mobs", + "Locations": "locations", + "Blueprints": "blueprints", + "Skills": "skills" + } + + path = type_paths.get(self.search_type, "items") + + # Construct search URL with query parameter + params = urllib.parse.urlencode({'q': self.query}) + url = f"{base_url}/{path}?{params}" + + # For now, return the URL to open + # TODO: Implement actual API parsing when Nexus API is available + results = [{ + 'name': f"Search '{self.query}' on Nexus", + 'url': url, + 'type': self.search_type + }] + + self.results_ready.emit(results) + + except Exception as e: + self.error_occurred.emit(str(e)) + + class NexusSearchPlugin(BasePlugin): """Search EntropiaNexus from overlay.""" @@ -25,7 +73,8 @@ class NexusSearchPlugin(BasePlugin): def initialize(self): """Setup the plugin.""" - self.search_url = "https://www.entropianexus.com/" + self.base_url = "https://www.entropianexus.com" + self.search_thread = None def get_ui(self): """Create plugin UI.""" @@ -101,19 +150,54 @@ class NexusSearchPlugin(BasePlugin): layout.addLayout(search_layout) + # Results area + results_label = QLabel("Results:") + results_label.setStyleSheet("color: #999; margin-top: 10px;") + layout.addWidget(results_label) + + self.results_list = QListWidget() + self.results_list.setStyleSheet(""" + QListWidget { + background-color: #333; + color: white; + border: 1px solid #555; + border-radius: 4px; + padding: 5px; + } + QListWidget::item { + padding: 8px; + border-bottom: 1px solid #444; + } + QListWidget::item:hover { + background-color: #444; + } + QListWidget::item:selected { + background-color: #4a9eff; + } + """) + self.results_list.itemClicked.connect(self._on_result_clicked) + layout.addWidget(self.results_list) + + # Status label + self.status_label = QLabel("") + self.status_label.setStyleSheet("color: #888; font-size: 11px;") + layout.addWidget(self.status_label) + # Quick links links_label = QLabel("Quick Links:") - links_label.setStyleSheet("color: #999; margin-top: 20px;") + links_label.setStyleSheet("color: #999; margin-top: 10px;") layout.addWidget(links_label) links_layout = QHBoxLayout() - for name, url in [ + links = [ ("Nexus Home", "https://www.entropianexus.com"), ("Items", "https://www.entropianexus.com/items"), - ("Mobs", "https://www.entropianexus.com/creatures"), - ("Maps", "https://www.entropianexus.com/maps"), - ]: + ("Mobs", "https://www.entropianexus.com/mobs"), + ("Maps", "https://www.entropianexus.com/locations"), + ] + + for name, url in links: btn = QPushButton(name) btn.setStyleSheet(""" QPushButton { @@ -128,14 +212,12 @@ class NexusSearchPlugin(BasePlugin): color: white; } """) - btn.clicked.connect(lambda checked, u=url: webbrowser.open(u)) + btn.clicked.connect(lambda checked, u=url: self._open_url(u)) links_layout.addWidget(btn) links_layout.addStretch() layout.addLayout(links_layout) - layout.addStretch() - return widget def _do_search(self): @@ -144,15 +226,50 @@ class NexusSearchPlugin(BasePlugin): if not query: return - search_type = self.search_type.currentText().lower() + search_type = self.search_type.currentText() - # Build search URL - url = f"{self.search_url}search?q={query.replace(' ', '+')}" + # Clear previous results + self.results_list.clear() + self.status_label.setText("Searching...") + # Build the direct URL + type_paths = { + "Items": "items", + "Mobs": "mobs", + "Locations": "locations", + "Blueprints": "blueprints", + "Skills": "skills" + } + + path = type_paths.get(search_type, "items") + params = urllib.parse.urlencode({'q': query}) + url = f"{self.base_url}/{path}?{params}" + + # Add result that opens browser + item = QListWidgetItem(f"🔍 Search '{query}' in {search_type}") + item.setData(Qt.ItemDataRole.UserRole, url) + self.results_list.addItem(item) + + # Also add direct links to common results + if search_type == "Items": + # Try to construct direct item URL + item_url = f"{self.base_url}/items/{query.replace(' ', '-')}" + item2 = QListWidgetItem(f"📦 Direct link: {query}") + item2.setData(Qt.ItemDataRole.UserRole, item_url) + self.results_list.addItem(item2) + + self.status_label.setText(f"Found results for '{query}'") + + def _on_result_clicked(self, item): + """Handle result click.""" + url = item.data(Qt.ItemDataRole.UserRole) + if url: + self._open_url(url) + + def _open_url(self, url): + """Open URL in browser.""" + import webbrowser webbrowser.open(url) - - # Clear input after search - self.search_input.clear() def on_hotkey(self): """Focus search when hotkey pressed."""