
    i>                       d Z ddlm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
Z
 e	d      Zedz  Zedz  Zedz  Zd	Zd
ZdZdZdZej(                  j+                  dd       ddlZddZddZddZddZd Zd Zedk(  r e        yy)u   Facebook 페이지 커버 이미지 생성: 전국보험설계사채용 (820×312px)
Gemini 배경 생성 + HTML 오버레이 + Playwright PNG 렌더링
    )annotationsN)Pathz#/home/jay/workspace/output/fb-pageszrecruit_bg.jpgzrecruit-cover-820x312.htmlzrecruit-cover-820x312.pngi4  i8  z0https://generativelanguage.googleapis.com/v1betagemini-2.5-flash-imageav  Professional office scene photograph. Modern corporate meeting room in Korea, wide panoramic view. Floor-to-ceiling windows showing city skyline, warm afternoon golden hour light. Clean minimalist interior with navy blue and warm wood accents. Empty conference table reflecting light, blurred depth of field background. Shot on Sony A7R V, 35mm f/2.8, cinematic color grade. No people, no text, no icons, no graphics. Wide horizontal composition suitable for a Facebook cover photo banner. High quality corporate real estate photography style. Color palette: deep navy, warm gold, cream white. Aspect ratio: landscape wide format.z&/home/jay/workspace/tools/ai-image-genc                 *    t        j                         S )N)gcloud_authget_access_token     R/home/jay/workspace/.worktrees/task-2116-dev1/output/fb-pages/gen_recruit_cover.py	get_tokenr   7   s    ''))r
   c                 ,    t        j                  d      S )NGEMINI_API_KEY)r   get_api_keyr	   r
   r   r   r   ;   s    ""#344r
   c                    t        d       	 t        j                         } d|  dd}d}t        d       d
dt        igigdddgid}g d}|D ]4  }	 |r+t	               }t         d| d| }d|v r+t         d| d| }nt         d| d}d|v rt         d| d}t        d|        d|v rdt        igdddd}t        j                  |||d      }	|	j                  dk(  r|	j                         }
|
j                  d g       }|rx|d!   j                  d"d#      }|r`t        j                  |      }t        j!                  |       t        d$t         d%t#        |      d&z   d'        yt        j                  |||d      }	|	j                  dk(  r|	j                         }
|
j                  d(g       }|D ]  }|j                  d)i       j                  d
g       }|D ]n  }d*|v s|d*   j                  d+d#      }|s t        j                  |      }t        j!                  |       t        d$t         d%t#        |      d&z   d'          y  n+t        d,|	j                   d-| d.|	j$                  d/d         7 t        d2       y# t        $ r6 t	               }|rddi}d}t        d	       nt               } d|  dd}d}Y w xY w# t        $ r}t        d0| d1|        Y d/}~d/}~ww xY w)3uJ   Gemini API로 배경 이미지를 생성하고 BG_PATH에 저장합니다.u+   [1/3] Gemini 배경 이미지 생성 중...zBearer zapplication/json)AuthorizationContent-TypeFu     SA 토큰 인증 사용r   Tu     API 키 인증 사용partstextresponseModalitiesIMAGETEXT)contentsgenerationConfig)r   zgemini-3-pro-image-previewzgemini-3.1-flash-image-previewzimagen-4.0-fast-generate-001z/models/z:generateContent?key=imagenz:predict?key=z:generateContentz:predictu     시도 중: prompt   z16:9)sampleCountaspectRatio)	instances
parametersx   )headersjsontimeout   predictionsr   bytesBase64Encoded u     [OK] 배경 저장:  (   KB)
candidatescontent
inlineDatadataz  [z] u	    실패: Nz
  [ERROR] z: uF     [WARN] Gemini 배경 생성 실패 — 그라데이션 폴백 사용)printr   get_service_account_token	Exceptionr   r   	BG_PROMPTGEMINI_API_BASErequestspoststatus_coder#   getbase64	b64decodeBG_PATHwrite_byteslenr   )tokenr"   use_api_keyapi_keypayloadmodels_to_trymodeltry_urlimagen_payloadrespr/   r&   b64	img_bytesr,   	candidater   partes                      r   generate_backgroundrL   C   sr   	
78 557&ug..
 )*   34561GV3DEG
