
    ɧ-iZ              	          d Z ddlZddlZddl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 ddlZddlmZ ej                            ej                            ej                            ej                            e                                        Z ej        e          Z G d de          Zd	ee
eef         z  d
e
eef         fdZde
eef         d
e
eef         fdZdede
eef         ded
efdZded
efdZ deded
efdZ!i ddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5Z"d6ed
efd7Z#d8ed
efd9Z$d8ed
efd:Z%d;ed<ed
eeef         fd=Z&de
eef         d
efd>Z'd?e
eef         d
efd@Z(dAed
efdBZ)dCe
eef         d
efdDZ*de
eef         d
efdEZ+de
eef         d
efdFZ,ded
efdGZ-de
eef         d
efdHZ.de
eef         ded
efdIZ/dJedKed
dfdLZ0g dMZ1dS )Nz
Automated Tasks for Website Generation - Phase 1 (No AI Required)
Handles JSON parsing, template selection, and template setup automatically
    N)Path)DictAnyTuple)datetime)settingsc                       e Zd ZdZdS )AutomatedTaskErrorz*Custom exception for automated task errorsN)__name__
__module____qualname____doc__     J/var/www/html/web-builder-api.evdpl.com/src/services/website_data_utils.pyr
   r
      s        44Dr   r
   
user_inputreturnc                 >   	 t          | t                    rt          j        |           n|                     d          pt          j        dd          t          _                            dd          t          _	        ddg}fd|D             }|r%t          d	d
                    |                     i dd                                         d                    dd                                          d                    dd          d                    dd          d                    dd          d                    di           d                    di           d                    dd          d                    dd          d                    dd          d                    dd          d                    dg           d                    dg           d                    d                    di                               dd                                        d                    di                               dd                                        d                    di                               dd                     d!d"t                              d"                    d#d$                              d%                    d%                    d&i                     }t                              d'|d                     |S # t          j        $ r}t          d(|           d)}~wt"          $ r-}t          |t                    r t          d*|           d)}~ww xY w)+z5Parse and validate JSON input for website generation.ModelIDAGENT_MODELzgpt-4o-minisystemPrompt websiteNamewebsiteDescriptionc                 >    g | ]}                     |          |S r   get).0fielddatas     r   
<listcomp>z$parse_json_input.<locals>.<listcomp>*   s(    TTTEDHHUOOT%TTTr   zMissing required fields: , restaurantPhonerestaurantEmailrestaurantAddressoperatingHours
socialUrlsfacebookUrlinstagramUrl
twitterUrlhasUSPsFuspspagescolorsprimaryColorprimary#2c3e50secondaryColor	secondary#3498dbaccentColoraccent#e74c3c)r0   r3   r6   
typographyselectedFontInterlogoInfowebsiteLogoz,Successfully parsed JSON input for website: zInvalid JSON format: NzError parsing JSON input: )
isinstancestrjsonloadsr   osgetenvr   agent_modelsystem_promptr
   joinstrip_normalize_font_keyloggerinfoJSONDecodeError	Exception)r   required_fieldsmissing_fieldswebsite_dataer    s        @r   parse_json_inputrP      s   3C)3J)D)DTtz*%%%*
  $xx	22]bi}6]6]!%."!=!=
 )*>?TTTT_TTT 	^$%\>AZAZ%\%\]]]
