
    51i                         d Z ddlZddlZddlZddlmZ ddlmZmZmZ ddl	m
Z
mZmZmZmZmZ  ej                   dd      Zde
d	ee   fd
Zdeded	edz  fdZde
d	e
fdZy)zL
Content Phase Node
Generates and queues content based on research findings
    N)datetime)AnyDictList)SEOCampaignStateCampaignPhasetransition_phase	add_erroradd_warningContentQueueItemNEXT_API_URLzhttp://127.0.0.1:3000statereturnc                 4   g }t        j                         j                         }| j                  dg       D ]  }|j                  dd      rd}|j                  d      dk(  rd}n-|j                  d      dk(  rd}n|j                  d      d	k(  rd
}|j	                  t        t        t        j                               |j                  dd      d|j                  dd      g|dd|              | j                  d      }|r|j                  dg       dd D ]  }|j                  dd      |j                  dd      }|j                  dd      }t        fd|D              rN|dkD  r|dkD  rd}n|dkD  r|dkD  rd}ni|j	                  t        t        t        j                               ddd	g|dd|              | j                  dg       D ]  }	|	j                  dg       dd D ]  }
|
j                  dd      t        fd |D              r*|
j                  d!d      }|d"kD  rd#}n
|d$kD  rd}nd%}|j	                  t        t        t        j                               d&dd	g|dd|               |j                  d' d()       |dd S )*a"  
    Analyze research data and prioritize content opportunities.

    Priority factors:
    - Keywords with SERP features we don't own
    - High-volume keywords from GSC with low position
    - Content gaps from competitor analysis
    - Keywords where we have AI Overview opportunity
    serp_features_datacapturedF
   feature_typeai_overviewsnippet	   paa   keyword serp_optimized_articlependingN)idr   content_typetarget_serp_featuresprioritystatuspage_id
created_atgsc_datatop_queries   querypositiond   impressionsr   c              3   .   K   | ]  }|d    k(    ywr   N .0or   s     5/var/www/html/langgraph-service/nodes/content_node.py	<genexpr>z3prioritize_content_opportunities.<locals>.<genexpr>G        Bq1Y<7*B      2      seo_articlecompetitor_datacontent_gapsc              3   .   K   | ]  }|d    k(    ywr-   r.   r/   s     r2   r3   z3prioritize_content_opportunities.<locals>.<genexpr>b   r4   r5   searchVolumei     i     competitive_contentc                     | d   S )Nr!   r.   )xs    r2   <lambda>z2prioritize_content_opportunities.<locals>.<lambda>z   s
    Qz]     T)keyreverse)r   utcnow	isoformatgetappendr   struuiduuid4anysort)r   opportunitiesnowfeaturer!   r%   r(   r)   r+   compgapvolumer   s               @r2    prioritize_content_opportunitiesrV      s    M
//

%
%
'C 99126 {{:u-H {{>*m;^,	9^,5  !1tzz|$Ir25&-kk."&E%F! 	" 	0 yy$H\\-4Sb9 	Eii,GyyS1H))M15K BMBB "}s!2B;#3  !1tzz|$*&/%7! 	" 	#	: 		+R0 88NB/4 	Cggi,GBMBB WW^Q/F}#  !1tzz|$2&/%7! 	" 		8 2DA"rD   opportunitysite_idc                   K   	 t        j                  d      4 d{   }|j                  t         dddt	        j
                  dd       i|| d	   | d
   | d   | d   dd       d{   }|j                  dv r2|j                         }|j                  d      cddd      d{    S ddd      d{    y7 7 W7 7 # 1 d{  7  sw Y   yxY w# t        $ r}t        d| d	    d|        Y d}~yd}~ww xY ww)z2Queue a content generation job via the Next.js APIg      >@)timeoutNz/api/admin/seo/content/queueAuthorizationzBearer INTERNAL_API_TOKENr   r   r   r    r!   langgraph_campaign)siteIdr   contentTypetargetFeaturesr!   source)headersjson)      jobIdz[ContentNode] Queue error for '': )httpxAsyncClientpostr   osgetenvstatus_coderc   rI   	Exceptionprint)rW   rX   clientresponsedataes         r2   queue_content_generationrt   ~   s8    
P$$T2 	) 	)f#[[. <=(GBII>RTV4W3X*YZ%*95#.~#>&12H&I +J 72 )  H ##z1}}xx(	) 	) 	) 	) 	)$ %	)	) 	) 	) 	) 	)$   P/I0F/Gs1#NOOPs   D
C  CC  AC-C.2C C  ,C-C  1D
2C  =C	>C  D
C  CC  	C  CCCC  D
C   	D)D=D
DD
c           	      D  K   t        d| d           | d   }t        j                         j                         }	 t	        |       }t        dt        |       d       || d<   d}| j                  di       j                  dd	      }|d
| D ]#  }	 t        ||       d
{   }|r
d|d<   |dz  }% |dk(  r3|r1t        | dd      } |d
d D ]  }d|d<   	 t        dt        |            }t        d| d       || d<   t        | t        j                        } || d<   | S 7 # t        $ r+}t        d|j                  dd       d|        Y d
}~d
}~ww xY w# t        $ r;}t        d|        t        | ddt        |             } g | d<   d| d<   Y d
}~d
}~ww xY ww)z
    Content phase node

    - Analyzes research data to prioritize content opportunities
    - Queues content generation jobs
    - Updates state with content queue
    z.[ContentNode] Starting content phase for site rX   z[ContentNode] Prioritized z content opportunitiescontent_queuer   configmax_content_per_runr   Nqueuedr"      z[ContentNode] Failed to queue 'r   r   rg   contentzAContent API unavailable - opportunities identified but not queuedr8   r   z[ContentNode] Queued z content generation jobspages_generatedz*[ContentNode] Error during content phase: zContent phase failed: 
updated_at)ro   r   rG   rH   rV   lenrI   rt   rn   r   minr
   rK   r	   r   SERP_FEATURES)	r   rX   rQ   rP   queued_countmax_to_queueoppjob_idrs   s	            r2   content_phaser      s     
:5;K:L
MNIG
//

%
%
'C'%8?*3}+=*>>TUV "/o yy2.223H"M ,/ 
	C	7WEE$,CM A%L
	 1y2uvE$Ra( * )H*q#m"45L%l^3KLM#/  UM$?$?@EE,L? F
  7	28N7OsSTRUVW   %:1#>?%.DSVH,MN!#o#$ 	%sl   9F AE D" D !D"1AE ?!F  D""	E+!EE EE 	F"1FF FF )__doc__rk   rL   rh   r   typingr   r   r   state.campaign_stater   r   r	   r
   r   r   rl   r   rV   rK   rt   r   r.   rD   r2   <module>r      s   
 
    " "  ryy)@Ab,< bFVAW bJ! 	4Z6:/ :4D :rD   