e52f7f3566
- New: sdk/plugin_web.py (PluginWebMixin: web pages, API routes, SSE) - New: services/web_panel/routes/plugin_web.py (3 endpoints) - New: plugins/example_plugin/dashboard.html (counter + SSE demo) - Updated: example_plugin uses PluginWebMixin - Tests: 28/28 passing
57 lines
2.2 KiB
Python
57 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
import logging, os
|
|
from typing import Dict
|
|
from aiohttp import web
|
|
try:
|
|
from sdk.plugin_command_decorator import plugin_command, command
|
|
from sdk.plugin_web import PluginWebMixin
|
|
except ImportError:
|
|
def plugin_command(n=None,d=None,p=None):
|
|
def deco(f):f._is_plugin_command=True;f._command_name=n or f.__name__;return f
|
|
return deco
|
|
class PluginWebMixin:
|
|
def register_web_page(self,*a,**k):pass
|
|
def register_api_route(self,*a,**k):pass
|
|
|
|
logger=logging.getLogger(__name__)
|
|
|
|
class Plugin(PluginWebMixin):
|
|
def __init__(self, plugin_name=None, config=None, bridge=None):
|
|
PluginWebMixin.__init__(self)
|
|
self.plugin_name=plugin_name or "example"
|
|
self.config=config or {}
|
|
self.bridge=bridge
|
|
self.network_bridge=None
|
|
self.is_running=False
|
|
|
|
async def initialize(self):
|
|
logger.info(f"init: {self.plugin_name}")
|
|
try:
|
|
internet=self.bridge.service_manager.get_service("internet")
|
|
from bridges.plugin_network_bridge import PluginNetworkBridge
|
|
self.network_bridge=PluginNetworkBridge(self.plugin_name,internet,self.bridge)
|
|
await self.network_bridge.register_http_route(
|
|
"/api/example/info",self._api_info,methods=["GET"],require_auth=False)
|
|
except Exception as e:
|
|
logger.warning(f"network skip: {e}")
|
|
# Load dashboard HTML from file
|
|
html_path=os.path.join(os.path.dirname(__file__),"dashboard.html")
|
|
if os.path.exists(html_path):
|
|
with open(html_path) as hf:
|
|
self.register_web_page("example_plugin","Example Plugin",hf.read(),icon="P")
|
|
self.is_running=True
|
|
|
|
async def _api_info(self,req):
|
|
return web.json_response({"plugin":self.plugin_name,"status":"running"})
|
|
|
|
@plugin_command(name="echo",description="echo input")
|
|
async def cmd_echo(self,*args):
|
|
return " ".join(args) if args else "echo: no input"
|
|
|
|
@plugin_command(name="plugin_status",description="show status")
|
|
async def cmd_status(self,*args):
|
|
return f"{self.plugin_name} v{self.config.get('version','?')} - running"
|
|
|
|
async def shutdown(self):
|
|
self.is_running=False
|