4.4466
 $((+?"D"D"J"J"L"L
 txx(92>>
 txx(92>>	

  *=r!B!B
 dhh'7<<
 $((<44
 488M266
 DHH^R88
 $((<44
 txx	511
 DHHVR((
 TXXgr**
 88NDHHXr4J4J4N4NyZc4d4dee!XX&628N8N8R8RS^`i8j8jkk((=$((8R2H2H2L2LXW`2a2abb 
( -dhh|TXXn^eEfEf.g.ghh)
* TXXmR-H-HII+
0 	`<P]C^``aaa > > > !<!<!<=== C C Ca+,, 	 !Aa!A!ABBBCs$   L=M NM""N/(NNrN   c                 t  K   	 | d         }|                      dg           }t          |          }t          t          j                            t          dd|                    }|j                            dd           |	                                r1t          j        |           t                              d|            |                    dd           t          || |           d{V }t          | |           d{V }dt!          |          |||t#          j                                                    | d	}t                              d
|            t                              d|            |S # t(          $ r-}t+          |t,                    r t-          d|           d}~ww xY w)z<Create website folder and HTML files for content generation.r   r-   	templates	generatedTparentsexist_okzRemoved existing directory: N)successdestination_pathsafe_folder_namehtml_files_createdlogo_files_copied	timestamprN   z%Successfully created website folder: zHTML files created: zError creating website folder: )r   _create_safe_folder_namer   rA   pathrE   PROJECT_ROOTparentmkdirexistsshutilrmtreerH   rI   _create_html_files_copy_logo_filesr>   r   now	isoformatrK   r=   r
   )	rN   website_namer-   rY   	dest_pathrZ   r[   setup_resultrO   s	            r   setup_templaterl   Q   s     )H#M2  "-- 4LAAlKN^__``	 	td;;; 	DM)$$$KKByBBCCC 	t444 $6iu#U#UUUUUUU #3<"K"KKKKKKK  #I 0"4!2!1133(
 
 	GIGGHHH?+=??@@@ H H Ha+,, 	 !F1!F!FGGGHs   E;F   
F7
(F22F7rj   r-   c                 >  K   g }	 | dz  }d}t          ||           d{V  |                    t          |                     t                              d|j                    |S # t          $ r)}t                              d|            g cY d}~S d}~ww xY w)z6Create single index.html file for single-page website.z
index.htmlz<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Loading...</title>
</head>
<body>
    <p>Website is being generated...</p>
</body>
</html>NzCreated placeholder HTML file: zError creating HTML file: )_write_file_asyncappendr>   rH   rI   namerK   error)rj   rN   r-   rZ   	page_filehtml_contentrO   s          r   re   re   ~   s      ,	
  	<888888888!!#i..111FinFFGGG!!   5!55666						s   A"A) )
B3BBBri   c                    | r|                                  sd}nd                    d |                                  D                       }t          j        dd|                                                               dd          }t          j        dd|                               d                                          }|sd}t          |          dk    r|d	d                             d          }t          t          j
                              d	d
         }t          j                                        d          }| d| d| S )zBCreate a safe, unguessable folder name using UUID to prevent IDOR.websiter   c              3   J   K   | ]}|                                 s|d v |V  dS )) -_Nisalnumr   cs     r   	<genexpr>z+_create_safe_folder_name.<locals>.<genexpr>   s:      cc!qyy{{caSbNbNbANbNbNbNbccr   z\s+rw   ry   z_+2   N   z%Y%m%d)rF   rE   resubreplacelowerlenrstripr>   uuiduuid4r   rg   strftime)ri   	safe_name	unique_idtimestamp_shorts       r   r]   r]      s:    3|1133 3		 GGcc|'9'9';';ccccc	F63	2288::BB3LL	F5#y1177<<BBDD	 	"!Iy>>B!#2#--c22I DJLL!!"1"%Ilnn--h77O77/77I777r   base_dirtarget_namec                    t           j                            |          }||k    rt          d          | |z                                  }|                                 }|                    |          st          d| d          |S )z
    Securely validate that a requested path is within the expected base directory.
    Prevents Path Traversal vulnerabilities.
    z3Invalid path: Directory traversal attempts detectedzAccess denied: Path z is outside allowed directory)rA   r^   basename
ValueErrorresolveis_relative_to)r   r   
clean_name	full_pathbase_resolveds        r   validate_safe_pathr      s     !!+..J[  NOOOJ&//11I$$&&M ##M22 [Y
YYYZZZr   playfairPlayfair Displayinterr:   robotoRobotoopensansz	Open SanslatoLato
montserrat
MontserratpoppinsPoppinsralewayRalewaynunitoNunitosourcezSource Sans ProdancingzDancing ScriptpacificoPacificosatisfySatisfy
greatvibeszGreat Vibesbebasz
Bebas Neue	righteous	Righteous
font_valuec                 "   | sdS t          |                                                                           }|t          v r|S d                    d |D                       }t                                          D ]n\  }}d                    d |                                D                       }||k    s.|                    |          s|                    |          s||v r|c S o|                                d         }|t          v r|S dS )zNormalize arbitrary font input to a canonical slug used across UI/backend.

    Tries to match known slugs first, then matches against known family names
    (e.g. 'Playfair Display' -> 'playfair'). Falls back to 'inter'.
    r   r   c              3   B   K   | ]}|                                 |V  d S Nrz   r|   s     r   r~   z&_normalize_font_key.<locals>.<genexpr>   s/      11QYY[[11111111r   c              3   B   K   | ]}|                                 |V  d S r   rz   r|   s     r   r~   z&_normalize_font_key.<locals>.<genexpr>   s/      DD		D1DDDDDDr   r   )r>   rF   r   FONT_KEY_TO_FAMILYrE   items
startswithsplit)r   valnormkeyfamilyfam_normfirsts          r   rG   rG      s!     w
j//


!
!
'
'
)
)C
   
7711c11111D)//11  V77DDfllnnDDDDD8tx88H<O<OPT<U<UYaeiYiYiJJJ Zj IIKKNE"""7r   font_keyc                 V    t          |           }t                              |d          S )z,Convert font key to actual font family name.r   )rG   r   r   )r   r   s     r   _get_font_family_namer      s&    
h
'
'C!!#'9:::r   c                 8    h d}t          |           }||v rdndS )z%Get appropriate fallback font family.>   loraptserifr   	cormorantmerriweatherserifz
sans-serif)rG   )r   
serif_keysr   s      r   _get_font_fallbackr      s.    MMMJ
h
'
'CZ''77\9r   original_htmlinstructionsc                    	 t          t                    j        j        dz  dz  dz  }t          |dd          5 }|                                }ddd           n# 1 swxY w Y   d|  d	| d
}t
                              d           ||fS # t          $ r4}t
                              d|            t          d|           d}~ww xY w)a<  
    Format edit request into AI prompt for website modification using SEARCH/REPLACE diffs.
    
    Args:
        original_html: The current HTML content to be edited
        instructions: User's instructions for changes
        
    Returns:
        Tuple of (system_prompt, user_prompt) for AI edit workflow
    	workflowspromptszfollowup_system_prompt.mdrutf-8encodingNzCURRENT HTML CODE:
```html
z 
```

USER'S REQUESTED CHANGES:
zd

Remember: Output ONLY the SEARCH/REPLACE blocks for the changes. Do NOT output the full HTML file.z=Successfully formatted edit prompt with SEARCH/REPLACE formatzError formatting edit prompt: )
r   __file__r`   openreadrH   rI   rK   rq   r
   )r   r   prompt_fileffollowup_system_promptuser_promptrO   s          r   format_edit_promptr      sA   G8nn+2[@9LOjj+sW555 	.%&VVXX"	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	. 	.ff f f f f 	STTT%{22 G G G9a99::: !E!!E!EFFFGs:   9B AB A  B #A $)B 
C/CCc                 x   	 |                      dd          }|                      dd          }|                      dd          }|                      dd          }|                      dd          }t          |                      di                     }t          |                      di                     }t          |           }t	          |           }	t          |                      d	g                     }
t          |           }d
dg}dg}|r|                    d| d           |                    d|            |                    dt          j	                    j
                    |                                r|                    d|            |                    d           |                    |           |                    d           dg}d}|                                r|                    d|            d}|                                r|                    d|            d}|                                r|                    d|            d}|r*|                    |           |                    d           |                                r|                    d|dg           |	                                r|                    d|	dg           n|                    ddg           |                                r|                    d|dg           |                    d|g           d                    |          }t                              d|            |S # t           $ r4}t                              d|            t%          d|           d }~ww xY w)!z
    Format website data into AI prompt for website generation.
    
    Args:
        website_data: Parsed website data from JSON input
        
    Returns:
        Formatted prompt string for AI workflow
    r   r   r   r#   r$   r%   r&   r;   r-   zJGenerate a website for a restaurant based on the following specifications:zGeneral Information:zLogo: zA - Display logo only in header, no restaurant name text beside itzWebsite Name: zYear: zDescription: zType: restaurantzContact Information:FzPhone: TzEmail: z	Address: zOperating Hours:zRestaurant USPs / Specialties:zRestaurant USPs / Specialties: NOT PROVIDED - DO NOT CREATE A 'SPECIAL FEATURES/UNIQUE OFFERINGS' OR 'WHAT MAKES US UNIQUE' SECTIONzSocial Media:zDesign & Branding:\nz6Successfully formatted website data to AI prompt for: z!Error formatting website prompt: N)r   _format_operating_hours_format_logo_info_format_social_media_format_usps_format_pages_format_design_inforo   r   rg   yearrF   extendrE   rH   rI   rK   rq   r
   )rN   ri   descriptionphoneemailaddressoperating_hours	logo_infosocial_media	usps_infor-   design_infoprompt_sectionsgeneral_infocontact_infocontact_addedpromptrO   s                     r   format_website_promptr     s5   WJ#''r::"&&';R@@  !2B77  !2B77""#6;; 2,2B2BCSUW2X2XYY &l&6&6z2&F&FGG	 ,L99 !..	 l..w;;<< *,77 hikl // 	w u u u uvvv;\;;<<<:X\^^%8::;;; 	? = = =>>>.///|,,,r""" //;;== 	! 1% 1 1222 M;;== 	! 1% 1 1222 M==?? 	! 5G 5 5666 M 	'""<000""2&&&   "" 	N""$6#LMMM ?? 	p""$DiQS#TUUUU ""  %j  ln  $o  p  p  p  	H""O\2#FGGG 	 4kBCCCO,,[\[[\\\ J J J<<<=== !HQ!H!HIIIJs   M8M; ;
