diff --git a/plugins/platforms/photon/auth.py b/plugins/platforms/photon/auth.py index a946d7afcf7..5caca102ac2 100644 --- a/plugins/platforms/photon/auth.py +++ b/plugins/platforms/photon/auth.py @@ -751,6 +751,21 @@ def register_user_if_absent( return user, True +def user_assigned_line(user: Optional[Dict[str, Any]]) -> Optional[str]: + """Return the iMessage number a Spectrum user is assigned to text on. + + This is the user's ``assignedPhoneNumber`` (the dashboard's "TEXTS ON" + column) — i.e. the number to text to reach the agent, as opposed to the + user's own ``phoneNumber``. On shared-number plans there is no dedicated + entry in ``/lines``, so this per-user field is the source of truth. + Returns ``None`` when unset (e.g. a freshly created, not-yet-assigned user). + """ + if not user: + return None + val = user.get("assignedPhoneNumber") + return str(val) if val else None + + # --------------------------------------------------------------------------- # Dashboard API: iMessage lines (the assigned number inventory) diff --git a/plugins/platforms/photon/cli.py b/plugins/platforms/photon/cli.py index 77e571b6025..924b70b01fc 100644 --- a/plugins/platforms/photon/cli.py +++ b/plugins/platforms/photon/cli.py @@ -182,6 +182,7 @@ def _cmd_setup(args: argparse.Namespace) -> int: Colors.CYAN, ) ) + agent_number = None if not phone: print(" Skipped user registration (no phone given). Re-run with --phone later.") else: @@ -190,7 +191,7 @@ def _cmd_setup(args: argparse.Namespace) -> int: first_name = args.first_name email = args.email try: - _user, created = photon_auth.register_user_if_absent( + user, created = photon_auth.register_user_if_absent( token, dashboard_id, phone_number=phone, first_name=first_name, @@ -204,18 +205,26 @@ def _cmd_setup(args: argparse.Namespace) -> int: print(f" user registration failed: {e}", file=sys.stderr) return 1 print(" ✓ phone registered" if created else " ✓ phone already registered") + # The number to text the agent is the user's assigned iMessage line + # (the dashboard's "TEXTS ON" column). On shared-number plans there is + # no dedicated entry in /lines, so this per-user field is the source of + # truth — and we already have it from the (reused) user object. + agent_number = photon_auth.user_assigned_line(user) - # 5. Surface the assigned iMessage line (the number to text the agent). - try: - line = photon_auth.get_imessage_line(token, dashboard_id) - except Exception as e: - line = None - print(f" (could not fetch the assigned line: {e})", file=sys.stderr) - if line and line.get("phoneNumber"): - status = line.get("status") or "active" + # 5. Surface the agent's iMessage number (the number to text the agent). + if not agent_number: + # No per-user assignment — fall back to a dedicated line if the project + # has one provisioned in its line inventory. + try: + line = photon_auth.get_imessage_line(token, dashboard_id) + if line: + agent_number = line.get("phoneNumber") + except Exception as e: + print(f" (could not fetch the assigned line: {e})", file=sys.stderr) + if agent_number: print() print("┌─ Your agent's iMessage number ───────────────────────────────") - print(f"│ 📱 {line['phoneNumber']} ({status})") + print(f"│ 📱 {agent_number}") print("│ Text this number from your phone to talk to your agent.") print("└──────────────────────────────────────────────────────────────") else: diff --git a/tests/plugins/platforms/photon/test_auth.py b/tests/plugins/platforms/photon/test_auth.py index afcd515f382..7fadcfda5f0 100644 --- a/tests/plugins/platforms/photon/test_auth.py +++ b/tests/plugins/platforms/photon/test_auth.py @@ -329,7 +329,11 @@ def test_register_user_if_absent_dedup(monkeypatch: pytest.MonkeyPatch) -> None: posted = {"n": 0} def fake_get(url: str, **kwargs: Any) -> _FakeResponse: - return _FakeResponse(json_body=[{"id": "u1", "phoneNumber": "+1 (555) 123-4567"}]) + return _FakeResponse(json_body=[{ + "id": "u1", + "phoneNumber": "+1 (555) 123-4567", + "assignedPhoneNumber": "+16282679185", + }]) def fake_post(url: str, **kwargs: Any) -> _FakeResponse: posted["n"] += 1 @@ -344,6 +348,20 @@ def test_register_user_if_absent_dedup(monkeypatch: pytest.MonkeyPatch) -> None: assert created is False assert user["id"] == "u1" assert posted["n"] == 0 + # The reused user carries the assigned iMessage line ("TEXTS ON"). + assert photon_auth.user_assigned_line(user) == "+16282679185" + + +def test_user_assigned_line() -> None: + assert ( + photon_auth.user_assigned_line({"assignedPhoneNumber": "+16282679185"}) + == "+16282679185" + ) + # Own number present but no assignment yet (e.g. freshly created user). + assert photon_auth.user_assigned_line({"phoneNumber": "+15551234567"}) is None + assert photon_auth.user_assigned_line({"assignedPhoneNumber": ""}) is None + assert photon_auth.user_assigned_line({}) is None + assert photon_auth.user_assigned_line(None) is None def test_register_user_if_absent_creates(monkeypatch: pytest.MonkeyPatch) -> None: