
    ~~je                        d Z ddlmZ ddlZddlmZ ddlZddlmZ  ej	        e
          ZdZ ej        dd	          Z G d
 de          ZdddddZdS )u.  Public URL + Open Graph verification (stages 12 + 13).

The `vps_deployment` stage writes the HTML; the `url_verification` and
`og_verification` stages fetch the public URL back over HTTPS to assert:

  url_verification:
    - status == 200
    - Content-Type starts with text/html
    - no `WWW-Authenticate` / no auth challenge header present
  og_verification:
    - all of: og:title / og:description / og:image / og:url are present in <head>
    - og:type, og:site_name, twitter:card present
    - the og:image URL itself returns HTTP 200 + image/* content-type (publicly accessible)

Synchronous (not async) by design — these run inside the orchestrator's
per-show coroutine; using httpx sync keeps the failure surface small. The
upstream calls are short (<10s timeout) and the failure semantics are early.
    )annotationsN)Iterable)BeautifulSoupz3maxamini-brief-verifier/12 (+https://just2done.com)g      .@g      $@)connectc                      e Zd ZdS )VerificationErrorN)__name__
__module____qualname__     6/workspace/show-city-briefing-agent/app/html/verify.pyr   r   "   s        Dr   r   F)
require_ogog_image_urlurlstrr   boolr   
str | NonereturnNonec                  	 t          j        t          ddt          i          5 }|                    |           }ddd           n# 1 swxY w Y   n*# t           j        $ r}t          d|           |d}~ww xY w|j        dk    rt          d|j         d          |j                            d	d
          }d|	                                vrt          d|d          |j                            d          rt          d          |sdS t          |j        d          }d |                    d          D             d}fd|D             }	|	r%t          dd                    |	                     |p                    d          }
|
st          d          	 t          j        t          ddt          i          5 }|                    |
          }ddd           n# 1 swxY w Y   n*# t           j        $ r}t          d|           |d}~ww xY w|j        dk    rt          d|j                   |j                            d	d
          }|	                                                    d          st          d|d          |j                            d          rt          d          dS )u   Raise `VerificationError` with a redacted reason if any assertion fails.

    No exception ⇒ assertions passed; the orchestrator marks the stage ok.
    Tz
User-Agent)timeoutfollow_redirectsheadersNzurl fetch failed:    zurl returned z, expected 200zcontent-type z	text/htmlz#content-type is not text/html (got )zwww-authenticatez:response carried a WWW-Authenticate header (auth required)zhtml.parserc                    i | ]@}|                     d           p|                     d          |                     d          AS )propertynamecontentget).0tags     r   
<dictcomp>z%verify_public_url.<locals>.<dictcomp>G   sQ     1 1 1 wwz""5cggfooswwy7I7I 1 1 1r   meta)zog:titlezog:descriptionog:imagezog:urlzog:typezog:site_nameztwitter:cardc                >    g | ]}                     |          |S r   r"   )r$   kog_tagss     r   
<listcomp>z%verify_public_url.<locals>.<listcomp>J   s(    999Q'++a..9q999r   zmissing OG tags: z, r(   zog:image missing contentzog:image fetch failed: zog:image returned zimage/z*og:image content-type is not image/* (got z3og:image response carried a WWW-Authenticate header)httpxClient_TIMEOUT_USER_AGENTr#   	HTTPErrorr   status_coder   lowerr   textfind_alljoin
startswith)r   r   r   clientresponseexccontent_typesouprequiredmissingog_imageimage_responseimage_ctr+   s                @r   verify_public_urlrB   &   s   E\(T#/"=? ? ? 	'BHzz#H	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' ? E E E :S : :;;DE s"" T0D T T TUUU#'';;L,,,.... Wl W W WXXX .// ^ \]]]  66D1 1--//1 1 1GnH9999(999G J HDIIg4F4F H HIII6w{{:66H < :;;;J\(T#/"=? ? ? 	2BH#ZZ11N	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 	2 ? J J J ?# ? ?@@cIJ!S(( Q^5O Q QRRR%))."==H>>&&x00 \ ZX Z Z Z[[[!!"455 W UVVVW Wsu   #A AA AA AA A;#A66A;&#G7 	G+G7 +G//G7 2G/3G7 7HHH)r   r   r   r   r   r   r   r   )__doc__
__future__r   loggingtypingr   r-   bs4r   	getLoggerr	   loggerr0   Timeoutr/   RuntimeErrorr   rB   r   r   r   <module>rL      s    & # " " " " "              		8	$	$C5=t,,,	 	 	 	 	 	 	 	 #	7W 7W 7W 7W 7W 7W 7W 7Wr   