N9/N44N9r   c                 b   | sdS g d}g }d}|t          |          k     r||         }|                     |i           }|                    dd          s1|                    |                                 d           |dz  }nt	          |                    dd	                    }t	          |                    d
d                    }| d| }|}	t          |dz   t          |                    D ]}
||
         }|                     |i           }|                    dd          s nXt	          |                    dd	                    }t	          |                    d
d                    }| d| }||k    r n|
}	|	|k    r-|                    |                                 d|            nK|                                }||	                                         }|                    | d| d|            |	dz   }|t          |          k     d                    |          S )z?Format operating hours for DeepSite prompt with smart grouping.r   )mondaytuesday	wednesdaythursdayfridaysaturdaysundayr   isOpenFz: Closed   r   z09:00closez22:00z - : r   )r   r   ro   
capitalize_convert_24h_to_12hrangerE   )r   days
hours_listidayday_data	open_time
close_timecurrent_hours	group_endjnext_daynext_day_datanext_open_timenext_close_time
next_hours	first_daylast_days                     r   r   r     sh    rYYYDJ	A
c$ii--1g"&&sB//||He,, (	!1!1;;;<<<FAA ,HLL,I,IJJI,X\\'7-K-KLLJ(99Z99M I1q5#d)),,  7 / 3 3Hb A A$((599 E!4]5F5Fvw5W5W!X!X"5m6G6GQX6Y6Y"Z"Z .DD?DD
..E		 A~~!!S^^%5%5"H"H"H"HIIII  NN,,		?5577!!Y"N"N8"N"N}"N"NOOOAAY c$ii--\ ::j!!!r   time_24hc                     	 |                      d          \  }}t          |          }t          |          }|dk    rd|ddS |dk     r	| d|ddS |dk    rd|ddS |dz
   d|ddS #  | cY S xY w)z'Convert 24-hour time to 12-hour format.:r   z12:02dz AM   z PM)r   int)r  hourminutes      r   r  r    s    ~~c**f4yyV199((((((BYY,,V,,,,,RZZ((((((Ri11&11111s   AA- A- A- !A- -A3r   c                 r    | sdS |                      d          p|                      dd          }|sdS d| S )z,Format logo information for DeepSite prompt.r   filenameserverFilenamez
