66from typing import Any
77
88from radioshaq .compliance_plugin import get_band_plan_source_for_config
9+ from radioshaq .constants import E164_PATTERN
910from radioshaq .radio .bands import BAND_PLANS
1011from radioshaq .relay .service import relay_message_between_bands_service
12+ from radioshaq .utils .phone import normalize_e164
1113
1214# Optional ISO datetime for deliver_at (lenient)
1315DELIVER_AT_PATTERN = re .compile (
@@ -34,12 +36,14 @@ def __init__(
3436 get_radio_tx : Any = None ,
3537 config : Any = None ,
3638 callsign_repository : Any = None ,
39+ message_bus : Any = None ,
3740 ) -> None :
3841 self ._storage = storage
3942 self ._injection_queue = injection_queue
4043 self ._get_radio_tx = get_radio_tx
4144 self ._config = config
4245 self ._callsign_repository = callsign_repository
46+ self ._message_bus = message_bus
4347
4448 def to_schema (self ) -> dict [str , Any ]:
4549 return {
@@ -119,6 +123,12 @@ def validate_params(self, params: dict[str, Any]) -> list[str]:
119123 errors .append ("target_channel must be radio, sms, or whatsapp" )
120124 if target_channel in ("sms" , "whatsapp" ) and not destination_phone :
121125 errors .append ("destination_phone is required when target_channel is sms or whatsapp" )
126+ if target_channel in ("sms" , "whatsapp" ) and destination_phone :
127+ normalised = normalize_e164 (destination_phone )
128+ if not E164_PATTERN .match (normalised ):
129+ errors .append (
130+ f"destination_phone must be E.164 (e.g. +14155552671); got: { destination_phone !r} "
131+ )
122132 if params .get ("emergency" ) is True and target_channel not in ("sms" , "whatsapp" ):
123133 errors .append ("emergency only applies when target_channel is sms or whatsapp" )
124134 config = self ._config
@@ -165,7 +175,7 @@ async def execute(
165175 emergency : bool = False ,
166176 ** kwargs : Any ,
167177 ) -> str :
168- if self ._storage is None or not getattr (self ._storage , "_db " , None ):
178+ if self ._storage is None or getattr (self ._storage , "db " , None ) is None :
169179 return "Error: Relay not available (no storage)."
170180
171181 config = self ._config
@@ -223,6 +233,7 @@ async def execute(
223233 target_channel = (target_channel or "radio" ).strip ().lower (),
224234 destination_phone = (destination_phone or "" ).strip () or None ,
225235 emergency = emergency ,
236+ message_bus = self ._message_bus ,
226237 )
227238
228239 if not result .get ("ok" ):
0 commit comments