feat(ntfy): separate C&C topic from message ingestion
- Add ntfy_cc_topic config for command and control - Add separate NtfyPoller for C&C in StreamController - Implement serial-port-like interface: commands are executed and responses are sent back to the same topic - Update cmdline.py to use C&C topic
This commit is contained in:
@@ -25,7 +25,12 @@ from engine import config
|
||||
from engine.effects.controller import handle_effects_command
|
||||
from engine.terminal import CLR, CURSOR_OFF, CURSOR_ON, G_DIM, G_HI, RST, W_GHOST
|
||||
|
||||
TOPIC = config.NTFY_TOPIC
|
||||
try:
|
||||
CC_TOPIC = config.NTFY_CC_TOPIC
|
||||
except AttributeError:
|
||||
CC_TOPIC = "https://ntfy.sh/klubhaus_terminal_mainline_cc/json"
|
||||
|
||||
TOPIC = CC_TOPIC
|
||||
|
||||
|
||||
def send_command(cmd: str) -> str:
|
||||
|
||||
@@ -105,6 +105,7 @@ class Config:
|
||||
firehose: bool = False
|
||||
|
||||
ntfy_topic: str = "https://ntfy.sh/klubhaus_terminal_mainline/json"
|
||||
ntfy_cc_topic: str = "https://ntfy.sh/klubhaus_terminal_mainline_cc/json"
|
||||
ntfy_reconnect_delay: int = 5
|
||||
message_display_secs: int = 30
|
||||
|
||||
@@ -148,6 +149,7 @@ class Config:
|
||||
mode="poetry" if "--poetry" in argv or "-p" in argv else "news",
|
||||
firehose="--firehose" in argv,
|
||||
ntfy_topic="https://ntfy.sh/klubhaus_terminal_mainline/json",
|
||||
ntfy_cc_topic="https://ntfy.sh/klubhaus_terminal_mainline_cc/json",
|
||||
ntfy_reconnect_delay=5,
|
||||
message_display_secs=30,
|
||||
font_dir=font_dir,
|
||||
|
||||
@@ -3,6 +3,7 @@ Stream controller - manages input sources and orchestrates the render stream.
|
||||
"""
|
||||
|
||||
from engine.config import Config, get_config
|
||||
from engine.effects.controller import handle_effects_command
|
||||
from engine.eventbus import EventBus
|
||||
from engine.events import EventType, StreamEvent
|
||||
from engine.mic import MicMonitor
|
||||
@@ -18,6 +19,7 @@ class StreamController:
|
||||
self.event_bus = event_bus
|
||||
self.mic: MicMonitor | None = None
|
||||
self.ntfy: NtfyPoller | None = None
|
||||
self.ntfy_cc: NtfyPoller | None = None
|
||||
|
||||
def initialize_sources(self) -> tuple[bool, bool]:
|
||||
"""Initialize microphone and ntfy sources.
|
||||
@@ -35,7 +37,38 @@ class StreamController:
|
||||
)
|
||||
ntfy_ok = self.ntfy.start()
|
||||
|
||||
return bool(mic_ok), ntfy_ok
|
||||
self.ntfy_cc = NtfyPoller(
|
||||
self.config.ntfy_cc_topic,
|
||||
reconnect_delay=self.config.ntfy_reconnect_delay,
|
||||
display_secs=5,
|
||||
)
|
||||
self.ntfy_cc.subscribe(self._handle_cc_message)
|
||||
ntfy_cc_ok = self.ntfy_cc.start()
|
||||
|
||||
return bool(mic_ok), ntfy_ok and ntfy_cc_ok
|
||||
|
||||
def _handle_cc_message(self, event) -> None:
|
||||
"""Handle incoming C&C message - like a serial port control interface."""
|
||||
import urllib.request
|
||||
|
||||
cmd = event.body.strip() if hasattr(event, "body") else str(event).strip()
|
||||
if not cmd.startswith("/"):
|
||||
return
|
||||
|
||||
response = handle_effects_command(cmd)
|
||||
|
||||
topic_url = self.config.ntfy_cc_topic.replace("/json", "")
|
||||
data = response.encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
topic_url,
|
||||
data=data,
|
||||
headers={"User-Agent": "mainline/0.1", "Content-Type": "text/plain"},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
urllib.request.urlopen(req, timeout=5)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def run(self, items: list) -> None:
|
||||
"""Run the stream with initialized sources."""
|
||||
|
||||
Reference in New Issue
Block a user