asset/img/r   )r   r  s     r   r   r     sS     r }}Z((OIMM:JB,O,OH r #"""r   c                 t   |                      di           }|                     d|                      dd                    }|                     d|                      dd                    }|                     d|                      dd                    }g }|r,|                                r|                    d	|            |r,|                                r|                    d
|            |r,|                                r|                    d|            |rd                    |          ndS )z-Format social media URLs for DeepSite prompt.r'   facebookr(   r   	instagramr)   twitterr*   z
Facebook: zInstagram: z	Twitter: r   )r   rF   ro   rE   )rN   social_urlsr"  r#  r$  liness         r   r   r     s;   ""<44Kz<+;+;M2+N+NOOH\-=-=nb-Q-QRRIooi)9)9,)K)KLLGE .HNN$$ .,(,,--- 0Y__&& 0.9../// ,7==?? ,***+++ %-5::e2-r   c                     |                      dd          }|                      dg           }|r|sdS d |D             }|sdS d t          |          D             }d                    |          S )z2Format USPs (Unique Selling Points) for AI prompt.r+   Fr,   r   c                 b    g | ],}||                                 |                                 -S r   )rF   )r   usps     r   r!   z _format_usps.<locals>.<listcomp>  s2    EEE#EE#))++EEEr   c                 (    g | ]\  }}|d z    d| S )r   z. r   )r   r  r)  s      r   r!   z _format_usps.<locals>.<listcomp>  s*    JJJ&!S1ooooJJJr   r   )r   	enumeraterE   )rN   has_uspsr,   
valid_uspsformatted_uspss        r   r   r     s    	511HFB''D 4 r FEEEEJ r KJIj4I4IJJJN::n%%%r   c                 4    | sdS d                     |           S )z&Format pages list for DeepSite prompt.zhome, about, contactr"   )rE   )r-   s    r   r   r     s"     &%%99Ur   c           
         |                      di           }|                      dd          }t          |          }d|                     dd           d|                     dd	           d
