
    (Gj!!                        d Z ddlmZ ddlZddlZddlZddlmZ  ej        e	          Z
 ej        d          ZddlmZ dd
Z ej        d          ZddZddZddZdS )u  Shared helpers for canonicalising WhatsApp sender identity.

WhatsApp's bridge can surface the same human under two different JID shapes
within a single conversation:

- LID form: ``999999999999999@lid``
- Phone form: ``15551234567@s.whatsapp.net``

Both the authorisation path (:mod:`gateway.run`) and the session-key path
(:mod:`gateway.session`) need to collapse these aliases to a single stable
identity. This module is the single source of truth for that resolution so
the two paths can never drift apart.

Public helpers:

- :func:`normalize_whatsapp_identifier` — strip JID/LID/device/plus syntax
  down to the bare numeric identifier.
- :func:`canonical_whatsapp_identifier` — walk the bridge's
  ``lid-mapping-*.json`` files and return a stable canonical identity
  across phone/LID variants.
- :func:`expand_whatsapp_aliases` — return the full alias set for an
  identifier. Used by authorisation code that needs to match any known
  form of a sender against an allow-list.

Plugins that need per-sender behaviour on WhatsApp (role-based routing,
per-contact authorisation, policy gating in a gateway hook) should use
``canonical_whatsapp_identifier`` so their bookkeeping lines up with
Hermes' own session keys.
    )annotationsN)Setz^[A-Za-z0-9@.+\-]+$)get_hermes_dirvaluestrreturnc                    t          | pd                                                              ddd                              dd          d                             dd          d         S )aN  Strip WhatsApp JID/LID syntax down to its stable numeric identifier.

    Accepts any of the identifier shapes the WhatsApp bridge may emit:
    ``"60123456789@s.whatsapp.net"``, ``"60123456789:47@s.whatsapp.net"``,
    ``"60123456789@lid"``, or a bare ``"+601****6789"`` / ``"60123456789"``.
    Returns just the numeric identifier (``"60123456789"``) suitable for
    equality comparisons.

    Useful for plugins that want to match sender IDs against
    user-supplied config (phone numbers in ``config.yaml``) without
    worrying about which variant the bridge happens to deliver.
     +   :r   @)r   stripreplacesplit)r   s    ?/home/rurouni/.hermes/hermes-agent/gateway/whatsapp_identity.pynormalize_whatsapp_identifierr   0   s\     	EKR		b!			sAq	 
sAq		    z^\+?[\d\s().\-]+$c                N   | sdS t          |                                           }d|v r>d|v r:|                    d          \  }}}|                    dd          d          d| }d|v r|S t                              |          rt          j        dd|          }|r| dS |S )u  Normalize an *outbound* WhatsApp target to a bridge-safe JID.

    Baileys' ``jidDecode`` crashes on a bare phone number — it expects a
    fully-qualified JID such as ``50766715226@s.whatsapp.net``. This helper
    is the inverse of :func:`normalize_whatsapp_identifier`: instead of
    stripping a JID down to its numeric core for comparison, it *builds* the
    JID a send must use.

    Behaviour:

    - ``"+50766715226"`` / ``"50766715226"`` → ``"50766715226@s.whatsapp.net"``
    - ``"50766715226@s.whatsapp.net"`` → unchanged
    - ``"group-id@g.us"`` / ``"130631430344750@lid"`` → unchanged
    - ``"user:device@s.whatsapp.net"`` style colon-before-``@`` → ``@`` form
    - anything that isn't a recognizable bare phone → returned unchanged so
      the bridge can surface a meaningful error rather than us mangling it.

    Returns ``""`` for an empty/whitespace input.
    r
   r   r   r   r   z\D+z@s.whatsapp.net)r   r   	partitionr   _BARE_PHONE_RE	fullmatchresub)r   
normalizedprefix_domaindigitss         r   to_whatsapp_jidr    M   s    (  rU!!##J
 jSJ..&00556S!,,Q/::&::
 j
++ .J// 	.----r   
identifierSet[str]c                   t          |           }|st                      S t          dd          }t                      }|g}|r|                    d          }|r||v rt                              |          s:|                    |           dD ]}|d| | dz  }|                                s"	 t          t          j	        |
                    d                              }n?# t          t          j        f$ r&}	t                              d	||	           Y d
}	~	d
}	~	ww xY w|r||vr|                    |           ||S )a  Resolve WhatsApp phone/LID aliases via bridge session mapping files.

    Returns the set of all identifiers transitively reachable through the
    bridge's ``$HERMES_HOME/whatsapp/session/lid-mapping-*.json`` files,
    starting from ``identifier``. The result always includes the
    normalized input itself, so callers can safely ``in`` check against
    the return value without a separate fallback branch.

    Returns an empty set if ``identifier`` normalizes to empty.
    zplatforms/whatsapp/sessionzwhatsapp/sessionr   )r
   _reversezlid-mapping-z.jsonzutf-8)encodingz(whatsapp_identity: failed to read %s: %sN)r   setr   pop_SAFE_IDENTIFIER_REmatchaddexistsjsonloads	read_textOSErrorJSONDecodeErrorloggerdebugappend)
r!   r   session_dirresolvedqueuecurrentsuffixmapping_pathmappedexcs
             r   expand_whatsapp_aliasesr<   y   s    /z::J uu !=?QRRKHLE
 %))A,, 	'X-- #((11 	W& 	% 	%F&)N)N)N)N)NNL&&(( 6J|55w5GGHH  T12   GWZ[[[  %&00V$$$9  %< Os   55C++D'D""D'c                j    t          |           }|sdS t          |          }t          |d           S )u  Return a stable WhatsApp sender identity across phone-JID/LID variants.

    WhatsApp may surface the same person under either a phone-format JID
    (``60123456789@s.whatsapp.net``) or a LID (``1234567890@lid``). This
    applies to a DM ``chat_id`` *and* to the ``participant_id`` of a
    member inside a group chat — both represent a user identity, and the
    bridge may flip between the two for the same human.

    This helper reads the bridge's ``whatsapp/session/lid-mapping-*.json``
    files, walks the mapping transitively, and picks the shortest
    (numeric-preferred) alias as the canonical identity.
    :func:`gateway.session.build_session_key` uses this for both WhatsApp
    DM chat_ids and WhatsApp group participant_ids, so callers get the
    same session-key identity Hermes itself uses.

    Plugins that need per-sender behaviour (role-based routing,
    authorisation, per-contact policy) should use this so their
    bookkeeping lines up with Hermes' session bookkeeping even when
    the bridge reshuffles aliases.

    Returns an empty string if ``identifier`` normalizes to empty. If no
    mapping files exist yet (fresh bridge install), returns the
    normalized input unchanged.
    r
   c                $    t          |           | fS )N)len)	candidates    r   <lambda>z/canonical_whatsapp_identifier.<locals>.<lambda>   s    s9~~y.I r   )key)r   r<   min)r!   r   aliasess      r   canonical_whatsapp_identifierrE      sD    2 /z::J r
 &j11GwIIJJJJr   )r   r   r   r   )r!   r   r   r"   )r!   r   r   r   )__doc__
__future__r   r,   loggingr   typingr   	getLogger__name__r1   compiler(   hermes_constantsr   r   r   r    r<   rE    r   r   <module>rO      s    < # " " " " "   				      		8	$	$
 !bj!788  + + + + + +   4 011) ) ) )X1 1 1 1h!K !K !K !K !K !Kr   