f
This commit is contained in:
181
CLI.py
181
CLI.py
@@ -15,17 +15,33 @@ import os
|
||||
from pathlib import Path
|
||||
if not os.environ.get("MM_DEBUG"):
|
||||
try:
|
||||
conf_path = Path(__file__).resolve().parent / "config.conf"
|
||||
if conf_path.exists():
|
||||
for ln in conf_path.read_text(encoding="utf-8").splitlines():
|
||||
ln_strip = ln.strip()
|
||||
if ln_strip.startswith("debug"):
|
||||
parts = ln_strip.split("=", 1)
|
||||
if len(parts) >= 2:
|
||||
val = parts[1].strip().strip('"').strip("'").strip().lower()
|
||||
if val in ("1", "true", "yes", "on"):
|
||||
os.environ["MM_DEBUG"] = "1"
|
||||
break
|
||||
# Check database first
|
||||
db_path = Path(__file__).resolve().parent / "medios.db"
|
||||
if db_path.exists():
|
||||
import sqlite3
|
||||
with sqlite3.connect(str(db_path)) as conn:
|
||||
cur = conn.cursor()
|
||||
# Check for global debug key
|
||||
cur.execute("SELECT value FROM config WHERE key = 'debug' AND category = 'global'")
|
||||
row = cur.fetchone()
|
||||
if row:
|
||||
val = str(row[0]).strip().lower()
|
||||
if val in ("1", "true", "yes", "on"):
|
||||
os.environ["MM_DEBUG"] = "1"
|
||||
|
||||
# Fallback to legacy config.conf if not set by DB
|
||||
if not os.environ.get("MM_DEBUG"):
|
||||
conf_path = Path(__file__).resolve().parent / "config.conf"
|
||||
if conf_path.exists():
|
||||
for ln in conf_path.read_text(encoding="utf-8").splitlines():
|
||||
ln_strip = ln.strip()
|
||||
if ln_strip.startswith("debug"):
|
||||
parts = ln_strip.split("=", 1)
|
||||
if len(parts) >= 2:
|
||||
val = parts[1].strip().strip('"').strip("'").strip().lower()
|
||||
if val in ("1", "true", "yes", "on"):
|
||||
os.environ["MM_DEBUG"] = "1"
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -297,7 +313,7 @@ class CmdletIntrospection:
|
||||
|
||||
if normalized_arg in ("storage", "store"):
|
||||
# Use cached/lightweight names for completions to avoid instantiating backends
|
||||
# (instantiating backends may perform initialization such as opening folder DBs).
|
||||
# (instantiating backends may perform heavy initialization).
|
||||
backends = cls.store_choices(config, force=False)
|
||||
if backends:
|
||||
return backends
|
||||
@@ -1484,7 +1500,7 @@ class CLI:
|
||||
@app.command("remote-server")
|
||||
def remote_server(
|
||||
storage_path: str = typer.Argument(
|
||||
None, help="Path to the store folder or store name from config"
|
||||
None, help="Path to the storage root"
|
||||
),
|
||||
port: int = typer.Option(None, "--port", help="Port to run the server on"),
|
||||
api_key: str | None = typer.Option(None, "--api-key", help="API key for authentication"),
|
||||
@@ -1492,81 +1508,16 @@ class CLI:
|
||||
debug_server: bool = False,
|
||||
background: bool = False,
|
||||
) -> None:
|
||||
"""Start the remote storage Flask server.
|
||||
"""Start the remote storage server.
|
||||
|
||||
If no path is provided, it looks for [networking=zerotier] 'serve' and 'port' in config.
|
||||
'serve' can be a path or the name of a [store=folder] entry.
|
||||
|
||||
Examples:
|
||||
mm remote-server C:\\path\\to\\store --port 999 --api-key mykey
|
||||
mm remote-server my_folder_name
|
||||
mm remote-server --background
|
||||
NOTE: The legacy local storage server has been removed. Use HydrusNetwork
|
||||
integrations instead.
|
||||
"""
|
||||
try:
|
||||
from scripts import remote_storage_server as rss
|
||||
except Exception as exc:
|
||||
print(
|
||||
"Error: remote_storage_server script not available:",
|
||||
exc,
|
||||
file=sys.stderr,
|
||||
)
|
||||
return
|
||||
|
||||
# Ensure Flask present
|
||||
if not getattr(rss, "HAS_FLASK", False):
|
||||
print(
|
||||
"ERROR: Flask and flask-cors required; install with: pip install flask flask-cors",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return
|
||||
|
||||
from SYS.config import load_config
|
||||
|
||||
conf = load_config()
|
||||
|
||||
# Resolve from Networking config if omitted
|
||||
zt_conf = conf.get("networking", {}).get("zerotier", {})
|
||||
if not storage_path:
|
||||
storage_path = zt_conf.get("serve")
|
||||
if port is None:
|
||||
port = int(zt_conf.get("port") or 999)
|
||||
if api_key is None:
|
||||
api_key = zt_conf.get("api_key")
|
||||
|
||||
if not storage_path:
|
||||
print(
|
||||
"Error: No storage path provided and no [networking=zerotier] 'serve' configured.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Check if storage_path is a named folder store
|
||||
folders = conf.get("store", {}).get("folder", {})
|
||||
found_path = None
|
||||
for name, block in folders.items():
|
||||
if name.lower() == storage_path.lower():
|
||||
found_path = block.get("path") or block.get("PATH")
|
||||
break
|
||||
|
||||
if found_path:
|
||||
storage = Path(found_path).resolve()
|
||||
else:
|
||||
storage = Path(storage_path).resolve()
|
||||
|
||||
if not storage.exists():
|
||||
print(f"Error: Storage path does not exist: {storage}", file=sys.stderr)
|
||||
return
|
||||
|
||||
rss.STORAGE_PATH = storage
|
||||
rss.API_KEY = api_key
|
||||
|
||||
try:
|
||||
app_obj = rss.create_app()
|
||||
except Exception as exc:
|
||||
print("Failed to create remote_storage_server app:", exc, file=sys.stderr)
|
||||
return
|
||||
print(
|
||||
"Error: remote-server is no longer available because legacy local storage has been removed.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return
|
||||
|
||||
print(
|
||||
f"Starting remote storage server at http://{host}:{port}, storage: {storage}"
|
||||
@@ -2102,64 +2053,6 @@ Come to love it when others take what you share, as there is no greater joy
|
||||
detail=str(exc)
|
||||
)
|
||||
|
||||
if _has_store_subtype(config, "folder"):
|
||||
store_cfg = config.get("store")
|
||||
folder_cfg = store_cfg.get("folder",
|
||||
{}) if isinstance(store_cfg,
|
||||
dict) else {}
|
||||
if isinstance(folder_cfg, dict) and folder_cfg:
|
||||
for instance_name, instance_cfg in folder_cfg.items():
|
||||
if not isinstance(instance_cfg, dict):
|
||||
continue
|
||||
name_key = str(instance_cfg.get("NAME") or instance_name)
|
||||
path_val = str(
|
||||
instance_cfg.get("PATH") or instance_cfg.get("path")
|
||||
or ""
|
||||
).strip()
|
||||
|
||||
ok = bool(
|
||||
store_registry
|
||||
and store_registry.is_available(name_key)
|
||||
)
|
||||
if ok and store_registry:
|
||||
backend = store_registry[name_key]
|
||||
scan_ok = bool(getattr(backend, "scan_ok", True))
|
||||
scan_detail = str(
|
||||
getattr(backend,
|
||||
"scan_detail",
|
||||
"") or ""
|
||||
)
|
||||
stats = getattr(backend, "scan_stats", None)
|
||||
files = None
|
||||
if isinstance(stats, dict):
|
||||
total_db = stats.get("files_total_db")
|
||||
if isinstance(total_db, (int, float)):
|
||||
files = int(total_db)
|
||||
status = "SCANNED" if scan_ok else "ERROR"
|
||||
detail = (path_val + (" - " if path_val else "")
|
||||
) + (scan_detail or "Up to date")
|
||||
_add_startup_check(
|
||||
status,
|
||||
name_key,
|
||||
store="folder",
|
||||
files=files,
|
||||
detail=detail
|
||||
)
|
||||
else:
|
||||
err = None
|
||||
if store_registry:
|
||||
err = store_registry.get_backend_error(
|
||||
instance_name
|
||||
) or store_registry.get_backend_error(name_key)
|
||||
detail = (path_val + (" - " if path_val else "")
|
||||
) + (err or "Unavailable")
|
||||
_add_startup_check(
|
||||
"ERROR",
|
||||
name_key,
|
||||
store="folder",
|
||||
detail=detail
|
||||
)
|
||||
|
||||
if _has_store_subtype(config, "debrid"):
|
||||
try:
|
||||
from SYS.config import get_debrid_api_key
|
||||
|
||||
Reference in New Issue
Block a user