|                     dd           d| d| 
S )z;Format design and branding information for DeepSite prompt.r.   r8   r   zPrimary Color: r0   r1   z
Secondary Color: r3   r4   z
Accent Color: r6   r7   z
Typography: z
Selected Font: )r   r   )rN   r.   r8   font_familys       r   r   r     s    h++F!!,88J (
33K vzz)Y??    **[)44   zz(I..        	     r   c                   K   g }	 |                      di           }|st                              d           |S |                     d          p|                     dd          }|st                              d           |S |dz  dz  }|                    d	d	
           t	          t
                    j        j        j        }|dz  dz  |z  }|                                r||z  }t          j	        ||           |
                    t          |                     t                              d|            	 |                                 t                              d|            n7# t          $ r*}	t                              d| d|	            Y d}	~	nd}	~	ww xY w|S # t          $ r)}
t                              d|
            |cY d}
~
S d}
~
ww xY w)a  
    Copy logo files to asset/img/ directory and delete from uploads after successful copy.
    
    Args:
        website_data: Website data containing logo information
        dest_path: Destination path for the website
        
    Returns:
        List of copied logo files
    r;   zNo logo file to copyr  r   r   zNo logo filename foundassetimgTrT   uploadslogoszCopied logo file: z'Deleted source logo file from uploads: z"Failed to delete source logo file r  NzError copying logo files: )r   rH   rI   ra   r   r   r`   rb   rc   copy2ro   r>   unlinkrK   rq   )rN   rj   r[   r   logo_filenameasset_img_dirproject_rootsource_logo_pathdest_logo_pathdelete_errorrO   s              r   rf   rf     s3      &! $$Z44	 	%KK.///$$ "j11XY]]CSUW5X5X 	%KK0111$$ "G+e3D4888 H~~,3:')3g=M""$$ 	c*]:NL)>:::$$S%8%8999KK<]<<===c '')))UmUUVVVV c c ca-aaS_aabbbbbbbbc !  ! ! !5!55666       !sT   3F) AF) B:F) >1E0 /F) 0
F$: FF) F$$F) )
G3GGG	file_pathcontentc                    K   t          j        | dd          4 d{V }|                    |           d{V  ddd          d{V  dS # 1 d{V swxY w Y   dS )z%Write content to file asynchronously.wr   r   N)aiofilesr   write)r?  r@  r   s      r   rn   rn   H  s      }Yg>>>       !ggg                             s   A
AA)rP   rl   r   r   rf   r   r
   )2r   r?   loggingrA   rc   r   r   pathlibr   typingr   r   r   r   rC  core.configr   r^   dirnameabspathr   r_   	getLoggerr   rH   rK   r
   r>   rP   rl   listre   r]   r   r   rG   r   r   r   r   r   r  r   r   r   r   r   rf   rn   __all__r   r   r   <module>rN     s?      				  				        # # # # # # # # # #                    wrwrwrwx?X?X/Y/YZZ[[		8	$	$	 	 	 	 	 	 	 	5CtCH~!5 5C$sCx. 5C 5C 5C 5Cn+HtCH~ +H$sCx. +H +H +H +HZ DcN SW \`    >83 83 8 8 8 8* C D    ("W h 	
 F , y y h   
 y - \  ! &C C    0;C ;C ; ; ; ;
: : : : : : Gc  G  GsCx  G  G  G  GDaJS#X aJ3 aJ aJ aJ aJF7"T#s(^ 7" 7" 7" 7" 7"r# #    $#c3h #C # # # #.tCH~ .# . . . .$&tCH~ &# & & & && #     d38n          3!c3h 3!D 3!T 3! 3! 3! 3!jt c d      r   