M  32	%-,-XeW<QRYQZ[u$!0 1%gYWG,-XeW<LMu$!0 1%IGN5'*+5  $,Y"7!823F"K"  }}WgN\_`##s*99;D"&((=""=K")!n001ErJ(.(8(8(=I#//	:!$:7)2c)nVZFZE[[^"_`#'}}WgGUXY##s*99;D!%,!;J%/ 	0	 )i < @ @" M$) 0D+t3&*<&8&<&<VR&H#&060@0@0EI$+$7$7	$B$),B7)2cR[n^bNbMccf*g$h+/0	0 C 0 01E7)DIIdsOCTUV_3j 

RSa   -%'9:GK+,KE#*5'!2 2G  K V  	JugRs+,	sD   )J DK2A:K-KAK/K;KK	K:K55K:c                    | r-t         j                         rdt         j                          d}nd}dt         dt         dt         dt         d| d}|S )	u1   820×312 Facebook 커버 HTML을 생성합니다.zbackground-image: url('file://z>'); background-size: cover; background-position: center right;zKbackground: linear-gradient(135deg, #1B365D 0%, #2C5282 60%, #1a4a6e 100%);ue  <!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=820">
<title>전국보험설계사채용 Facebook 커버</title>
<style>
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
    font-style: normal;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
    font-style: normal;
  }
  @font-face {
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
    font-style: normal;
  }

  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }

  body {
    width: zpx;
    height: zfpx;
    overflow: hidden;
    background: #0a0a0a;
  }

  .cover {
    position: relative;
    width: zpx;
    u  
    overflow: hidden;
  }

  /* 좌→우 그라데이션 오버레이: 텍스트 가독성 확보 */
  .overlay-gradient {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to right,
      rgba(27, 54, 93, 0.92) 0%,
      rgba(27, 54, 93, 0.88) 30%,
      rgba(27, 54, 93, 0.65) 55%,
      rgba(27, 54, 93, 0.10) 80%,
      transparent 100%
    );
  }

  /* 하단 미묘한 섀도우 — 배경 틴티드 */
  .overlay-bottom {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 80px;
    background: linear-gradient(to top, rgba(11, 29, 58, 0.4) 0%, transparent 100%);
  }

  /* 텍스트 블록: 좌측 55% 영역 */
  .text-block {
    position: absolute;
    top: 50%;
    left: 48px;
    transform: translateY(-50%);
    width: 420px;
    display: flex;
    flex-direction: column;
    gap: 14px;
  }

  /* 상단 배지 */
  .badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    padding: 5px 14px;
    border: 1.5px solid rgba(201, 168, 76, 0.6);
    border-radius: 100px;
    background: rgba(201, 168, 76, 0.12);
  }

  .badge-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #C9A84C;
    flex-shrink: 0;
  }

  .badge-text {
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 700;
    font-size: 11px;
    letter-spacing: 0.12em;
    color: #C9A84C;
    white-space: nowrap;
    text-transform: uppercase;
  }

  /* 메인 헤드라인 */
  .headline {
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 800;
    font-size: 36px;
    line-height: 1.2;
    color: #F5F0E8;
    white-space: nowrap;
    word-break: keep-all;
    text-shadow: 0 2px 12px rgba(11, 29, 58, 0.5);
    letter-spacing: -0.02em;
  }

  /* 서브카피 */
  .subcopy {
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 700;
    font-size: 15px;
    line-height: 1.375;
    color: #C9A84C;
    white-space: nowrap;
    word-break: keep-all;
    letter-spacing: 0.04em;
  }

  /* 구분자 스타일 */
  .subcopy .sep {
    color: rgba(201, 168, 76, 0.5);
    margin: 0 8px;
    font-weight: 400;
  }

  /* 하단 구분선 + 태그라인 */
  .divider {
    width: 40px;
    height: 2px;
    background: linear-gradient(to right, #C9A84C, rgba(201, 168, 76, 0.2));
    border-radius: 1px;
  }

  .tagline {
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 400;
    font-size: 12px;
    color: rgba(245, 240, 232, 0.65);
    white-space: nowrap;
    letter-spacing: 0.01em;
  }

  /* 우측 로고 영역 (선택적 — 브랜딩) */
  .logo-area {
    position: absolute;
    top: 24px;
    right: 32px;
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .logo-icon {
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background: rgba(201, 168, 76, 0.2);
    border: 1.5px solid rgba(201, 168, 76, 0.4);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .logo-icon svg {
    width: 18px;
    height: 18px;
  }
</style>
</head>
<body>
<div class="cover">
  <!-- 배경 그라데이션 오버레이 -->
  <div class="overlay-gradient"></div>
  <div class="overlay-bottom"></div>

  <!-- 텍스트 블록 (좌측) -->
  <div class="text-block">
    <!-- 배지 -->
    <div class="badge">
      <div class="badge-dot"></div>
      <span class="badge-text">NATIONWIDE RECRUITING</span>
    </div>

    <!-- 메인 헤드라인 -->
    <h1 class="headline">전국 보험설계사 채용</h1>

    <!-- 서브카피 -->
    <p class="subcopy">
      정착지원금<span class="sep">|</span>경력 인정<span class="sep">|</span>전문 교육
    </p>

    <!-- 구분선 + 태그라인 -->
    <div class="divider"></div>
    <p class="tagline">당신의 커리어를 새로운 수준으로 — 지금 바로 시작하세요</p>
  </div>

  <!-- 우측 로고 아이콘 -->
  <div class="logo-area">
    <div class="logo-icon">
      <svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M9 2L11.5 7H16.5L12.5 10.5L14 15.5L9 12.5L4 15.5L5.5 10.5L1.5 7H6.5L9 2Z"
              fill="#C9A84C" opacity="0.9"/>
      </svg>
    </div>
  </div>
</div>
</body>
</html>)r;   existsresolveWIDTHHEIGHT)bg_availablebg_stylehtmls      r   
build_htmlrU      s     (3GOO4E3F  GE  F a!B 7 H  7 H J xWcDH Kr
   c            
     X   t        d       ddlm}   |        5 }|j                  j	                         }	 |j                  t        t        d      }|j                  dt        j                          d       |j                  d	       |j                  t        t              d
ddt        t        d       |j                          	 ddd       t        j!                         j"                  dz  }t        dt         d|dd       y# |j                          w xY w# 1 sw Y   WxY w)u9   Playwright로 HTML을 820×312 PNG로 렌더링합니다.u%   [3/3] Playwright PNG 렌더링 중...r   )sync_playwright)widthheight)viewportzfile://networkidle)
wait_untili  png)xyrX   rY   )pathtypeclipNr*   u     [OK] PNG 저장: r)   .0fr+   )r0   playwright.sync_apirW   chromiumlaunchnew_pagerP   rQ   goto	HTML_PATHrO   wait_for_timeout
screenshotstrPNG_PATHclosestatst_size)rW   pbrowserpagesize_kbs        r   
render_pngru     s    	
123		 a**##%		##u-O#PDII	 1 1 345-IP!!$'OOXUQ&BO 
 MMO mmo%%,G	zGC=
<= MMO s#   D BD9D DD  D)c                    t         j                  dd       t               } t        d       t	        |       }t
        j                  |d       t        dt
                t                t        j                         rht        j                         j                  dz  }t        d       t        d	t         d
|dd       t        dt
                t        d| rdnd        y t        d       t        j                  d       y )NT)parentsexist_oku%   [2/3] HTML 오버레이 생성 중...zutf-8)encodingu     [OK] HTML 저장: r*   u   
=== 완료 ===zPNG: r)   rc   r+   zHTML: u   배경: z	Gemini AIu   그라데이션 폴백u3   
[FAIL] PNG 파일이 생성되지 않았습니다.r   )
OUTPUT_DIRmkdirrL   r0   rU   ri   
write_textru   rm   rN   ro   rp   sysexit)bg_okhtml_contentrt   s      r   mainr     s    TD1  !E 

12e$L8	 
,- L --/))D0 "hZr'#c23yk"#3KLMNDEr
   __main__)returnrl   )r   z
str | None)r   bool)rR   r   r   rl   )__doc__
__future__r   r9   r#   osr}   timepathlibr   r5   rz   r;   ri   rm   rP   rQ   r4   GEMINI_MODELr3   r`   insertr   r   r   rL   rU   ru   r   __name__r	   r
   r   <module>r      s    #   	 
    78

'
'55	33	D'
+ 
$ ; < *5]Hmh>46 zF r
   