115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
"""
|
|
Application orchestrator — boot sequence, signal handling, main loop wiring.
|
|
"""
|
|
|
|
import sys
|
|
import time
|
|
import signal
|
|
import atexit
|
|
|
|
from engine import config
|
|
from engine.terminal import (
|
|
RST, G_HI, G_MID, G_DIM, W_DIM, W_GHOST, CLR, CURSOR_OFF, CURSOR_ON, tw,
|
|
slow_print, boot_ln,
|
|
)
|
|
from engine.fetch import fetch_all, fetch_poetry, load_cache, save_cache
|
|
from engine.ntfy import NtfyPoller
|
|
from engine.mic import MicMonitor
|
|
from engine.scroll import stream
|
|
|
|
TITLE = [
|
|
" ███╗ ███╗ █████╗ ██╗███╗ ██╗██╗ ██╗███╗ ██╗███████╗",
|
|
" ████╗ ████║██╔══██╗██║████╗ ██║██║ ██║████╗ ██║██╔════╝",
|
|
" ██╔████╔██║███████║██║██╔██╗ ██║██║ ██║██╔██╗ ██║█████╗ ",
|
|
" ██║╚██╔╝██║██╔══██║██║██║╚██╗██║██║ ██║██║╚██╗██║██╔══╝ ",
|
|
" ██║ ╚═╝ ██║██║ ██║██║██║ ╚████║███████╗██║██║ ╚████║███████╗",
|
|
" ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝╚══════╝╚═╝╚═╝ ╚═══╝╚══════╝",
|
|
]
|
|
|
|
|
|
def main():
|
|
atexit.register(lambda: print(CURSOR_ON, end="", flush=True))
|
|
|
|
def handle_sigint(*_):
|
|
print(f"\n\n {G_DIM}> SIGNAL LOST{RST}")
|
|
print(f" {W_GHOST}> connection terminated{RST}\n")
|
|
sys.exit(0)
|
|
|
|
signal.signal(signal.SIGINT, handle_sigint)
|
|
|
|
w = tw()
|
|
print(CLR, end="")
|
|
print(CURSOR_OFF, end="")
|
|
print()
|
|
time.sleep(0.4)
|
|
|
|
for ln in TITLE:
|
|
print(f"{G_HI}{ln}{RST}")
|
|
time.sleep(0.07)
|
|
|
|
print()
|
|
_subtitle = "literary consciousness stream" if config.MODE == 'poetry' else "digital consciousness stream"
|
|
print(f" {W_DIM}v0.1 · {_subtitle}{RST}")
|
|
print(f" {W_GHOST}{'─' * (w - 4)}{RST}")
|
|
print()
|
|
time.sleep(0.4)
|
|
|
|
cached = load_cache() if '--refresh' not in sys.argv else None
|
|
if cached:
|
|
items = cached
|
|
boot_ln("Cache", f"LOADED [{len(items)} SIGNALS]", True)
|
|
elif config.MODE == 'poetry':
|
|
slow_print(" > INITIALIZING LITERARY CORPUS...\n")
|
|
time.sleep(0.2)
|
|
print()
|
|
items, linked, failed = fetch_poetry()
|
|
print()
|
|
print(f" {G_DIM}>{RST} {G_MID}{linked} TEXTS LOADED{RST} {W_GHOST}· {failed} DARK{RST}")
|
|
print(f" {G_DIM}>{RST} {G_MID}{len(items)} STANZAS ACQUIRED{RST}")
|
|
save_cache(items)
|
|
else:
|
|
slow_print(" > INITIALIZING FEED ARRAY...\n")
|
|
time.sleep(0.2)
|
|
print()
|
|
items, linked, failed = fetch_all()
|
|
print()
|
|
print(f" {G_DIM}>{RST} {G_MID}{linked} SOURCES LINKED{RST} {W_GHOST}· {failed} DARK{RST}")
|
|
print(f" {G_DIM}>{RST} {G_MID}{len(items)} SIGNALS ACQUIRED{RST}")
|
|
save_cache(items)
|
|
|
|
if not items:
|
|
print(f"\n {W_DIM}> NO SIGNAL — check network{RST}")
|
|
sys.exit(1)
|
|
|
|
print()
|
|
mic = MicMonitor(threshold_db=config.MIC_THRESHOLD_DB)
|
|
mic_ok = mic.start()
|
|
if mic.available:
|
|
boot_ln("Microphone", "ACTIVE" if mic_ok else "OFFLINE · check System Settings → Privacy → Microphone", bool(mic_ok))
|
|
|
|
ntfy = NtfyPoller(
|
|
config.NTFY_TOPIC,
|
|
poll_interval=config.NTFY_POLL_INTERVAL,
|
|
display_secs=config.MESSAGE_DISPLAY_SECS,
|
|
)
|
|
ntfy_ok = ntfy.start()
|
|
boot_ln("ntfy", "LISTENING" if ntfy_ok else "OFFLINE", ntfy_ok)
|
|
|
|
if config.FIREHOSE:
|
|
boot_ln("Firehose", "ENGAGED", True)
|
|
|
|
time.sleep(0.4)
|
|
slow_print(" > STREAMING...\n")
|
|
time.sleep(0.2)
|
|
print(f" {W_GHOST}{'─' * (w - 4)}{RST}")
|
|
print()
|
|
time.sleep(0.4)
|
|
|
|
stream(items, ntfy, mic)
|
|
|
|
print()
|
|
print(f" {W_GHOST}{'─' * (tw() - 4)}{RST}")
|
|
print(f" {G_DIM}> {config.HEADLINE_LIMIT} SIGNALS PROCESSED{RST}")
|
|
print(f" {W_GHOST}> end of stream{RST}")
|
|
print()
|