This commit is contained in:
2026-01-26 02:29:56 -08:00
parent 0c336ef1d1
commit 334841dcfa
5 changed files with 510 additions and 65 deletions

View File

@@ -9,6 +9,7 @@ import uuid
from urllib.parse import parse_qs, urlparse
from cmdlet._shared import Cmdlet, CmdletArg
from SYS.config import load_config, save_config
from SYS.logger import log, debug
from SYS.result_table import Table
from SYS import pipeline as ctx
@@ -78,55 +79,43 @@ def _extract_set_value_arg(args: Sequence[str]) -> Optional[str]:
def _update_matrix_config(config: Dict[str, Any], key: str, value: Any) -> bool:
"""Update a Matrix config value and write to config file.
Returns True if successful, False otherwise.
"""Update the Matrix provider block in the shared config.
This method writes to the unified config store so changes persist between
sessions.
"""
try:
from SYS.config import get_config_path
from configparser import ConfigParser
if not isinstance(config, dict):
return False
# Ensure provider.matrix section exists
providers = config.get("provider", {})
value_str = str(value)
current_cfg = load_config() or {}
providers = current_cfg.setdefault("provider", {})
if not isinstance(providers, dict):
providers = {}
config["provider"] = providers
matrix_conf = providers.get("matrix", {})
if not isinstance(matrix_conf, dict):
matrix_conf = {}
providers["matrix"] = matrix_conf
# Update the in-memory config
matrix_conf[key] = value
# Try to write to config file using configparser
try:
config_path = get_config_path()
if not config_path:
return False
parser = ConfigParser()
if Path(config_path).exists():
parser.read(config_path)
section_name = "provider=matrix"
if not parser.has_section(section_name):
parser.add_section(section_name)
parser.set(section_name, key, str(value))
with open(config_path, "w") as f:
parser.write(f)
return True
except Exception as exc:
debug(f"[matrix] Failed to write config file: {exc}")
# Config was updated in memory at least
return True
current_cfg["provider"] = providers
matrix_cfg = providers.setdefault("matrix", {})
if not isinstance(matrix_cfg, dict):
matrix_cfg = {}
providers["matrix"] = matrix_cfg
matrix_cfg[key] = value_str
save_config(current_cfg)
# Keep the supplied config dict in sync for the running CLI
target_providers = config.setdefault("provider", {})
if not isinstance(target_providers, dict):
target_providers = {}
config["provider"] = target_providers
target_matrix = target_providers.setdefault("matrix", {})
if not isinstance(target_matrix, dict):
target_matrix = {}
target_providers["matrix"] = target_matrix
target_matrix[key] = value_str
return True
except Exception as exc:
debug(f"[matrix] Failed to update Matrix config: {exc}")
return False
@@ -628,14 +617,14 @@ def _show_settings_table(config: Dict[str, Any]) -> int:
settings_items = []
if isinstance(matrix_conf, dict):
sensitive_keys = {"access_token", "password"}
for key in sorted(matrix_conf.keys()):
value = matrix_conf[key]
# Skip sensitive/complex values
if key in ("password",):
value = "***"
display_value = "***" if key in sensitive_keys else str(value)
settings_items.append({
"key": key,
"value": str(value),
"label": key,
"value": display_value,
"original_value": value,
})
@@ -643,10 +632,19 @@ def _show_settings_table(config: Dict[str, Any]) -> int:
log("No Matrix settings configured. Edit config.conf manually.", file=sys.stderr)
return 0
settings_items.append({
"action": "test",
"label": "Test connection",
"value": "Verify the homeserver and token before picking rooms",
"description": "Runs a health check and then prompts for default rooms",
})
for item in settings_items:
row = table.add_row()
row.add_column("Key", item["key"])
row.add_column("Value", item["value"])
label = item.get("label") or item.get("key") or "Setting"
value_text = item.get("value") or item.get("description") or ""
row.add_column("Key", label)
row.add_column("Value", value_text)
ctx.set_last_result_table_overlay(table, settings_items)
ctx.set_current_stage_table(table)
@@ -712,6 +710,15 @@ def _handle_settings_edit(result: Any, args: Sequence[str], config: Dict[str, An
return 1
selected_item = last_items[idx]
selected_action = None
if isinstance(selected_item, dict):
selected_action = selected_item.get("action")
else:
selected_action = getattr(selected_item, "action", None)
if selected_action == "test":
return _handle_settings_test(config)
key = None
if isinstance(selected_item, dict):
key = selected_item.get("key")
@@ -742,6 +749,132 @@ def _handle_settings_edit(result: Any, args: Sequence[str], config: Dict[str, An
return 1
def _handle_settings_test(config: Dict[str, Any]) -> int:
"""Test Matrix credentials and prompt for default rooms upon success."""
from Provider.matrix import Matrix
try:
provider = Matrix(config)
except Exception as exc:
log(f"Matrix test failed: {exc}", file=sys.stderr)
return 1
log("Matrix configuration validated. Select default rooms to share.")
return _show_default_room_picker(config, provider=provider)
def _show_default_room_picker(config: Dict[str, Any], *, provider: Optional["Matrix"] = None) -> int:
"""Display joined rooms so the user can select defaults for sharing."""
from Provider.matrix import Matrix
try:
if provider is None:
provider = Matrix(config)
except Exception as exc:
log(f"Matrix not available: {exc}", file=sys.stderr)
return 1
try:
rooms = provider.list_rooms()
except Exception as exc:
log(f"Failed to list Matrix rooms: {exc}", file=sys.stderr)
return 1
if not rooms:
log("No joined rooms found.", file=sys.stderr)
return 0
default_ids = {
str(v).strip()
for v in _parse_config_room_filter_ids(config)
if str(v).strip()
}
table = Table("Matrix Rooms (select defaults with @N)")
table.set_table("matrix")
table.set_source_command(".matrix", ["-settings"])
room_items: List[Dict[str, Any]] = []
for room in rooms:
if isinstance(room, dict):
room_id = str(room.get("room_id") or "").strip()
name = str(room.get("name") or "").strip()
else:
room_id = ""
name = ""
row = table.add_row()
row.add_column("Name", name)
row.add_column("Room", room_id)
row.add_column("Default", "" if room_id and room_id in default_ids else "")
room_items.append({
**(room if isinstance(room, dict) else {}),
"room_id": room_id,
"name": name,
"store": "matrix",
"title": name or room_id or "Matrix Room",
})
ctx.set_last_result_table_overlay(table, room_items)
ctx.set_current_stage_table(table)
ctx.set_pending_pipeline_tail([[".matrix", "-settings-rooms"]], ".matrix")
log("Select default rooms to share (used by @N and autocomplete).")
return 0
def _handle_settings_rooms(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
"""Store the selected rooms list as the default sharing target."""
selection_indices = []
try:
selection_indices = ctx.get_last_selection() or []
except Exception:
pass
last_items = []
try:
last_items = ctx.get_last_result_items() or []
except Exception:
pass
if not selection_indices or not last_items:
log("No Matrix room selected. Use @N on the rooms table.", file=sys.stderr)
return 1
room_ids: List[str] = []
for idx in selection_indices:
if not isinstance(idx, int):
continue
if idx < 0 or idx >= len(last_items):
continue
item = last_items[idx]
candidate = None
if isinstance(item, dict):
candidate = item.get("room_id") or item.get("id")
else:
candidate = getattr(item, "room_id", None) or getattr(item, "id", None)
if candidate:
room_ids.append(str(candidate).strip())
cleaned: List[str] = []
for rid in room_ids:
clean = str(rid or "").strip()
if clean and clean not in cleaned:
cleaned.append(clean)
if not cleaned:
log("No valid Matrix room selected.", file=sys.stderr)
return 1
value = ", ".join(cleaned)
if not _update_matrix_config(config, "rooms", value):
log("✗ Failed to save default rooms", file=sys.stderr)
return 1
log(f"✓ Default rooms saved: {value}")
return _show_settings_table(config)
def _show_rooms_table(config: Dict[str, Any]) -> int:
"""Display rooms (refactored original behavior)."""
from Provider.matrix import Matrix
@@ -855,6 +988,9 @@ def _run(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
if _has_flag(args, "-settings-edit"):
return _handle_settings_edit(result, args, config)
if _has_flag(args, "-settings-rooms"):
return _handle_settings_rooms(result, args, config)
# Internal stage: send previously selected items to selected rooms.
if _has_flag(args, "-send"):
# Ensure we don't re-print the rooms picker table on the send stage.
@@ -1031,6 +1167,12 @@ CMDLET = Cmdlet(
description="(internal) Handle settings modification",
required=False,
),
CmdletArg(
name="settings-rooms",
type="bool",
description="(internal) Save selected default rooms",
required=False,
),
CmdletArg(
name="set-value",
type="string",